0.0.2d: Added BGA support, graphics!

This commit is contained in:
2026-06-05 16:14:14 -05:00
parent 5971218b56
commit c741f55be1
40 changed files with 1007 additions and 1197 deletions

View File

@ -12,9 +12,11 @@ NASMFLAGS := -f elf32
WNOFLAGS := -Wno-discarded-qualifiers WNOFLAGS := -Wno-discarded-qualifiers
CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse $(WNOFLAGS) -nostdlib -nostartfiles -include include/kincl.h CFLAGS := -std=gnu99 -ffreestanding -O2 -Wall -Wextra -msse $(WNOFLAGS) -nostdlib -nostartfiles -include include/kincl.h
LDFLAGS := -T linker.ld -ffreestanding -O2 -nostdlib -nostartfiles LDFLAGS := -T linker.ld -ffreestanding -O2 -nostdlib -nostartfiles
QEMUFLAGS := -no-shutdown -boot d -cdrom $(ISO) -drive file=$(FAT16_DISK),format=raw,if=ide,readonly=off,rerror=report,werror=report -cpu qemu32,sse4.1 QEMUFLAGS := -no-shutdown -drive file=$(FAT16_DISK),format=raw,if=ide,readonly=off,rerror=report,werror=report -cpu qemu32,sse4.1
QEMUFLGS_EXT := -vga std -d int,cpu_reset -D qemu.log # -audiodev pa,id=speaker -machine pcspk-audiodev=speaker QEMUFLGS_EXT := -vga std
MOR_QEMUFLGS := -net none -netdev user,id=n0 -device rtl8139,netdev=n0 -serial file:serial.log MOR_QEMUFLGS := -net none -netdev user,id=n0 -device rtl8139,netdev=n0 -serial file:serial.log
QEMU_BOOT_FLG := -boot d -cdrom $(ISO)
QEMU_BOOT_RPI := -kernel $(TARGET)
SRC_DIRS := kernel drivers lib SRC_DIRS := kernel drivers lib
INCLUDE_DIRS := include INCLUDE_DIRS := include
ARCH_DIR := arch ARCH_DIR := arch
@ -26,6 +28,9 @@ BOOT_DIR := $(ISO_DIR)/boot
GRUB_DIR := $(BOOT_DIR)/grub GRUB_DIR := $(BOOT_DIR)/grub
GRUB_CFG := grub.cfg GRUB_CFG := grub.cfg
# === Host checks ===
IS_RPI := $(shell [ -f /proc/device-tree/model ] && grep -qi "Raspberry Pi" /proc/device-tree/model && echo 1 || echo 0)
# === File collection === # === File collection ===
C_SRCS := $(foreach dir, $(SRC_DIRS), $(shell find $(dir) -name '*.c')) C_SRCS := $(foreach dir, $(SRC_DIRS), $(shell find $(dir) -name '*.c'))
S_SRCS := $(foreach dir, $(ARCH_DIR), $(shell find $(dir) -name '*.s')) S_SRCS := $(foreach dir, $(ARCH_DIR), $(shell find $(dir) -name '*.s'))
@ -73,9 +78,11 @@ $(TARGET): ./arch/x86/boot/boot.o $(filter-out boot.o, $(OBJ_LINK_LIST))
iso: $(TARGET) iso: $(TARGET)
@grub-file --is-x86-multiboot $(TARGET) && echo "multiboot confirmed" || (echo "not multiboot" && exit 1) @grub-file --is-x86-multiboot $(TARGET) && echo "multiboot confirmed" || (echo "not multiboot" && exit 1)
mkdir -p $(GRUB_DIR) mkdir -p $(GRUB_DIR)
cp $(TARGET) $(BOOT_DIR)/ cp $(TARGET) $(BOOT_DIR)
cp $(GRUB_CFG) $(GRUB_DIR)/ ifneq ($(IS_RPI),1)
cp $(GRUB_CFG) $(GRUB_DIR)
grub-mkrescue -o $(ISO) $(ISO_DIR) grub-mkrescue -o $(ISO) $(ISO_DIR)
endif
# === Run in QEMU === # === Run in QEMU ===
run: iso run: iso
@ -83,8 +90,12 @@ run: iso
$(QEMU_MKE_IMG); \ $(QEMU_MKE_IMG); \
sudo mkfs.fat $(MKFS_FLAGS) espresso.img; \ sudo mkfs.fat $(MKFS_FLAGS) espresso.img; \
fi fi
@echo @echo $(IS_RPI)
qemu-system-i386 $(QEMUFLAGS) $(QEMUFLGS_EXT) $(MOR_QEMUFLGS) ifeq ($(IS_RPI),1)
qemu-system-i386 $(QEMU_BOOT_RPI) $(QEMUFLAGS) $(QEMUFLGS_EXT) $(MOR_QEMUFLGS)
else
qemu-system-i386 $(QEMU_BOOT_FLG) $(QEMUFLAGS) $(QEMUFLGS_EXT) $(MOR_QEMUFLGS)
endif
# === Clean all build artifacts === # === Clean all build artifacts ===
@ -99,9 +110,15 @@ clean_disk:
commit: commit:
ifndef MSG ifndef MSG
$(error MSG required) $(error MSG required)
endif
ifndef RELEASENUM
$(error RELEASENUM required)
endif endif
git add . git add .
git commit -m "$(MSG)" git commit -m "$(MSG)"
git push git push origin main
git tag -a "$(RELEASENUM)" -m "Espresso $(RELEASENUM)"
git push origin "$(RELEASENUM)"
.PHONY: all clean clean_disk iso run debug build buildc .PHONY: all clean clean_disk iso run debug build buildc

View File

@ -1 +0,0 @@
I'm back (maybe?)

View File

@ -11,7 +11,7 @@
#define ALIGN_UP(x) (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) #define ALIGN_UP(x) (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
elf_executable_t* load_elf32(void* elf_data) int load_elf32(void* elf_data, elf_executable_t** ptr)
{ {
Elf32_Ehdr* ehdr = (Elf32_Ehdr*)elf_data; Elf32_Ehdr* ehdr = (Elf32_Ehdr*)elf_data;
@ -19,13 +19,13 @@ elf_executable_t* load_elf32(void* elf_data)
if (memcmp(ehdr->e_ident, (uint8_t*)("\x7F""ELF"), 4) != 0) if (memcmp(ehdr->e_ident, (uint8_t*)("\x7F""ELF"), 4) != 0)
{ {
printf("Invalid ELF file\n"); printf("Invalid ELF file\n");
return NULL; return -1;
} }
if (ehdr->e_machine != 3 || ehdr->e_type != 2) if (ehdr->e_machine != 3 || ehdr->e_type != 2)
{ {
printf("Unsupported ELF type or architecture\n"); printf("Unsupported ELF type or architecture\n");
return NULL; return -1;
} }
Elf32_Phdr* phdrs = (Elf32_Phdr*)((uint8_t*)elf_data + ehdr->e_phoff); Elf32_Phdr* phdrs = (Elf32_Phdr*)((uint8_t*)elf_data + ehdr->e_phoff);
@ -60,10 +60,17 @@ elf_executable_t* load_elf32(void* elf_data)
#endif #endif
} }
elf_executable_t* result = malloc(sizeof(elf_executable_t)); *ptr = malloc(sizeof(elf_executable_t));
result->entry_point = (elf_entry_t)(uintptr_t)ehdr->e_entry;
return result;
return NULL; if (ptr)
{
(*ptr)->entry_point = (elf_entry_t)(uintptr_t) ehdr->e_entry;
return 0;
}
/*
elf_executable_t* result = malloc(sizeof(elf_executable_t));
result->entry_point = (elf_entry_t)(uintptr_t)ehdr->e_entry;*/
return -1;
} }

View File

@ -1,49 +0,0 @@
#include <types.h>
#include <string.h>
#include <drivers/ide.h>
#include <fs/ekfs.h>
/* work on this later */
#if 0
/* note: __l being 0 is allowed, because that way read() can be used to tell if a file exists (with return value 0) */
int ekfs_read(struct ekfs_file* __f, void* __b, size_t __l)
{
int rv = 0;
if (!__f || !__b || (!__f->f_inode))
{
return -1;
}
/* we assume drive 0 is already mounted */
char buffer[512];
memset(buffer, 0, 512);
int num_sectors = __f->f_inode->i_len / 512;
if ((__l / 512) > num_sectors)
{
return EKFS_E_FILETOOSMALL;
}
int read_sectors = num_sectors;
for (int i = 0; i < read_sectors; i++);
{
rv = read_sector(__f->f_inode->i_start, buffer);
if (rv != 0)
{
break;
}
}
return rv;
}
#endif

View File

