Espresso 0.0.2c

This commit is contained in:
2026-03-20 16:57:08 -05:00
parent 021fdbbcef
commit 5971218b56
77 changed files with 4538 additions and 518 deletions

15
include/arch/x86/intrin.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef _INTRINSICS_H
#define _INTRINSICS_H
#include <stdint.h>
static inline uint64_t rdtsc(void)
{
uint32_t lo, hi;
asm volatile ("rdtsc" : "=a"(lo), "=d"(hi));
return ((uint64_t) hi << 32) | lo;
}
#endif

View File

@ -0,0 +1,11 @@
#ifndef ESPRESSO_PC_SPEAKER_H
#define ESPRESSO_PC_SPEAKER_H
#include <stdint.h>
void play_sound(uint32_t nfrequence);
void stop_sound(void);
void beep(void);
#endif

View File

@ -9,35 +9,37 @@
#define PT_LOAD 1
typedef struct {
unsigned char e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint32_t e_entry;
uint32_t e_phoff;
uint32_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
unsigned char e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint32_t e_entry;
uint32_t e_phoff;
uint32_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} Elf32_Ehdr;
typedef struct {
uint32_t p_type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
uint32_t p_type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
} Elf32_Phdr;
typedef int (*elf_entry_t)(void);
typedef struct {
void* entry_point;
elf_entry_t entry_point;
} elf_executable_t;
elf_executable_t* load_elf32(void* elf_data);

View File

@ -1,13 +1,18 @@
#ifndef _IDT_H
#define _IDT_H
#include <drivers/irq.h>
#include <types.h>
void idt_init(void);
void pic_remap(void);
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags);
void exception_dispatcher(uint32_t int_no, uint32_t err_code);
void exception_handler(registers_t* regs);
#endif

View File

@ -3,13 +3,28 @@
#include <types.h>
typedef void (*irq_func_t)(void);
typedef struct {
uint32_t ds, es, fs, gs;
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
uint32_t int_no;
uint32_t err_code;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
} registers_t;
typedef registers_t* (*irq_func_t)(registers_t*);
void irq_init(void);
void irq_handler(uint8_t irq_number);
registers_t* irq_handler(uint32_t irq, registers_t* regs);
void set_irq_handler(uint32_t num, irq_func_t* handler);
void add_irq_handler(uint32_t num, irq_func_t* handler);
void set_irq_handler(uint32_t num, irq_func_t handler);
/*void add_irq_handler(uint32_t num, irq_func_t* handler);*/
uint32_t get_interrupts_missed(void);
#endif

View File

@ -0,0 +1,10 @@
#ifndef _KEYBOARD_DRIVER_H
#define _KEYBOARD_DRIVER_H
#include <drivers/irq.h>
int init_keyboard(void);
registers_t* keyboard_handler(registers_t* regs);
#endif

View File

@ -3,10 +3,11 @@
#include <types.h>
extern volatile uint64_t pit_ticks;
#include <drivers/irq.h>
void pit_init(void);
void pit_handler(void);
registers_t* pit_handler(registers_t* regs);
void pit_sleep(uint64_t ms);
#endif

View File

