Add ELF loader and first process !
This commit is contained in:
parent
6c0971e661
commit
9a9ac9614b
6
Makefile
6
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
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
#ifndef __ELF_H__
|
||||
# define __ELF_H__ 1
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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__ */
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <kernel/types.h>
|
||||
|
||||
#ifndef FILE_OPEN_NUMBER
|
||||
# define FILE_OPEN_NUMBER 4
|
||||
|
|
|
@ -3,8 +3,13 @@
|
|||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <kernel/fs/file.h>
|
||||
#include <kernel/process.h>
|
||||
#include <kernel/elf.h>
|
||||
|
||||
// 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__*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -2,23 +2,58 @@
|
|||
#include <kernel/fs/smem.h>
|
||||
#include <kernel/fs/file.h>
|
||||
#include <kernel/util.h>
|
||||
#include <kernel/elf.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#include <kernel/loader.h>
|
||||
#include <kernel/fs/smem.h>
|
||||
#include <kernel/util.h>
|
||||
#include <kernel/elf.h>
|
||||
|
||||
/* 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);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
#include <kernel/loader.h>
|
||||
#include <kernel/fs/smem.h>
|
||||
#include <kernel/memory.h>
|
||||
#include <kernel/util.h>
|
||||
#include <kernel/elf.h>
|
||||
|
||||
/* 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));
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -1,18 +1,49 @@
|
|||
#include <kernel/syscall.h>
|
||||
#include <kernel/util.h>
|
||||
|
||||
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]);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.global _dtest
|
||||
|
||||
.align 2
|
||||
_dtest:
|
||||
trapa #0
|
||||
rts
|
||||
nop
|
|
@ -1,7 +1,6 @@
|
|||
#include <kernel/util.h>
|
||||
#include <kernel/atomic.h>
|
||||
#include <kernel/devices/display.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// 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 */
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
#include <kernel/util.h>
|
||||
#include <kernel/font.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;
|
||||
|
||||
// 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);
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "builtin.h"
|
||||
/*#include "builtin.h"
|
||||
#include <lib/display.h>
|
||||
|
||||
VHEX_BUILTIN(fxdb)
|
||||
|
@ -33,4 +33,4 @@ VHEX_BUILTIN(fxdb)
|
|||
// Power OFF UBC module.
|
||||
// ubc_close();
|
||||
return (0);
|
||||
}
|
||||
}*/
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include "util.h"
|
||||
/*#include "util.h"
|
||||
#include "builtin.h"
|
||||
#include <lib/string.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;
|
||||
|
@ -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);
|
||||
}
|
||||
}*/
|
||||
|
|
Loading…
Reference in New Issue