From 9a9ac9614bb69c9078ba0ab978029346f2d5c157 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Wed, 1 Jan 2020 14:19:18 +0100 Subject: [PATCH] Add ELF loader and first process ! --- Makefile | 6 +- include/kernel/elf.h | 116 ++++++++++++++++++++++++ include/kernel/fs/file.h | 1 + include/kernel/loader.h | 7 +- include/kernel/process.h | 21 +++++ include/kernel/util.h | 8 +- include/lib/display.h | 2 +- src/kernel/Makefile | 2 +- src/kernel/bootstrap/kernel_switch.s | 3 +- src/kernel/bootstrap/start.c | 11 +-- src/kernel/fs/smem/open.c | 5 -- src/kernel/fs/smem/read.c | 1 - src/kernel/hardware/vbr/exception.c | 2 +- src/kernel/hardware/vbr/interrupt.c | 2 +- src/kernel/hardware/vbr/tlb.c | 2 +- src/kernel/loader/entry.c | 51 +++++++++-- src/kernel/loader/header.c | 38 ++++++++ src/kernel/loader/image.c | 62 +++++++++++++ src/kernel/process/create.c | 38 ++++---- src/kernel/syscall/handler.c | 39 +++++++- src/kernel/syscall/test.S | 7 ++ src/kernel/util/kvram.c | 91 +------------------ src/kernel/util/printk.c | 127 +++++++++++++++++++++++++++ src/user/Makefile | 8 +- src/user/shell.ld | 23 +++++ src/user/shell/builtin/fxdb.c | 4 +- src/user/shell/main.c | 7 +- src/user/shell/util/check_builtin.c | 12 +-- 28 files changed, 543 insertions(+), 153 deletions(-) create mode 100644 include/kernel/elf.h create mode 100644 src/kernel/loader/header.c create mode 100644 src/kernel/loader/image.c create mode 100644 src/kernel/syscall/test.S create mode 100644 src/kernel/util/printk.c diff --git a/Makefile b/Makefile index 00d77d6..dae1e50 100644 --- a/Makefile +++ b/Makefile @@ -13,8 +13,8 @@ USER := output/shell.elf ## General rules ##--- all: - @ make --no-print-directory -C src/kernel @ make --no-print-directory -C src/lib + @ make --no-print-directory -C src/kernel @ make --no-print-directory -C src/user install: all @@ -28,13 +28,13 @@ install: all ## Cleaning rules ##--- clean: - make clean --no-print-directory -C src/kernel make clean --no-print-directory -C src/lib + make clean --no-print-directory -C src/kernel make clean --no-print-directory -C src/user fclean: clean - make fclean --no-print-directory -C src/kernel make fclean --no-print-directory -C src/lib + make fclean --no-print-directory -C src/kernel make fclean --no-print-directory -C src/user re: fclean all diff --git a/include/kernel/elf.h b/include/kernel/elf.h new file mode 100644 index 0000000..44befdb --- /dev/null +++ b/include/kernel/elf.h @@ -0,0 +1,116 @@ +#ifndef __ELF_H__ +# define __ELF_H__ 1 + +#include +#include + +typedef uint16_t Elf32_Half; /* Type for a 16-bit quantity. */ +typedef uint32_t Elf32_Word; /* Types for signed and unsigned 32-bit quantities. */ +typedef int32_t Elf32_Sword; /* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Addr; /* Type of addresses. */ +typedef uint32_t Elf32_Off; /* Type of file offsets. */ +typedef uint16_t Elf32_Section; /* Type for section indices, which are 16-bit quantities. */ +typedef Elf32_Half Elf32_Versym; /* Type for version symbol information. */ + + +/* The ELF file header. This appears at the start of every ELF file. */ +#define EI_NIDENT (16) + +typedef struct +{ + uint8_t e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + + +/* Magic number macros */ +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Class macros */ +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASS32 1 /* 32-bit objects */ + +/* Data encoding macros */ +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ + +/* ABI info macros */ +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define EI_ABIVERSION 8 /* ABI version */ + +/* Other header macors */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define EV_CURRENT 1 /* Current version */ +#define EM_SH 42 /* Hitachi SH */ +#define EF_SH3 3 /* SH3 flags */ + + + + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +/* Legal values for p_type (segment type). */ +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ + +/* Legal values for p_flags (segment flags). */ +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ + + + +/* Section header. */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +#endif /* __ELF_H__ */ diff --git a/include/kernel/fs/file.h b/include/kernel/fs/file.h index 31abc53..dc31334 100644 --- a/include/kernel/fs/file.h +++ b/include/kernel/fs/file.h @@ -3,6 +3,7 @@ #include #include +#include #ifndef FILE_OPEN_NUMBER # define FILE_OPEN_NUMBER 4 diff --git a/include/kernel/loader.h b/include/kernel/loader.h index 54937d4..3d47c6b 100644 --- a/include/kernel/loader.h +++ b/include/kernel/loader.h @@ -3,8 +3,13 @@ #include #include +#include +#include +#include // Function -extern void *loader(const char *path); +extern void *loader(const char *path, process_t *process); +extern int loader_get_header(FILE *file, Elf32_Ehdr *header); +extern void *loader_load_image(FILE *file, Elf32_Ehdr *header, process_t *process); #endif /*__KERNEL_LOADER_H__*/ diff --git a/include/kernel/process.h b/include/kernel/process.h index 334fa0a..309c4ee 100644 --- a/include/kernel/process.h +++ b/include/kernel/process.h @@ -25,6 +25,27 @@ typedef struct process_s // Signals management. //sighandler_t signal[NSIG]; + // Virtual / Physical memory management. + // @note + // For now, we can not use the MMU + // so we just save all physical allocated + // space. This is an hardcode of each + // process memory management. + struct { + struct { + uint32_t start; + uint32_t size; + } stack; + struct { + uint32_t start; + uint32_t size; + } program; + struct { + uint32_t start; + uint32_t size; + } exit; + } memory; + // Other process management. struct process_s *parent; struct process_s *child; diff --git a/include/kernel/util.h b/include/kernel/util.h index 5e7cd33..a1d0a0e 100644 --- a/include/kernel/util.h +++ b/include/kernel/util.h @@ -15,9 +15,12 @@ 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_print(int x, int y, char const *str); extern void kvram_ascii(int x, int y, char const c); +// Kernel printf-wrapper +extern void printk(int x, int y, char const *str, ...); + // Hardware specific function (do not use !) extern void t6k11_display(void *vram); @@ -25,4 +28,7 @@ extern void t6k11_display(void *vram); extern int timer_uninstall(int timer_ID); extern int timer_install(void *callback, void *arg, uint32_t delay_ms, uint8_t mode); +// Debug wait +#define DBG_WAIT for(int i = 0 ; i < 3000000 ; i++) + #endif /*__KERNEL_UTIL_H__*/ diff --git a/include/lib/display.h b/include/lib/display.h index bdc3c62..ec71229 100644 --- a/include/lib/display.h +++ b/include/lib/display.h @@ -6,7 +6,7 @@ // Draw primtives extern void dclear(void); -extern void dprint(int x, int y, char const *str, ...); +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); diff --git a/src/kernel/Makefile b/src/kernel/Makefile index dac0682..3ff5610 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -49,7 +49,7 @@ OBJ := $(patsubst ._%,$(BUILD)/%.o,$(subst /,_,$(basename $(SRC)))) all: | $(BUILD) $(DEBUG) $(OUTPUT) $(EXEC) $(EXEC): $(OBJ) - $(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) $(HEADER) -lgcc > $(MEMORY_MAP) + $(CC) -Wl,-M $(LDFLAG) $(CFLAGS) -o $(DEBUG)/$(NAME).elf $(OBJ) $(HEADER) -lgcc -L../lib -l_display > $(MEMORY_MAP) $(OBJCOPY) -R .comment -R .bss -O binary $(DEBUG)/$(NAME).elf $(DEBUG)/$(NAME).bin $(WRAPPER) $(DEBUG)/$(NAME).bin -o $@ -i $(ICON) diff --git a/src/kernel/bootstrap/kernel_switch.s b/src/kernel/bootstrap/kernel_switch.s index 297ef40..e7ae1e0 100644 --- a/src/kernel/bootstrap/kernel_switch.s +++ b/src/kernel/bootstrap/kernel_switch.s @@ -40,12 +40,13 @@ _kernel_switch: mov.l @r0+, r12 ! set r12 regsiter mov.l @r0+, r13 ! set r13 regsiter mov.l @r0+, r14 ! set r14 regsiter - mov.l @r0+, r2 ! Stack not handled for now + mov.l @r0+, r15 ! set r15 register ldc.l @r0+, gbr ! set gbr regsiter lds.l @r0+, macl ! set macl regsiter lds.l @r0+, mach ! set mach regsiter ldc.l @r0+, ssr ! set ssr regsiter ldc.l @r0+, spc ! set spc regsiter + lds.l @r0+, pr ! set pr regsiter ! Process switch rte diff --git a/src/kernel/bootstrap/start.c b/src/kernel/bootstrap/start.c index 6373324..adb5c04 100644 --- a/src/kernel/bootstrap/start.c +++ b/src/kernel/bootstrap/start.c @@ -127,15 +127,14 @@ int start(void) atomic_end(); // Create first process: Vhex. - uint32_t ssr = atomic_start(); pid_t vhex_pid = process_create("Vhex"); process_t *vhex_process = process_get(vhex_pid); // Initialize CPU configuration for the process. - vhex_process->context.ssr = ssr; + vhex_process->context.ssr = atomic_start(); // Load programe. - vhex_process->context.spc = (uint32_t)loader("VHEX/shell.elf"); + vhex_process->context.spc = (uint32_t)loader("VHEX/shell.elf", vhex_process); if (vhex_process->context.spc == 0x00000000) { // Display message. @@ -161,12 +160,14 @@ int start(void) } } - // Switch to first process. - //kernel_switch(&vhex_process->context); + kernel_switch(&vhex_process->context); // normally the kernel SHOULD not // arrive here. + kvram_clear(); + kvram_print(0, 0, "Kernel job fini !"); + kvram_display(); while (1) { __asm__ volatile ("sleep"); diff --git a/src/kernel/fs/smem/open.c b/src/kernel/fs/smem/open.c index f758d99..663b5ad 100644 --- a/src/kernel/fs/smem/open.c +++ b/src/kernel/fs/smem/open.c @@ -120,11 +120,6 @@ int casio_smem_open(FILE *file, char const *name, int mode) } } - kvram_clear(); - kvram_print(0, 0, "CUL !"); - kvram_display(); - while (1); - // Initilaize fiel object // TODO: Use VFS to do this !! file->cursor = 0; diff --git a/src/kernel/fs/smem/read.c b/src/kernel/fs/smem/read.c index ef354c3..7e528a7 100644 --- a/src/kernel/fs/smem/read.c +++ b/src/kernel/fs/smem/read.c @@ -76,6 +76,5 @@ ssize_t casio_smem_read(FILE *file, void *buf, size_t count) file->cursor = file->cursor + real_size; fragment = fragment + 1; } - ((uint8_t*)buf)[current_size] = '\0'; return (current_size); } diff --git a/src/kernel/hardware/vbr/exception.c b/src/kernel/hardware/vbr/exception.c index 2c1453a..d7cea0c 100644 --- a/src/kernel/hardware/vbr/exception.c +++ b/src/kernel/hardware/vbr/exception.c @@ -19,7 +19,7 @@ void exception_handler(void) // Write exception informations. kvram_clear(); - kvram_print(0, 0, + printk(0, 0, "Ho crap ! Exception !\n" "tra: %#x\n" "expevt: %#x\n" diff --git a/src/kernel/hardware/vbr/interrupt.c b/src/kernel/hardware/vbr/interrupt.c index baa5753..8f6b50e 100644 --- a/src/kernel/hardware/vbr/interrupt.c +++ b/src/kernel/hardware/vbr/interrupt.c @@ -26,7 +26,7 @@ void interrupt_handler(void) // Display error. kvram_clear(); - kvram_print(0, 0, + printk(0, 0, "Ho crap ! Interrupt error !\n" "Interrupt ID (%#x)\n" "Error: handler not foud !\n", diff --git a/src/kernel/hardware/vbr/tlb.c b/src/kernel/hardware/vbr/tlb.c index f41428a..478544b 100644 --- a/src/kernel/hardware/vbr/tlb.c +++ b/src/kernel/hardware/vbr/tlb.c @@ -20,7 +20,7 @@ void tlb_handler(void) // Write exception informations. kvram_clear(); - kvram_print(0, 0, + printk(0, 0, "Ho crap ! TLB Exception !\n" "tra: %#x\n" "expevt: %#x\n" diff --git a/src/kernel/loader/entry.c b/src/kernel/loader/entry.c index 343a3ad..cac95d8 100644 --- a/src/kernel/loader/entry.c +++ b/src/kernel/loader/entry.c @@ -2,23 +2,58 @@ #include #include #include +#include -void *loader(const char *path) +void *loader(const char *path, process_t *process) { + Elf32_Ehdr header; FILE file; + // Check error. + if (process == NULL) + return (NULL); + // TODO: use VFS ! if (casio_smem_open(&file, path, O_RDONLY) != 0) return (NULL); + // Debug ! kvram_clear(); - kvram_print(0, 0, "File found !!"); - kvram_print(0, 1, "inode = %p", file.abstract); - kvram_print(0, 2, "path = %s", path); + printk(0, 0, "File found !!"); + printk(0, 1, "inode = %p", file.abstract); + printk(0, 2, "path = %s", path); kvram_display(); - while (1); + DBG_WAIT; - // TODO: detect format !! - //return (loader_elf(file)); - return (NULL); + //@NOTE: Only ELF supported !!! + //TODO: USE VFS !! + // + // Get / Check ELF header + if (loader_get_header(&file, &header) != 0) + { + kvram_clear(); + printk(0, 0, "loader: ELF file header error !"); + kvram_display(); + DBG_WAIT; + return (NULL); + } + + // Get / Check program validity + void *entry = loader_load_image(&file, &header, process); + if (entry == NULL) + { + kvram_clear(); + printk(0, 0, "loader: ELF file image error !"); + kvram_display(); + DBG_WAIT; + return (NULL); + } + + // Success ! + kvram_clear(); + printk(0, 0, "loader: file loaded sucees !!"); + printk(0, 1, "loader: Entry at %p", entry); + kvram_display(); + DBG_WAIT; + return (entry); } diff --git a/src/kernel/loader/header.c b/src/kernel/loader/header.c new file mode 100644 index 0000000..28f4bf1 --- /dev/null +++ b/src/kernel/loader/header.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +/* loader_get_header() - get ELF header and check validity */ +int loader_get_header(FILE *file, Elf32_Ehdr *header) +{ + // Read ELF header. + if (casio_smem_read(file, header, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)) + return (-1); + + // Check magic number + if (header->e_ident[EI_MAG0] != 0x7f || + header->e_ident[EI_MAG1] != 'E' || + header->e_ident[EI_MAG2] != 'L' || + header->e_ident[EI_MAG3] != 'F') + return (-2); + + // Check class + if (header->e_ident[EI_CLASS] != 1) + return (-3); + + //TODO: Check OSABI (?) + + // Check ELF type. + if (header->e_type != ET_EXEC) + return (-4); + + // Check ELF specifique instruction + if (header->e_machine != 0x2A) + return (-5); + + // Check ELF version + if (header->e_version != 0x01) + return (-6); + return (0); +} diff --git a/src/kernel/loader/image.c b/src/kernel/loader/image.c new file mode 100644 index 0000000..417d6f1 --- /dev/null +++ b/src/kernel/loader/image.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include + +/* loader_load_image() - Load the program into Virtual Memory */ +void *loader_load_image(FILE *file, Elf32_Ehdr *header, process_t *process) +{ + Elf32_Phdr program; + uint32_t paddress; + uint16_t i; + + // Walk one time to get program size and + // check ELF validity. + i = -1; + process->memory.program.size = 0; + while (++i < header->e_phnum) + { + // Read programme header. + casio_smem_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET); + if (casio_smem_read(file, &program, sizeof(Elf32_Phdr)) != sizeof(Elf32_Phdr)) + return (NULL); + + // Check programe type. + if (program.p_type != PT_LOAD) + return (NULL); + + // Update program size + process->memory.program.size = process->memory.program.size + program.p_memsz; + } + + // Allocate programe space into + // physical memory. + process->memory.program.start = (uint32_t)pm_alloc(process->memory.program.size); + if (process->memory.program.start == 0x00000000) + return (NULL); + + // Now, load all program section into + // physical memory. + i = -1; + while (++i < header->e_phnum) + { + // Read programme header. + casio_smem_lseek(file, header->e_phoff + (sizeof(Elf32_Phdr) * i), SEEK_SET); + casio_smem_read(file, &program, sizeof(Elf32_Phdr)); + + // Generate physical address + paddress = program.p_vaddr + process->memory.program.start; + + // p_filesz can be smaller than p_memsz so, we need to wipe the area + // before the dump. + memset((void *)paddress, 0, program.p_memsz); + + // Dump the program. + casio_smem_lseek(file, program.p_offset, SEEK_SET); + casio_smem_read(file, (void *)paddress, program.p_filesz); + } + + // Generate program entry address + return ((void*)(header->e_entry + process->memory.program.start)); +} diff --git a/src/kernel/process/create.c b/src/kernel/process/create.c index 802d591..ffca96e 100644 --- a/src/kernel/process/create.c +++ b/src/kernel/process/create.c @@ -19,20 +19,39 @@ pid_t process_create(const char *name) return (-1); // Initialize stack - process->context.reg[15] = (uint32_t)pm_alloc(PROCESS_STACK_SIZE); - if (process->context.reg[15] == 0x00000000) + process->memory.stack.size = PROCESS_STACK_SIZE; + process->memory.stack.start = (uint32_t)pm_alloc(process->memory.stack.size); + if (process->memory.stack.start == 0x00000000) { //TODO: errno //FIXME: free allocated process. return (-1); } + // initialize "exit" part. + uint8_t callexit[6] = { + 0b11000011, __NR_exit, // trapa #__NR_exit + 0b10110000, 0b00000100, // bsr PC + 2 - 4 + 0b00000000, 0b00001001 // nop + }; + process->memory.exit.size = 6; + process->memory.exit.start = (uint32_t)pm_alloc(process->memory.exit.size); + if (process->memory.exit.start == 0x00000000) + { + //TODO: errno + //FIXME: free allocated process. + return (-1); + } + process->context.pr = process->memory.exit.start; + memcpy((void *)process->memory.exit.start, callexit, 6); + // Set process name. strncpy(process->name, name, PROCESS_NAME_LENGHT); // Initialize context. for (int i = 0 ; i < 15 ; i = i + 1) process->context.reg[i] = 0x00000000; + process->context.reg[15] = process->memory.stack.start; // Initialize "special" registers. process->context.gbr = 0x00000000; @@ -41,21 +60,6 @@ pid_t process_create(const char *name) 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; diff --git a/src/kernel/syscall/handler.c b/src/kernel/syscall/handler.c index 749c177..73dd0a1 100644 --- a/src/kernel/syscall/handler.c +++ b/src/kernel/syscall/handler.c @@ -1,18 +1,49 @@ #include +#include -static const void *sys_handler[] = { - NULL, //restart +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(); + DBG_WAIT; +} + +static const void *sys_handler[14] = { + sys_test, //restart NULL, //exit - sys_fork, //fork + NULL, //exiec NULL, //read NULL, //write NULL, //open NULL, //close sys_waitpid, //waitpid + + // Custom + kvram_display, //kvram_display + kvram_clear, //kvram_clear + kvram_print, //kvram_print + kvram_ascii, //kvram_ascii + kvram_reverse, //kvram_reverse + kvram_scroll //kvram_scroll }; void *sys_get_handler(int sysno) { - //FIXME: Check sysno validity + // Check sysno validity + if (sysno < 0 || sysno >= 14) + return (0); + + // DEBUG +/* kvram_clear(); + printk(0, 0, "sysno = %d", sysno); + printk(0, 0, "handler = %p", sys_handler[sysno]); + kvram_display(); + DBG_WAIT; +*/ + // Return syscall return ((void *)sys_handler[sysno]); } diff --git a/src/kernel/syscall/test.S b/src/kernel/syscall/test.S new file mode 100644 index 0000000..0d15d8d --- /dev/null +++ b/src/kernel/syscall/test.S @@ -0,0 +1,7 @@ +.global _dtest + +.align 2 +_dtest: + trapa #0 + rts + nop diff --git a/src/kernel/util/kvram.c b/src/kernel/util/kvram.c index 62a1bae..0686f22 100644 --- a/src/kernel/util/kvram.c +++ b/src/kernel/util/kvram.c @@ -1,7 +1,6 @@ #include #include #include -#include // Internal Video RAM uint32_t vram[256]; @@ -134,22 +133,13 @@ void kvram_reverse(int x, int y, int width, int height) atomic_end(); } -/* kvram_print() - Print formated string on Video RAM */ -void kvram_print(int x, int y, char const *str, ...) +/* kvram_print() - Print 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; @@ -174,88 +164,11 @@ void kvram_print(int x, int y, char const *str, ...) 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 */ diff --git a/src/kernel/util/printk.c b/src/kernel/util/printk.c new file mode 100644 index 0000000..49055d6 --- /dev/null +++ b/src/kernel/util/printk.c @@ -0,0 +1,127 @@ +#include +#include +#include + +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; + + // 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; + } + + // End of variodic args. + va_end(ap); +} diff --git a/src/user/Makefile b/src/user/Makefile index dae3621..f0dd72b 100644 --- a/src/user/Makefile +++ b/src/user/Makefile @@ -45,7 +45,7 @@ OBJ := $(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $(SRC))))) all: | $(BUILD) $(DEBUG) $(EXEC) $(EXEC): $(OBJ) - $(CC) -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) -lgcc > $(MEMORY_MAP) $(OBJCOPY) -S $(DEBUG)/$(NAME).elf.big $@ rm -f $(DEBUG)/$(NAME).elf.big @@ -62,13 +62,13 @@ check: @ echo 'directory: $(DIRECTORY)' asm: - @ $(OBJDUMP) -D $(DEBUG)/$(NAME).elf | less + @ $(OBJDUMP) -D $(EXEC) | less map: @ cat $(MEMORY_MAP) | less sec: - @ $(OBJDUMP) -h $(DEBUG)/$(NAME).elf + @ $(OBJDUMP) -h $(EXEC) ##--- @@ -77,7 +77,7 @@ sec: define rule-src $(patsubst %,$(BUILD)/%.o,$(subst /,_,$(subst src/,,$(basename $1)))): $1 @ printf "compiling $(white)$$<$(nocolor)..." - @ $(CC) $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc + @ $(CC) -fPIC $(CFLAGS) -o $$@ -c $$< $(HEADER) -lgcc @ printf "$(green)[ok]$(nocolor)\n" endef diff --git a/src/user/shell.ld b/src/user/shell.ld index 02046d5..7729fdd 100644 --- a/src/user/shell.ld +++ b/src/user/shell.ld @@ -39,4 +39,27 @@ SECTIONS *(.bss.*); *(COMMON); } : data + + + .relocgot : { + BRELOC_GOT = . ; + *(.got.plt) + *(.got) + ERELOC_GOT = . ; + } + + /* unwanted section */ + /DISCARD/ : { + *(.debug_info) + *(.debug_abbrev) + *(.debug_loc) + *(.debug_aranges) + *(.debug_ranges) + *(.debug_line) + *(.debug_str) + *(.jcr) + *(.eh_frame_hdr) + *(.eh_frame) + *(.comment) + } } diff --git a/src/user/shell/builtin/fxdb.c b/src/user/shell/builtin/fxdb.c index 5958733..79bc87f 100644 --- a/src/user/shell/builtin/fxdb.c +++ b/src/user/shell/builtin/fxdb.c @@ -1,4 +1,4 @@ -#include "builtin.h" +/*#include "builtin.h" #include VHEX_BUILTIN(fxdb) @@ -33,4 +33,4 @@ VHEX_BUILTIN(fxdb) // Power OFF UBC module. // ubc_close(); return (0); -} +}*/ diff --git a/src/user/shell/main.c b/src/user/shell/main.c index f79cea0..6cb1638 100644 --- a/src/user/shell/main.c +++ b/src/user/shell/main.c @@ -7,7 +7,12 @@ int main(void) dclear(); dprint(0, 0, "First user program !"); dupdate(); - while (1); + while (1) + { + // @note: we can use "sleep" because we + // are in privilegied mode + __asm__ volatile ("sleep"); + } /* char input[12]; diff --git a/src/user/shell/util/check_builtin.c b/src/user/shell/util/check_builtin.c index cdee8d4..c312599 100644 --- a/src/user/shell/util/check_builtin.c +++ b/src/user/shell/util/check_builtin.c @@ -1,11 +1,11 @@ -#include "util.h" +/*#include "util.h" #include "builtin.h" #include //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; @@ -26,13 +26,13 @@ int check_builtin(char *cmd) // If we are the child execute // the builtins. -*/ //if (pid == 0) + //if (pid == 0) //{ - /*dclear(); + dclear(); dprint(0, 0, "Child process !!"); dprint(0, 1, "PID = %d", getpid()); dprint(0, 2, "PPID = %d", getppid()); - dupdate();*/ + dupdate(); // list[i].entry(0, NULL); return (0); @@ -42,4 +42,4 @@ int check_builtin(char *cmd) // } // } // return (1); -} +}*/