@ -23,7 +23,9 @@ typedef enum {
typedef void (*ps2_hook_t)(char);
void keyboard_init(void);
void keyboard_handler(void);
registers_t* ps2_keyboard_handler(registers_t* regs);
void set_use_new_tty(bool t);
char get_char(void);
uint16_t get_key(void);

37
include/fs/ekfs.h Normal file
View File

@ -0,0 +1,37 @@
//#ifndef _ESPRESSO_KERNEL_FS_H
#if 0
#define _ESPRESSO_KERNEL_FS_H
#include <types.h>
#define EKFS_FILENAME_MAX_LEN 64
enum {
EKFS_E_FILETOOSMALL = -16;
};
struct ekfs_inode {
char i_name[EKFS_FILENAME_MAX_LEN];
uint64_t i_start; /* LBA48 */
size_t i_len; /* rounded up to the nearest multiple of 512 */
} __attribute__((packed));
struct ekfs_ops {
int (*read)(struct ekfs_file*, void*, size_t);
int (*write)(struct ekfs_file*, void*, size_t);
};
struct ekfs_file {
struct ekfs_inode* f_inode;
size_t f_offset;
size_t f_refcount;
struct ekfs_ops f_ops;
};
int ekfs_read(struct ekfs_file* __f, void* __b, size_t __l);
#endif

78
include/fs/fat16.h Normal file
View File

@ -0,0 +1,78 @@
#ifndef _FAT16_H
#define _FAT16_H
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#define FAT16_MAX_FILENAME 12 /* 8.3 + null */
#define SECTOR_SIZE 512
typedef struct {
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sector_count;
uint8_t num_fats;
uint16_t root_entry_count;
uint16_t total_sectors_16;
uint16_t sectors_per_fat;
uint32_t fat_start_lba;
uint32_t root_dir_lba;
uint32_t data_start_lba;
uint32_t total_sectors;
} fat16_fs_t;
typedef struct {
char name[FAT16_MAX_FILENAME]; /* 8.3 format */
uint8_t attr;
uint16_t first_cluster;
uint32_t size;
} fat16_file_t;
int fat16_mount(uint8_t drive);
int fat16_find_file(const char* name, fat16_file_t* out_file);
int fat16_create_file(const char* name, fat16_file_t* out_file);
int fat16_delete_file(const char* filename);
int fat16_read_file(fat16_file_t* file, void* buffer);
int fat16_write_file(fat16_file_t* file, const void* buffer, uint32_t size);
/*
Small helper function that converts a normal filename like "test.txt" into FAT16 8.3 uppercase format padded with spaces.
This makes creating and writing files much easier.
*/
static void filename_to_83(const char* input, char out[12])
{
memset(out, ' ', 11);
out[11] = '\0';
/* Find dot */
const char* dot = strchr(input, '.');
size_t name_len = dot ? (size_t) (dot - input) : strlen(input);
if (name_len > 8)
{
name_len = 8;
}
for (size_t i = 0; i < name_len; i++)
{
out[i] = toupper((unsigned char)input[i]);
}
if (dot)
{
size_t ext_len = strlen(dot + 1);
if (ext_len > 3) ext_len = 3;
for (size_t i = 0; i < ext_len; i++)
{
out[8 + i] = toupper((unsigned char)dot[1 + i]);
}
}
}
#endif

View File

@ -1,8 +1,6 @@
#ifndef _KERNEL_SHELL_H
#define _KERNEL_SHELL_H
#include <types.h>
int kshell_start(int argc, char** argv);
void kshell_start(void);
#endif

111
include/kernel/syscall.h Normal file
View File

@ -0,0 +1,111 @@
#ifndef _ESPRESSO_SYSCALL_H
#define _ESPRESSO_SYSCALL_H
#include <drivers/idt.h>
#define SYSCALL_INT 0x30
enum {
SYS_MAP_PAGE = 0, /* void map_page(void* phys_addr, void* virt_addr); */
SYS_PMM_ALLOC_PAGE, /* void* pmm_alloc_page(void); */
SYS_PMM_FREE_PAGE, /* void pmm_free_page(void* addr); */
SYS_SERIAL_WRITE, /* void serial_write(char a); */
SYS_SERIAL_READ, /* char serial_read(void); */
SYS_SERIAL_PUTS, /* void serial_puts(const char* s); */
SYS_USE_SERIAL, /* bool use_serial(void); */
SYS_TERMINAL_SCROLL, /* void terminal_scroll(void); */
SYS_TERMINAL_CLEAR, /* void terminal_clear(void); */
SYS_TERMINAL_SET_CURSOR, /* void terminal_set_cursor(uint16_t row, uint16_t column); */
SYS_TERMINAL_GET_CURSOR, /* void terminal_get_cursor(int* row, int* column); */
SYS_TERMINAL_WRITE, /* void terminal_write(const char* data, size_t size); */
SYS_TERMINAL_WRITESTRING, /* void terminal_writestring(const char* data) */
SYS_TERMINAL_DEBUG_WRITESTRING, /* void terminal_debug_writestring(const char* data); */
SYS_TERMINAL_PUTCHAR, /* void terminal_putchar(char c); */
SYS_TERMINAL_PUTENTRYAT, /* void terminal_putentryat(unsigned char c, uint8_t color, size_t x, size_t y); */
SYS_TERMINAL_GETCOLOR, /* uint8_t terminal_getcolor(void); */
SYS_TERMINAL_SETCOLOR, /* void terminal_setcolor(uint8_t color); */
SYS_READ, /* int read(uint32_t fd, void* data, size_t max_len); */
SYS_WRITE, /* int write(uint32_t fd, void* data, size_t len); */
__ENUM_END_MARKER__,
};
#define syscall0(num) ({ \
int ret; \
asm volatile ( \
"int %1" \
: "=a"(ret) \
: "i"(SYSCALL_INT), "a"(num) \
: "memory" \
); \
ret; \
})
/* syscall 1 */
#define syscall1(num, a) ({ \
int ret; \
asm volatile ( \
"int %1" \
: "=a"(ret) \
: "i"(SYSCALL_INT), "a"(num), "b"(a) \
: "memory" \
); \
ret; \
})
#define syscall2(num, a, b) ({ \
int ret; \
asm volatile ( \
"int %1" \
: "=a"(ret) \
: "i"(SYSCALL_INT), "a"(num), "b"(a), "c"(b) \
: "memory" \
); \
ret; \
})
#define syscall3(num, a, b, c) ({ \
int ret; \
asm volatile ( \
"int %1" \
: "=a"(ret) \
: "i"(SYSCALL_INT), "a"(num), "b"(a), "c"(b), "d"(c) \
: "memory" \
); \
ret; \
})
#define syscall4(num, a, b, c, d) ({ \
int ret; \
asm volatile ( \
"int %1" \
: "=a"(ret) \
: "i"(SYSCALL_INT), "a"(num), "b"(a), "c"(b), "d"(c), "S"(d) \
: "memory" \
); \
ret; \
})
#define syscall5(num, a, b, c, d, e) ({ \
int ret; \
asm volatile ( \
"int %1" \
: "=a"(ret) \
: "i"(SYSCALL_INT), "a"(num), "b"(a), "c"(b), "d"(c), "S"(d), "D"(e) \
: "memory" \
); \
ret; \
})
/* some macros for commonly used functions */
#define syscall_terminal_writestring(ptr) syscall1(SYS_TERMINAL_WRITESTRING, ptr);
#define syscall_terminal_putchar(chr) syscall1(SYS_TERMINAL_PUTCHAR, chr);
#define syscall_map_page(phys, virt) syscall2(SYS_MAP_PAGE, phys, virt);
#define syscall_pmm_alloc_page() syscall0(SYS_PMM_ALLOC_PAGE);
#define syscall_pmm_free_page(addr) syscall1(SYS_PMM_FREE_PAGE, addr);
void init_sysints(void);
registers_t* int16_handler(registers_t* regs);
#endif