@ -20,6 +20,8 @@ int fat16_mount(uint8_t drive)
return -1; return -1;
} }
(void) drive;
fs.bytes_per_sector = boot_sector[11] | (boot_sector[12] << 8); fs.bytes_per_sector = boot_sector[11] | (boot_sector[12] << 8);
fs.sectors_per_cluster = boot_sector[13]; fs.sectors_per_cluster = boot_sector[13];
fs.reserved_sector_count = boot_sector[14] | (boot_sector[15] << 8); fs.reserved_sector_count = boot_sector[14] | (boot_sector[15] << 8);
@ -53,7 +55,7 @@ static int read_fat_entry(uint16_t cluster, uint16_t* out_value)
return -1; return -1;
} }
if (idx == fs.bytes_per_sector - 1) if (idx == (uint32_t)(fs.bytes_per_sector - 1))
{ {
/* entry spans boundary -> read next sector */ /* entry spans boundary -> read next sector */
uint8_t next_sector[SECTOR_SIZE]; uint8_t next_sector[SECTOR_SIZE];

View File

@ -7,25 +7,7 @@
/* we use something similar to the Linux kernel in terms of a VFS system */ /* we use something similar to the Linux kernel in terms of a VFS system */
#define MAX_FDS 64
struct inode {
size_t size;
int permissions;
void *fs_data; /* FS-specific */
};
struct file_ops {
int (*read)(struct file*, char*, size_t);
int (*write)(struct file*, const char*, size_t);
};
struct file {
struct inode* f_inode;
size_t f_offset;
size_t f_refcount;
const struct file_ops f_ops;
};
@ -35,17 +17,9 @@ struct fdtable {
int vfs_handle_stdout(struct file* __f, const char* __s, size_t __l) #if 0
{
(void) __f;
terminal_write(__s, __l);
return 0;
}
struct fdtable* vfs_init_kernel_fdtable(void) struct fdtable* vfs_init_kernel_fdtable(void)
{ {
#if 0
struct fdtable* ft = malloc(sizeof(struct fdtable)); struct fdtable* ft = malloc(sizeof(struct fdtable));
struct file* _stdout = malloc(sizeof(struct file)); struct file* _stdout = malloc(sizeof(struct file));
struct file* _stdin = malloc(sizeof(struct file)); struct file* _stdin = malloc(sizeof(struct file));
@ -59,9 +33,9 @@ struct fdtable* vfs_init_kernel_fdtable(void)
_stdout->f_offset = 0; _stdout->f_offset = 0;
_stdout->f_refcount = 1; _stdout->f_refcount = 1;
_stdout->f_ops = { .read = NULL, .write = vfs_handle_stdout }; _stdout->f_ops = { .read = NULL, .write = vfs_handle_stdout };
#endif
return NULL; return NULL;
} }
#endif
int init_vfs(int argc, char** argv) int init_vfs(int argc, char** argv)
{ {

173
drivers/graphics/vga.c Normal file
View File

@ -0,0 +1,173 @@
#include <types.h>
#include <mm/paging.h>
#include <stdio.h>
#include <port_io.h>
#include <math.h>
#include <drivers/graphics/vga.h>
#define VBE_DISPI_IOPORT_INDEX 0x01CE
#define VBE_DISPI_IOPORT_DATA 0x01CF
#define VBE_DISPI_INDEX_ID 0x0
#define VBE_DISPI_INDEX_XRES 0x1
#define VBE_DISPI_INDEX_YRES 0x2
#define VBE_DISPI_INDEX_BPP 0x3
#define VBE_DISPI_INDEX_ENABLE 0x4
#define VBE_DISPI_INDEX_BANK 0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
#define VBE_DISPI_INDEX_X_OFFSET 0x8
#define VBE_DISPI_INDEX_Y_OFFSET 0x9
#define VBE_DISPI_DISABLED 0x00
#define VBE_DISPI_ENABLED 0x01
#define VBE_DISPI_LFB_ENABLED 0x40
static bool bga_init = false;
static bool bga_error = false;
uint32_t current_bpp = 0;
uint32_t current_xres = 0;
uint32_t current_yres = 0;
static struct bga_framebuffer bga_fb;
void init_bga_framebuffer(uint32_t* _p)
{
uint32_t width = 1024;
uint32_t height = 768;
uint32_t bpp = 32;
uint32_t pitch = width * (bpp / 8);
uint32_t fb_size = pitch * height;
fb_size = (fb_size + 0xFFF) & ~0xFFF;
uint8_t* bp = (uint8_t*) _p;
for (uint32_t off = 0; off < fb_size; off += 0x1000)
{
map_page(bp + off, bp + off);
}
bga_fb.addr = _p;
bga_fb.bpp = bpp;
bga_fb.height = height;
bga_fb.width = width;
bga_fb.pitch = pitch;
bga_init = true;
}
uint8_t* bga_get_framebuffer(void)
{
return bga_fb.addr;
}
void bga_write_register(uint16_t index, uint16_t data)
{
outw(VBE_DISPI_IOPORT_INDEX, index);
outw(VBE_DISPI_IOPORT_DATA, data);
}
uint16_t bga_read_register(uint16_t index)
{
outw(VBE_DISPI_IOPORT_INDEX, index);
return inw(VBE_DISPI_IOPORT_DATA);
}
void bga_set_video_mode(uint32_t width, uint32_t height, uint32_t bit_depth)
{
bga_write_register(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
bga_write_register(VBE_DISPI_INDEX_XRES, width);
bga_write_register(VBE_DISPI_INDEX_YRES, height);
bga_write_register(VBE_DISPI_INDEX_BPP, bit_depth);
bga_write_register(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED);
/* now we check to see if any info we gave was rejected, in which case everything would be the way it was before we wrote the configuration info. */
uint16_t bpp = bga_read_register(VBE_DISPI_INDEX_BPP);
if (bpp != bit_depth)
{
bga_error = true;
}
else
{
current_bpp = bit_depth;
current_xres = width;
current_yres = height;
}
}
void bga_defaults(void)
{
// Disable device while changing settings
bga_write_register(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_DISABLED);
// Set resolution
bga_write_register(VBE_DISPI_INDEX_XRES, 1024);
bga_write_register(VBE_DISPI_INDEX_YRES, 768);
bga_write_register(VBE_DISPI_INDEX_BPP, 32);
// Enable graphics + linear framebuffer
bga_write_register(
VBE_DISPI_INDEX_ENABLE,
VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED
);
}
/*void bga_putpixel(uint32_t x, uint32_t y, uint32_t color)
{
if (current_bpp == 16)
{
uint16_t* fb = (uint16_t*) bga_framebuffer;
uint32_t idx = (y * current_xres + x) * 2;
*(fb + idx) = (uint16_t) color;
}
}*/
void bga_putpixel(uint32_t x, uint32_t y, uint32_t color)
{
uint32_t bytes_per_pixel = bga_fb.bpp / 8;
uint8_t* pixel = (uint8_t*)bga_fb.addr + (y * bga_fb.pitch) + (x * bytes_per_pixel);
*(volatile uint32_t*)pixel = color;
}
void bga_drawline(int x0, int y0, int x1, int y1, uint32_t color)
{
int dx = abs(x1 - x0);
int dy = abs(y1 - y0);
int sx = (x0 < x1) ? 1 : -1;
int sy = (y0 < y1) ? 1 : -1;
int err = dx - dy;
while (1)
{
bga_putpixel(x0, y0, color);
if (x0 == x1 && y0 == y1)
break;
int e2 = err * 2;
if (e2 > -dy)
{
err -= dy;
x0 += sx;
}
if (e2 < dx)
{
err += dx;
y0 += sy;
}
}
}

View File

@ -35,6 +35,12 @@ static int32_t ide_wait_ready(uint16_t io)
return 1; return 1;
} }
int get_sector_size(uint8_t drive)
{
(void) drive;
return SECTOR_SIZE;
}
int32_t ide_identify(uint8_t drive, uint16_t* buffer) int32_t ide_identify(uint8_t drive, uint16_t* buffer)
{ {
uint16_t io = ATA_PRIMARY_IO; uint16_t io = ATA_PRIMARY_IO;

View File

@ -61,7 +61,6 @@ int init_keyboard(void)
return 0; return 0;
} }
registers_t* keyboard_handler(registers_t* regs) registers_t* keyboard_handler(registers_t* regs)
{ {
if (!(inb(PS2_STATUS_PORT) & 1)) if (!(inb(PS2_STATUS_PORT) & 1))
@ -71,13 +70,77 @@ registers_t* keyboard_handler(registers_t* regs)
uint8_t scancode = inb(PS2_DATA_PORT); uint8_t scancode = inb(PS2_DATA_PORT);
if (scancode & 0x80) if (scancode == 0xE0)
{ {
extended = true;
return regs; return regs;
} }
bool is_release = scancode & 0x80;
uint8_t key = scancode & 0x7F;
if (extended)
{
if (is_release)
{
if (key == 0x1D)
{
mods &= ~MODIFIER_RCTRL;
}
}
else
{
if (key == 0x1D)
{
mods |= MODIFIER_RCTRL;
}
}
/* delete key, should add this functionality */
/*if (key == 0x53)*/
extended = false;
return regs;
}
if (is_release)
{
if (key == 0x2A || key == 0x36)
{
mods &= ~MODIFIER_SHIFT;
}
return regs;
}
else
{
if (key == 0x2A || key == 0x36)
{
mods |= MODIFIER_SHIFT;
return regs;
}
else if (key == 0x3A)
{
mods ^= MODIFIER_CAPS;
return regs;
}
}
uint16_t c = (uint16_t) scancode_map[scancode];
if (c)
{
//tty_receive_char(c, mods);
char ch = tty_translate_char(c, mods);
tty_input_char(tty_get_active(), ch);
}
return regs;
}
/* Handle shift press/release */ /* Handle shift press/release */
if (scancode == 0x2A || scancode == 0x36) /*if (scancode == 0x2A || scancode == 0x36)
{ {
mods |= MODIFIER_SHIFT; mods |= MODIFIER_SHIFT;
return regs; return regs;
@ -89,9 +152,11 @@ registers_t* keyboard_handler(registers_t* regs)
} }
else if (scancode == 0x3A) else if (scancode == 0x3A)
{ {
TOGGLE_BIT(mods, 0); /* TOGGLE_BIT defined in types.h, should move elsewhere. */ TOGGLE_BIT(mods, 0);
return regs; return regs;
} }*/
/*else if (scancode == 0xE0) /*else if (scancode == 0xE0)
{ {
extended = true; extended = true;
@ -127,22 +192,10 @@ registers_t* keyboard_handler(registers_t* regs)
return; return;
}*/ }*/
bool release = scancode & 0x80; /*bool release = scancode & 0x80;
scancode &= 0x7F; scancode &= 0x7F;
if (release) if (release)
{ {
return regs; return regs;
} }*/
uint16_t c = (uint16_t) scancode_map[scancode];
if (c)
{
//tty_receive_char(c, mods);
char ch = tty_translate_char(c, mods);
tty_input_char(tty_get_active(), ch);
}
return regs;
}

View File

@ -33,11 +33,27 @@ static inline bool is_canonical(tty_t* tty)
return (tty->flags & TTY_CANONICAL) != 0; return (tty->flags & TTY_CANONICAL) != 0;
} }
static void raw_put(tty_t* tty, char c)
{
size_t next = (tty->raw_head + 1) % TTY_RAW_BUFFER_SIZE;
if (next != tty->raw_tail) // avoid overflow
{
tty->raw_buf[tty->raw_head] = c;
tty->raw_head = next;
}
}
tty_t* tty_get_active(void) tty_t* tty_get_active(void)
{ {
return active_tty; return active_tty;
} }
int tty_fread(struct file* f, char* b, size_t s)
{
return (int) tty_read_active(b, s);
}
void tty_backspace(tty_t* tty) void tty_backspace(tty_t* tty)
{ {
if (tty->head == tty->tail) if (tty->head == tty->tail)
@ -48,50 +64,88 @@ void tty_backspace(tty_t* tty)
tty->head = (tty->head + TTY_BUFFER_SIZE - 1) / TTY_BUFFER_SIZE; tty->head = (tty->head + TTY_BUFFER_SIZE - 1) / TTY_BUFFER_SIZE;
} }
void tty_and_flags(tty_t* tty, uint32_t flags)
{
tty->flags &= flags;
}
uint32_t tty_get_flags(tty_t* tty)
{
return tty->flags;
}
ssize_t tty_read_active(char* buf, size_t count) ssize_t tty_read_active(char* buf, size_t count)
{ {
return tty_read(active_tty, buf, count); return tty_read(active_tty, buf, count);
} }
/*ssize_t tty_read(tty_t* tty, char* buf, size_t count) /*
this is special, because when this is called the char returned by this function
is NOT added to the TTY buffer.
This can be changed however by setting flag TTY_ADDCHAR_ALWAYS.
*/
/*char tty_get_char(void)
{ {
size_t bytes_read = 0; tty_t* tty = get_active_tty();
if (!tty)
{
return 0;
}
while (bytes_read < count) while (1)
{ {
IRQ_DISABLE(); IRQ_DISABLE();
spin_lock(&tty->lock); spin_lock(&tty->lock);
if (!tty_empty(tty)) if (tty->char_available)
{ {
char c = tty->input_buffer[tty->tail]; char c = tty->last_char;
tty->tail = (tty->tail + 1) % TTY_BUFFER_SIZE; tty->char_available = false;
tty->tail = next_index(tty->tail);
spin_unlock(&tty->lock);
IRQ_ENABLE(); /* change? *//*
buf[bytes_read++] = c;
if (is_canonical(tty) && c == '\n')
{
break;
}
}
else
{
spin_unlock(&tty->lock); spin_unlock(&tty->lock);
IRQ_ENABLE(); IRQ_ENABLE();
}
}
return bytes_read; return c;
}
spin_unlock(&tty->lock);
IRQ_ENABLE();
}
}*/ }*/
char tty_get_char(void)
{
tty_t* tty = get_active_tty();
if (!tty)
return 0;
while (1)
{
IRQ_DISABLE();
spin_lock(&tty->lock);
if (tty->raw_head != tty->raw_tail)
{
char c = tty->raw_buf[tty->raw_tail];
tty->raw_tail = (tty->raw_tail + 1) % TTY_RAW_BUFFER_SIZE;
spin_unlock(&tty->lock);
IRQ_ENABLE();
return c;
}
spin_unlock(&tty->lock);
IRQ_ENABLE();
}
}
ssize_t tty_read(tty_t* tty, char* buf, size_t count) ssize_t tty_read(tty_t* tty, char* buf, size_t count)
{ {
if (!tty || !buf) if (!tty || !buf)
return -1; {
return -1;
}
size_t bytes = 0; size_t bytes = 0;
@ -169,6 +223,9 @@ int init_tty(void)
active_tty = t; active_tty = t;
num_ttys = 1; num_ttys = 1;
t->f_ops.read = tty_fread;
t->line_ready = false;
return 0; return 0;
} }
@ -238,15 +295,18 @@ void tty_receive_char(char c, uint32_t kbd_mod)
} }
} }
void tty_input_char(tty_t* tty, char c) /*void tty_input_char(tty_t* tty, char c)
{ {
if (!tty || c == 0) if (!tty || c == 0)
return; {
return;
}
IRQ_DISABLE(); IRQ_DISABLE();
spin_lock(&tty->lock); spin_lock(&tty->lock);
/* backspace */ raw_put(tty, c);
if (c == '\b') if (c == '\b')
{ {
if (tty->head != tty->tail) if (tty->head != tty->tail)
@ -255,9 +315,7 @@ void tty_input_char(tty_t* tty, char c)
if (tty->flags & TTY_ECHO) if (tty->flags & TTY_ECHO)
{ {
putc('\b');/* putc('\b');
putc(' ');
putc('\b');*/
} }
} }
@ -282,6 +340,65 @@ void tty_input_char(tty_t* tty, char c)
spin_unlock(&tty->lock); spin_unlock(&tty->lock);
IRQ_ENABLE(); IRQ_ENABLE();
if (tty->flags & TTY_ECHO)
{
putc(c);
}
}*/
void tty_input_char(tty_t* tty, char c)
{
if (!tty || c == 0)
{
return;
}
IRQ_DISABLE();
spin_lock(&tty->lock);
/* RAW queue always gets input */
raw_put(tty, c);
if (!(tty->flags & TTY_RAW))
{
/* canonical behavior */
if (c == '\b')
{
if (tty->head != tty->tail)
{
tty->head = (tty->head + TTY_BUFFER_SIZE - 1) % TTY_BUFFER_SIZE;
putc('\b');
putc(' ');
putc('\b');
spin_unlock(&tty->lock);
IRQ_ENABLE();
return;
}
}
else
{
size_t next = next_index(tty->head);
if (next != tty->tail)
{
tty->input_buffer[tty->head] = c;
tty->head = next;
if (c == '\n')
{
tty->line_ready = true;
}
}
}
}
spin_unlock(&tty->lock);
IRQ_ENABLE();
if (tty->flags & TTY_ECHO) if (tty->flags & TTY_ECHO)
{ {
putc(c); putc(c);

View File

@ -17,96 +17,104 @@
uint32_t pci_config_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset) uint32_t pci_config_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset)
{ {
uint32_t address = 0; uint32_t address = 0;
address |= (bus << 16); /* Bus number (bits 23-16) */ address |= (bus << 16); /* Bus number (bits 23-16) */
address |= (device << 11); /* Device number (bits 15-11) */ address |= (device << 11); /* Device number (bits 15-11) */
address |= (function << 8); /* Function number (bits 10-8) */ address |= (function << 8); /* Function number (bits 10-8) */
address |= (offset & 0xFC); /* Register offset (bits 7-0) */ address |= (offset & 0xFC); /* Register offset (bits 7-0) */
address |= (1 << 31); /* Enable configuration access */ address |= (1 << 31); /* Enable configuration access */
outl(PCI_CONFIG_ADDRESS, address); /* Write address to PCI config space */ outl(PCI_CONFIG_ADDRESS, address); /* Write address to PCI config space */
return inl(PCI_CONFIG_DATA); /* Read data from PCI config space */ return inl(PCI_CONFIG_DATA); /* Read data from PCI config space */
} }
void pci_config_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value) void pci_config_write(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, uint32_t value)
{ {
uint32_t address = 0x80000000 | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC); uint32_t address = 0x80000000 | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC);
outl(PCI_CONFIG_ADDRESS, address); /* Send the address to PCI config space */ outl(PCI_CONFIG_ADDRESS, address); /* Send the address to PCI config space */
outl(PCI_CONFIG_DATA, value); /* Write data to PCI config space */ outl(PCI_CONFIG_DATA, value); /* Write data to PCI config space */
} }
void pci_config_read_block(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, void* buffer, size_t size) void pci_config_read_block(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset, void* buffer, size_t size)
{ {
uint8_t* buf = (uint8_t*)buffer; uint8_t* buf = (uint8_t*)buffer;
for (size_t i = 0; i < size; i += 4) for (size_t i = 0; i < size; i += 4)
{ {
uint32_t value = pci_config_read(bus, device, function, offset + i); uint32_t value = pci_config_read(bus, device, function, offset + i);
size_t remaining = size - i; size_t remaining = size - i;
if (remaining >= 4) if (remaining >= 4)
{ {
*(uint32_t*)(buf + i) = value; *(uint32_t*)(buf + i) = value;
}
else
{
for (size_t j = 0; j < remaining; ++j)
{
buf[i + j] = (value >> (8 * j)) & 0xFF;
}
}
} }
else
{
for (size_t j = 0; j < remaining; ++j)
{
buf[i + j] = (value >> (8 * j)) & 0xFF;
}
}
}
} }
void pci_init(void) void pci_init(void)
{ {
#ifdef _DEBUG #ifdef _DEBUG
printf("[ PCI ] Initializing PCI...\n"); printf("[ PCI ] Initializing PCI...\n");
#endif #endif
pci_enumerate(); pci_enumerate();
#ifdef _DEBUG #ifdef _DEBUG
printf("[ PCI ] PCI initialized\n"); printf("[ PCI ] PCI initialized\n");
#endif #endif
} }
void pci_enumerate(void) void pci_enumerate(void)
{ {
for (uint16_t bus = 0; bus < 256; bus++) /* Maximum 256 buses */ for (uint16_t bus = 0; bus < 256; bus++) /* Maximum 256 buses */
{
for (uint8_t device = 0; device < 32; device++) /* Maximum 32 devices per bus */
{ {
for (uint8_t function = 0; function < 8; function++) /* Maximum 8 functions per device */ for (uint8_t device = 0; device < 32; device++) /* Maximum 32 devices per bus */
{
struct pci_header pre_header;
pci_config_read_block(bus, device, function, 0x00, &pre_header, sizeof(pre_header));
if (pre_header.vendor_id == 0xFFFF)
{ {
continue; /* No device present */ for (uint8_t function = 0; function < 8; function++) /* Maximum 8 functions per device */
{
struct pci_header pre_header;
pci_config_read_block(bus, device, function, 0x00, &pre_header, sizeof(pre_header));
if (pre_header.vendor_id == 0xFFFF)
{
continue; /* No device present */
}
if (pre_header.class_code == 0xB)
{
printf("Processor found on PCI bus, what?!?!\n"); /* For some stupid reason, processors can be on the PCI bus? */
continue;
}
if (pre_header.header_type == 0x00)
{
struct pci_header_type_0 hdr;
pci_config_read_block(bus, device, function, 0x00, &hdr, sizeof(hdr));
if (hdr.class_code == 0x1 && hdr.subclass == 0x6 && hdr.prog_if == 0x1)
{
/*configure_ahci_controller(hdr);*/
}
if (hdr.class_code == 0x03)
{
uint32_t bar0 = hdr.bar0;
extern void init_bga_framebuffer(uint32_t* _p);
init_bga_framebuffer((uint32_t*) bar0);
printf("Found framebffer addr 0x%x on device %x \n", bar0, hdr.device_id);
}
/*printf("PCI device: cc: %x sc: %x pi: %x b: %x d: %x f: %x int: %x\n", hdr.class_code, hdr.subclass, hdr.prog_if, bus, device, function, (uint32_t) hdr.interrupt_line);*/
}
}
} }
if (pre_header.class_code == 0xB)
{
printf("Processor found on PCI bus, what?!?!\n"); /* For some stupid reason, processors can be on the PCI bus? */
continue;
}
if (pre_header.header_type == 0x00)
{
struct pci_header_type_0 hdr;
pci_config_read_block(bus, device, function, 0x00, &hdr, sizeof(hdr));
if (hdr.class_code == 0x1 && hdr.subclass == 0x6 && hdr.prog_if == 0x1)
{
/*configure_ahci_controller(hdr);*/
}
/*printf("PCI device: cc: %x sc: %x pi: %x b: %x d: %x f: %x int: %x\n", hdr.class_code, hdr.subclass, hdr.prog_if, bus, device, function, (uint32_t) hdr.interrupt_line);*/
}
}
} }
}
} }

