Add ELF loader and first process !

This commit is contained in:
Yann MAGNIN 2020-01-01 14:19:18 +01:00
parent 6c0971e661
commit 9a9ac9614b
28 changed files with 543 additions and 153 deletions

View File

@ -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

116
include/kernel/elf.h Normal file
View File

@ -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__ */

View File

@ -3,6 +3,7 @@
#include <stdint.h>
#include <stddef.h>
#include <kernel/types.h>
#ifndef FILE_OPEN_NUMBER
# define FILE_OPEN_NUMBER 4

View File

@ -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__*/

View File

@ -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;

View File

@ -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__*/

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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");

View File

@ -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;

View File

@ -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);
}

View File

@ -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"

View File

@ -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",

View File

@ -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"

View File

@ -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);
}

View File

@ -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);
}

62
src/kernel/loader/image.c Normal file
View File

@ -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));
}

View File

@ -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;

View File

@ -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]);
}

View File

@ -0,0 +1,7 @@
.global _dtest
.align 2
_dtest:
trapa #0
rts
nop

View File

@ -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 */

127
src/kernel/util/printk.c Normal file
View File

@ -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);
}

View File

@ -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

View File

@ -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)
}
}

View File

@ -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);
}
}*/

View File

@ -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];

View File

@ -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);
}
}*/