Updated project organization to isolate kernel, libraries and user applications

This commit is contained in:
Yann MAGNIN 2019-12-30 16:31:03 +01:00
parent 145e75088c
commit 6c0971e661
62 changed files with 1394 additions and 3458 deletions

110
Makefile
View File

@ -2,105 +2,24 @@
## ---
## Project: Vhex - On-calc debugger
## Author: yann.magnin@epitech.eu
## ---
##---
## Static variables
##--
HEADER := -Iinclude -Iinclude/user
BUILD := build
DEBUG := debug
NAME := vhex
EXEC := $(NAME).g1a
LDFLAG := -T $(NAME).ld
MEMORY_MAP := $(DEBUG)/$(NAME).map
ICON := icon.bmp
COMPILER := sh3eb-elf-
CC := $(COMPILER)gcc
OBJCOPY := $(COMPILER)objcopy
OBJDUMP := $(COMPILER)objdump
WRAPPER := g1a-wrapper
CFLAGS := -Werror -Wall -W -Wextra -std=c18 -m3 -mb -mrenesas \
-ffreestanding -nostdlib -fstrict-volatile-bitfields \
-Wno-unused-const-variable -Wno-unused-function \
-Wno-unused-variable -Wno-unused-but-set-variable \
-Wno-unused-parameter
red := \033[1;31m
green := \033[1;32m
blue := \033[1;34m
white := \033[1;37m
nocolor := \033[1;0m
##---
## Automated variables
##---
SRC :=
DIRECTORY := $(shell find src -not -path "*/\.*" -type d)
# Get all source files
$(foreach path,$(DIRECTORY),$(eval \
SRC += $(wildcard $(path)/*.c) \
$(wildcard $(path)/*.S) \
$(wildcard $(path)/*.s) \
))
# Geneate all object files
OBJ := $(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
## ---
KERNEL := output/vhex.g1a
USER := output/shell.elf
##---
## General rules
##---
all: | $(BUILD) $(DEBUG) $(EXEC)
all:
@ make --no-print-directory -C src/kernel
@ make --no-print-directory -C src/lib
@ make --no-print-directory -C src/user
$(EXEC): $(OBJ)
$(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) $(HEADER) -lgcc > $(MEMORY_MAP)
$(OBJCOPY) -R .comment -R .bss -O binary $(DEBUG)/$(NAME).elf $(DEBUG)/$(NAME).bin
$(WRAPPER) $(DEBUG)/$(NAME).bin -o $@ -i $(ICON)
$(BUILD) $(DEBUG):
@ printf "Create $(blue)$@$(nocolor) directory\n"
@ mkdir -p $@
install: $(EXEC)
sudo p7 send --force $^
check:
@ echo 'src: $(SRC)'
@ echo 'obj: $(OBJ)'
@ echo 'directory: $(DIRECTORY)'
asm:
@ $(OBJDUMP) -D $(DEBUG)/$(NAME).elf | less
map:
@ cat $(MEMORY_MAP) | less
sec:
@ $(OBJDUMP) -h $(DEBUG)/$(NAME).elf
##---
## Automated rules
##---
define rule-src
$(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"
endef
$(foreach source,$(SRC),$(eval \
$(call rule-src,$(source))) \
)
install: all
sudo p7 send --force --no-term $(KERNEL)
sudo p7 send --force --directory=VHEX $(USER)
@ -109,11 +28,14 @@ $(foreach source,$(SRC),$(eval \
## Cleaning rules
##---
clean:
rm -rf $(BUILD)
rm -rf $(DEBUG)
make clean --no-print-directory -C src/kernel
make clean --no-print-directory -C src/lib
make clean --no-print-directory -C src/user
fclean: clean
rm -f $(EXEC)
make fclean --no-print-directory -C src/kernel
make fclean --no-print-directory -C src/lib
make fclean --no-print-directory -C src/user
re: fclean all

28
global.mk Normal file
View File

@ -0,0 +1,28 @@
# Global option use in each Makefile
# Tools
COMPILER := sh3eb-elf-
CC := $(COMPILER)gcc
OBJCOPY := $(COMPILER)objcopy
OBJDUMP := $(COMPILER)objdump
WRAPPER := g1a-wrapper
# Flags
CFLAGS := -Werror -Wall -W -Wextra -std=c18 -m3 -mb -mrenesas \
-ffreestanding -nostdlib -fstrict-volatile-bitfields \
-Wno-unused-const-variable -Wno-unused-function \
-Wno-unused-variable -Wno-unused-but-set-variable \
-Wno-unused-parameter
# Colors
red := \033[1;31m
green := \033[1;32m
blue := \033[1;34m
white := \033[1;37m
nocolor := \033[1;0m
define n
# Force newline character
endef

View File

@ -46,6 +46,7 @@ typedef struct fx9860_context_s
} timer[3];
} tmu;
uint32_t vbr;
//TODO: SR SSR SPC GBR MACL MACH
} fx9860_context_t;
typedef struct common_context_s
@ -56,6 +57,7 @@ typedef struct common_context_s
uint32_t mach;
uint32_t ssr;
uint32_t spc;
uint32_t pr;
} common_context_t;
// Context primitive.

20
include/kernel/fs/file.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef __FILE_H__
# define __FILE_H__
#include <stdint.h>
#include <stddef.h>
#ifndef FILE_OPEN_NUMBER
# define FILE_OPEN_NUMBER 4
#endif
struct file_s
{
void *abstract;
off_t cursor;
uint8_t mode;
size_t size;
};
typedef struct file_s FILE;
#endif /*__FILE_H__*/

89
include/kernel/fs/smem.h Normal file
View File

@ -0,0 +1,89 @@
#ifndef __CASIO_SMEM_H__
# define __CASIO_SMEM_H__
#include <stdint.h>
#include <stddef.h>
#include <kernel/types.h>
#include <kernel/fs/file.h>
#define CASIO_SMEM_NAME_LENGHT 12
#define CASIO_SMEM_ROOT_ID 0xffff
#define CASIO_SMEM_BLOCK_ENTRY_MAGIC 0x4200
#define CASIO_SMEM_HEADER_INFO_EXIST 0x51
#define CASIO_SMEM_HEADER_INFO_DELETE 0x01
#define CASIO_SMEM_HEADER_TYPE_DIRECTORY 0x10
#define CASIO_SMEM_HEADER_TYPE_FILE 0x20
#define CASIO_SMEM_FRAGMENT_INFO_EXIST CASIO_SMEM_HEADER_INFO_EXIST
#define CASIO_SMEM_FRAGMENT_INFO_DELETE CASIO_SMEM_HEADER_INFO_DELETE
#define CASIO_SMEM_FRAGMENT_MAGIC 0x0120
#define CASIO_SMEM_ROOT_ID 0xffff
#define O_RDONLY 0x00
#define O_WRONLY 0x01
#define O_RDWR 0x02
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
//
typedef struct casio_smem_block_s
{
uint16_t magic_start; // always 0x4200
uint16_t entry_number; // indicate the block number
uint32_t offset; // offset in the memory (?)
struct {
uint8_t used; // Indicate if the block is used (0xff yes, 0x00 no)
uint8_t fileTable; // Indicate if the block is used by File Header Table.
uint16_t id; // Indicate the block ID in the File Header Table.
} info;
uint8_t magic_end[20]; // Content always 0xff 0xff 0xff 0xff 0x00 0x00 0x00 0x01 0xff 0xff...
} casio_smem_block_t;
// Define file header.
typedef struct casio_smem_header_s
{
uint8_t info; // 0x51 if entry exist, 0x01 if entry refer to delete file. (?)
uint8_t type; // 0x10 for a directory, 0x20 for preheader.
uint16_t id; // Indicate the block entry ID (directory)
struct {
uint16_t type; // 0xffff for root, 0x0110 for directory
uint16_t id; // directory ID, 0xffff for root
} parent;
uint16_t name[12]; // File name
} casio_smem_header_t;
// Define frament data.
typedef struct casio_smem_fragment_s
{
uint8_t info; // 0x51 if entry exit, 0x01 if entry refer to delete file.
uint8_t unknown0; // always 0x30
uint16_t id; // Fragment ID.
uint16_t magic; // always 0x0120
uint16_t file_id; // File ID.
uint16_t unknown1; // 0x0002 (?)
uint16_t frag_total; // total number of fragments for this file.
uint16_t frag_current_number; // Current fragment number.
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
// have the real size of data!
uint16_t data_size; // size of this fragment data
uint8_t fill[12]; // 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, ...
} casio_smem_fragment_t;
// Primitives
extern int casio_smem_mount(void);
extern int casio_smem_open(FILE *file, char const *name, int mode);
extern ssize_t casio_smem_read(FILE *file, void *buf, size_t count);
extern off_t casio_smem_lseek(FILE *file, off_t offset, int whence);
#endif /*_CASIO_SMEM_H__*/

10
include/kernel/loader.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef __KERNEL_LOADER_H__
# define __KERNEL_LOADER_H__
#include <stddef.h>
#include <stdint.h>
// Function
extern void *loader(const char *path);
#endif /*__KERNEL_LOADER_H__*/

View File

@ -6,6 +6,7 @@
#include <kernel/context.h>
#include <kernel/types.h>
#define PROCESS_STACK_SIZE (2048)
#define PROCESS_NAME_LENGHT (16)
#define PROCESS_MAX (3)

View File

@ -1,13 +1,21 @@
#ifndef __KERNEL_UNISTD_32_H__
# define __KERNEL_UNISTD_32_H__
#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_exec 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
// Custom !
#define __NR_kvram_display 8
#define __NR_kvram_clear 9
#define __NR_kvram_print 10
#define __NR_kvram_ascii 11
#define __NR_kvram_reverse 12
#define __NR_kvram_scroll 13
#endif /*__KERNEL_UNISTD_32_H__*/

28
include/kernel/util.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef __KERNEL_UTIL_H__
# define __KERNEL_UTIL_H__
#include <stddef.h>
#include <stdint.h>
// String function
extern void *memset(void *s, int c, size_t n);
extern void *memcpy(void *dest, const void *src, size_t count);
extern char *strncpy(char *dest, char const *str, size_t size);
extern size_t strnlen(char const *str, size_t maxlen);
// Video RAM functions
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_print(int x, int y, char const *str, ...);
extern void kvram_ascii(int x, int y, char const c);
// Hardware specific function (do not use !)
extern void t6k11_display(void *vram);
// Timer functions.
extern int timer_uninstall(int timer_ID);
extern int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode);
#endif /*__KERNEL_UTIL_H__*/

View File

@ -1,11 +0,0 @@
#ifndef __LIB_TIMER_H__
# define __LIB_TIMER_H__
#include <stddef.h>
#include <stdint.h>
// Internal functions.
extern int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode);
extern int timer_uninstall(int timer_ID);
#endif /*__LIB_TIMER_H__*/

116
src/kernel/Makefile Normal file
View File

@ -0,0 +1,116 @@
#!/usr/bin/make -f
## ---
## Project: Vhex - Kernel for fx9860
## Author: yann.magnin@epitech.eu
## ---
include ../../global.mk
##---
## Static variables
##--
HEADER := -I../../include
BUILD := ../../build/kernel
OUTPUT := ../../output
DEBUG := ../../debug
NAME := vhex
EXEC := $(OUTPUT)/$(NAME).g1a
LDFLAG := -T $(NAME).ld
MEMORY_MAP := $(DEBUG)/$(NAME).map
ICON := icon.bmp
##---
## Automated variables
##---
# Get all directory
SRC :=
DIRECTORY := $(shell find . -not -path "*/\.*" -type d)
# Get all source files
$(foreach path,$(DIRECTORY),$(eval \
SRC += $$(wildcard $(path)/*.c) $n\
SRC += $$(wildcard $(path)/*.S) $n\
SRC += $$(wildcard $(path)/*.s) $n\
))
# Geneate all object files
OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(basename $(SRC))))
##---
## General rules
##---
all: | $(BUILD) $(DEBUG) $(OUTPUT) $(EXEC)
$(EXEC): $(OBJ)
$(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) $(HEADER) -lgcc > $(MEMORY_MAP)
$(OBJCOPY) -R .comment -R .bss -O binary $(DEBUG)/$(NAME).elf $(DEBUG)/$(NAME).bin
$(WRAPPER) $(DEBUG)/$(NAME).bin -o $@ -i $(ICON)
$(BUILD) $(DEBUG) $(OUTPUT):
@ printf "Create $(blue)$@$(nocolor) directory\n"
@ mkdir -p $@
##---
## Debugging rules
##---
debug:
@ echo 'src: $(SRC)'
@ echo 'obj: $(OBJ)'
@ echo 'directory: $(DIRECTORY)'
asm:
@ $(OBJDUMP) -D $(DEBUG)/$(NAME).elf | less
map:
@ cat $(MEMORY_MAP) | less
sec:
@ $(OBJDUMP) -h $(DEBUG)/$(NAME).elf
##---
## Automated rules
##---
define rule-src
$(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(basename $1))): $1
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"
endef
$(foreach source,$(SRC),$(eval \
$(call rule-src,$(source))) \
)
##---
## Cleaning rules
##---
clean:
rm -rf $(BUILD)
rm -rf $(DEBUG)
fclean: clean
rm -f $(EXEC)
re: fclean all
.PHONY: re fclean clean all
.PHONY: debug asm map sec

View File

@ -4,8 +4,12 @@
#include <kernel/atomic.h>
#include <kernel/types.h>
#include <kernel/process.h>
#include <lib/display.h>
#include <lib/string.h>
#include <kernel/syscall.h>
#include <kernel/util.h>
//TODO: remove me !
#include <kernel/fs/smem.h>
#include <kernel/loader.h>
// Internal symbols
mpu_t current_mpu = MPU_UNKNOWN;
@ -77,6 +81,7 @@ static void section_execute(void *bsection, void *esection)
__attribute__((section(".pretext")))
int start(void)
{
extern uint32_t vram[256];
int error;
// Wipe .bss section and dump .data / Vhex sections
@ -102,6 +107,10 @@ int start(void)
// before switching the VBR.
rom_explore(&brom, (int32_t)&srom);
// Mount Casio FS
// TODO: Use Virtual File System !
casio_smem_mount();
// Save Casio's hardware context and set
// Vhex hardware context.
// @note:
@ -121,11 +130,40 @@ int start(void)
uint32_t ssr = atomic_start();
pid_t vhex_pid = process_create("Vhex");
process_t *vhex_process = process_get(vhex_pid);
vhex_process->context.spc = (uint32_t)&main;
// Initialize CPU configuration for the process.
vhex_process->context.ssr = ssr;
// Load programe.
vhex_process->context.spc = (uint32_t)loader("VHEX/shell.elf");
if (vhex_process->context.spc == 0x00000000)
{
// Display message.
kvram_clear();
kvram_print(0, 0, "Vhex fatal error !");
kvram_print(0, 1, "File \"VHEX/shell.elf\" not found !");
kvram_print(0, 2, "Press [MENU key]...");
kvram_display();
// Restore Casio context.
fx9860_context_restore(&casio_context);
atomic_end();
// Casio VRAM workaround
// @note: GetKey call Bdisp_PutDD_VRAM()
memcpy(casio_Bdisp_GetVRAM(), vram, 1024);
// Wait MENU key.
unsigned int key;
while (1)
{
casio_GetKey(&key);
}
}
// Switch to first process.
kernel_switch(&vhex_process->context);
//kernel_switch(&vhex_process->context);
// normally the kernel SHOULD not
// arrive here.

View File

@ -6,8 +6,6 @@
#include <kernel/hardware/tmu.h>
#include <kernel/vbr.h>
#include <lib/display.h>
void vhex_context_set(void)
{
extern uint32_t vhex_vbr;

View File

@ -1,5 +1,5 @@
#include <kernel/devices/display.h>
#include <lib/display.h>
#include <kernel/util.h>
#include <stdarg.h>
void display_ioctl(uint32_t cmd, ...)
@ -35,12 +35,12 @@ void display_ioctl(uint32_t cmd, ...)
}
case DISPLAY_IOCTL_CLEAR:
{
dclear(); // <- remove me ?
kvram_clear();
break;
}
case DISPLAY_IOCTL_DISPLAY:
{
dupdate(); // <- remove me ?
kvram_display();
break;
}
}

View File

@ -1,8 +1,7 @@
#include <kernel/devices/tty.h>
#include <kernel/devices/display.h>
#include <kernel/devices/keyboard.h>
#include <lib/display.h>
#include <lib/string.h>
#include <kernel/util.h>
// Internal TTY object.
struct tty_s tty;

View File

@ -3,10 +3,7 @@
#include <kernel/context.h>
#include <kernel/atomic.h>
#include <kernel/syscall.h>
#include <lib/display.h>
#include <lib/string.h>
#include <lib/stdio.h>
#include <lib/timer.h>
#include <kernel/util.h>
// Intenral functions
static void wait_keyboard_event(void);
@ -340,8 +337,8 @@ static void cursor_callback(struct keyboard_obj_s *keyboard)
tty_ioctl(TTY_IOCTL_GETDY, &y);
// Display cursor.
dreverse(x, y, (KERNEL_FONT_REAL_WIDTH + 1), (KERNEL_FONT_REAL_HEIGHT + 1));
dupdate();
kvram_reverse(x, y, (KERNEL_FONT_REAL_WIDTH + 1), (KERNEL_FONT_REAL_HEIGHT + 1));
kvram_display();
// Restore TTY cursor position
tty.cursor.x = sttyx;

View File

@ -1,8 +1,7 @@
#include <kernel/devices/tty.h>
#include <kernel/devices/display.h>
#include <kernel/atomic.h>
#include <lib/display.h>
#include <lib/string.h>
#include <kernel/util.h>
// Internal TTY object.
extern struct tty_s tty;

View File

@ -2,15 +2,13 @@
#include <kernel/hardware/ubc.h>
#include <kernel/hardware/power.h>
#include <kernel/syscall.h>
#include <kernel/dbr.h>
#include <kernel/extra.h>
#include <lib/display.h>
#include <kernel/dbr.h>
// Internal data used by UBC device.
void *casio_dbr;
// Internal function.
extern void test(void);
extern void ubc_handler_pre(void);
int ubc_open(void)
@ -36,7 +34,7 @@ int ubc_open(void)
SH7305_UBC.CBR0.CE = 0; // Disable Channel 0.
// Set up target address.
SH7305_UBC.CAR0 = (uint32_t)&test; // Tested programe address !
SH7305_UBC.CAR0 = 0x00000000; // Tested programe address !
SH7305_UBC.CAMR0 = 0x00000000; // Address Mask.
// Setup Control register.

View File

@ -0,0 +1,24 @@
#include <kernel/fs/smem.h>
#include <kernel/fs/file.h>
/* casio_smem_lseek() - File cursor management */
off_t casio_smem_lseek(FILE *file, off_t offset, int whence)
{
// Check potential error.
if (file == NULL)
return (-1);
if (whence == SEEK_SET){
file->cursor = offset;
return (file->cursor);
}
if (whence == SEEK_CUR){
file->cursor = file->cursor + offset;
return (file->cursor);
}
if (whence == SEEK_END){
file->cursor = file->size + offset - 1;
return (file->cursor);
}
return (-1);
}

View File

@ -0,0 +1,25 @@
#include <kernel/fs/smem.h>
// Internal symbols
casio_smem_header_t *casio_smem_header_table;
casio_smem_block_t *casio_smem_block_table;
uint16_t current_parent_id;
/* casio_smem_mount() - Get Block and Preheader Table addresses */
int casio_smem_mount(void)
{
// Casio SMEM block table start always at 0xa0270000
casio_smem_block_table = (void *)0xa0270000;
//TODO: check block table intergrity.
// Casio SMEM preheader table start always at the end of the block table.
// Normaly start at 0xa0270320 but not always (?)
int i = -1;
while (casio_smem_block_table[++i].magic_start == CASIO_SMEM_BLOCK_ENTRY_MAGIC);
casio_smem_header_table = (void *)&casio_smem_block_table[i];
//TODO: check header intergrity !
current_parent_id = CASIO_SMEM_ROOT_ID;
return (0);
}

135
src/kernel/fs/smem/open.c Normal file
View File

@ -0,0 +1,135 @@
#include <kernel/fs/smem.h>
#include <kernel/fs/file.h>
#include <kernel/util.h>
//FIXME: find better way to walk into fragment (use ID)
static size_t casio_smem_get_file_size(casio_smem_header_t *file)
{
casio_smem_fragment_t *fragment;
size_t count;
count = 0;
fragment = (void *)((uint32_t)file + sizeof(casio_smem_header_t));
while (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC)
{
count = count + fragment->data_size + 1;
fragment = fragment + 1;
}
return (count);
}
/* casio_smem_get_file() - Walk into the Casio's File System and search the target file */
static casio_smem_header_t *casio_smem_get_file(char const *name, uint16_t *parent_id)
{
extern casio_smem_header_t *casio_smem_header_table;
casio_smem_fragment_t *fragment;
casio_smem_header_t *header;
int i;
// Walk into Casio SMEM File System.
header = casio_smem_header_table;
while (header->info == CASIO_SMEM_HEADER_INFO_EXIST ||
header->info == CASIO_SMEM_HEADER_INFO_DELETE)
{
// Check new file validity.
if (header->info == CASIO_SMEM_HEADER_INFO_EXIST &&
header->parent.id == *parent_id)
{
// Compare File name.
i = -1;
while (++i < 12 &&
header->name[i] != 0x0000 &&
header->name[i] != 0xffff &&
(header->name[i] & 0x00ff) == name[i]);
// Check error.
if (name[i] == '\0' &&
(header->name[i] == 0x0000 ||
header->name[i] == 0xffff))
{
*parent_id = header->id;
return (header);
}
}
// We need to skip fragmented data
fragment = (void *)((uint32_t)header + sizeof(casio_smem_header_t));
if (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC)
{
// The fastest way to skip fragmented data
fragment = (void *)((uint32_t)fragment +
(sizeof(casio_smem_fragment_t) * fragment->frag_total));
}
// Get next header.
header = (void *)fragment;
}
return (NULL);
}
/* casio_smem_open() - Find target file and setup abstraction file structure */
int casio_smem_open(FILE *file, char const *name, int mode)
{
extern uint16_t current_parent_id;
casio_smem_header_t *file_raw;
uint16_t parent_id;
char file_name[14];
int slot_number;
int i;
// check error.
if (mode != O_RDONLY || name == NULL)
return (-1);
// Get parent ID.
if (*name == '/')
{
parent_id = CASIO_SMEM_ROOT_ID;
name += 1;
} else {
parent_id = current_parent_id;
}
// File Systeme walk entry.
while (*name != '\0')
{
// Get current file name.
i = -1;
while (name[++i] != '\0' && name[i] != '/' && i < 14)
file_name[i] = name[i];
// Check file name validity.
if (i >= 12 && name[i] != '\0' && name[i] != '/')
return (-1);
// Update internal informations.
file_name[i] = '\0';
name = name + i;
// find the file.
file_raw = casio_smem_get_file(file_name, &parent_id);
if (file_raw == NULL)
return (-1);
// Directory check
if (name[0] == '/')
{
if (file_raw->type != CASIO_SMEM_HEADER_TYPE_DIRECTORY)
return (-2);
name = name + 1;
}
}
kvram_clear();
kvram_print(0, 0, "CUL !");
kvram_display();
while (1);
// Initilaize fiel object
// TODO: Use VFS to do this !!
file->cursor = 0;
file->mode = mode;
file->abstract = file_raw;
file->size = casio_smem_get_file_size(file_raw);
return (0);
}

81
src/kernel/fs/smem/read.c Normal file
View File

@ -0,0 +1,81 @@
#include <kernel/fs/smem.h>
#include <kernel/fs/file.h>
#include <kernel/util.h>
/* casio_smem_data_base_address() - Generate the fragmented data address (0xa0000000 + offset) */
static void *casio_smem_get_data_base_address(casio_smem_fragment_t *fragment)
{
extern casio_smem_block_t *casio_smem_block_table;
casio_smem_block_t *block;
block = casio_smem_block_table;
while (block->magic_start == CASIO_SMEM_BLOCK_ENTRY_MAGIC &&
block->info.id != fragment->data_block_id)
{
block = block + 1;
}
if (block->info.id != fragment->data_block_id)
return (NULL);
return ((void *)(block->offset + fragment->data_offset));
}
/* casio_smem_read() - Read the file data (based on internal cursor) */
ssize_t casio_smem_read(FILE *file, void *buf, size_t count)
{
casio_smem_fragment_t *fragment;
off_t fragment_data_offset;
void *data_base_addr;
ssize_t current_size;
size_t real_size;
// Get Check obvious error.
if (file == NULL || buf == NULL || file->cursor > (off_t)file->size)
return (-1);
// Get the "real" reading size
if (file->size - file->cursor < count)
count = file->size - file->cursor;
// Get the current data fragment.
current_size = 0;
fragment = (void *)((uint32_t)file->abstract + sizeof(casio_smem_header_t));
while (fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC &&
file->cursor > (off_t)(current_size + fragment->data_size + 1))
{
current_size = current_size + fragment->data_size + 1;
fragment = fragment + 1;
}
fragment_data_offset = file->cursor - current_size;
// Read file data
current_size = 0;
while (current_size < (ssize_t)count &&
fragment->magic == CASIO_SMEM_FRAGMENT_MAGIC)
{
// Calculate the real size to read.
real_size = fragment->data_size + 1 - fragment_data_offset;
if (real_size >= count - current_size)
real_size = count - current_size;
// Get the data address.
data_base_addr = casio_smem_get_data_base_address(fragment);
if (data_base_addr == NULL)
return (current_size);
// Handle fragment data offset.
if (fragment_data_offset != 0){
data_base_addr = (void *)(((uint32_t)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);
// Update informations.
current_size = current_size + real_size;
file->cursor = file->cursor + real_size;
fragment = fragment + 1;
}
((uint8_t*)buf)[current_size] = '\0';
return (current_size);
}

View File

@ -1,6 +1,5 @@
#include <kernel/hardware/keysc.h>
#include <kernel/hardware/intc.h>
#include <lib/display.h>
// Internal functions
extern void keycache_update(int row, int column, uint8_t key_frame);

View File

@ -1,6 +1,5 @@
#include <kernel/hardware/tmu.h>
#include <kernel/devices/timer.h>
#include <lib/display.h>
// Internal timer "cache".
struct timer_cache_s timercache[TIMER_NUMBER];

View File

@ -4,7 +4,6 @@
#include <kernel/keybios.h>
#include <kernel/syscall.h>
#include <kernel/extra.h>
#include <lib/display.h>
// Internal function.
@ -23,7 +22,7 @@ void ubc_module_handler(int action)
void ubc_handler(struct ubc_context_s *context, int channel)
{
void (*menu)(ubc_session_t *session);
/* void (*menu)(ubc_session_t *session);
ubc_session_t session;
// Initialize new session.
@ -47,12 +46,12 @@ void ubc_handler(struct ubc_context_s *context, int channel)
case KEY_CTRL_F1: menu = &menu_disassembly; break;
case KEY_CTRL_F2: menu = &menu_context; break;
}
}
}*/
// Update UBC
SH7305_UBC.CBR0.CE = 0; // Disable channel.
SH7305_UBC.CAR0 = context->spc; // Update break address.
SH7305_UBC.CAMR0 = 0x00000000; // Update break address.
SH7305_UBC.CBR0.CE = 1; // Disable channel.
// SH7305_UBC.CAR0 = context->spc; // Update break address.
// SH7305_UBC.CAMR0 = 0x00000000; // Update break address.
// SH7305_UBC.CBR0.CE = 1; // Enable channel.
icbi((void*)0xa0000000);
}

View File

@ -1,120 +0,0 @@
#include <kernel/devices/ubc.h>
#include <kernel/devices/display.h>
#include <kernel/hardware/ubc.h>
#include <kernel/keybios.h>
#include <lib/display.h>
// Menu string format.
const char *content_string[] = {
"!!!! UBC INTERRUPT !!!!",
"Special registers:",
"SPC = %p",
"Stack = %p",
"SSR = %#x",
"\n",
"Generale registers:",
"r0 = %#x",
"r1 = %#x",
"r2 = %#x",
"r3 = %#x",
"r4 = %#x",
"r5 = %#x",
"r6 = %#x",
"r7 = %#x",
"r8 = %#x",
"r9 = %#x",
"r10 = %#x",
"r11 = %#x",
"r12 = %#x",
"r13 = %#x",
"r14 = %#x",
"r15 = %#x",
"\n",
"Debug informations:",
"context = %p",
"UBC interrupt = %#x",
"Channel = %#x",
NULL
};
//
// cursor_update - Update cursor position key pressed based.
// @note:
// Some limits are hard coded so be careful.
//
static void cursor_update(ubc_session_t *session)
{
if (session->key == KEY_CTRL_UP &&
session->menu.context.cursor > 0)
{
session->menu.context.cursor = session->menu.context.cursor - 1;
return;
}
if (session->key == KEY_CTRL_DOWN &&
session->menu.context.cursor < 28 - DISPLAY_VCHAR_MAX)
{
session->menu.context.cursor = session->menu.context.cursor + 1;
return;
}
}
//
// menu_context - Show programe context.
// @note:
// This is not the best way to do the job,
// but for now the goal is the create a fonctionnal
// on-calc debugger.
//
void menu_context(ubc_session_t *session)
{
// Menu string data
uint32_t content_data[] = {
0,
0,
session->context->spc,
session->context->reg[15],
session->context->ssr,
0,
0,
session->context->reg[0],
session->context->reg[1],
session->context->reg[2],
session->context->reg[3],
session->context->reg[4],
session->context->reg[5],
session->context->reg[6],
session->context->reg[7],
session->context->reg[8],
session->context->reg[9],
session->context->reg[10],
session->context->reg[11],
session->context->reg[12],
session->context->reg[13],
session->context->reg[14],
session->context->reg[15],
0,
0,
(uint32_t)session->context,
SH7305_UBC.CCMFR.LONG_WORD,
session->channel
};
// Update cursor position.
cursor_update(session);
// Clear VRAM.
dclear();
// Display menu based on cursor position.
for (int i = 0 ; content_string[i + session->menu.context.cursor] != NULL &&
i < DISPLAY_VCHAR_MAX ; i = i + 1)
{
dprint(0, i,
content_string[i + session->menu.context.cursor],
content_data[i + session->menu.context.cursor]
);
}
// Display VRAM
dupdate();
}

View File

@ -1,111 +0,0 @@
#include <kernel/devices/ubc.h>
#include <kernel/devices/display.h>
#include <kernel/opcode.h>
#include <kernel/keybios.h>
#include <lib/display.h>
#include <lib/stdio.h>
static uint32_t get_arg(uint16_t code, const struct opcode_s *opcode, int id)
{
int shift;
// Check arg mask
if (opcode->arg_mask[id] == 0x0000)
return (0);
// Get arg shift.
shift = -1;
while (++shift < 16 && !(opcode->arg_mask[id] & (0x01 << shift)));
// Get argument.
return ((code & opcode->arg_mask[id]) >> shift);
}
static void display_mnemonic(ubc_session_t *session)
{
char line[128];
uint16_t *area;
int i;
int j;
// Get starting area.
// TODO: update me !!
area = (void *)(session->context->spc + (session->menu.disassembly.vcursor << 1));
// Main Loop.
i = -1;
while (++i < DISPLAY_VCHAR_MAX)
{
// Generate first part.
sprintf(line, "%8x %4x ", &area[i], area[i]);
// Try to find opcode.
j = -1;
while (opcode_list[++j].name != NULL)
{
// Check opcode.
if ((area[i] & opcode_list[j].mask) != opcode_list[j].code)
continue;
// Generate line via special function.
if (opcode_list[j].special != NULL)
{
opcode_list[j].special(&line[14], &area[i]);
break;
}
// Generate common line.
sprintf(&line[14],
opcode_list[j].name,
get_arg(area[i], &opcode_list[j], 0),
get_arg(area[i], &opcode_list[j], 1),
get_arg(area[i], &opcode_list[j], 2)
);
break;
}
// If no opcode are found, generate "empty" line.
if (opcode_list[j].name == NULL)
sprintf(&line[14], ".word 0x%4x", area[i]);
// Display line !
dprint(session->menu.disassembly.hcursor, i, line);
// Highlight break line if needed.
if ((uint32_t)&area[i] == session->context->spc)
{
dreverse(
0,
i * (KERNEL_FONT_REAL_HEIGHT + 1),
DISPLAY_SCREEN_WIDTH,
KERNEL_FONT_REAL_HEIGHT + 1
);
}
}
}
static void cursor_update(ubc_session_t *session)
{
// Horizontal update.
if (session->key == KEY_CTRL_LEFT)
session->menu.disassembly.hcursor += 1;
if (session->key == KEY_CTRL_RIGHT)
session->menu.disassembly.hcursor -= 1;
// Vertical update.
if (session->key == KEY_CTRL_UP)
session->menu.disassembly.vcursor -= 1;
if (session->key == KEY_CTRL_DOWN)
session->menu.disassembly.vcursor += 1;
}
void menu_disassembly(ubc_session_t *session)
{
// Update cursor position.
cursor_update(session);
// display ASM.
dclear();
display_mnemonic(session);
dupdate();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
#include <lib/display.h>
#include <kernel/util.h>
void exception_handler(void)
{
@ -18,8 +18,8 @@ void exception_handler(void)
);
// Write exception informations.
dclear();
dprint(0, 0,
kvram_clear();
kvram_print(0, 0,
"Ho crap ! Exception !\n"
"tra: %#x\n"
"expevt: %#x\n"
@ -32,6 +32,6 @@ void exception_handler(void)
ssr,
sr
);
dupdate();
kvram_display();
while (1);
}

View File

@ -1,4 +1,4 @@
#include <lib/display.h>
#include <kernel/util.h>
// Handler prototype.
extern void keysc_handler(void);
@ -25,13 +25,13 @@ void interrupt_handler(void)
}
// Display error.
dclear();
dprint(0, 0,
kvram_clear();
kvram_print(0, 0,
"Ho crap ! Interrupt error !\n"
"Interrupt ID (%#x)\n"
"Error: handler not foud !\n",
intevt
);
dupdate();
kvram_display();
while (1);
}

View File

@ -1,5 +1,4 @@
#include <lib/display.h>
#include <kernel/syscall.h>
#include <kernel/util.h>
__attribute__((section(".vhex.tlb"), interrupt_handler))
void tlb_handler(void)
@ -20,8 +19,8 @@ void tlb_handler(void)
);
// Write exception informations.
dclear();
dprint(0, 0,
kvram_clear();
kvram_print(0, 0,
"Ho crap ! TLB Exception !\n"
"tra: %#x\n"
"expevt: %#x\n"
@ -34,6 +33,6 @@ void tlb_handler(void)
ssr,
sr
);
dupdate();
kvram_display();
while (1);
}

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

24
src/kernel/loader/entry.c Normal file
View File

@ -0,0 +1,24 @@
#include <kernel/loader.h>
#include <kernel/fs/smem.h>
#include <kernel/fs/file.h>
#include <kernel/util.h>
void *loader(const char *path)
{
FILE file;
// TODO: use VFS !
if (casio_smem_open(&file, path, O_RDONLY) != 0)
return (NULL);
kvram_clear();
kvram_print(0, 0, "File found !!");
kvram_print(0, 1, "inode = %p", file.abstract);
kvram_print(0, 2, "path = %s", path);
kvram_display();
while (1);
// TODO: detect format !!
//return (loader_elf(file));
return (NULL);
}

View File

@ -1,5 +1,4 @@
#include <kernel/memory.h>
#include <lib/display.h>
// Internal data.
struct memory_info_s pmemory;

View File

@ -1,5 +1,4 @@
#include <kernel/process.h>
#include <lib/string.h>
// This function SHOULD not be called
// without atomic operation !!

View File

@ -1,5 +1,7 @@
#include <kernel/process.h>
#include <lib/string.h>
#include <kernel/unistd_32.h>
#include <kernel/memory.h>
#include <kernel/util.h>
pid_t process_create(const char *name)
{
@ -16,18 +18,44 @@ pid_t process_create(const char *name)
if (process == NULL)
return (-1);
// Initialize stack
process->context.reg[15] = (uint32_t)pm_alloc(PROCESS_STACK_SIZE);
if (process->context.reg[15] == 0x00000000)
{
//TODO: errno
//FIXME: free allocated process.
return (-1);
}
// Set process name.
strncpy(process->name, name, PROCESS_NAME_LENGHT);
// Initialize context.
for (int i = 0 ; i < 16 ; i = i + 1)
for (int i = 0 ; i < 15 ; i = i + 1)
process->context.reg[i] = 0x00000000;
// Initialize "special" registers.
process->context.gbr = 0x00000000;
process->context.macl = 0x00000000;
process->context.mach = 0x00000000;
process->context.ssr = 0x00000000;
process->context.spc = 0x00000000;
// initialize "exit" part.
uint8_t callexit[6] = {
0b11000011, __NR_exit, // trapa #__NR_exit
0b10110000, 0b00000100, // bsr PC + 2 - 4
0b00000000, 0b00001001 // nop
};
process->context.pr = (uint32_t)pm_alloc(6);
if (process->context.pr == 0x00000000)
{
//TODO: errno
//FIXME: free allocated process.
return (-1);
}
memcpy((void *)process->context.pr, callexit, 6);
// Initialize processes.
process->parent = process_current;
process->child = NULL;

View File

@ -1,5 +1,4 @@
#include <kernel/syscall.h>
#include <lib/display.h>
static const void *sys_handler[] = {
NULL, //restart

265
src/kernel/util/kvram.c Normal file
View File

@ -0,0 +1,265 @@
#include <kernel/util.h>
#include <kernel/atomic.h>
#include <kernel/devices/display.h>
#include <stdarg.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_end();
}
/* kvram_display() - Disaplay Video RAM into screen */
void kvram_display(void)
{
//TODO: handle screen hadware !
t6k11_display(vram);
}
/* kvram_scroll() - Scroll up the Video RAM */
void kvram_scroll(int lines)
{
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_end();
}
/* kvram_reverse() - Reverse Video RAM area */
void kvram_reverse(int x, int y, int width, int height)
{
int vram_offset_y;
int j;
// Check error.
if (width < 0 || height < 0)
return;
// Get "real" X position and area width.
if (x < 0)
{
width = width + x;
x = 0;
} else {
if (x + width >= DISPLAY_SCREEN_WIDTH)
width = DISPLAY_SCREEN_WIDTH - x;
}
// Get "real" Y position and area height.
if (y < 0)
{
height = height + x;
y = 0;
} else {
if (y + height >= DISPLAY_SCREEN_HEIGHT)
height = DISPLAY_SCREEN_HEIGHT - x;
}
// Check potential error.
// @note we do not check height because the while()
// while do the job for us.
if (width < 0)
return;
// Generate VRAM offset for Y axis.
// @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 = (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);
}
vram_offset_y = vram_offset_y - 4;
}
// End of atomic operation
atomic_end();
}
/* kvram_print() - Print formated string on Video RAM */
void kvram_print(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;
// 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)
{
font_draw(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')
{
font_draw(x, y, '@');
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
// Add "0x"
font_draw(x, y, '0');
x = x + KERNEL_FONT_REAL_WIDTH + 1;
font_draw(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)
{
font_draw(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')
{
font_draw(x, y, ((char*)nb)[digits++]);
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
i = i + 1;
continue;
}
}
// Default, display character
font_draw(x, y, str[i]);
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
va_end(ap);
}
/* kvram_ascii() - Draw ASCII character into Video RAM */
void kvram_ascii(int x, int y, char const c)
{
font_draw(x, y, c);
}

43
src/kernel/util/string.c Normal file
View File

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

@ -1,9 +1,9 @@
#include <lib/timer.h>
#include <kernel/util.h>
#include <kernel/hardware/tmu.h>
#include <kernel/devices/timer.h>
#include <kernel/atomic.h>
#include <lib/display.h>
//TODO: update !
int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
{
extern struct timer_cache_s timercache[TIMER_NUMBER];
@ -47,3 +47,32 @@ int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode)
atomic_end();
return (timer_ID);
}
//TODO: update !
int timer_uninstall(int timer_ID)
{
extern struct timer_cache_s timercache[TIMER_NUMBER];
// Check bad ID
if (timer_ID < 0 || timer_ID >= TIMER_NUMBER)
return (-1);
// Start Atomic operation.
atomic_start();
// Stop Hardware timer.
SH7305_TMU.TSTR.BYTE &= ~(1 << timer_ID);
// Uninit hardware timer.
SH7305_TMU.TIMER[timer_ID].TCR.UNF = 0; // Clear interrupt flag.
SH7305_TMU.TIMER[timer_ID].TCR.UNIE = 0; // Disable interrupt.
SH7305_TMU.TIMER[timer_ID].TCOR = 0xffffffff;
SH7305_TMU.TIMER[timer_ID].TCNT = 0xffffffff;
// Free'd timer cache.
timercache[timer_ID].status = TIMER_UNUSED;
// Stop atomic operation and return.
atomic_end();
return (0);
}

99
src/lib/Makefile Normal file
View File

@ -0,0 +1,99 @@
#!/usr/bin/make -f
# ---
# Project: Vhex - Librairies part.
# Author: yann.magnin@epitech.eu
# ---
include ../../global.mk
#------- --------#
# Generic variables #
#------- --------#
HEADER := -I../../include
BUILD := ../../build/lib/
TARGET-MODULES := stdio string unistd display
#------- --------#
# Automated variables #
#------- --------#
$(foreach mod,$(TARGET-MODULES),$(eval \
target-$(mod)-src := $$(wildcard $(mod)/*.c) $n\
target-$(mod)-src += $$(wildcard $(mod)/*.s) $n\
target-$(mod)-src += $$(wildcard $(mod)/*.S) $n\
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))
#------- --------#
# Generic rules #
#------- --------#
all: | $(BUILD) $(TARGET-LIBS)
$(BUILD):
@ printf "Create $(blue)$@$(nocolor) directory\n"
@ mkdir -p $@
debug:
@ echo 'lib: $(TARGET-LIBS)'
@ echo 'src: $(target-stdio-src)'
@ echo 'obj: $(target-stdio-obj)'
@ echo 'directory: $(TARGET-MODULES)'
@ echo 'debug: $(BUILD)'
#------- --------#
# Rule functions #
#------- --------#
define rule-src
$(patsubst %,$(BUILD)%.o,$(subst /,_,$(basename $1))): $1
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) $(CFLAGS) -c $$< -o $$@ $(HEADER)
@ printf "$(green)[ok]$(nocolor)\n"
endef
define rule-link
$(patsubst %,lib_%.a,$1): $2
@ printf "Link $(green)$$@$(nocolor) lib\n"
$(AR) crs $$@ $$^
endef
#------- --------#
# Automated rules #
#------- --------#
$(foreach mod,$(TARGET-MODULES), \
$(foreach source,$(target-$(mod)-src), \
$(eval $(call rule-src,$(source),$(mod)))) \
$(eval $(call rule-link,$(mod),$(target-$(mod)-obj))) \
)
#------- --------#
# Clean rules #
#------- --------#
clean:
rm -rf $(BUILD)
fclean: clean
rm -f $(TARGET-LIBS)
re: fclean all
.PHONY: re clean fclean all debug

12
src/lib/display/dascii.S Normal file
View File

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

View File

@ -1,8 +0,0 @@
#include <lib/display.h>
#include <kernel/font.h>
void dascii(int x, int y, char const c)
{
font_draw(x, y, c);
}

12
src/lib/display/dclear.S Normal file
View File

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

View File

@ -1,13 +0,0 @@
#include <lib/display.h>
// Internal VRAM address.
uint32_t vram[256];
void dclear(void)
{
int i;
i = 256;
while (--i >= 0)
vram[i] = 0x00000000;
}

12
src/lib/display/dprint.S Normal file
View File

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

View File

@ -1,42 +0,0 @@
#include <lib/display.h>
#include <kernel/devices/display.h>
#include <lib/stdio.h>
#include <stdarg.h>
void dprint(int x, int y, char const *str, ...)
{
char buffer[512];
int default_pos_x;
int starting_x;
va_list ap;
int i;
// printf string manipulation.
// TODO: remove me !
va_start(ap, str);
vsprintf(buffer, str, ap);
va_end(ap);
i = -1;
starting_x = x;
x = x * (KERNEL_FONT_REAL_WIDTH + 1);
y = y * (KERNEL_FONT_REAL_HEIGHT + 1);
default_pos_x = x;
while (buffer[++i] != '\0')
{
if (buffer[i] == '\n')
{
y = y + KERNEL_FONT_REAL_HEIGHT + 1;
x = default_pos_x;
continue;
}
if (buffer[i] == '\t')
{
x = x / (KERNEL_FONT_REAL_WIDTH + 1);
x = (x + (4 - ((x - starting_x) & 3))) * (KERNEL_FONT_REAL_WIDTH + 1);
continue;
}
font_draw(x, y, buffer[i]);
x = x + KERNEL_FONT_REAL_WIDTH + 1;
}
}

View File

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

View File

@ -1,57 +0,0 @@
#include <lib/display.h>
#include <kernel/devices/display.h>
void dreverse(int x, int y, int width, int height)
{
int vram_offset_y;
int j;
// Check error.
if (width < 0 || height < 0)
return;
// Get "real" X position and area width.
if (x < 0)
{
width = width + x;
x = 0;
} else {
if (x + width >= DISPLAY_SCREEN_WIDTH)
width = DISPLAY_SCREEN_WIDTH - x;
}
// Get "real" Y position and area height.
if (y < 0)
{
height = height + x;
y = 0;
} else {
if (y + height >= DISPLAY_SCREEN_HEIGHT)
height = DISPLAY_SCREEN_HEIGHT - x;
}
// Check potential error.
// @note we do not check height because the while()
// while do the job for us.
if (width < 0)
return;
// Generate VRAM offset for Y axis.
// @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 = (y + height - 1) << 2;
while (--height >= 0)
{
j = width + x;
while (--j >= x)
{
vram[(j >> 5) + vram_offset_y] ^= 0x80000000 >> (j & 31);
}
vram_offset_y = vram_offset_y - 4;
}
}

12
src/lib/display/dscroll.S Normal file
View File

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

View File

@ -1,27 +0,0 @@
#include <lib/display.h>
#include <kernel/devices/display.h>
void dscroll(int lines)
{
int i;
// 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;
}
}

12
src/lib/display/dupdate.S Normal file
View File

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

View File

@ -1,8 +0,0 @@
#include <lib/display.h>
#include <kernel/devices/display.h>
#include <kernel/hardware/t6k11.h>
void dupdate(void)
{
t6k11_display(vram);
}

View File

@ -1,33 +0,0 @@
#include <lib/timer.h>
#include <kernel/hardware/tmu.h>
#include <kernel/devices/timer.h>
#include <kernel/atomic.h>
int timer_uninstall(int timer_ID)
{
extern struct timer_cache_s timercache[TIMER_NUMBER];
// Check bad ID
if (timer_ID < 0 || timer_ID >= TIMER_NUMBER)
return (-1);
// Start Atomic operation.
atomic_start();
// Stop Hardware timer.
SH7305_TMU.TSTR.BYTE &= ~(1 << timer_ID);
// Uninit hardware timer.
SH7305_TMU.TIMER[timer_ID].TCR.UNF = 0; // Clear interrupt flag.
SH7305_TMU.TIMER[timer_ID].TCR.UNIE = 0; // Disable interrupt.
SH7305_TMU.TIMER[timer_ID].TCOR = 0xffffffff;
SH7305_TMU.TIMER[timer_ID].TCNT = 0xffffffff;
// Free'd timer cache.
timercache[timer_ID].status = TIMER_UNUSED;
// Stop atomic operation and return.
atomic_end();
return (0);
}

View File

@ -6,7 +6,8 @@
.align 2
_fork:
trapa #__NR_fork
!trapa #__NR_fork
mov #-1, r0
rts
nop
.end

106
src/user/Makefile Normal file
View File

@ -0,0 +1,106 @@
#!/usr/bin/make -f
## ---
## Project: Vhex - On-calc debugger
## Author: yann.magnin@epitech.eu
## ---
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
DEBUG := ../../debug
OUTPUT := ../../output
NAME := shell
EXEC := $(OUTPUT)/$(NAME).elf
LDFLAG := -T $(NAME).ld
MEMORY_MAP := $(DEBUG)/$(NAME).map
##---
## Automated variables
##---
SRC :=
DIRECTORY := $(shell find shell -not -path "*/\.*" -type d)
# Get all source files
$(foreach path,$(DIRECTORY),$(eval \
SRC += $(wildcard $(path)/*.c) \
$(wildcard $(path)/*.S) \
$(wildcard $(path)/*.s) \
))
# Geneate all object files
OBJ := $(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC)))))
##---
## General rules
##---
all: | $(BUILD) $(DEBUG) $(EXEC)
$(EXEC): $(OBJ)
$(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf.big $(OBJ) $(HEADER) $(LIBS) -lgcc > $(MEMORY_MAP)
$(OBJCOPY) -S $(DEBUG)/$(NAME).elf.big $@
rm -f $(DEBUG)/$(NAME).elf.big
$(BUILD) $(DEBUG):
@ printf "Create $(blue)$@$(nocolor) directory\n"
@ mkdir -p $@
install: $(EXEC)
sudo p7 send --force -d VHEX $^
check:
@ echo 'src: $(SRC)'
@ echo 'obj: $(OBJ)'
@ echo 'directory: $(DIRECTORY)'
asm:
@ $(OBJDUMP) -D $(DEBUG)/$(NAME).elf | less
map:
@ cat $(MEMORY_MAP) | less
sec:
@ $(OBJDUMP) -h $(DEBUG)/$(NAME).elf
##---
## Automated rules
##---
define rule-src
$(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1
@ printf "compiling $(white)$$<$(nocolor)..."
@ $(CC) $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc
@ printf "$(green)[ok]$(nocolor)\n"
endef
$(foreach source,$(SRC),$(eval \
$(call rule-src,$(source))) \
)
##---
## Cleaning rules
##---
clean:
rm -rf $(BUILD)
rm -rf $(DEBUG)
fclean: clean
rm -f $(EXEC)
re: fclean all
.PHONY: re fclean clean all install

42
src/user/shell.ld Normal file
View File

@ -0,0 +1,42 @@
OUTPUT_ARCH(sh3)
OUTPUT_FORMAT(elf32-sh)
ENTRY(_main)
/*
** Linker script for user executables.
*/
MEMORY
{
/* virtual memory, read-write segment */
userram (WX) : o = 0x00000000, l = 256k
}
PHDRS
{
text PT_LOAD ;
data PT_LOAD ;
}
SECTIONS
{
.text : {
*(.text);
*(.text.*);
} : text
.rodata : {
*(.rodata);
*(.rodata.*);
}
.data ALIGN(4) : {
*(.plt);
*(.data);
*(.data.*);
/* bss section included to avoid missaligned segment */
*(.bss);
*(.bss.*);
*(COMMON);
} : data
}

View File

@ -1,10 +1,5 @@
#include "builtin.h"
#include <kernel/devices/ubc.h>
#include <lib/display.h>
#include <lib/unistd.h>
// TODO: remove me !!
extern void test(void);
VHEX_BUILTIN(fxdb)
{
@ -16,14 +11,6 @@ VHEX_BUILTIN(fxdb)
dprint(0, 0, "FXDB - entry !!");
dupdate();
for (int i = 0 ; i < 9000000 ; i = i + 1);
int fion = fork();
dclear();
dprint(0, 0, "FXDB - entry !!");
dprint(0, 1, "fork test = %d", fion);
dupdate();
for (int i = 0 ; i < 9000000 ; i = i + 1);
return (0);
// Open User Break Controller.
@ -35,15 +22,15 @@ VHEX_BUILTIN(fxdb)
// linker script.
// This module is only on SH7305 - SH4 based MPU.
// THis function SHOULD not be called !
ubc_open();
// ubc_open();
// Jump into the tested function.
// @note:
// Thus USC should be start after the jump.
//
test();
// test();
// Power OFF UBC module.
ubc_close();
// ubc_close();
return (0);
}

View File

@ -1,4 +1,4 @@
#include "builtin.h"
/*#include "builtin.h"
#include <kernel/memory.h>
#include <lib/display.h>
@ -57,4 +57,4 @@ VHEX_BUILTIN(ram)
for (int i = 0 ; i < 9000000 ; i = i + 1);
return (0);
}
}*/

View File

@ -1,10 +1,16 @@
#include <kernel/devices/tty.h>
#include <lib/display.h>
#include "util.h"
//TODO: documentation.
int main(void)
{
char input[12];
dclear();
dprint(0, 0, "First user program !");
dupdate();
while (1);
/* char input[12];
int cmd_size;
char **argv;
int argc;
@ -33,5 +39,5 @@ int main(void)
tty_write(": command not found\n", 20);
}
}
return (0);
return (0);*/
}

View File

@ -1,17 +1,15 @@
#include "util.h"
#include "builtin.h"
#include <lib/string.h>
#include <lib/display.h>
#include <lib/unistd.h>
//TODO: use agc, argv.
int check_builtin(char *cmd)
{
extern uint32_t bbuiltin_section;
/* extern uint32_t bbuiltin_section;
extern uint32_t ebuiltin_section;
struct builtin_s *list;
int wstatus;
pid_t pid;
//pid_t pid;
int i;
i = -1;
@ -28,7 +26,7 @@ int check_builtin(char *cmd)
// If we are the child execute
// the builtins.
//if (pid == 0)
*/ //if (pid == 0)
//{
/*dclear();
dprint(0, 0, "Child process !!");
@ -36,12 +34,12 @@ int check_builtin(char *cmd)
dprint(0, 2, "PPID = %d", getppid());
dupdate();*/
list[i].entry(0, NULL);
// list[i].entry(0, NULL);
return (0);
// } else {
// waitpid(pid, &wstatus, WCONTINUED);
//TODO: signal handling.
// }
}
return (1);
// }
// return (1);
}