View File

@ -2,6 +2,8 @@
#include <vga/vga.h> #include <vga/vga.h>
#include <stdio.h> #include <stdio.h>
#include <port_io.h> #include <port_io.h>
#include <new_tty.h>
#include <fs/vfs.h>
#include <tty.h> #include <tty.h>
@ -18,6 +20,19 @@ void terminal_initialize(void)
terminal_update_cursor(); terminal_update_cursor();
} }
ssize_t tty_write(struct file* f, const char* buf, size_t size)
{
/*struct tty* tty = (struct tty*)f->private_data;*/
for (size_t i = 0; i < size; i++)
{
/*tty_putchar(tty, buf[i]);*/ /* do this when we have multiple TTY outputs & stuff */
terminal_putchar(buf[i]);
}
return size;
}
void terminal_get_cursor(int* row, int* column) void terminal_get_cursor(int* row, int* column)
{ {
*row = (int) terminal_row; *row = (int) terminal_row;
@ -106,6 +121,33 @@ void terminal_putchar(const char c)
return; return;
} }
/*else if (uc == '\b')
{
if (terminal_column == 0)
{
if (terminal_row > 0)
{
terminal_row--;
terminal_column = VGA_WIDTH - 1;
}
else
{
terminal_update_cursor();
return;
}
}
else
{
terminal_column--;
}
terminal_putentryat(' ', terminal_color, terminal_column, terminal_row);
terminal_update_cursor();
return;
}*/
else if (uc == '\b') else if (uc == '\b')
{ {
if (terminal_column == 0) if (terminal_column == 0)
@ -117,7 +159,7 @@ void terminal_putchar(const char c)
} }
else else
{ {
terminal_update_cursor(); /* For good measure */ terminal_update_cursor();
return; return;
} }
@ -127,8 +169,6 @@ void terminal_putchar(const char c)
terminal_column--; terminal_column--;
} }
terminal_putentryat(' ', terminal_color, terminal_column, terminal_row);
terminal_update_cursor(); terminal_update_cursor();
return; return;