View File

@ -3,7 +3,8 @@
#define ESPRESSO_KERNEL_
#define KERNEL_VERSION "0.0.2a"
#define KERNEL_VERSION "0.0.2c"
#define KERNEL_RELEASE_YEAR "2026"
#define _STATE_NORMAL 0
#define _STATE_HANDLED 1
@ -18,4 +19,14 @@
#define __noreturn __attribute__((noreturn))
#define __section(x) __attribute__((section(x)))
#define __noreturn __attribute__((noreturn))
extern void _cli_asm(void);
extern void _sti_asm(void);
#define IRQ_DISABLE() _cli_asm();
#define IRQ_ENABLE() _sti_asm();
//#define DEBUG_USE_SSE2
#endif

15
include/math/random.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef _RANDOM_H
#define _RANDOM_H
#include <types.h>
void seed_rand(uint32_t seed);
uint32_t uirand(void); /* 32 bits / 4 bytes */
uint64_t ulrand(void); /* 64 bits / 8 bytes */
/* get a number between 0 and max-1 */
uint32_t uirand_range(uint32_t max);
uint64_t ulrand_range(uint64_t max);
#endif

73
include/new_tty.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef _TTY_H
#define _TTY_H
#include <types.h>
#include <processes.h>
#include <sync.h>
#define TTY_BUFFER_SIZE 4096
#define MAX_TTYS 8 /* to make things easy, might change later */
#define TTY_ECHO 0x10 /* 0b00010000 */
#define TTY_PASSWORD 0x20 /* 0b00100000 */
#define TTY_ACTIVE 0x01 /* 0b00000001 */
#define TTY_CANONICAL 0x40 /* 0b01000000 */
#define TTY_NULL 0x80 /* 0b10000000 --- used to end the list of tty_t structs in the ttys array */
#define TTY_NORMAL TTY_ECHO | TTY_ACTIVE | TTY_CANONICAL
#define MODIFIER_CAPS 0x01 /* 0b00000001 */
#define MODIFIER_CAPS_DESTROY 0b11111110
#define MODIFIER_SHIFT 0x02 /* 0b00000010 */
#define MODIFIER_SHIFT_DESTROY 0b11111101
#define MODIFIER_ALT 0x04 /* 0b00000100 */
#define MODIFIER_ALT_DESTROY 0b11111011
#define MODIFIER_LCTRL 0x10 /* 0b00010000 */
#define MODIFIER_LCTRL_DESTROY 0b11101111
#define MODIFIER_RCTRL 0x0 /* 0b00100000*/
#define MODIFIER_RCTRL_DESTROY 0b11011111
typedef struct tty_t {
char input_buffer[TTY_BUFFER_SIZE];
size_t head;
size_t tail;
uint32_t flags;
bool canonical;
bool line_ready;
spinlock_t lock;
pid_t foreground_pgid; /* not used yet */
} tty_t;
/* essentially, key is non-zero if a key like the up arrow is pressed, otherwise c is the char that was entered */
struct keyevent {
uint8_t key;
char c;
};
int init_tty(void);
ssize_t tty_read(tty_t* tty, char* buf, size_t count);
ssize_t tty_read_active(char* buf, size_t count);
tty_t* get_active_tty(void);
tty_t* tty_get_active(void);
tty_t* make_tty(uint32_t flags);
void tty_receive_char(char c, uint32_t kbd_mod);
char tty_translate_char(char c, uint32_t modifiers);
void tty_input_char(tty_t* tty, char c);
#endif