BIN
espresso.img Normal file

Binary file not shown.

View File

@ -1,177 +0,0 @@
#include <stdio.h>
#include <port_io.h>
#include <drivers/irq.h>
#include <drivers/idt.h>
#define IDT_MAX_DESCRIPTORS 256
#define PIC1_COMMAND 0x20
#define PIC1_DATA 0x21
#define PIC2_COMMAND 0xA0
#define PIC2_DATA 0xA1
/*
Most of the code is this file (and idt.h) are taken from the osdev wiki: https://wiki.osdev.org/Interrupts_Tutorial, though not all of it.
*/
typedef struct {
uint16_t isr_low; // The lower 16 bits of the ISR's address
uint16_t kernel_cs; // The GDT segment selector that the CPU will load into CS before calling the ISR
uint8_t reserved; // Set to zero
uint8_t attributes; // Type and attributes; see the IDT page
uint16_t isr_high; // The higher 16 bits of the ISR's address
} __attribute__((packed)) idt_entry_t;
typedef struct {
uint16_t limit;
uint32_t base;
} __attribute__((packed)) idtr_t;
__attribute__((aligned(0x10)))
static idt_entry_t idt[256]; // Create an array of IDT entries; aligned for performance
static idtr_t idtr;
static bool vectors[IDT_MAX_DESCRIPTORS];
extern void* isr_stub_table[];
void idt_init(void)
{
idtr.base = (uintptr_t)&idt[0];
idtr.limit = (uint16_t)sizeof(idt_entry_t) * IDT_MAX_DESCRIPTORS - 1;
for (uint8_t vector = 0; vector < 32; vector++)
{
idt_set_descriptor(vector, isr_stub_table[vector], 0x8E);
vectors[vector] = true;
}
extern void* irq_stub_table[];
for (uint8_t i = 0; i < 16; i++)
{
idt_set_descriptor(32 + i, irq_stub_table[i], 0x8E);
}
asm volatile ("lidt %0" : : "m"(idtr)); /* load the new IDT */
asm volatile ("sti"); /* set the interrupt flag */
}
void interrupt_dispatcher(registers_t* regs)
{
if (regs->int_no < 32)
{
exception_handler(regs);
}
else if (regs->int_no < 48)
{
uint32_t irq = regs->int_no - 32;
irq_handler(irq, regs);
if (irq >= 8)
{
outb(0xA0, 0x20); /* acknowledge the IRQ to slave PIC */
}
outb(0x20, 0x20); /* acknowledge the IRQ to master PIC */
}
}
__noreturn
void exception_handler(registers_t* regs)
{
uint32_t int_no = regs->int_no;
uint32_t err_code = regs->err_code;
switch (int_no)
{
case 0:
printf("Divide by zero exception (or other division error)\n");
break;
case 2:
printf("NMI encountered\n");
break;
case 6: /* XXX: NOTE: this can be used to emulate instructions that do not exist on the current CPU :NOTE :XXX */
printf("Invalid opcode encountered\n");
break;
case 7: /* XXX: NOTE: use this for FPU emulation and for saving/restoring FPU registers in a multiprocessing enviroment :NOTE :XXX */
printf("FPU instructions used, but FPU is nonexistant/disabled\n");
break;
case 13:
printf("General Protection Fault: err=0x%x at %p\n", err_code, regs->eip);
break;
case 14:
{
uint32_t cr2;
asm volatile ("mov %%cr2, %0" : "=r"(cr2));
printf("Page Fault at address: 0x%x, err=0x%x\n", cr2, err_code);
break;
}
default:
printf("Unhandled exception #%u, err=0x%x at %p\n", int_no, err_code, regs->eip);
break;
}
uint16_t cs, ds, es, ss;
asm volatile ("mov %%cs, %0" : "=r"(cs));
asm volatile ("mov %%ds, %0" : "=r"(ds));
asm volatile ("mov %%es, %0" : "=r"(es));
asm volatile ("mov %%ss, %0" : "=r"(ss));
printf("CS=0x%04x DS=0x%04x ES=0x%04x SS=0x%04x\n", cs, ds, es, ss);
asm volatile ("cli; hlt");
/* Will never be reached */
while (true)
{
asm volatile ("hlt" ::: "memory");
}
}
void idt_set_descriptor(uint8_t vector, void* isr, uint8_t flags)
{
idt_entry_t* descriptor = &idt[vector];
descriptor->isr_low = (uint32_t) isr & 0xFFFF;
descriptor->kernel_cs = 0x08;
descriptor->attributes = flags;
descriptor->isr_high = (uint32_t) isr >> 16;
descriptor->reserved = 0;
}
void pic_remap(void)
{
uint8_t a1, a2;
/* save masks */
a1 = inb(PIC1_DATA);
a2 = inb(PIC2_DATA);
/* start initialization sequence (in cascade mode) */
outb(PIC1_COMMAND, 0x11);
outb(PIC2_COMMAND, 0x11);
/* set vector offset */
outb(PIC1_DATA, 0x20); /* IRQs 0-7 mapped to IDT entries 0x20-0x27 (3239) */
outb(PIC2_DATA, 0x28); /* IRQs 8-15 mapped to IDT entries 0x28-0x2F (4047) */
/* tell the master PIC about Slave PIC at IRQ2 (0000 0100) */
outb(PIC1_DATA, 0x04);
/* tell the slave PIC its cascade identity (0000 0010) */
outb(PIC2_DATA, 0x02);
/* set 8086/88 mode */
outb(PIC1_DATA, 0x01);
outb(PIC2_DATA, 0x01);
/* restore saved masks */
outb(PIC1_DATA, a1);
outb(PIC2_DATA, a2);
}

View File

@ -1,18 +0,0 @@
#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_handler(registers_t* regs);
#endif

View File

@ -1,69 +0,0 @@
#include <stdio.h>
#include <drivers/ps2_keyboard.h>
#include <drivers/pit.h>
#include <port_io.h>
#include <drivers/irq.h>
#define MAX_IRQ_HANDLERS 128 /* the maximum number of irq handlers */
typedef struct {
uint32_t irq_no;
irq_func_t func;
} irq_handler_t;
uint32_t num_irq_handlers = 0;
irq_handler_t handler_list[MAX_IRQ_HANDLERS];
static volatile uint32_t num_irqs_missed = 0;
void irq_init(void)
{
for (int i = 0; i < MAX_IRQ_HANDLERS; i++)
{
handler_list[i].irq_no = 0;
handler_list[i].func = NULL;
}
set_irq_handler(0, (irq_func_t) pit_handler);
set_irq_handler(1, (irq_func_t) ps2_keyboard_handler);
}
void irq_handler(uint32_t irq, registers_t* regs)
{
uint8_t funcs_called = 0;
if (num_irq_handlers > 0)
{
for (unsigned int i = 0; i < num_irq_handlers; i++)
{
if (handler_list[i].irq_no == irq && handler_list[i].func != NULL)
{
handler_list[i].func(regs);
funcs_called++;
/* PIC IRQ acknowledgement happens in idt.c */
}
}
}
if (funcs_called == 0)
{
num_irqs_missed++;
}
}
uint32_t get_interrupts_missed(void)
{
return num_irqs_missed;
}
void set_irq_handler(uint32_t num, irq_func_t handler)
{
if (num < MAX_IRQ_HANDLERS)
{
handler_list[num].irq_no = num;
handler_list[num].func = handler;
num_irq_handlers++;
}
}

View File

@ -1,43 +0,0 @@
#ifndef _IRQ_H
#define _IRQ_H
#include <types.h>
/*
typedef struct registers {
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, cs, eflags;
} registers_t;
*/
typedef struct {
uint32_t ds, es, fs, gs;
uint32_t eax, ecx, edx, ebx;
uint32_t esp, ebp, esi, edi;
uint32_t int_no;
uint32_t err_code;
uint32_t eip, cs, eflags;
} registers_t;
typedef void (*irq_func_t)(registers_t*);
void irq_init(void);
void 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);*/
uint32_t get_interrupts_missed(void);
#endif

View File

@ -1,154 +0,0 @@
[BITS 32]
[GLOBAL isr_stub_table]
[GLOBAL irq_stub_table]
[GLOBAL interrupt_entry]
extern interrupt_dispatcher
section .text
; ============================================================
; COMMON INTERRUPT ENTRY
; ============================================================
interrupt_entry:
; Stack already contains:
; err_code
; int_no
; eip
; cs
; eflags
pusha ; eax, ecx, edx, ebx, esp, ebp, esi, edi
;push ds
;push es
;push fs
;push gs
push gs
push fs
push es
push ds
mov ax, 0x10 ; load kernel data selector
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
push esp ; pass pointer to registers_t
call interrupt_dispatcher
add esp, 4
pop gs
pop fs
pop es
pop ds
popa
add esp, 8 ; remove int_no + err_code
iret
; ============================================================
; IRQ STUBS
; ============================================================
%macro IRQ 1
irq_stub_%+%1:
push dword 0 ; fake error code
push dword (32 + %1) ; vector number
jmp interrupt_entry
%endmacro
IRQ 0
IRQ 1
IRQ 2
IRQ 3
IRQ 4
IRQ 5
IRQ 6
IRQ 7
IRQ 8
IRQ 9
IRQ 10
IRQ 11
IRQ 12
IRQ 13
IRQ 14
IRQ 15
irq_stub_table:
%assign i 0
%rep 16
dd irq_stub_%+i
%assign i i+1
%endrep
; ============================================================
; EXCEPTION STUBS
; ============================================================
%macro ISR_NOERR 1
isr_stub_%+%1:
push dword 0 ; fake error code
push dword %1 ; interrupt number
jmp interrupt_entry
%endmacro
%macro ISR_ERR 1
isr_stub_%+%1:
push dword %1 ; interrupt number
jmp interrupt_entry
%endmacro
; Exceptions 031
ISR_NOERR 0
ISR_NOERR 1
ISR_NOERR 2
ISR_NOERR 3
ISR_NOERR 4
ISR_NOERR 5
ISR_NOERR 6
ISR_NOERR 7
ISR_ERR 8
ISR_NOERR 9
ISR_ERR 10
ISR_ERR 11
ISR_ERR 12
ISR_ERR 13
ISR_ERR 14
ISR_NOERR 15
ISR_NOERR 16
ISR_ERR 17
ISR_NOERR 18
ISR_NOERR 19
ISR_NOERR 20
ISR_NOERR 21
ISR_NOERR 22
ISR_NOERR 23
ISR_NOERR 24
ISR_NOERR 25
ISR_NOERR 26
ISR_NOERR 27
ISR_NOERR 28
ISR_NOERR 29
ISR_ERR 30
ISR_NOERR 31
isr_stub_table:
%assign i 0
%rep 32
dd isr_stub_%+i
%assign i i+1
%endrep

View File

@ -1,164 +0,0 @@
/* Check if the compiler thinks you are targeting the wrong operating system. */
#if defined(__linux__)
#error "You are not using a cross-compiler, you will most certainly run into trouble"
#endif
/* This tutorial will only work for the 32-bit ix86 targets. */
#if !defined(__i386__)
#error "This kernel needs to be compiled with a ix86-elf compiler"
#endif
#include <types.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <kernel/boot.h>
#include <kernel/kshell.h>
#include <kdebug.h>
#include <gdt.h>
#include <drivers/idt.h>
#include <drivers/irq.h>
#include <scheduler.h>
#include <multiboot.h>
#include <drivers/pci.h>
#include <drivers/ps2_keyboard.h>
#include <drivers/pit.h>
/*#include <drivers/ahci.h>*/
#include <drivers/ide.h>
#include <mm/mm.h>
#include <fs/fat32.h>
/*#include <fs/duckfs.h>*/
#include <fs/vfs.h>
#include <fs/sfs.h>
#include <vector_extensions/sse.h>
#include <kernel/intro.h>
#include <builtin_games/miner.h>
#include <fs/ssfs.h>
extern void _hang_asm(void);
extern void _sti_asm(void);
void idle_task(void)
{
while (1)
asm volatile("hlt");
}
void kernel_main(multiboot_info_t* mbd, uint32_t magic)
{
/* --- BEGIN INITIALIZATION SECTION --- */
/* We need to initialize the terminal so that any error/debugging messages show. */
terminal_initialize();
printf("Loading Espresso %s... ", KERNEL_VERSION);
#ifdef _DEBUG
printf("[ DEBUG BUILD ]");
#endif
printf("\n");
terminal_setcolor(VGA_COLOR_RED);
/* Make sure the magic number matches for memory mapping */
if(magic != MULTIBOOT_BOOTLOADER_MAGIC)
{
printf("[ ERROR ] invalid magic number!\n");
_hang_asm();
}
/* Check bit 6 to see if we have a valid memory map */
if(!(mbd->flags >> 6 & 0x1))
{
printf("[ ERROR ] invalid memory map given by GRUB bootloader\n");
_hang_asm();
}
gdt_install(false);
pic_remap(); /* must be done before idt_init() */
idt_init();
_sti_asm();
irq_init(); /* MUST be done after pic_remap() and idt_init() */
terminal_setcolor(VGA_COLOR_GREEN);
pmm_init(mbd);
paging_init();
heap_init(0xC2000000, 0x80000);
#ifdef _DEBUG
printd("Testing SSE...\n");
#endif
int32_t sse_test_result = test_sse();
if (sse_test_result != 0)
{
printf("[ SSE ] SSE test failed with RV %d\n", sse_test_result);
}
else
{
#ifdef _DEBUG
printd("SSE test passed\n");
#endif
}
pit_init();
keyboard_init();
ide_initialize();
pci_init();
scheduler_init();
/* --- END INITIALIZATION SECTION --- */
terminal_setcolor(VGA_COLOR_LIGHT_GREEN);
printf("Guten tag and welcome to Espresso %s\n", KERNEL_VERSION);
//terminal_clear();
create_task(kshell_start);
create_task(idle_task);
extern task_t* task_list;
extern task_t* current_task;
current_task = task_list;
printf("in kernel_main\n");
/*extern void terminal_clear(void);
terminal_clear();
kshell_start(1, NULL);*/
for(;;) /* Loop infinitely. We only do something when an interrupt/syscall happens now. */
{
asm volatile("hlt" ::: "memory");
}
}