View File

@ -1,10 +1,10 @@
#ifndef _PRINTF_H
#define _PRINTF_H
#include <tty.h>
//#include <tty.h>
#include <string.h>
#include <vga/vga.h> /* Only for the vga_color enum */
//#include <vga/vga.h> /* Only for the vga_color enum */
void printwc(const char*, uint8_t);

View File

@ -5,15 +5,17 @@
#include <drivers/elf.h>
typedef uint32_t pid_t;
typedef struct process {
int32_t id;
int32_t group;
pid_t id;
pid_t group;
elf_executable_t* exe;
struct process* next;
} process_t;
int32_t make_process(char* name, char* group, elf_executable_t* exe);
pid_t make_process(char* name, char* group, elf_executable_t* exe);
#endif

21
include/scheduler.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _SCHEDULER_H
#define _SCHEDULER_H
#include <drivers/irq.h>
#include <types.h>
typedef struct task {
registers_t* regs; /* saved interrupt frame */
uint32_t id;
struct task* next;
} task_t;
void init_scheduler(void);
registers_t* schedule(registers_t* regs);
task_t* create_task(void (*entry)());
#endif

View File

@ -4,10 +4,23 @@
#include <types.h>
#include <printf.h>
#define STDIN 0
#define STDOUT 1
#define STDERR 2
int read(uint32_t fd, void* data, size_t max_len);
int write(uint32_t fd, void* data, size_t len);
char getchar(void);
char* getstring(void);
char* gets(void); /* Use this instead of getstring() */
int getstr(char* dest);
char* gets_new(int* num);
void putc(char c);
static inline void putchar(char c)
{
printf("%c", c);

View File

@ -17,8 +17,10 @@ char* strdup(const char* s);
char* strtok(char* str, const char* delim);
char* strchr(const char* s, int c);
/* this function is NOT in the standard C library */
/* these functions are NOT in the standard C library */
int num_strchr(const char* s, int c);
char* strnlstrip(const char* __s);
void strlnstripip(char* s);
void lowers(char* str);
void uppers(char* str);

14
include/sync.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef _SYNC_H
#define _SYNC_H
typedef struct {
volatile int locked;
} spinlock_t;
void spinlock_init(spinlock_t* lock);
void spin_lock(spinlock_t* lock);
void spin_unlock(spinlock_t* lock);
#endif

View File

@ -1,5 +1,5 @@
#ifndef _TTY_H
#define _TTY_H
#ifndef TTY_H
#define TTY_H
#include <types.h>
@ -32,4 +32,7 @@ void terminal_set_cursor(uint16_t row, uint16_t column);
void terminal_get_cursor(int* row, int* column);
void terminal_update_cursor(void);
void terminal_putcharat(char c, uint16_t row, uint16_t column);
#endif

View File

@ -5,6 +5,11 @@
#include <stddef.h>
#include <stdbool.h>
#define ARG64_LO(x) ((uint32_t)(x))
#define ARG64_HI(x) ((uint32_t)((x) >> 32))
#define TOGGLE_BIT(x, bit) ((x) ^= (1U << (bit)))
typedef unsigned char uchar;
typedef uint8_t u8;
@ -12,4 +17,19 @@ typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
/* this might not be POSIX compatable. */
typedef uint32_t size_t;
typedef int32_t ssize_t;
#if 0
#if sizeof(size_t) != sizeof(ssize_t)
#error "size_t is a different size than ssize_t"
#endif
#endif
#endif