View File

@ -1,62 +0,0 @@
#include <types.h>
#include <port_io.h>
#include <stdio.h>
#include <scheduler.h>
#include <drivers/pit.h>
#define PIT_CHANNEL0 0x40
#define PIT_COMMAND 0x43
#define PIT_IRQ_LINE 0
#define PIT_FREQUENCY_BASE 1193182
volatile uint64_t pit_ticks = 0;
bool pit_initialized = false;
void pit_init(void)
{
#ifdef _DEBUG
printf("[ PIT ] Initializing the PIT...\n");
#endif
uint16_t divisor = (uint16_t) 1193;
/* Send command byte */
outb(PIT_COMMAND, 0x36); /* Channel 0, low/high byte, mode 3 (square wave), binary */
/* Send divisor low and high byte */
outb(PIT_CHANNEL0, (uint8_t)(divisor & 0xFF)); /* Low byte */
outb(PIT_CHANNEL0, (uint8_t)((divisor >> 8) & 0xFF)); /* High byte */
pit_initialized = true;
#ifdef _DEBUG
printf("[ PIT ] PIT Initialized\n");
#endif
}
void pit_handler(void)
{
pit_ticks++;
}
/*void pit_sleep(uint64_t ms)
{
uint64_t target = pit_ticks + ms;
while (pit_ticks < target)
{
asm volatile ("hlt");
}
}*/
void pit_sleep(uint64_t ms)
{
extern task_t* current_task;
current_task->wakeup_tick = pit_ticks + ms;
current_task->state = TASK_SLEEPING;
asm volatile("int $32"); /* force reschedule immediately */
}

View File

@ -1,158 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include <drivers/irq.h>
#include <scheduler.h>
#define STACK_SIZE 4096
task_t* task_list = NULL;
task_t* current_task = NULL;
uint32_t next_task_id = 1;
static void schedule(void);
/* scheduler init */
void scheduler_init(void)
{
set_irq_handler(0, (irq_func_t) scheduler_tick);
}
static void schedule(void)
{
if (!task_list)
{
return;
}
/* wake sleeping tasks */
task_t* t = task_list;
extern uint64_t pit_ticks;
do
{
if (t->state == TASK_SLEEPING && pit_ticks >= t->wakeup_tick)
{
t->state = TASK_READY;
}
t = t->next;
}
while (t != task_list);
/* find next ready task */
task_t* start = current_task;
do
{
current_task = current_task->next;
if (current_task->state == TASK_READY)
{
return;
}
}
while (current_task != start);
}
/* tick handler */
void scheduler_tick(registers_t* regs)
{
if (!task_list)
{
printf("!task_list\n");
return;
}
if (!current_task)
{
printf("!current_task\n");
current_task = task_list;
}
/* save current task state */
*(current_task->regs) = *regs;
/* pick next */
schedule();
/* load next task state */
*regs = *(current_task->regs);
}
/* task creation */
task_t* create_task(void (*entry)())
{
task_t* task = malloc(sizeof(task_t));
if (!task)
{
return NULL;
}
memset(task, 0, sizeof(task_t));
/* allocate stack */
uint8_t* stack = malloc(STACK_SIZE);
if (!stack)
{
free(task);
return NULL;
}
printf("Creating task %i @ %p\n", next_task_id, entry);
/*
align stack to 16 bytes for safety (SSE friendly).
stack grows downward.
*/
uintptr_t stack_top = (uintptr_t)(stack + STACK_SIZE);
stack_top &= ~0xF;
registers_t* regs = (registers_t*) (stack_top - sizeof(registers_t));
memset(regs, 0, sizeof(registers_t));
/* initialize register frame */
regs->eip = (uint32_t) entry;
regs->cs = 0x08; /* Kernel code segment */
regs->eflags = 0x202; /* IF=1 */
task->id = next_task_id++;
task->regs = regs;
task->stack_base = (uint32_t*) stack;
task->state = TASK_READY;
/* insert into circular list */
if (!task_list)
{
task_list = task;
task->next = task;
}
else
{
task_t* last = task_list;
while (last->next != task_list)
{
last = last->next;
}
last->next = task;
task->next = task_list;
}
printf("Task %i @ %p created successfully\n", next_task_id - 1, entry);
return task;
}
/* task destruction */
void destroy_task(task_t* task)
{
free(task->stack_base);
free(task);
}

View File

@ -1,32 +0,0 @@
#ifndef _SCHEDULER_H
#define _SCHEDULER_H
#include <drivers/irq.h>
#include <types.h>
typedef enum {
TASK_READY,
TASK_RUNNING,
TASK_SLEEPING,
TASK_BLOCKED,
TASK_TERMINATED,
} task_state_t;
typedef struct task {
uint32_t id;
registers_t* regs; /* pointer to saved register frame */
uint32_t* stack_base; /* original malloc() pointer */
task_state_t state;
struct task* next;
uint64_t wakeup_tick;
} task_t;
void scheduler_init(void);
task_t* create_task(void (*entry)());
void scheduler_tick(registers_t* regs);
#endif

View File

@ -1,4 +1,9 @@
set gfxmode=1024x768x32
set gfxpayload=keep
terminal_output gfxterm
menuentry "Espresso" { menuentry "Espresso" {
multiboot /boot/espresso.elf multiboot /boot/espresso.elf
boot
} }

View File

@ -36,12 +36,13 @@ typedef struct {
uint32_t p_align; uint32_t p_align;
} Elf32_Phdr; } Elf32_Phdr;
//typedef int (*elf_entry_t)(int, char**);
typedef int (*elf_entry_t)(void); typedef int (*elf_entry_t)(void);
typedef struct { typedef struct {
elf_entry_t entry_point; elf_entry_t entry_point;
} elf_executable_t; } elf_executable_t;
elf_executable_t* load_elf32(void* elf_data); int load_elf32(void* elf_data, elf_executable_t** ptr);
#endif #endif

View File

@ -0,0 +1,26 @@
#ifndef _VGA_GRAPHICS_H
#define _VGA_GRAPHICS_H
#include <types.h>
struct bga_framebuffer
{
volatile uint8_t* addr;
uint32_t width;
uint32_t height;
uint32_t pitch; /* bytes per scanline */
uint32_t bpp;
};
void bga_defaults(void);
void bga_set_video_mode(uint32_t width, uint32_t height, uint32_t bit_depth);
void bga_putpixel(uint32_t x, uint32_t y, uint32_t color);
void bga_drawline(int x0, int y0, int x1, int y1, uint32_t color);
#endif

View File

@ -44,4 +44,6 @@ int32_t ide_write48(uint8_t drive, uint64_t lba, uint8_t sector_count, const voi
int32_t read_sector(uint64_t lba, void* buffer); int32_t read_sector(uint64_t lba, void* buffer);
int32_t write_sector(uint64_t lba, const void* buffer); int32_t write_sector(uint64_t lba, const void* buffer);
int get_sector_size(uint8_t drive);
#endif #endif

View File

@ -1,37 +0,0 @@
//#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

View File

@ -4,7 +4,32 @@
#include <types.h> #include <types.h>
#define MAX_FDS 64
struct file;
struct inode {
size_t size;
int permissions;
/* | | */
/* \/ FS-specific \/ */
union {
void* fs_data;
void* private_data;
};
};
struct file_ops {
int (*read)(struct file*, char*, size_t);
int (*write)(struct file*, const char*, size_t);
};
struct file {
struct inode* f_inode;
size_t f_offset;
size_t f_refcount;
const struct file_ops* f_ops;
};
#endif #endif

View File

@ -13,5 +13,7 @@ static inline int div_round_up(int a, int b)
return (a + b - 1) / b; return (a + b - 1) / b;
} }
int abs(int x);
#endif #endif

View File

@ -4,11 +4,14 @@
#include <types.h> #include <types.h>
#include <fs/vfs.h>
#include <processes.h> #include <processes.h>
#include <sync.h> #include <sync.h>
#define TTY_BUFFER_SIZE 4096 #define TTY_BUFFER_SIZE 4096
#define TTY_RAW_BUFFER_SIZE 16
#define MAX_TTYS 8 /* to make things easy, might change later */ #define MAX_TTYS 8 /* to make things easy, might change later */
#define TTY_ECHO 0x10 /* 0b00010000 */ #define TTY_ECHO 0x10 /* 0b00010000 */
@ -16,7 +19,9 @@
#define TTY_ACTIVE 0x01 /* 0b00000001 */ #define TTY_ACTIVE 0x01 /* 0b00000001 */
#define TTY_CANONICAL 0x40 /* 0b01000000 */ #define TTY_CANONICAL 0x40 /* 0b01000000 */
#define TTY_RAW 0x04 /* 0b00000100 */
#define TTY_ADDCHAR_ALWAYS 0x02 /* 0b00000010 */
#define TTY_NULL 0x80 /* 0b10000000 --- used to end the list of tty_t structs in the ttys array */ #define TTY_NULL 0x80 /* 0b10000000 --- used to end the list of tty_t structs in the ttys array */
@ -44,8 +49,18 @@ typedef struct tty_t {
bool canonical; bool canonical;
bool line_ready; bool line_ready;
/* for raw mode */
char raw_buf[TTY_RAW_BUFFER_SIZE];
size_t raw_head;
size_t raw_tail;
spinlock_t lock; spinlock_t lock;
size_t user_input_start;
size_t user_input_end;
struct file_ops f_ops;
pid_t foreground_pgid; /* not used yet */ pid_t foreground_pgid; /* not used yet */
} tty_t; } tty_t;
@ -60,9 +75,14 @@ int init_tty(void);
ssize_t tty_read(tty_t* tty, char* buf, size_t count); ssize_t tty_read(tty_t* tty, char* buf, size_t count);
ssize_t tty_read_active(char* buf, size_t count); ssize_t tty_read_active(char* buf, size_t count);
char tty_get_char(void);
tty_t* get_active_tty(void); tty_t* get_active_tty(void);
tty_t* tty_get_active(void); tty_t* tty_get_active(void);
void tty_and_flags(tty_t* tty, uint32_t flags);
uint32_t tty_get_flags(tty_t* tty);
tty_t* make_tty(uint32_t flags); tty_t* make_tty(uint32_t flags);
void tty_receive_char(char c, uint32_t kbd_mod); void tty_receive_char(char c, uint32_t kbd_mod);

View File

@ -10,11 +10,23 @@ static inline uint32_t inl(uint16_t port)
return rv; return rv;
} }
static inline uint16_t inw(uint16_t port)
{
uint16_t rv;
asm volatile ("inw %%dx, %%ax" : "=a" (rv) : "dN" (port));
return rv;
}
static inline __attribute__((always_inline)) void outl(uint16_t port, uint32_t data) static inline __attribute__((always_inline)) void outl(uint16_t port, uint32_t data)
{ {
asm volatile ("outl %%eax, %%dx" : : "dN" (port), "a" (data)); asm volatile ("outl %%eax, %%dx" : : "dN" (port), "a" (data));
} }
static inline __attribute__((always_inline)) void outw(uint16_t port, uint16_t val)
{
asm volatile ( "outw %0, %1" : : "a"(val), "Nd"(port) : "memory");
}
static inline __attribute__((always_inline)) void outb(uint16_t port, uint8_t val) static inline __attribute__((always_inline)) void outb(uint16_t port, uint8_t val)
{ {
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) : "memory"); asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) : "memory");

View File

@ -17,11 +17,6 @@ char* strdup(const char* s);
char* strtok(char* str, const char* delim); char* strtok(char* str, const char* delim);
char* strchr(const char* s, int c); char* strchr(const char* s, int c);
/* 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 lowers(char* str);
void uppers(char* str); void uppers(char* str);
@ -35,4 +30,11 @@ int atoi(const char *str);
long atol(const char *str); long atol(const char *str);
double atof(const char *str); double atof(const char *str);
/* 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);
char** split(const char* str, char delim);
void free_split(char** parts);
#endif #endif

View File

@ -37,6 +37,7 @@
#include <drivers/ps2_keyboard.h> #include <drivers/ps2_keyboard.h>
#include <drivers/keyboard.h> #include <drivers/keyboard.h>
#include <drivers/pit.h> #include <drivers/pit.h>
#include <drivers/graphics/vga.h>
/*#include <drivers/ahci.h>*/ /*#include <drivers/ahci.h>*/
#include <drivers/ide.h> #include <drivers/ide.h>
#include <mm/mm.h> #include <mm/mm.h>
@ -53,6 +54,7 @@
#include <builtin_games/miner.h> #include <builtin_games/miner.h>
extern void _hang_asm(void); extern void _hang_asm(void);
extern void _sti_asm(void); extern void _sti_asm(void);
@ -154,6 +156,9 @@ void kernel_main(multiboot_info_t* mbd, uint32_t magic)
extern void terminal_clear(void); extern void terminal_clear(void);
//bga_defaults();
terminal_clear(); terminal_clear();
kshell_start(); kshell_start();

View File

@ -21,7 +21,7 @@ const char* shell_version = "0.0.2";
char* prompt = NULL; char* prompt = NULL;
int command = -1; int command = -1;
bool _debug = true; bool _debug = false;
int execute(void); int execute(void);
@ -85,10 +85,12 @@ static char* commands[] = {
"int16test", "int16test",
"startbga",
NULL, NULL,
}; };
const int NUM_COMMANDS = 19; /* Yes, including the NULL */ const int NUM_COMMANDS = 21; /* Yes, including the NULL */
void kshell_start(void) void kshell_start(void)
{ {
@ -120,7 +122,7 @@ void kshell_start(void)
command = -1; command = -1;
if (strcmp(i, "") == 0) if (strlen(i) == 0)
{ {
continue; continue;
} }
@ -129,6 +131,9 @@ void kshell_start(void)
break; break;
} }
/*char** argv = split(i, ' ');*/
for (int j = 0; j < NUM_COMMANDS; j++) for (int j = 0; j < NUM_COMMANDS; j++)
{ {
if (strcmp(i, commands[j]) == 0) if (strcmp(i, commands[j]) == 0)
@ -171,9 +176,9 @@ void kshell_start(void)
} }
printf("\n"); printf("\n");
}
printf("C: %s; %i\n", commands[command], command); printf("C: %s; %i\n", commands[command], command);
}
execute(); execute();
@ -269,8 +274,8 @@ int execute(void)
extern uint8_t __kernel_end; extern uint8_t __kernel_end;
size_t kernel_size = (size_t)&__kernel_end - (size_t)&__kernel_start; size_t kernel_size = (size_t)&__kernel_end - (size_t)&__kernel_start;
printf("Kernel start: 0x%x\n", (&__kernel_start)); printf("Kernel start: %p\n", (&__kernel_start));
printf("Kernel end: 0x%x\n", (&__kernel_end)); printf("Kernel end: %p\n", (&__kernel_end));
printf("Kernel size (bytes): %llu\n", (uint64_t) kernel_size); printf("Kernel size (bytes): %llu\n", (uint64_t) kernel_size);
printf("Kernel size (kbytes): %llu\n", (((uint64_t) kernel_size) / 1000)); printf("Kernel size (kbytes): %llu\n", (((uint64_t) kernel_size) / 1000));
printf("Kernel size (mbytes): %f\n", (((uint64_t) kernel_size) / 1000.0) / 1000.0); printf("Kernel size (mbytes): %f\n", (((uint64_t) kernel_size) / 1000.0) / 1000.0);
@ -287,8 +292,10 @@ int execute(void)
extern uint8_t __bss_start; extern uint8_t __bss_start;
extern uint8_t __bss_end; extern uint8_t __bss_end;
printf(".text: %i\n.data: %i\n.rodata: %i\n.bss: %i\n", ((&__kernel_text_end) - (&__kernel_text_start)), ((&__kernel_data_end) - (&__kernel_data_start)), printf(".text: %i\n.data: %i\n.rodata: %i\n.bss: %i\n", ((&__kernel_text_end) - (&__kernel_text_start)),
((&__kernel_rodata_end) - (&__kernel_rodata_start)), ((&__bss_end) - (&__bss_start))); ((&__kernel_data_end) - (&__kernel_data_start)),
((&__kernel_rodata_end) - (&__kernel_rodata_start)),
((&__bss_end) - (&__bss_start)));
break; break;
} }
@ -412,7 +419,7 @@ int execute(void)
} }
case 14: case 14:
{ {
#if 0 #if 1
void taskA() { while (1) printf("A"); } void taskA() { while (1) printf("A"); }
void taskB() { while (1) printf("B"); } void taskB() { while (1) printf("B"); }
@ -516,14 +523,28 @@ int execute(void)
printf("Parsing ELF headers\n"); printf("Parsing ELF headers\n");
elf_executable_t* f = load_elf32(buffer); elf_executable_t* f = NULL;
int j = load_elf32(buffer, &f);
printf("Attempting execution of executable...\n"); if (j != 0)
{
printf("Invalid ELF file\n");
goto b_1;
}
printf("Attempting execution of executable at (%p)...\n", f->entry_point);
retv = f->entry_point(); retv = f->entry_point();
printf("\nreturn value: %i\n", retv); printf("\nreturn value: %i\n", retv);
b_1:
if (f)
{
free(f);
}
break; break;
} }
case 18: case 18:
@ -536,6 +557,17 @@ int execute(void)
printf("test ran\n"); printf("test ran\n");
break;
}
case 19:
{
extern void bga_defaults(void);
bga_defaults();
extern void bga_drawline(int, int, int, int, uint32_t);
bga_drawline(0, 0, 100, 100, 0x00FFFF00);
break; break;
} }
} }

View File

@ -2,75 +2,230 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <drivers/ps2_keyboard.h>
#include <new_tty.h>
#include <builtin_games/miner.h> #include <builtin_games/miner.h>
#define PLAYER '@'
#define SHOP '$'
#define STONE '#'
#define IRON ';'
#define COAL ':'
#define COPPER '^'
#define GOLD '%'
#define RUBY '*'
#define DIAMOND '~'
#define PLATINUM '&'
#define NOTHING ' '
/* /*
static const size_t VGA_WIDTH = 80; static const size_t VGA_WIDTH = 80;
static const size_t VGA_HEIGHT = 25; static const size_t VGA_HEIGHT = 25;
*/ */
/* clear screen */
void cls(void)
{
terminal_clear();
}
static bool pointer_valid(void* ptr)
{
if (ptr/* && (ptr < (heap_end + 4096))*/)
{
return true;
}
return false;
}
static inline bool valid_pointer(void* ptr)
{
return pointer_valid(ptr);
}
/*const char PLAYER = '@';
const char ENEMY = '*';
const char PLAYER_BULLET = '^';
const char ENEMY_BULLET = '`'
const char BOMB = '*';
const char EMPTY = ' ';*/
#define MAP_ROWS 25
#define MAP_COLUMNS 25
#define PLAYER_STARTING_POS (MAP_COLUMNS / 2) /* for MAP_COLUMNS being 25, this will be 12. */
#define STARTING_ENEMY_NUM 4
enum {
PLAYER = '@',
PLAYER_BULLET = '^',
ENEMY = '%',
ENEMY_BULLET = '`',
BOMB = '*',
EMPTY = ' ',
};
struct bullet {
bool players; /* if enemies, false */
int row;
int column;
};
struct game_vars {
tty_t* tty;
uint32_t stored_tty_flags;
int v;
char c;
int player_score;
int player_credits;
bool error;
int num_enemies;
int num_enemy_step;
char** map; /* char map[MAP_ROWS][MAP_COLUMNS] */
bool enemys[MAP_COLUMNS]; /* enemy bitmap */
struct bullet* bullets;
int num_bullets;
};
void init_map(struct game_vars* gv)
{
for (int i = 0; i < MAP_ROWS; i++)
{
for (int j = 0; j < MAP_COLUMNS; j++)
{
gv->map[i][j] = EMPTY;
}
}
gv->map[0][PLAYER_STARTING_POS] = PLAYER;
int enemy_pos = 0;
for (int b = 0; b < STARTING_ENEMY_NUM; b++)
{
gv->map[24][enemy_pos] = ENEMY;
enemy_pos++;
gv->num_enemies++;
gv->enemys[b] = true;
}
if (!valid_pointer(gv->map))
{
gv->error = true;
}
}
void ai(struct game_vars* gv)
{
for (int i = 0; i < MAP_COLUMNS; i++)
{
if ((gv->map[24][i] == ENEMY) && (gv->map[0][i] == PLAYER))
{
gv->map[23][i] = ENEMY_BULLET;
int num_bullets = gv->num_bullets;
gv->bullets[num_bullets].players = false;
gv->bullets[num_bullets].column = i;
gv->bullets[num_bullets].row = 23;
gv->num_bullets++;
}
}
}
void tick(struct game_vars* gv)
{
for (int i = 0; i < gv->num_bullets; i++)
{
struct bullet* b = &gv->bullets[i];
gv->map[b->row][b->column] = EMPTY;
b->column++;
b->row++;
gv->map[b->row][b->column] = b->players ? PLAYER_BULLET : ENEMY_BULLET;
}
}
int init_game(struct game_vars* ptr)
{
if (ptr)
{
ptr->error = false;
init_map(ptr);
ptr->num_enemy_step++;
return 0;
}
return -1;
}
void miner_main(void) void miner_main(void)
{ {
terminal_clear(); #if 0
cls();
struct game_vars gv = { .tty = get_active_tty(), .stored_tty_flags = tty_get_flags(get_active_tty()),
.v = 0, .c = 0,
.player_score = 0, .player_credits = 0,
.error = false,
.num_enemies = STARTING_ENEMY_NUM, .num_enemy_step = 0,
.map = malloc(MAP_COLUMNS * MAP_ROWS),
.bullets = NULL, .num_bullets = 0,
};
memset(gv.enemys, 0, sizeof(gv.enemys));
if (!gv.map)
{
goto quit;
}
printf("gv.map = %p\n", gv.map);
gv.tty->flags |= TTY_RAW;
gv.tty->flags &= ~TTY_CANONICAL;
gv.tty->flags &= ~TTY_ECHO; /* disable echo */
printf("\n\tMiner\n\t\tMine ores to sell for money and upgrade your drone\n\n\n\t\t\tHIT ENTER TO CONTINUE, TAB TO EXIT\n"); printf("\n\tMiner\n\t\tMine ores to sell for money and upgrade your drone\n\n\n\t\t\tHIT ENTER TO CONTINUE, TAB TO EXIT\n");
char b = get_char(); /*while (gv.c != '\n' && gv.c != '\t')
while (b != '\n' && b != '\t')
{ {
sleep(10); gv.c = getchar();
b = get_char();
} }
if (b == '\t') if (gv.c == '\t')
{ {
return; goto quit;
} }
uint16_t c = 0x0; cls();*/
terminal_clear(); while (1)
while (true)
{ {
sleep(10); gv.c = getchar();
c = get_key(); if (gv.c == '\t')
if (c == 0xFFFA || c == 0x0)
{ {
continue; goto quit;
} }
break; sleep(500);
} }
b = getchar(); quit:
while (b == 0x5) gv.tty->flags = gv.stored_tty_flags;
if (gv.map && pointer_valid(gv.map))
{ {
sleep(10); free(gv.map);
b = getchar();
} }
terminal_clear(); cls();
printf("Goodbye!\n");
sleep(2000);
cls();
#endif
} }

View File

@ -35,3 +35,9 @@ uint64_t int_pow(uint64_t base, uint32_t exp)
return result; return result;
} }
int abs(int x)
{
return (x < 0) ? -x : x;
}

View File

@ -1,7 +1,8 @@
#include <drivers/ps2_keyboard.h> #include <types.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <drivers/ps2_keyboard.h>
#include <kernel/syscall.h> #include <kernel/syscall.h>
#include <tty.h> #include <tty.h>
@ -13,7 +14,7 @@ int write(uint32_t fd, void* data, size_t len)
{ {
if (fd == STDOUT) if (fd == STDOUT)
{ {
print_uint((uint32_t) len); /*print_uint((uint32_t) len);*/
terminal_write((char*) data, len); terminal_write((char*) data, len);
} }
else else
@ -30,8 +31,14 @@ int read(uint32_t fd, void* data, size_t max_len)
if (fd == STDIN) if (fd == STDIN)
{ {
char* sptr = (char*) data; /* this really shouldn't be needed... */ char* rd = gets_new(&rv);
sptr = gets_new(&rv); size_t sz = strlen(rd);
memcpy(data, rd, (sz < max_len) ? sz : max_len);
if (!rd)
{
printf("rd is NULL!\n");
}
} }
else else
{ {
@ -45,12 +52,7 @@ extern bool ps2keyboard_initialized;
char getchar(void) char getchar(void)
{ {
if (ps2keyboard_initialized) return tty_get_char();
{
return get_char();
}
return '\0';
} }
char* getstring(void) char* getstring(void)
@ -92,6 +94,8 @@ int getstr(char* dest)
} }
strcpy(dest, p); strcpy(dest, p);
return 0;
} }
void putc(char c) void putc(char c)

View File

@ -492,3 +492,78 @@ void strlnstripip(char* s)
s[len-1] = '\0'; s[len-1] = '\0';
} }
} }
char** split(const char* str, char delim)
{
if (!str)
{
return NULL;
}
size_t count = 1;
for (const char* p = str; *p; p++)
{
if (*p == delim)
{
count++;
}
}
char** result = malloc((count + 1) * sizeof(char*));
if (!result)
{
return NULL;
}
size_t idx = 0;
const char* start = str;
for (const char* p = str; ; p++)
{
if (*p == delim || *p == '\0')
{
size_t len = p - start;
char* token = malloc(len + 1);
if (!token)
{
return NULL;
}
for (size_t i = 0; i < len; i++)
{
token[i] = start[i];
}
token[len] = '\0';
result[idx++] = token;
start = p + 1;
if (*p == '\0')
{
break;
}
}
}
result[idx] = NULL; /* null-terminate the array */
return result;
}
void free_split(char** parts)
{
if (!parts)
{
return;
}
for (int i = 0; parts[i] != NULL; i++)
{
free(parts[i]);
}
free(parts);
}

Binary file not shown.

View File

@ -28,7 +28,8 @@ int main(void)
{ {
writestring("command: "); writestring("command: ");
char* istr; char istr[128];
memset(istr, 0, sizeof(istr));
int rv = getstring(istr); int rv = getstring(istr);
@ -38,7 +39,7 @@ int main(void)
break; break;
} }
if (rv != 0) if (rv < 0)
{ {
writestring("\nERROR: getstring did not return 0\n"); writestring("\nERROR: getstring did not return 0\n");
break; break;
@ -54,6 +55,10 @@ int main(void)
writestring("you entered: "); writestring("you entered: ");
writestring(istr); writestring(istr);
writestring("len: ");
print_uint((uint32_t) len);
writestring("\nfirst char: ");
writechar(*istr);
writestring(" ASCII -> "); writestring(" ASCII -> ");