summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan McFarlane <i.mcfarlane2002@gmail.com>2025-05-06 15:14:11 -0400
committerIan McFarlane <i.mcfarlane2002@gmail.com>2025-05-06 15:14:11 -0400
commitda396afa8b612b8f8ff07d71c57761a627b158eb (patch)
treeb4935b29aca686c6ee17a583cffe149d7bb3c819
parentupdate forkman with spinlock (diff)
parentstart docs (diff)
downloadcomus-forkman.tar.gz
comus-forkman.tar.bz2
comus-forkman.zip
merge main into forkmanforkman
-rw-r--r--Makefile4
-rw-r--r--config/grub.cfg2
-rw-r--r--docs/DRIVERS.md47
-rw-r--r--docs/FS.md0
-rw-r--r--docs/HEADERS.md0
-rw-r--r--docs/MEMORY.md0
-rw-r--r--docs/MODULES.md109
-rw-r--r--docs/PCB.md53
-rw-r--r--kernel/cpu/idt.c9
-rw-r--r--kernel/drivers.c2
-rw-r--r--kernel/drivers/pit.c62
-rw-r--r--kernel/drivers/ps2.c15
-rw-r--r--kernel/efi/gop.c4
-rw-r--r--kernel/fs/fs.c21
-rw-r--r--kernel/fs/ramfs.c171
-rw-r--r--kernel/fs/tar.c306
-rw-r--r--kernel/include/comus/drivers/pit.h14
-rw-r--r--kernel/include/comus/drivers/ps2.h13
-rw-r--r--kernel/include/comus/drivers/spkr.h29
-rw-r--r--kernel/include/comus/fs.h17
-rw-r--r--kernel/include/comus/fs/tar.h18
-rw-r--r--kernel/include/comus/limits.h6
-rw-r--r--kernel/include/comus/mboot.h10
-rw-r--r--kernel/include/comus/procs.h4
-rw-r--r--kernel/include/comus/ramfs.h40
-rw-r--r--kernel/include/comus/syscalls.h9
-rw-r--r--kernel/include/comus/tar.h6
-rw-r--r--kernel/include/comus/user.h4
-rw-r--r--kernel/include/lib/klib.h5
-rw-r--r--kernel/lib/backtrace.c5
-rw-r--r--kernel/lib/kalloc.c144
-rw-r--r--kernel/lib/panic.c15
-rw-r--r--kernel/main.c46
-rw-r--r--kernel/mboot/mboot.c19
-rw-r--r--kernel/mboot/module.c42
-rw-r--r--kernel/memory/paging.c150
-rw-r--r--kernel/memory/physalloc.c45
-rw-r--r--kernel/memory/virtalloc.c56
-rw-r--r--kernel/memory/virtalloc.h2
-rw-r--r--kernel/procs.c2
-rw-r--r--kernel/syscall.c211
-rw-r--r--kernel/term.c26
-rw-r--r--kernel/user.c136
-rw-r--r--user/include/stdio.h6
-rw-r--r--user/include/sys/types.h15
-rw-r--r--user/include/unistd.h14
-rw-r--r--user/init.c115
-rw-r--r--user/lib/entry.S5
-rw-r--r--user/lib/fclose.c10
-rw-r--r--user/lib/fseek.c16
-rw-r--r--user/lib/syscall.S3
51 files changed, 1711 insertions, 352 deletions
diff --git a/Makefile b/Makefile
index 54fa441..2b78eb6 100644
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,8 @@ GRUB ?= grub-mkrescue
QEMUOPTS += -cdrom $(BIN)/$(ISO) \
-no-reboot \
- -drive format=raw,file=user/bin/forkman \
+ -drive format=raw,file=user/bin/initrd.tar \
+ -audiodev pa,id=speaker -machine pcspk-audiodev=speaker \
-serial mon:stdio \
-m 4G \
-name kern
@@ -55,5 +56,6 @@ $(BIN)/$(ISO): build config/grub.cfg
mkdir -p $(BIN)/iso/boot/grub
cp config/grub.cfg $(BIN)/iso/boot/grub
cp kernel/bin/kernel $(BIN)/iso/boot
+ cp user/bin/initrd.tar $(BIN)/iso/boot
$(GRUB) -o $(BIN)/$(ISO) bin/iso 2>/dev/null
diff --git a/config/grub.cfg b/config/grub.cfg
index 62c9792..13c5167 100644
--- a/config/grub.cfg
+++ b/config/grub.cfg
@@ -4,5 +4,5 @@ insmod all_video
menuentry "kern" {
multiboot2 /boot/kernel
- boot
+ module2 /boot/initrd.tar
}
diff --git a/docs/DRIVERS.md b/docs/DRIVERS.md
new file mode 100644
index 0000000..e17e15e
--- /dev/null
+++ b/docs/DRIVERS.md
@@ -0,0 +1,47 @@
+# Drivers
+
+All drivers and their uses
+
+## acpi.c
+
+ACPI (Advanced Configuration and Power Interface)
+- allows powering off the system
+
+## ata.c
+
+ATA (Advanced Technology Attachment) / IDE (Integrated Drive Electronics)
+- ide/ata disk device driver
+
+## clock.c
+
+COMS real time clock driver
+
+## gpu/
+
+Contains drivers for each type of gpu
+- Bochs (QEMU default gpu device)
+- GOP (Graphics Output Protocol), UEFI framebuffer
+
+## gpu.c
+
+Functions for abstracting over current loaded gpu
+
+## pci.c
+
+PCI (Peripheral Component Interconnect)
+- driver to load pci devices (not pcie)
+
+## pit.c
+
+PIT (Programmable Interval Timer)
+- sends timer interrupts to the pic
+- set pc speaker tones
+
+## ps2.c
+
+PS2 Controller / Keyboard / Mouse driver
+- allows keyboard / mouse input
+
+## uart.c
+
+Serial (UART) driver
diff --git a/docs/FS.md b/docs/FS.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/docs/FS.md
diff --git a/docs/HEADERS.md b/docs/HEADERS.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/docs/HEADERS.md
diff --git a/docs/MEMORY.md b/docs/MEMORY.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/docs/MEMORY.md
diff --git a/docs/MODULES.md b/docs/MODULES.md
new file mode 100644
index 0000000..cf452ff
--- /dev/null
+++ b/docs/MODULES.md
@@ -0,0 +1,109 @@
+# modules
+
+list of all kernel modules and their functions
+
+## cpu/
+
+Initalizes all cpu components and low level tabels.
+- FPU / SSE / AVX
+- IDT (Interrupt Descriptor Table)
+- PIC (Programmable Interrupt Controller)
+- TSS (Task State Segment)
+ - used for allowing kernel to switch into ring 3
+ - used for setting kernel stack on interrupt
+
+## drivers/
+
+Folder `drivers/` contains drivers for the system. See DRIVERS.md.
+
+File `drivers.c` loads each of the drivers in `drivers/`.
+
+## efi/
+
+Load UEFI components
+- UEFI memory map
+- GOP (Graphics Output Protocol), UEFI framebuffer
+
+## entry.S
+
+Entry point into the kernel along with:
+- GDT (Global Descriptor Table)
+- Multiboot header see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html
+- Inital kernel stack
+ - not used once interrupts since interrupt stack will be used
+- Inital page tables
+ - see MEMORY.md
+
+Symbols:
+- `_start`
+ - generic legacy bios entrypoint in IA-32 mode
+
+- `_start_efi`
+ - uefi entrypoint in IA-32e mode
+
+## font/
+
+Loads psf2 font files into kernel .rodata segment
+
+## fs/
+
+See FS.md
+
+## include/
+
+All kernel headers.
+
+- SEE HEADERS.md
+
+## input.c
+
+Abstracts all input from all sources over a single keycode / mouseevent buffer.
+- uses ps2 and uart
+
+## lib/
+
+Kernel c library
+
+Notable files:
+
+- `backtrace.c` - does stack backtraces and logs them to output
+ - used during exceptions
+- `kspin.c`
+ - spinlock in kernel space
+- `panic.c`
+ - implements panic functions, along with halt called during exceptions or panic
+
+## main.c
+
+Kernel main entrypoint.
+- Loads all components of the kernel in order.
+- Loads init process
+- Dispatches init
+
+## mboot/
+
+Laod information provided by multiboot standard
+- `efi.c` - gets `EFI_SYSTEM_TABLE` & `EFI_HANDLE`
+ - read UEFI standard for more information
+- `mmap.c` - load memory map when in legacy boot
+ - memory map is loaded from `efi/` module when booting from UEFI
+- `module.c`
+ - loads initrd (ramdisk)
+- `rsdp.c`
+ - load root ACPI table, provided for the ACPI driver
+
+## memory/
+
+See MEMORY.md
+
+## procs.c
+
+Stores loaded process information and scheduler
+- multiple queues for scheduling
+ - ready - pcb is ready to be executed
+ - zombie - pcb is a zombie, and waiting to be cleaned up
+ - syscall - replaced blocked/waiting in baseline
+ - each syscall has its own queue
+ - acessed though syscall_queue[SYS_num]
+
+See PCB.md for pcb information.
diff --git a/docs/PCB.md b/docs/PCB.md
new file mode 100644
index 0000000..9eaa2a2
--- /dev/null
+++ b/docs/PCB.md
@@ -0,0 +1,53 @@
+# PCB
+
+PCB information
+
+## context
+
+Contains context infromation for the curernt process.
+- memory context (pcb->memctx)
+ - stores page directory and vitural address allocateor (see MEMORY.md)
+- context save area (pcb->regs)
+
+## medatada
+
+- `pid` - process idenfitication number
+- `parent` ` - parent of the current process
+ - can be NULL if the init process
+- `state` - the current runing state of the process
+ - `UNUSED` - proces in ptable is not used
+ - `NEW` - process in ptable has been allocated but has not been initalized
+ - `READY` - process is ready to be dispatched (and in ready queue)
+ - `RUNNING` - process is the current running process (and in no queues)
+ - `BLOCKED` - process is in a syscall queue waiting on their syscall to return
+ - `ZOMBIE` - process is a zombie and waiting to be cleaned up (in zombie queue)
+- `priority` - running process priority
+ - any number form 0 to SIZET_MAX
+ - higher priority means longer wait to be scheduled
+- `ticks` - number of ticks the process has been running for
+ - set to zero when process is not running
+
+## heap
+
+- `heap_start` is the start of the progams heap
+- `heap_len` is the length of the programs heap
+
+## open files
+
+- `open_files` is a list of currently opened files indexed by file descriptor
+
+## elf metadata
+
+- `elf_header` - the programs elf header (Elf64_Ehdr)
+- `elf_segments` - the programs loadable elf segments (Elf64_Phdr[])
+- `n_elf_segments` - the number of elf segmsnts the program has
+
+## queue linkage
+
+- `next` - the next pcb in the current queue this pcb is in
+
+## processs state information
+
+- `syscall` - the current syscall this process is blocked on
+- `wakeup` - the number of ticks until the process can be waked up (used during SYS_sleep)
+- `exit_status` - the exit status of the process when a zombie
diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c
index 7cbbb65..50e15e0 100644
--- a/kernel/cpu/idt.c
+++ b/kernel/cpu/idt.c
@@ -1,3 +1,5 @@
+#include "comus/drivers/spkr.h"
+#include "lib/klib.h"
#include <lib.h>
#include <comus/memory.h>
#include <comus/asm.h>
@@ -64,10 +66,11 @@ void idt_init(void)
uint64_t isr = (uint64_t)isr_stub_table[vector];
// interrupts before 0x20 are for cpu exceptions
+ uint64_t gate_type = (isr < 0x20) ? GATE_64BIT_TRAP : GATE_64BIT_INT;
entry->kernel_cs = 0x08; // offset of 1 into GDT
entry->ist = 0;
- entry->flags = PRESENT | RING0 | GATE_64BIT_INT;
+ entry->flags = PRESENT | RING0 | gate_type;
entry->isr_low = isr & 0xffff;
entry->isr_mid = (isr >> 16) & 0xffff;
entry->isr_high = (isr >> 32) & 0xffffffff;
@@ -148,9 +151,7 @@ __attribute__((noreturn)) void idt_exception_handler(uint64_t exception,
log_backtrace_ex((void *)state->rip, (void *)state->rbp);
- while (1) {
- halt();
- }
+ fatal_loop();
}
void isr_save(struct cpu_regs *regs)
diff --git a/kernel/drivers.c b/kernel/drivers.c
index 3d6ec10..572ab98 100644
--- a/kernel/drivers.c
+++ b/kernel/drivers.c
@@ -10,7 +10,7 @@
void drivers_init(void)
{
- pit_set_divider(1193); // 1ms
+ pit_set_freq(CHAN_TIMER, 1000); // 1ms
uart_init();
ps2_init();
pci_init();
diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c
index 53a9263..05b6a3a 100644
--- a/kernel/drivers/pit.c
+++ b/kernel/drivers/pit.c
@@ -1,29 +1,65 @@
+#include "lib/klib.h"
#include <comus/asm.h>
#include <comus/drivers/pit.h>
+#include <comus/drivers/spkr.h>
+#include <lib.h>
-#define CHAN_0 0x40
-#define CHAN_1 0x41
-#define CHAN_2 0x42
#define CMD 0x43
+#define SPKR 0x61
+
+#define BASE 1193180
volatile uint64_t ticks = 0;
-uint16_t pit_read_divider(void)
+uint32_t pit_read_freq(uint8_t chan)
{
- uint16_t count = 0;
+ uint16_t div = 0;
cli();
- outb(CMD, 0); // clear bits
- count = inb(CHAN_0); // low byte
- count |= inb(CHAN_0) << 8; // highbyte
+ outb(CMD, 0x36); // clear bits
+ div = inb(chan); // low byte
+ div |= inb(chan) << 8; // highbyte
sti();
- return count;
+ return div * BASE;
}
-void pit_set_divider(uint16_t count)
+void pit_set_freq(uint8_t chan, uint32_t hz)
{
- (void)count;
+ uint16_t div = BASE / hz;
cli();
- outb(CHAN_0, count & 0xFF); // low byte
- outb(CHAN_0, (count & 0xFF00) >> 8); // high byte
+ outb(CMD, 0x36);
+ outb(chan, div & 0xFF); // low byte
+ outb(chan, (div & 0xFF00) >> 8); // high byte
sti();
}
+
+void spkr_play_tone(uint32_t hz)
+{
+ uint8_t reg;
+
+ if (hz == 0) {
+ spkr_quiet();
+ return;
+ }
+
+ // set spkr freq
+ pit_set_freq(CHAN_SPKR, hz);
+
+ // enable spkr gate
+ reg = inb(SPKR);
+ if (reg != (reg | 0x3))
+ outb(SPKR, reg | 0x3);
+}
+
+void spkr_quiet(void)
+{
+ uint8_t reg;
+ reg = inb(SPKR) & 0xFC;
+ outb(SPKR, reg);
+}
+
+void spkr_beep(void)
+{
+ spkr_play_tone(1000);
+ kspin_milliseconds(100);
+ spkr_quiet();
+}
diff --git a/kernel/drivers/ps2.c b/kernel/drivers/ps2.c
index e260f6b..409ca09 100644
--- a/kernel/drivers/ps2.c
+++ b/kernel/drivers/ps2.c
@@ -266,3 +266,18 @@ int ps2_init(void)
sti();
return 0;
}
+
+int ps2_set_leds(uint8_t state)
+{
+ uint8_t result;
+
+ if (!(has_mouse || has_kbd))
+ return 1;
+
+ ps2ctrl_out_cmd(0xED);
+ ps2ctrl_out_data(state);
+ if ((result = ps2ctrl_in()) != 0xFA)
+ return 1;
+
+ return 0;
+}
diff --git a/kernel/efi/gop.c b/kernel/efi/gop.c
index 899bbee..5495980 100644
--- a/kernel/efi/gop.c
+++ b/kernel/efi/gop.c
@@ -4,6 +4,8 @@
static EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL;
+#define MAX_H_RES 1920
+
EFI_STATUS efi_load_gop(EFI_SYSTEM_TABLE *ST)
{
EFI_STATUS status = EFI_SUCCESS;
@@ -33,6 +35,8 @@ EFI_STATUS efi_load_gop(EFI_SYSTEM_TABLE *ST)
if (info->PixelFormat != PixelBlueGreenRedReserved8BitPerColor &&
info->PixelFormat != PixelRedGreenBlueReserved8BitPerColor)
continue;
+ if (info->HorizontalResolution > MAX_H_RES)
+ continue;
if (info->HorizontalResolution > width) {
width = info->HorizontalResolution;
best = i;
diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c
index a887ca4..ef031f2 100644
--- a/kernel/fs/fs.c
+++ b/kernel/fs/fs.c
@@ -1,5 +1,6 @@
#include <lib.h>
#include <comus/fs.h>
+#include <comus/fs/tar.h>
#include <comus/mboot.h>
#include <comus/error.h>
@@ -50,9 +51,9 @@ static void load_fs(struct disk *disk)
fs->fs_id = disk->d_id;
fs->fs_present = 1;
- // // try examplefs
- // if (example_mount(fs) == SUCCESS)
- // return;
+ // try tarfs
+ if (tar_mount(fs) == SUCCESS)
+ return;
fs->fs_present = 0;
WARN("failed to load fs on disk %u", disk->d_id);
@@ -122,13 +123,16 @@ int fs_find_file_rel(struct file *rel, char *rel_path, struct file *res)
static int disk_read_rd(struct disk *disk, size_t offset, size_t len,
uint8_t *buffer)
{
- if (offset + len >= disk->rd.len) {
+ if (offset >= disk->rd.len) {
WARN("attempted to read past length of ramdisk");
return -E_BAD_PARAM;
}
+ if (disk->rd.len - offset < len)
+ len = disk->rd.len - offset;
+
memcpy(buffer, disk->rd.start + offset, len);
- return 0;
+ return len;
}
static int disk_read_ata(struct disk *disk, size_t offset, size_t len,
@@ -181,13 +185,16 @@ int disk_read(struct disk *disk, size_t offset, size_t len, void *buffer)
static int disk_write_rd(struct disk *disk, size_t offset, size_t len,
uint8_t *buffer)
{
- if (offset + len >= disk->rd.len) {
+ if (offset >= disk->rd.len) {
WARN("attempted to write past length of ramdisk");
return -E_BAD_PARAM;
}
+ if (disk->rd.len - offset < len)
+ len = disk->rd.len - offset;
+
memcpy(disk->rd.start + offset, buffer, len);
- return 0;
+ return len;
}
static int disk_write_ata(struct disk *disk, size_t offset, size_t len,
diff --git a/kernel/fs/ramfs.c b/kernel/fs/ramfs.c
new file mode 100644
index 0000000..0c92c96
--- /dev/null
+++ b/kernel/fs/ramfs.c
@@ -0,0 +1,171 @@
+#include <comus/fs.h>
+/*#include <lib.h>
+//#include <comus/tar.h>
+//#include <string.h>
+#include <comus/ramfs.h>
+
+#define NOERROR 0
+#define ERROR 1
+
+int ramfs_check_exists(const char *name) {
+ for(int i = 0; i < numberOfFiles; i++) {
+ if(memcmp(allTheFiles[i].name, name, strlen(allTheFiles[i].name)) == 0) {
+ // found it
+ return i;
+ }
+ }
+ // doesn't exist
+ return -1;
+}
+int ramfs_create(const char *name) {
+ if(ramfs_check_exists(name) != -1) {
+ // already exists
+ return ERROR;
+ }
+ struct file *newFile;
+ *newFile->name = name;
+ newFile->size = 0;
+ newFile->data = kalloc(MAX_FILE_SIZE);
+ newFile = &allTheFiles[numberOfFiles];
+
+}
+
+int ramfs_delete(const char *name) {
+ int i = ramfs_check_exists(name);
+ if(i >= 0) {
+ kfree(allTheFiles[i].data);
+ for(int j = i; j < numberOfFiles; j++) {
+ allTheFiles[j] = allTheFiles[j+1];
+ numberOfFiles -= 1;
+ }
+ return NOERROR;
+
+ }
+ return ERROR;
+}
+
+int ramfs_read(const char *name, char *buffer, size_t len) {
+ int i = ramfs_check_exists(name);
+ if(i >= 0) {
+ memcpy(buffer, allTheFiles[i].data, len);
+ return NOERROR;
+ }
+ return ERROR;
+}
+
+
+int ramfs_write(const char *name, char *buffer) {
+ int i = ramfs_check_exists(name);
+ if(i >= 0) {
+ memcpy(buffer)
+ }
+}
+
+// here we return the index of the file as well.
+*int ramfs_find_file(root *r, const char *fullpath, const char *name, file *out, directory *outDirectory) {
+ directory *location = r->root;
+ if(ramfs_find_directory(r, fullpath, name, location) == NOERROR) {
+ for(int i = 0; i < location->file_count; i++) {
+ if(strcmp(location->files[i]->name, name) == 0) {
+ outDirectory = location;
+ out = location->files[i];
+ return i;
+ }
+ }
+
+ }
+ return -1;
+}
+int ramfs_find_directory(root *r, const char *fullpath, const char *name, directory *out) {
+ directory *location = r->root;
+ char *path = fullpath;
+ char *tempPath = strtok(tempPath, "/");
+ while(tempPath != NULL) {
+ bool wasItFound = false;
+
+ for(int i = 0; i < location->directory_count; i++) {
+ if(strcmp(location->directories[i]->name, tempPath) == 0) {
+ // yay we found it;
+ location = location->directories[i];
+ wasItFound = true;
+ break;
+
+ }
+ }
+ if(!wasItFound) {
+ return ERROR;
+ }
+ tempPath = strtok(NULL, "/");
+
+ }
+ out = location;
+ return NOERROR;
+
+}
+
+int ramfs_create_file(root *r, const char *fullpath, const char *name) {
+ // trace through the path
+ // struct ramfs_directory *location = r->root;
+ directory *location = r->root;
+
+ if(ramfs_find_directory(r, fullpath, name, location) == NOERROR) {
+ if(location->file_count >= MAX_FILES) {
+ return ERROR;
+ }
+ file *newFile = malloc(sizeof(file));
+ strcpy(newFile->name, name);
+ newFile->size = 0;
+ newFile->data = malloc(MAX_FILE_SIZE);
+ location->files[location->file_count] = newFile;
+ location->file_count += 1;
+
+ return NOERROR;
+
+ }
+ return ERROR;
+}
+
+int ramfs_delete_file(root *r, const char *fullpath, const char *name) {
+ directory *location;
+ if(ramfs_find_directory(r, fullpath, name, location) == NOERROR) {
+ file *find_file;
+ int file_index = ramfs_find_file(r, fullpath, name, find_file, location) >= 0;
+ if(file_index >= 0) {
+ free(location->files[file_index]->data);
+ free(location->files[file_index]);
+ for(int i = file_index + 1; i < location->file_count; i++) {
+ location->files[i-1] = location->files[i];
+ //memcpy(location->files[i-1], location->files[i], location->files[i]->size);
+ //free(location->files[i]);
+ }
+ location->file_count -= 1;
+ return NOERROR;
+ }
+ return ERROR;
+
+ }
+ return ERROR;
+}
+
+int ramfs_create_directory() {
+
+}
+
+int ramfs_delete_directory() {
+}
+
+int ramfs_write() {
+
+}
+
+
+root *ramfs_init() {
+ root *r = malloc(sizeof(root));
+ r->root = malloc(sizeof(directory));
+ strcpy(r->root->name, "/");
+ r->root->file_count = 0;
+ r->root->directory_count = 0;
+ return r;
+}
+
+*/
diff --git a/kernel/fs/tar.c b/kernel/fs/tar.c
new file mode 100644
index 0000000..5f02c34
--- /dev/null
+++ b/kernel/fs/tar.c
@@ -0,0 +1,306 @@
+#include <comus/fs.h>
+#include <lib.h>
+#include <comus/tar.h>
+
+// the placements of these values mimics their placement in standard UStar
+struct tar_header {
+ char name[100]; // 0-99
+ char mode[8]; // 100-107
+ char ownerUID[8]; // 108-115
+ char groupUID[8]; // 116-123
+ char fileSize[12]; // 124-135
+ char lastMod[12]; // 136-147
+ char checksum[8]; // 148-155
+ char type_flag; // 156
+ char linked_name[100]; // 157-256
+ char magic[6]; // 257-262
+ char version[2]; // 263-264
+ char username[32]; // 265-296
+ char groupname[32]; // 297-328
+ char majorNum[8]; // 329-336
+ char minorNum[8]; // 337-344
+ char prefix[155]; // 345-499
+ char notUsed[12]; // 500-511
+};
+#define TAR_SIZE 512
+#define TMAGIC "ustar" /* ustar and a null */
+#define TMAGLEN 6
+#define TVERSION "00" /* 00 and no null */
+#define TVERSLEN 2
+#define ERROR_TAR 1
+#define NOERROR_TAR 0
+
+#define REGTYPE '0' /* regular file */
+#define DIRTYPE '5' /* directory */
+
+struct tar_file {
+ struct file file;
+ struct file_system *fs;
+ size_t len;
+ size_t offset;
+ size_t sect;
+};
+// read_tar_header reads what is in tar
+int read_tar_header(struct disk *disk, uint32_t sect, struct tar_header *hdr)
+{
+ if (disk_read(disk, sect * TAR_SIZE, TAR_SIZE, hdr) < TAR_SIZE) {
+ return ERROR_TAR;
+ }
+ if (memcmp(hdr->magic, TMAGIC, TMAGLEN) != 0 ||
+ memcmp(hdr->version, TVERSION, TVERSLEN) != 0) {
+ return ERROR_TAR;
+ }
+ return NOERROR_TAR;
+}
+
+/// @brief
+/// @param f the file to be read
+/// @param buffer the buffer that the content of the file is read into
+/// @param len
+/// @return
+int tar_read(struct file *f, void *buffer, size_t len)
+{
+ struct tar_file *tf = (struct tar_file *)f;
+ long size = MIN((tf->len - tf->offset), len);
+ if (tf->file.f_type != F_REG || size < 1) {
+ return ERROR_TAR;
+ }
+ size = disk_read(tf->fs->fs_disk, (tf->sect + 1) * TAR_SIZE + tf->offset,
+ size, buffer);
+ tf->offset += size;
+ return size;
+}
+//static int read_tar()
+// we are assuming that things are formatted correctly.
+int find_file(struct file_system *fs, const char *filepath, size_t *sect,
+ size_t *sect_return, struct tar_header *outHeader)
+{
+ //char *tempFilePath = filepath;
+ struct tar_header hdr;
+ size_t curr_sect;
+ if (sect == NULL) {
+ curr_sect = 0;
+ } else {
+ curr_sect = *sect;
+ }
+ while (1 == 1) {
+ if (read_tar_header(fs->fs_disk, curr_sect, &hdr) != 0) {
+ return ERROR_TAR;
+ }
+ if (memcmp(hdr.name, filepath, strlen(filepath) + 1) != 0) {
+ // didn't find it.
+
+ curr_sect +=
+ ((strtoull(hdr.fileSize, NULL, 8) + TAR_SIZE - 1) / TAR_SIZE) +
+ 1;
+ continue;
+ } else {
+ *outHeader = hdr;
+ *sect_return = curr_sect;
+ if (sect != NULL) {
+ sect += curr_sect;
+ }
+ return NOERROR_TAR;
+ }
+ }
+ return ERROR_TAR;
+}
+int find_file_redux(struct file_system *fs, const char *filepath, size_t *sect,
+ size_t *sect_return, struct tar_header *outHeader)
+{
+ struct tar_header hdr;
+ size_t curr_sect;
+ if (sect == NULL) {
+ curr_sect = 0;
+ } else {
+ curr_sect = *sect;
+ }
+ while (1 == 1) {
+ if (read_tar_header(fs->fs_disk, curr_sect, &hdr) != 0) {
+ return ERROR_TAR;
+ }
+ if (memcmp(hdr.name, filepath,
+ MIN(strlen(filepath), strlen(hdr.name))) != 0) {
+ // didn't find it.
+
+ curr_sect +=
+ ((strtoull(hdr.fileSize, NULL, 8) + TAR_SIZE - 1) / TAR_SIZE) +
+ 1;
+ continue;
+ } else {
+ *outHeader = hdr;
+ *sect_return = curr_sect;
+ if (sect != NULL) {
+ sect += curr_sect +
+ ((strtoull(hdr.fileSize, NULL, 8) + TAR_SIZE - 1) /
+ TAR_SIZE) +
+ 1;
+ }
+ return NOERROR_TAR;
+ }
+ }
+ return ERROR_TAR; // it should never actually reach here.
+}
+
+void tar_close(struct file *f)
+{
+ kfree(f);
+}
+
+int tar_seek(struct file *f, long int offsetAdd, int theSeek)
+{
+ struct tar_file *tf = (struct tar_file *)f;
+ if (theSeek == SEEK_SET) {
+ tf->offset = offsetAdd;
+ return tf->offset;
+ } else if (theSeek == SEEK_CUR) {
+ tf->offset = tf->offset + offsetAdd;
+ return tf->offset;
+ } else if (theSeek == SEEK_END) {
+ tf->offset = tf->len + offsetAdd;
+ return tf->offset;
+ } else {
+ return -1;
+ }
+}
+
+int tar_write(struct file *f, const void *buffer, size_t len)
+{
+ // tar doesn't do write lol. This is just here so there is something to send to write
+ (void)f;
+ (void)buffer;
+ (void)len;
+ return ERROR_TAR;
+}
+
+/*int tar_ents(struct file *f, struct dirent *d, size_t dIndex) {
+ struct tar_header hdr;
+ struct tar_header dir;
+ struct tar_file *tf = (struct tar_file*) f;
+ size_t sect = 0;
+ size_t sect_off = 0;
+ size_t curr_index = 0;
+ if(read_tar_header(tf->fs->fs_disk, sect, &hdr) != 0) {
+ return ERROR_TAR;
+ }
+ while(1 == 1) {
+ if(find_file_redux(tf->fs, dir.name, &sect_off, &sect, &dir) != 0) {
+ return ERROR_TAR;
+ }
+ if(curr_index < dIndex) {
+ curr_index += 1;
+ } else if(curr_index > dIndex) {
+ // something went seriously wrong
+ return ERROR_TAR;
+ } else {
+ d->d_namelen = strlen(hdr.name);
+ dir.type_flag = DIRTYPE;
+ d->d_offset = dIndex;
+ memcpy(d->d_name, hdr.name, d->d_namelen + 1);
+ return NOERROR_TAR;
+ }
+
+
+ }
+
+
+}*/
+
+int tar_ents(struct file *f, struct dirent *ent, size_t entry)
+{
+ struct tar_file *tf;
+ struct tar_header dir, hdr;
+ size_t sect;
+ size_t sect_off = 0;
+ size_t idx = 0;
+
+ tf = (struct tar_file *)f;
+ sect = 0;
+
+ if (tf->file.f_type != F_DIR)
+ return -1;
+
+ if (read_tar_header(tf->fs->fs_disk, sect, &dir)) {
+ return ERROR_TAR;
+ }
+
+ while (1) {
+ if (find_file_redux(tf->fs, dir.name, &sect_off, &sect, &hdr))
+ return ERROR_TAR;
+
+ if (idx != entry) {
+ idx++;
+ continue;
+ }
+
+ ent->d_offset = entry;
+ ent->d_namelen = strlen(hdr.name);
+ memcpy(ent->d_name, hdr.name, ent->d_namelen + 1);
+ return NOERROR_TAR;
+ }
+
+ return ERROR_TAR;
+}
+
+// opens up the tar file at fullpath, and puts it in out.
+int tar_open(struct file_system *fs, const char *fullpath, int flags,
+ struct file **out)
+{
+ struct tar_header hdr;
+ struct tar_file *newFile;
+ size_t sect_result;
+ find_file(fs, fullpath, NULL, &sect_result, &hdr);
+ if (flags != O_RDONLY) {
+ return ERROR_TAR;
+ }
+ newFile = kalloc(sizeof(struct tar_file));
+
+ newFile->file.f_type = F_REG;
+ newFile->fs = fs;
+ newFile->file.read = tar_read;
+ newFile->file.close = tar_close;
+ newFile->file.write = tar_write; // doesn't actually work;
+ newFile->file.ents = tar_ents;
+ newFile->file.seek = tar_seek;
+ newFile->offset = 0;
+ newFile->len = strtoull(hdr.fileSize, NULL, 8);
+ newFile->sect = sect_result;
+
+ *out = (struct file *)newFile;
+ return NOERROR_TAR;
+}
+
+// gets stats at the file at fullpath, putting them in out.
+int tar_stat(struct file_system *fs, const char *fullpath, struct stat *out)
+{
+ struct tar_header hdr;
+ size_t sect_result;
+ find_file(fs, fullpath, NULL, &sect_result, &hdr);
+ out->s_length = strtoull(hdr.fileSize, NULL, 8);
+ if (hdr.type_flag == REGTYPE) {
+ out->s_type = F_REG;
+ } else if (hdr.type_flag == DIRTYPE) {
+ out->s_type = F_DIR;
+ } else {
+ // wth
+ return ERROR_TAR;
+ }
+ return NOERROR_TAR;
+}
+
+// use tar for the filesystem.
+int tar_mount(struct file_system *fs)
+{
+ struct tar_header hdr;
+ // reads into hdr
+ if (read_tar_header(fs->fs_disk, 0, &hdr) == 0) {
+ fs->fs_name = "tar";
+ fs->open = tar_open;
+ fs->stat = tar_stat;
+ fs->fs_present = true;
+ return NOERROR_TAR;
+ }
+ return ERROR_TAR;
+}
+
+// no need to unmount, since mount just overrides whatever it was using previously. \ No newline at end of file
diff --git a/kernel/include/comus/drivers/pit.h b/kernel/include/comus/drivers/pit.h
index 77f0a14..22b8153 100644
--- a/kernel/include/comus/drivers/pit.h
+++ b/kernel/include/comus/drivers/pit.h
@@ -9,13 +9,23 @@
#ifndef PIT_H_
#define PIT_H_
+#define CHAN_TIMER 0x40
+#define CHAN_SPKR 0x42
+
#include <stdint.h>
// how many time the pit has ticked
// not accurate time, good for spinning though
extern volatile uint64_t ticks;
-uint16_t pit_read_divider(void);
-void pit_set_divider(uint16_t count);
+/**
+ * Read timer frequency
+ */
+uint32_t pit_read_freq(uint8_t chan);
+
+/**
+ * Set timer frequency
+ */
+void pit_set_freq(uint8_t chan, uint32_t hz);
#endif
diff --git a/kernel/include/comus/drivers/ps2.h b/kernel/include/comus/drivers/ps2.h
index 7634e5f..c012ad4 100644
--- a/kernel/include/comus/drivers/ps2.h
+++ b/kernel/include/comus/drivers/ps2.h
@@ -9,6 +9,8 @@
#ifndef PS2_H_
#define PS2_H_
+#include <stdint.h>
+
/**
* Initalize the ps2 controller
*/
@@ -24,4 +26,15 @@ void ps2kb_recv(void);
*/
void ps2mouse_recv(void);
+/**
+ * Set ps2 led state
+ *
+ * Bits
+ * ----
+ * 0 - Scroll lock
+ * 1 - Num Lock
+ * 2 - Caps lock
+ */
+int ps2_set_leds(uint8_t state);
+
#endif /* ps2.h */
diff --git a/kernel/include/comus/drivers/spkr.h b/kernel/include/comus/drivers/spkr.h
new file mode 100644
index 0000000..f9e427e
--- /dev/null
+++ b/kernel/include/comus/drivers/spkr.h
@@ -0,0 +1,29 @@
+/**
+ * @file spkr.h
+ *
+ * @author Freya Murphy <freya@freyacat.org>
+ *
+ * PC Speaker
+ */
+
+#ifndef SPKR_H_
+#define SPKR_H_
+
+#include <stdint.h>
+
+/**
+ * Play a tone on the pc speaker continuously
+ */
+void spkr_play_tone(uint32_t hz);
+
+/**
+ * Shut up the pc speaker
+ */
+void spkr_quiet(void);
+
+/**
+ * Beep the pc speaker for a short period
+ */
+void spkr_beep(void);
+
+#endif /* spkr.h */
diff --git a/kernel/include/comus/fs.h b/kernel/include/comus/fs.h
index 2f678b6..b1d0e80 100644
--- a/kernel/include/comus/fs.h
+++ b/kernel/include/comus/fs.h
@@ -28,7 +28,7 @@ struct disk {
/// internal disk device
union {
struct {
- char *start;
+ uint8_t *start;
size_t len;
} rd;
ide_device_t ide;
@@ -137,9 +137,9 @@ struct file {
/// file type
enum file_type f_type;
/// read from the file
- int (*read)(struct file *file, char *buffer, size_t nbytes);
+ int (*read)(struct file *file, void *buffer, size_t nbytes);
/// write into the file
- int (*write)(struct file *file, const char *buffer, size_t nbytes);
+ int (*write)(struct file *file, const void *buffer, size_t nbytes);
/// seeks the file
int (*seek)(struct file *file, long int offset, int whence);
/// get directory entry at index
@@ -148,6 +148,15 @@ struct file {
void (*close)(struct file *file);
};
+/// open flags
+enum {
+ O_CREATE = 0x01,
+ O_RDONLY = 0x02,
+ O_WRONLY = 0x04,
+ O_APPEND = 0x08,
+ O_RDWR = 0x10,
+};
+
/// file system vtable, used for opening
/// and stating files. filesystem mount functions must
/// set fs_name, fs_disk, open, and stat.
@@ -200,7 +209,7 @@ struct file_system {
/// filesystem name
const char *fs_name;
/// opens a file
- int (*open)(struct file_system *fs, const char *fullpath,
+ int (*open)(struct file_system *fs, const char *fullpath, int flags,
struct file **out);
/// stats a file
int (*stat)(struct file_system *fs, const char *fullpath,
diff --git a/kernel/include/comus/fs/tar.h b/kernel/include/comus/fs/tar.h
new file mode 100644
index 0000000..084c8bd
--- /dev/null
+++ b/kernel/include/comus/fs/tar.h
@@ -0,0 +1,18 @@
+/**
+ * @file tar.h
+ *
+ * Tarball
+ */
+
+#ifndef TAR_FS_H_
+#define TAR_FS_H_
+
+#include <comus/fs.h>
+
+/**
+ * Attempts to mount tar filesystem on disk
+ * @returns 0 on success
+ */
+int tar_mount(struct file_system *fs);
+
+#endif /* fs.h */
diff --git a/kernel/include/comus/limits.h b/kernel/include/comus/limits.h
index 4cb348d..a036fcb 100644
--- a/kernel/include/comus/limits.h
+++ b/kernel/include/comus/limits.h
@@ -7,11 +7,15 @@
*/
/// number of pts to identity map the kernel (1pt = 2MB)
-#define N_IDENT_PTS 4 // max 512 (1G)
+#define N_IDENT_PTS 64 // max 512 (1G)
/// max number of processes
#define N_PROCS 256
+/// process limits
+#define N_OPEN_FILES 64
+#define N_ARGS 64
+
/// max nubmer of pci devices
#define N_PCI_DEV 256
diff --git a/kernel/include/comus/mboot.h b/kernel/include/comus/mboot.h
index aba3e4e..bed29f1 100644
--- a/kernel/include/comus/mboot.h
+++ b/kernel/include/comus/mboot.h
@@ -47,4 +47,14 @@ EFI_HANDLE mboot_get_efi_hdl(void);
*/
void *mboot_get_initrd(size_t *len);
+/**
+ * Returns the physical pointer to the loaded init ram disk with size given by len
+ */
+void *mboot_get_initrd_phys(size_t *len);
+
+/**
+ * Gets the end of the mboot pointer
+ */
+void *mboot_end(void);
+
#endif /* mboot.h */
diff --git a/kernel/include/comus/procs.h b/kernel/include/comus/procs.h
index 717f27a..ee723aa 100644
--- a/kernel/include/comus/procs.h
+++ b/kernel/include/comus/procs.h
@@ -13,6 +13,7 @@
#include <comus/limits.h>
#include <comus/memory.h>
#include <comus/syscalls.h>
+#include <comus/fs.h>
#include <lib.h>
#include <elf.h>
@@ -59,6 +60,9 @@ struct pcb {
char *heap_start;
size_t heap_len;
+ // open files
+ struct file *open_files[N_OPEN_FILES];
+
// elf metadata
Elf64_Ehdr elf_header;
Elf64_Phdr elf_segments[N_ELF_SEGMENTS];
diff --git a/kernel/include/comus/ramfs.h b/kernel/include/comus/ramfs.h
new file mode 100644
index 0000000..d3cd703
--- /dev/null
+++ b/kernel/include/comus/ramfs.h
@@ -0,0 +1,40 @@
+/*#include <comus/fs.h>
+#ifndef RAMFS_H_
+#define RAMFS_H_
+#define MAX_FILES 32
+#define MAX_FILE_SIZE 4096
+
+struct file {
+ char name[32];
+ size_t size;
+ char *data;
+} file;
+
+struct file allTheFiles[MAX_FILES];
+int numberOfFiles = 0;
+
+#endif
+/*
+typedef struct ramfs_file {
+ char name[32];
+ int size;
+ char *data;
+} file;
+
+typedef struct ramfs_directory {
+ char name[32];
+ file *files[MAX_FILES];
+ directory *directories[MAX_FILES];
+ int file_count;
+ int directory_count;
+} directory;
+
+typedef struct ramfs_root {
+ directory *root;
+} root;
+
+//struct file allTheFiles[MAX_FILES];
+int numberOfFiles = 0;
+
+
+#endif*/ \ No newline at end of file
diff --git a/kernel/include/comus/syscalls.h b/kernel/include/comus/syscalls.h
index ffc9d1b..146bce1 100644
--- a/kernel/include/comus/syscalls.h
+++ b/kernel/include/comus/syscalls.h
@@ -30,12 +30,13 @@
#define SYS_poweroff 17
#define SYS_drm 18
#define SYS_ticks 19
-#define SYS_allocshared 20
-#define SYS_popsharedmem 21
-#define SYS_keypoll 22
+#define SYS_seek 20
+#define SYS_allocshared 21
+#define SYS_popsharedmem 22
+#define SYS_keypoll 23
// UPDATE THIS DEFINITION IF MORE SYSCALLS ARE ADDED!
-#define N_SYSCALLS 23
+#define N_SYSCALLS 24
// interrupt vector entry for system calls
#define VEC_SYSCALL 0x80
diff --git a/kernel/include/comus/tar.h b/kernel/include/comus/tar.h
new file mode 100644
index 0000000..b08f668
--- /dev/null
+++ b/kernel/include/comus/tar.h
@@ -0,0 +1,6 @@
+#include <comus/fs.h>
+#ifndef TAR_FS_H_
+#define TAR_FS_H_
+
+int tar_mount(struct file_system *fs);
+#endif \ No newline at end of file
diff --git a/kernel/include/comus/user.h b/kernel/include/comus/user.h
index f51ada5..1b35ac4 100644
--- a/kernel/include/comus/user.h
+++ b/kernel/include/comus/user.h
@@ -9,13 +9,15 @@
#ifndef USER_H_
#define USER_H_
+#include "comus/memory.h"
#include <comus/procs.h>
#include <comus/fs.h>
/**
* Load a user elf program from a file into a pcb
*/
-int user_load(struct pcb *pcb, struct disk *disk);
+int user_load(struct pcb *pcb, struct file *file, const char **args,
+ mem_ctx_t args_ctx);
/**
* Clone a user process. Used for fork().
diff --git a/kernel/include/lib/klib.h b/kernel/include/lib/klib.h
index b4d26ed..f549a09 100644
--- a/kernel/include/lib/klib.h
+++ b/kernel/include/lib/klib.h
@@ -264,6 +264,11 @@ __attribute__((noreturn, format(printf, 3, 4))) void
__panic(unsigned int line, const char *file, const char *format, ...);
/**
+ * Loop kernel in fatal notifier (beep and blink caps lock key)
+ */
+__attribute__((noreturn)) void fatal_loop(void);
+
+/**
* Fill dst with a stack trace consisting of return addresses in order
* from top to bottom
*
diff --git a/kernel/lib/backtrace.c b/kernel/lib/backtrace.c
index 2507be4..2783b74 100644
--- a/kernel/lib/backtrace.c
+++ b/kernel/lib/backtrace.c
@@ -50,10 +50,9 @@ void log_backtrace_ex(void *ip, void *bp)
if (!VALID(frame))
return;
kputs("Stack trace:\n");
- kprintf(" %p\t%s\n", ip, mboot_get_elf_sym((uint64_t)ip));
+ kprintf(" %p\n", ip);
while (VALID(frame)) {
- kprintf(" %p\t%s\n", frame->rip,
- mboot_get_elf_sym((uint64_t)frame->rip));
+ kprintf(" %p\n", frame->rip);
frame = frame->rbp;
}
}
diff --git a/kernel/lib/kalloc.c b/kernel/lib/kalloc.c
index 0141149..23b8b73 100644
--- a/kernel/lib/kalloc.c
+++ b/kernel/lib/kalloc.c
@@ -4,117 +4,35 @@
#define MAGIC 0xBEEFCAFE
struct page_header {
- struct page_header *next;
- struct page_header *prev;
- size_t
- node_number; // all headers on the same page alloc have the same node number (so they can be merged)
- size_t
- free; // free space after the node (if its the last node in the alloc block)
- size_t used; // how much space this allocation is using
+ size_t len;
uint64_t magic;
};
-static const size_t header_len = sizeof(struct page_header);
-static struct page_header *start_header = NULL;
-static struct page_header *end_header = NULL;
-
static struct page_header *get_header(void *ptr)
{
struct page_header *header =
- (struct page_header *)((uintptr_t)ptr - header_len);
+ (struct page_header *)((uintptr_t)ptr - PAGE_SIZE);
- // PERF: do we want to make sure this pointer is paged
- // before reading it???
- if (header->magic != MAGIC) {
+ if (header->magic != MAGIC)
return NULL; // invalid pointer
- }
return header;
}
-static void *alloc_new(size_t size)
+void *kalloc(size_t size)
{
- size_t pages = ((size + header_len) / PAGE_SIZE) + 1;
-
- void *addr = kalloc_pages(pages);
- void *mem = (char *)addr + header_len;
-
- size_t total = pages * PAGE_SIZE;
- size_t free = total - (size + header_len);
+ struct page_header *header;
+ size_t pages;
- if (addr == NULL) {
+ pages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+ header = kalloc_pages(pages + 1);
+ if (header == NULL)
return NULL;
- }
-
- size_t node;
- if (end_header != NULL) {
- node = end_header->node_number + 1;
- } else {
- node = 0;
- }
-
- struct page_header *header = addr;
- memsetv(header, 0, sizeof(struct page_header));
- header->magic = MAGIC;
- header->used = size;
- header->free = free;
- header->prev = end_header;
- header->next = NULL;
- header->node_number = node;
-
- if (start_header == NULL) {
- start_header = header;
- }
-
- if (end_header != NULL) {
- end_header->next = header;
- } else {
- end_header = header;
- }
-
- return mem;
-}
-
-static void *alloc_block(size_t size, struct page_header *block)
-{
- struct page_header *header =
- (struct page_header *)((char *)block + block->used + header_len);
-
- size_t free = block->free - (size + header_len);
- block->free = 0;
header->magic = MAGIC;
- header->used = size;
- header->free = free;
- header->prev = block;
- header->next = block->next;
- block->next = header;
- header->node_number = block->node_number;
+ header->len = size;
- void *mem = (char *)header + header_len;
-
- return mem;
-}
-
-void *kalloc(size_t size)
-{
- struct page_header *header = start_header;
-
- for (; header != NULL; header = header->next) {
- size_t free = header->free;
- if (free < header_len)
- continue;
- if (size <=
- (free - header_len)) { // we must be able to fit data + header
- break;
- }
- }
-
- if (header != NULL) {
- return alloc_block(size, header);
- } else {
- return alloc_new(size);
- }
+ return (char *)header + PAGE_SIZE;
}
void *krealloc(void *src, size_t dst_len)
@@ -140,7 +58,7 @@ void *krealloc(void *src, size_t dst_len)
if (header == NULL)
return NULL;
- src_len = header->used;
+ src_len = header->len;
if (src_len == 0)
return NULL;
@@ -171,41 +89,5 @@ void kfree(void *ptr)
if (header == NULL)
return;
- header->free += header->used;
- header->used = 0;
-
- struct page_header *neighbor;
-
- // merge left
- for (neighbor = header->prev; neighbor != NULL; neighbor = neighbor->prev) {
- if (neighbor->node_number != header->node_number)
- break;
- if (neighbor->used && header->used)
- break;
- neighbor->free += header->free + header_len;
- neighbor->next = header->next;
- header = neighbor;
- }
-
- // merge right
- for (neighbor = header->next; neighbor != NULL; neighbor = neighbor->next) {
- if (neighbor->node_number != header->node_number)
- break;
- if (neighbor->used)
- break;
- header->free += neighbor->free + header_len;
- header->next = neighbor->next;
- }
-
- if ((header->next == NULL ||
- header->next->node_number != header->node_number) &&
- (header->prev == NULL ||
- header->prev->node_number != header->node_number) &&
- header->used == 0) {
- if (header->next)
- header->next->prev = header->prev;
- if (header->prev)
- header->prev->next = header->next;
- kfree_pages(header);
- }
+ kfree_pages(header);
}
diff --git a/kernel/lib/panic.c b/kernel/lib/panic.c
index 3a6e029..99936c1 100644
--- a/kernel/lib/panic.c
+++ b/kernel/lib/panic.c
@@ -1,6 +1,8 @@
#include <lib.h>
#include <stdarg.h>
#include <comus/asm.h>
+#include <comus/drivers/ps2.h>
+#include <comus/drivers/spkr.h>
__attribute__((noreturn)) void __panic(unsigned int line, const char *file,
const char *format, ...)
@@ -16,6 +18,15 @@ __attribute__((noreturn)) void __panic(unsigned int line, const char *file,
log_backtrace();
#endif
- while (1)
- halt();
+ fatal_loop();
+}
+
+__attribute__((noreturn)) void fatal_loop(void)
+{
+ while (1) {
+ spkr_play_tone(1000);
+ kspin_milliseconds(200);
+ spkr_quiet();
+ kspin_milliseconds(800);
+ }
}
diff --git a/kernel/main.c b/kernel/main.c
index c15c38d..52f832b 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -22,6 +22,44 @@ void kreport(void)
gpu_report();
}
+void load_init(void)
+{
+ struct file_system *fs;
+ struct file *file;
+ const char *init_vector[] = { NULL };
+
+ if (pcb_alloc(&init_pcb)) {
+ WARN("failed to alloc init pcb");
+ return;
+ }
+
+ // get root fs
+ fs = fs_get_root_file_system();
+ if (fs == NULL) {
+ WARN("failed to get root fs");
+ return;
+ }
+
+ // get init bin
+ if (fs->open(fs, "bin/init", O_RDONLY, &file)) {
+ WARN("cannot find init elf");
+ return;
+ }
+
+ if (user_load(init_pcb, file, init_vector, kernel_mem_ctx)) {
+ WARN("init elf failed to load! bad bad BAD!!");
+ file->close(file);
+ return;
+ }
+
+ // close file
+ file->close(file);
+
+ // schedule and dispatch init
+ schedule(init_pcb);
+ dispatch();
+}
+
__attribute__((noreturn)) void main(long magic, volatile void *mboot)
{
// initalize idt and pic
@@ -49,11 +87,7 @@ __attribute__((noreturn)) void main(long magic, volatile void *mboot)
kreport();
// load init process
- pcb_alloc(&init_pcb);
- if (user_load(init_pcb, &fs_disks[0]))
- panic("failed to load init");
+ load_init();
- // schedule and dispatch init
- schedule(init_pcb);
- dispatch();
+ panic("failed to load init");
}
diff --git a/kernel/mboot/mboot.c b/kernel/mboot/mboot.c
index e4547e7..8163f04 100644
--- a/kernel/mboot/mboot.c
+++ b/kernel/mboot/mboot.c
@@ -5,6 +5,8 @@
static volatile void *mboot = NULL;
+extern char kernel_end[];
+
void mboot_init(long magic, volatile void *ptr)
{
if (magic != MULTIBOOT2_BOOTLOADER_MAGIC)
@@ -12,6 +14,23 @@ void mboot_init(long magic, volatile void *ptr)
mboot = ptr;
}
+void *mboot_end(void)
+{
+ if (mboot == NULL)
+ return NULL;
+
+ struct multiboot *info = (struct multiboot *)mboot;
+ uintptr_t mboot_end, initrd_end;
+ size_t initrd_len;
+
+ mboot_end = (uintptr_t)info + info->total_size;
+ initrd_end = (uintptr_t)mboot_get_initrd_phys(&initrd_len);
+ if (initrd_end)
+ initrd_end += initrd_len;
+
+ return (void *)MAX(mboot_end, initrd_end);
+}
+
void *locate_mboot_table(uint32_t type)
{
if (mboot == NULL)
diff --git a/kernel/mboot/module.c b/kernel/mboot/module.c
index 79d092e..03c5147 100644
--- a/kernel/mboot/module.c
+++ b/kernel/mboot/module.c
@@ -1,3 +1,4 @@
+#include <comus/memory.h>
#include <comus/mboot.h>
#include "mboot.h"
@@ -12,13 +13,44 @@ struct multiboot_tag_module {
char cmdline[];
};
-void *mboot_get_initrd(size_t *len)
+static void *mapped_addr = NULL;
+size_t initrd_len;
+
+void *mboot_get_initrd_phys(size_t *len)
{
- void *tag = locate_mboot_table(MULTIBOOT_TAG_TYPE_MODULE);
+ struct multiboot_tag_module *mod;
+ void *tag, *phys;
+
+ // if already loaded, return
+ if (mapped_addr) {
+ *len = initrd_len;
+ return mapped_addr;
+ }
+
+ // locate
+ tag = locate_mboot_table(MULTIBOOT_TAG_TYPE_MODULE);
if (tag == NULL)
return NULL;
- struct multiboot_tag_module *mod = (struct multiboot_tag_module *)tag;
- *len = mod->mod_end - mod->mod_start;
- return (void *)(uintptr_t)mod->mod_start;
+ mod = (struct multiboot_tag_module *)tag;
+ phys = (void *)(uintptr_t)mod->mod_start;
+ initrd_len = mod->mod_end - mod->mod_start;
+
+ *len = initrd_len;
+ return phys;
+}
+
+void *mboot_get_initrd(size_t *len)
+{
+ // get phys
+ void *phys = mboot_get_initrd_phys(len);
+ if (phys == NULL)
+ return NULL;
+
+ // map addr
+ mapped_addr = kmapaddr(phys, NULL, initrd_len, F_PRESENT | F_WRITEABLE);
+ if (mapped_addr == NULL)
+ return NULL;
+
+ return mapped_addr;
}
diff --git a/kernel/memory/paging.c b/kernel/memory/paging.c
index 763bdce..fc3b256 100644
--- a/kernel/memory/paging.c
+++ b/kernel/memory/paging.c
@@ -5,7 +5,6 @@
#include "physalloc.h"
#include "paging.h"
#include "memory.h"
-#include <stdint.h>
// PAGE MAP LEVEL 4 ENTRY
struct pml4e {
@@ -258,8 +257,10 @@ static volatile struct pml4 *pml4_alloc(void)
volatile struct pml4 *pPML4, *vPML4;
pPML4 = alloc_phys_page();
- if (pPML4 == NULL)
+ if (pPML4 == NULL) {
+ ERROR("Could not allocate PML4");
return NULL;
+ }
vPML4 = PML4_MAP(pPML4);
memsetv(vPML4, 0, sizeof(struct pml4));
@@ -287,8 +288,10 @@ static volatile struct pdpt *pdpt_alloc(volatile struct pml4 *pPML4,
}
pPDPT = alloc_phys_page();
- if (pPML4 == NULL)
+ if (pPDPT == NULL) {
+ ERROR("Could not allocate PDPT");
return NULL;
+ }
vPDPT = PDPT_MAP(pPDPT);
memsetv(vPDPT, 0, sizeof(struct pdpt));
@@ -320,8 +323,10 @@ static volatile struct pd *pd_alloc(volatile struct pdpt *pPDPT, void *vADDR,
}
pPD = alloc_phys_page();
- if (pPDPT == NULL)
+ if (pPD == NULL) {
+ ERROR("Could not allocate PD");
return NULL;
+ }
vPD = PD_MAP(pPD);
memsetv(vPD, 0, sizeof(struct pd));
@@ -353,8 +358,10 @@ static volatile struct pt *pt_alloc(volatile struct pd *pPD, void *vADDR,
}
pPT = alloc_phys_page();
- if (pPD == NULL)
+ if (pPT == NULL) {
+ ERROR("Could not allocate PT");
return NULL;
+ }
vPT = PT_MAP(pPT);
memsetv(vPT, 0, sizeof(struct pt));
@@ -910,11 +917,15 @@ void *mem_mapaddr(mem_ctx_t ctx, void *phys, void *virt, size_t len,
// get page aligned (or allocate) vitural address
if (virt == NULL)
virt = virtaddr_alloc(&ctx->virtctx, pages);
- if (virt == NULL)
+ if (virt == NULL) {
+ ERROR("Could not alloc vitural address for %zu pages", pages);
return NULL;
+ }
- if (virtaddr_take(&ctx->virtctx, virt, pages))
+ if (virtaddr_take(&ctx->virtctx, virt, pages)) {
+ ERROR("Could not take vitural address: %p", virt);
return NULL;
+ }
assert((uint64_t)virt % PAGE_SIZE == 0,
"mem_mapaddr: vitural address not page aligned");
@@ -922,6 +933,7 @@ void *mem_mapaddr(mem_ctx_t ctx, void *phys, void *virt, size_t len,
if (map_pages((volatile struct pml4 *)ctx->pml4, virt, aligned_phys,
F_PRESENT | flags, pages)) {
virtaddr_free(&ctx->virtctx, virt);
+ ERROR("Could not map pages");
return NULL;
}
@@ -1025,64 +1037,90 @@ void *mem_alloc_pages(mem_ctx_t ctx, size_t count, unsigned int flags)
void *mem_alloc_pages_at(mem_ctx_t ctx, size_t count, void *virt,
unsigned int flags)
{
- size_t pages_needed = count;
-
- struct phys_page_slice prev_phys_block = PHYS_PAGE_SLICE_NULL;
- struct phys_page_slice phys_pages;
+ void *phys = NULL;
- if (virtaddr_take(&ctx->virtctx, virt, count))
+ if (virtaddr_take(&ctx->virtctx, virt, count)) {
+ ERROR("Could not take vitural address: %p", virt);
return NULL;
+ }
- while (pages_needed > 0) {
- phys_pages = alloc_phys_page_withextra(pages_needed);
- if (phys_pages.pagestart == NULL) {
- goto mem_alloc_pages_at_fail;
- }
-
- {
- // allocate the first page and store in it the physical address of the
- // previous chunk of pages
- // TODO: skip this if there are already enough pages from first alloc
- void *pageone = kmapaddr(phys_pages.pagestart, NULL, 1,
- F_PRESENT | F_WRITEABLE);
- if (pageone == NULL) {
- panic("kernel out of virtual memory");
- }
- *((struct phys_page_slice *)pageone) = prev_phys_block;
- prev_phys_block = phys_pages;
- kunmapaddr(pageone);
- }
-
- // index into virtual page array at index [count - pages_needed]
- void *vaddr = ((uint8_t *)virt) + ((count - pages_needed) * PAGE_SIZE);
-
- assert(pages_needed >= phys_pages.num_pages, "overflow");
- pages_needed -= phys_pages.num_pages;
+ phys = alloc_phys_pages_exact(count);
+ if (phys == NULL) {
+ ERROR("Could not allocate %zu physical pages", count);
+ goto fail;
+ }
- if (map_pages((volatile struct pml4 *)ctx->pml4, vaddr,
- phys_pages.pagestart, flags, phys_pages.num_pages)) {
- goto mem_alloc_pages_at_fail;
- }
+ if (map_pages((volatile struct pml4 *)ctx->pml4, virt, phys, flags,
+ count)) {
+ ERROR("Could not map pages");
+ goto fail;
}
return virt;
-mem_alloc_pages_at_fail:
- while (prev_phys_block.pagestart) {
- void *virtpage = kmapaddr(prev_phys_block.pagestart, NULL, 1,
- F_PRESENT | F_WRITEABLE);
- if (!virtpage) {
- // memory corruption, most likely a bug
- // could also ERROR here and exit with leak
- panic("unable to free memory from failed mem_alloc_pages_at call");
- }
- struct phys_page_slice prev = *(struct phys_page_slice *)virtpage;
- prev_phys_block = prev;
- free_phys_pages_slice(prev);
- kunmapaddr(virtpage);
- }
-
+fail:
+ free_phys_pages(phys, count);
+ virtaddr_free(&ctx->virtctx, virt);
return NULL;
+
+ // size_t pages_needed = count;
+ //
+ // struct phys_page_slice prev_phys_block = PHYS_PAGE_SLICE_NULL;
+ // struct phys_page_slice phys_pages;
+ //
+ // if (virtaddr_take(&ctx->virtctx, virt, count))
+ // return NULL;
+ //
+ // while (pages_needed > 0) {
+ // phys_pages = alloc_phys_page_withextra(pages_needed);
+ // if (phys_pages.pagestart == NULL) {
+ // goto mem_alloc_pages_at_fail;
+ // }
+ //
+ // {
+ // // allocate the first page and store in it the physical address of the
+ // // previous chunk of pages
+ // // TODO: skip this if there are already enough pages from first alloc
+ // void *pageone = kmapaddr(phys_pages.pagestart, NULL, 1,
+ // F_PRESENT | F_WRITEABLE);
+ // if (pageone == NULL) {
+ // panic("kernel out of virtual memory");
+ // }
+ // *((struct phys_page_slice *)pageone) = prev_phys_block;
+ // prev_phys_block = phys_pages;
+ // kunmapaddr(pageone);
+ // }
+ //
+ // // index into virtual page array at index [count - pages_needed]
+ // void *vaddr = ((uint8_t *)virt) + ((count - pages_needed) * PAGE_SIZE);
+ //
+ // assert(pages_needed >= phys_pages.num_pages, "overflow");
+ // pages_needed -= phys_pages.num_pages;
+ //
+ // if (map_pages((volatile struct pml4 *)ctx->pml4, vaddr,
+ // phys_pages.pagestart, flags, phys_pages.num_pages)) {
+ // goto mem_alloc_pages_at_fail;
+ // }
+ // }
+ //
+ // return virt;
+ //
+ //mem_alloc_pages_at_fail:
+ // while (prev_phys_block.pagestart) {
+ // void *virtpage = kmapaddr(prev_phys_block.pagestart, NULL, 1,
+ // F_PRESENT | F_WRITEABLE);
+ // if (!virtpage) {
+ // // memory corruption, most likely a bug
+ // // could also ERROR here and exit with leak
+ // panic("unable to free memory from failed mem_alloc_pages_at call");
+ // }
+ // struct phys_page_slice prev = *(struct phys_page_slice *)virtpage;
+ // prev_phys_block = prev;
+ // free_phys_pages_slice(prev);
+ // kunmapaddr(virtpage);
+ // }
+ //
+ // return NULL;
}
void mem_free_pages(mem_ctx_t ctx, const void *virt)
diff --git a/kernel/memory/physalloc.c b/kernel/memory/physalloc.c
index 8971bcf..7551c75 100644
--- a/kernel/memory/physalloc.c
+++ b/kernel/memory/physalloc.c
@@ -1,11 +1,14 @@
#include <lib.h>
#include <comus/memory.h>
#include <comus/asm.h>
+#include <comus/mboot.h>
+#include <stdint.h>
#include "physalloc.h"
extern char kernel_start[];
extern char kernel_end[];
+static void *kernel_real_end = NULL;
// between memory_start and kernel_start will be the bitmap
static uintptr_t memory_start = 0;
@@ -26,19 +29,20 @@ static const char *segment_type_str[] = {
static int n_pages(const struct memory_segment *m)
{
- return m->len / PAGE_SIZE;
+ return (m->len + PAGE_SIZE - 1) / PAGE_SIZE;
}
-static void *page_at(int i)
+static void *page_at(size_t i)
{
- int cur_page = 0;
+ size_t cur_page = 0;
+ const struct memory_segment *m = page_start;
for (uint64_t idx = 0; idx < segment_count; idx++) {
- const struct memory_segment *m = page_start;
- int pages = n_pages(m);
+ size_t pages = n_pages(m);
if (i - cur_page < pages) {
return (void *)(m->addr + (PAGE_SIZE * (i - cur_page)));
}
cur_page += pages;
+ m++;
}
return NULL;
}
@@ -47,8 +51,8 @@ static long page_idx(void *page)
{
uintptr_t addr = (uintptr_t)page;
int cur_page = 0;
+ const struct memory_segment *m = page_start;
for (uint64_t idx = 0; idx < segment_count; idx++) {
- const struct memory_segment *m = page_start;
if (addr < m->addr) {
return -1;
}
@@ -56,13 +60,14 @@ static long page_idx(void *page)
return cur_page + ((addr - m->addr) / PAGE_SIZE);
}
cur_page += n_pages(m);
+ m++;
}
return -1;
}
static inline bool bitmap_get(size_t i)
{
- return (bitmap[i / 64] >> i % 64) & 1;
+ return (bitmap[i / 64] >> (i % 64)) & 1;
}
static inline void bitmap_set(size_t i, bool v)
@@ -71,9 +76,9 @@ static inline void bitmap_set(size_t i, bool v)
free_memory -= PAGE_SIZE;
else
free_memory += PAGE_SIZE;
- int idx = i / 64;
- bitmap[idx] &= ~(1 << i % 64);
- bitmap[idx] |= (v << i % 64);
+ size_t idx = i / 64;
+ bitmap[idx] &= ~(1 << (i % 64));
+ bitmap[idx] |= (v << (i % 64));
}
void *alloc_phys_page(void)
@@ -105,9 +110,17 @@ void *alloc_phys_pages_exact(size_t pages)
free_region_start = i;
n_contiguous++;
if (n_contiguous == pages) {
+ void *pADDR;
+ pADDR = page_at(free_region_start);
+
+ if (pADDR == NULL) {
+ n_contiguous = 0;
+ continue;
+ }
+
for (size_t j = 0; j < pages; j++)
bitmap_set(free_region_start + j, true);
- return page_at(free_region_start);
+ return pADDR;
}
} else
n_contiguous = 0;
@@ -118,6 +131,7 @@ void *alloc_phys_pages_exact(size_t pages)
struct phys_page_slice alloc_phys_page_withextra(size_t max_pages)
{
+ panic("please dont use this its broken i think?!\n");
if (max_pages == 0)
return PHYS_PAGE_SLICE_NULL;
@@ -160,6 +174,7 @@ void free_phys_page(void *ptr)
void free_phys_pages_slice(struct phys_page_slice slice)
{
+ panic("please dont use this its broken i think?!\n");
free_phys_pages(slice.pagestart, slice.num_pages);
}
@@ -200,7 +215,7 @@ static struct memory_segment clamp_segment(const struct memory_segment *segment)
if (memory_start)
start = memory_start;
else
- start = (uintptr_t)kernel_end;
+ start = (uintptr_t)kernel_real_end;
if (segment->addr < start) {
addr = start;
@@ -232,6 +247,10 @@ void physalloc_init(struct memory_map *map)
segment_count = 0;
+ kernel_real_end = mboot_end();
+ if ((char *)kernel_real_end < kernel_end)
+ kernel_real_end = kernel_end;
+
for (uint32_t i = 0; i < map->entry_count; i++) {
struct memory_segment *segment = &map->entries[i];
@@ -245,7 +264,7 @@ void physalloc_init(struct memory_map *map)
long bitmap_pages = (page_count / 64 / PAGE_SIZE) + 1;
long bitmap_size = bitmap_pages * PAGE_SIZE;
- bitmap = (uint64_t *)page_align((uintptr_t)kernel_end);
+ bitmap = (uint64_t *)page_align((uintptr_t)kernel_real_end);
long page_area_size = segment_count * sizeof(struct memory_segment);
char *page_area_addr = (char *)bitmap + bitmap_size;
diff --git a/kernel/memory/virtalloc.c b/kernel/memory/virtalloc.c
index 0cbba33..3d60a9f 100644
--- a/kernel/memory/virtalloc.c
+++ b/kernel/memory/virtalloc.c
@@ -1,10 +1,12 @@
-#include "lib/kio.h"
#include <lib.h>
#include <comus/memory.h>
#include <stdint.h>
#include "virtalloc.h"
+extern char kernel_start[];
+extern char kernel_end[];
+
static struct virt_addr_node *get_node_idx(struct virt_ctx *ctx, int idx)
{
if (idx < BOOTSTRAP_VIRT_ALLOC_NODES) {
@@ -64,6 +66,7 @@ static struct virt_addr_node *get_node(struct virt_ctx *ctx)
for (; idx < count; idx++) {
struct virt_addr_node *node = get_node_idx(ctx, idx);
if (!node->is_used) {
+ node->is_used = true;
ctx->used_node_count++;
return node;
}
@@ -81,7 +84,7 @@ static void free_node(struct virt_ctx *ctx, struct virt_addr_node *node)
void virtaddr_init(struct virt_ctx *ctx)
{
struct virt_addr_node init = {
- .start = 0x50000000,
+ .start = 0x0,
.end = 0x1000000000000, // 48bit memory address max
.next = NULL,
.prev = NULL,
@@ -96,6 +99,10 @@ void virtaddr_init(struct virt_ctx *ctx)
ctx->alloc_node_count = 0;
ctx->used_node_count = 0;
ctx->is_allocating = false;
+
+ virtaddr_take(ctx, (void *)0,
+ ((uint64_t)kernel_end + PAGE_SIZE - 1) / PAGE_SIZE *
+ PAGE_SIZE);
}
int virtaddr_clone(struct virt_ctx *old, struct virt_ctx *new)
@@ -138,32 +145,31 @@ int virtaddr_clone(struct virt_ctx *old, struct virt_ctx *new)
static void merge_back(struct virt_ctx *ctx, struct virt_addr_node *node)
{
- while (node->prev) {
- if (node->is_alloc != node->prev->is_alloc)
+ struct virt_addr_node *prev;
+ for (prev = node->prev; prev != NULL; prev = prev->prev) {
+ if (prev->is_alloc)
break;
- struct virt_addr_node *temp = node->prev;
- node->start = temp->start;
- node->prev = temp->prev;
- if (temp->prev)
- temp->prev->next = node;
- free_node(ctx, temp);
+ node->start = prev->start;
+ node->prev = prev->prev;
+ if (node->prev)
+ node->prev->next = node;
+ free_node(ctx, prev);
}
- if (node->prev == NULL) {
+ if (node->prev == NULL)
ctx->start_node = node;
- }
}
static void merge_forward(struct virt_ctx *ctx, struct virt_addr_node *node)
{
- while (node->next) {
- if (node->is_alloc != node->next->is_alloc)
+ struct virt_addr_node *next;
+ for (next = node->next; next != NULL; next = next->next) {
+ if (next->is_alloc)
break;
- struct virt_addr_node *temp = node->next;
- node->end = temp->end;
- node->next = temp->next;
- if (temp->next)
- temp->next->prev = node;
- free_node(ctx, temp);
+ node->end = next->end;
+ node->next = next->next;
+ if (node->next)
+ node->next->prev = node;
+ free_node(ctx, next);
}
}
@@ -211,9 +217,9 @@ int virtaddr_take(struct virt_ctx *ctx, const void *virt, int n_pages)
left->prev = node->prev;
left->start = node->start;
left->end = (uintptr_t)virt;
- left->is_used = true;
left->is_alloc = false;
- node->prev->next = left;
+ if (node->prev)
+ node->prev->next = left;
node->prev = left;
}
@@ -224,16 +230,15 @@ int virtaddr_take(struct virt_ctx *ctx, const void *virt, int n_pages)
right->next = node->next;
right->start = (uintptr_t)virt + n_length;
right->end = node->end;
- right->is_used = true;
right->is_alloc = false;
- node->next->prev = right;
+ if (node->next)
+ node->next->prev = right;
node->next = right;
}
node->start = (uintptr_t)virt;
node->end = node->start + n_length;
node->is_alloc = true;
- node->is_used = true;
return 0;
}
@@ -257,6 +262,7 @@ long virtaddr_free(struct virt_ctx *ctx, const void *virtaddr)
if (node->start == virt) {
int length = node->end - node->start;
int pages = length / PAGE_SIZE;
+ node->is_alloc = false;
merge_back(ctx, node);
merge_forward(ctx, node);
return pages;
diff --git a/kernel/memory/virtalloc.h b/kernel/memory/virtalloc.h
index 5033242..44bf8d7 100644
--- a/kernel/memory/virtalloc.h
+++ b/kernel/memory/virtalloc.h
@@ -13,7 +13,7 @@
#include <stdint.h>
#include <stdbool.h>
-#define BOOTSTRAP_VIRT_ALLOC_NODES 64
+#define BOOTSTRAP_VIRT_ALLOC_NODES 256
struct virt_addr_node {
/// first virtural address
diff --git a/kernel/procs.c b/kernel/procs.c
index 9bf7508..6017e3a 100644
--- a/kernel/procs.c
+++ b/kernel/procs.c
@@ -218,7 +218,7 @@ void pcb_zombify(struct pcb *victim)
status = (int *)PCB_ARG2(parent);
if (pid == 0 || pid == victim->pid) {
- PCB_RET(parent) = zchild->pid;
+ PCB_RET(parent) = victim->pid;
assert(
pcb_queue_remove(syscall_queue[SYS_waitpid], parent) == SUCCESS,
diff --git a/kernel/syscall.c b/kernel/syscall.c
index d98f886..8ed7631 100644
--- a/kernel/syscall.c
+++ b/kernel/syscall.c
@@ -1,3 +1,5 @@
+#include "comus/fs.h"
+#include "lib/kio.h"
#include <comus/user.h>
#include <comus/cpu.h>
#include <comus/syscalls.h>
@@ -24,6 +26,16 @@ static struct pcb *pcb;
#define stdout 1
#define stderr 2
+static struct file *get_file_ptr(int fd)
+{
+ // valid index?
+ if (fd < 3 || fd >= (N_OPEN_FILES + 3))
+ return NULL;
+
+ // will be NULL if not open
+ return pcb->open_files[fd - 3];
+}
+
__attribute__((noreturn)) static int sys_exit(void)
{
ARG1(int, status);
@@ -37,6 +49,33 @@ __attribute__((noreturn)) static int sys_exit(void)
static int sys_waitpid(void)
{
+ ARG1(pid_t, pid);
+ ARG2(int *, status);
+
+ struct pcb *child;
+ for (int i = 0; i < N_PROCS; i++) {
+ child = &ptable[i];
+ if (child->state != PROC_STATE_ZOMBIE)
+ continue;
+ if (child->parent != pcb)
+ continue;
+
+ // we found a child!
+ if (pid && pid != child->pid)
+ continue;
+
+ // set status
+ mem_ctx_switch(pcb->memctx);
+ *status = child->exit_status;
+ mem_ctx_switch(kernel_mem_ctx);
+
+ // clean up child process
+ pcb_cleanup(child);
+
+ // return
+ return child->pid;
+ }
+
// arguments are read later
// by procs.c
pcb->state = PROC_STATE_BLOCKED;
@@ -61,6 +100,125 @@ static int sys_fork(void)
return 0;
}
+static int sys_exec(void)
+{
+ ARG1(const char *, in_filename);
+ ARG2(const char **, in_args);
+
+ struct file_system *fs;
+ struct file *file;
+ char filename[N_FILE_NAME];
+ struct pcb save;
+
+ // save data
+ file = NULL;
+ save = *pcb;
+
+ // read filename
+ mem_ctx_switch(pcb->memctx);
+ memcpy(filename, in_filename, strlen(in_filename) + 1);
+ mem_ctx_switch(kernel_mem_ctx);
+
+ // get binary
+ fs = fs_get_root_file_system();
+ if (fs == NULL)
+ goto fail;
+ if (fs->open(fs, filename, O_RDONLY, &file))
+ goto fail;
+
+ // load program
+ save = *pcb;
+ if (user_load(pcb, file, in_args, save.memctx))
+ goto fail;
+ file->close(file);
+ mem_ctx_free(save.memctx);
+ schedule(pcb);
+ dispatch();
+
+fail:
+ *pcb = save;
+ if (file)
+ file->close(file);
+ return 1;
+}
+
+static int sys_open(void)
+{
+ ARG1(const char *, in_filename);
+ ARG2(int, flags);
+
+ char filename[N_FILE_NAME];
+ struct file_system *fs;
+ struct file **file;
+ int fd;
+
+ // read filename
+ mem_ctx_switch(pcb->memctx);
+ memcpy(filename, in_filename, strlen(in_filename));
+ mem_ctx_switch(kernel_mem_ctx);
+
+ // get fd
+ for (fd = 3; fd < (N_OPEN_FILES + 3); fd++) {
+ if (pcb->open_files[fd - 3] == NULL) {
+ file = &pcb->open_files[fd - 3];
+ break;
+ }
+ }
+
+ // could not find fd
+ if (fd == (N_OPEN_FILES + 3))
+ return -1;
+
+ // open file
+ fs = fs_get_root_file_system();
+ if (fs == NULL)
+ return -1;
+ if (fs->open(fs, filename, flags, file))
+ return -1;
+
+ // file opened
+ return fd;
+}
+
+static int sys_close(void)
+{
+ ARG1(int, fd);
+
+ struct file *file;
+ file = get_file_ptr(fd);
+ if (file == NULL)
+ return 1;
+
+ file->close(file);
+ return 0;
+}
+
+static int sys_read(void)
+{
+ ARG1(int, fd);
+ ARG2(void *, buffer);
+ ARG3(size_t, nbytes);
+
+ struct file *file;
+ char *map_buf;
+
+ map_buf = kmapuseraddr(pcb->memctx, buffer, nbytes);
+ if (map_buf == NULL)
+ return -1;
+
+ file = get_file_ptr(fd);
+ if (file == NULL)
+ goto fail;
+
+ nbytes = file->read(file, map_buf, nbytes);
+ kunmapaddr(map_buf);
+ return nbytes;
+
+fail:
+ kunmapaddr(map_buf);
+ return -1;
+}
+
static int sys_write(void)
{
ARG1(int, fd);
@@ -418,31 +576,38 @@ static int sys_keypoll(void)
return 0;
}
+static int sys_seek(void)
+{
+ RET(long int, ret);
+ ARG1(int, fd);
+ ARG2(long int, off);
+ ARG3(int, whence);
+
+ struct file *file;
+ file = get_file_ptr(fd);
+ if (file == NULL)
+ return -1;
+
+ *ret = file->seek(file, off, whence);
+ return 0;
+}
+
+// clang-format off
static int (*syscall_tbl[N_SYSCALLS])(void) = {
- [SYS_exit] = sys_exit,
- [SYS_waitpid] = sys_waitpid,
- [SYS_fork] = sys_fork,
- [SYS_exec] = NULL,
- [SYS_open] = NULL,
- [SYS_close] = NULL,
- [SYS_read] = NULL,
- [SYS_write] = sys_write,
- [SYS_getpid] = sys_getpid,
- [SYS_getppid] = sys_getppid,
- [SYS_gettime] = sys_gettime,
- [SYS_getprio] = sys_getprio,
- [SYS_setprio] = sys_setprio,
- [SYS_kill] = sys_kill,
- [SYS_sleep] = sys_sleep,
- [SYS_brk] = sys_brk,
- [SYS_sbrk] = sys_sbrk,
- [SYS_poweroff] = sys_poweroff,
- [SYS_drm] = sys_drm,
- [SYS_ticks] = sys_ticks,
- [SYS_allocshared] = sys_allocshared,
- [SYS_popsharedmem] = sys_popsharedmem,
- [SYS_keypoll] = sys_keypoll,
+ [SYS_exit] = sys_exit, [SYS_waitpid] = sys_waitpid,
+ [SYS_fork] = sys_fork, [SYS_exec] = sys_exec,
+ [SYS_open] = sys_open, [SYS_close] = sys_close,
+ [SYS_read] = sys_read, [SYS_write] = sys_write,
+ [SYS_getpid] = sys_getpid, [SYS_getppid] = sys_getppid,
+ [SYS_gettime] = sys_gettime, [SYS_getprio] = sys_getprio,
+ [SYS_setprio] = sys_setprio, [SYS_kill] = sys_kill,
+ [SYS_sleep] = sys_sleep, [SYS_brk] = sys_brk,
+ [SYS_sbrk] = sys_sbrk, [SYS_poweroff] = sys_poweroff,
+ [SYS_drm] = sys_drm, [SYS_ticks] = sys_ticks,
+ [SYS_seek] = sys_seek, [SYS_allocshared] = sys_allocshared,
+ [SYS_popsharedmem] = sys_popsharedmem, [SYS_keypoll] = sys_keypoll,
};
+// clang-format on
void syscall_handler(void)
{
diff --git a/kernel/term.c b/kernel/term.c
index 917f645..88fa072 100644
--- a/kernel/term.c
+++ b/kernel/term.c
@@ -7,8 +7,10 @@
// terminal data
static char buffer[TERM_MAX_WIDTH * TERM_MAX_HEIGHT];
static uint16_t buffer_line = UINT16_MAX;
-static uint16_t width = 80; // baseline vga text mode until resized
-static uint16_t height = 25;
+static uint16_t last_width = 80,
+ width = 80; // baseline vga text mode until resized
+static uint16_t last_height = 25, height = 25;
+static uint16_t scrolling = 0;
static uint16_t x = 0;
static uint16_t y = 0;
@@ -140,10 +142,26 @@ void term_redraw(void)
for (uint16_t j = 0; j < height; j++) {
for (uint16_t i = 0; i < width; i++) {
- char c = buffer[BUFIDX(i, j)];
+ char c;
+
+ c = buffer[BUFIDX(i, j)];
+
+ // if screen hasnet changed size
+ // dont redraw what we dont need to redraw
+ if (last_width == height && last_width == width) {
+ char prev;
+ prev = buffer[BUFIDX(i, (j - scrolling))];
+ if (c == prev)
+ continue;
+ }
+
gpu_draw_char(c, i, j);
}
}
+
+ last_width = width;
+ last_height = height;
+ scrolling = 0;
}
void term_scroll(uint16_t lines)
@@ -151,6 +169,8 @@ void term_scroll(uint16_t lines)
if (!lines)
return;
buffer_line += lines;
+ term_clear_line(y);
+ scrolling = lines;
term_redraw();
}
diff --git a/kernel/user.c b/kernel/user.c
index e22248a..27b46df 100644
--- a/kernel/user.c
+++ b/kernel/user.c
@@ -1,3 +1,4 @@
+#include "lib/kio.h"
#include <comus/fs.h>
#include <comus/procs.h>
#include <comus/memory.h>
@@ -20,7 +21,7 @@ static uint8_t *load_buffer = NULL;
#define USER_DATA 0x20
#define RING3 3
-static int user_load_segment(struct pcb *pcb, struct disk *disk, int idx)
+static int user_load_segment(struct pcb *pcb, struct file *file, int idx)
{
Elf64_Phdr hdr;
size_t mem_bytes, mem_pages;
@@ -49,12 +50,22 @@ static int user_load_segment(struct pcb *pcb, struct disk *disk, int idx)
// allocate memory in user process
if (mem_alloc_pages_at(pcb->memctx, mem_pages, (void *)hdr.p_vaddr,
- F_WRITEABLE | F_UNPRIVILEGED) == NULL)
+ F_WRITEABLE | F_UNPRIVILEGED) == NULL) {
+ ERROR("Could not allocate memory for elf segment");
return 1;
+ }
mapADDR = kmapuseraddr(pcb->memctx, (void *)hdr.p_vaddr, mem_bytes);
- if (mapADDR == NULL)
+ if (mapADDR == NULL) {
+ ERROR("Could load memory for elf segment");
return 1;
+ }
+
+ // seek to start of segment
+ if (file->seek(file, hdr.p_offset, SEEK_SET) < 0) {
+ ERROR("Could not load elf segment");
+ return 1;
+ }
// load data
size_t total_read = 0;
@@ -62,12 +73,14 @@ static int user_load_segment(struct pcb *pcb, struct disk *disk, int idx)
size_t read = BLOCK_SIZE;
if (read > file_bytes - total_read)
read = file_bytes - total_read;
- if ((read = disk_read(disk, hdr.p_offset + total_read, read,
- load_buffer)) < 1) {
+ TRACE("Reading %zu bytes...", read);
+ if ((read = file->read(file, load_buffer, read)) < 1) {
kunmapaddr(mapADDR);
+ ERROR("Could not load elf segment");
return 1;
}
- memcpy(mapADDR + total_read, load_buffer, read);
+ TRACE("Read %zu bytes", read);
+ memcpyv(mapADDR + total_read, load_buffer, read);
total_read += read;
}
@@ -79,19 +92,24 @@ static int user_load_segment(struct pcb *pcb, struct disk *disk, int idx)
return 0;
}
-static int user_load_segments(struct pcb *pcb, struct disk *disk)
+static int user_load_segments(struct pcb *pcb, struct file *file)
{
int ret = 0;
pcb->heap_start = NULL;
pcb->heap_len = 0;
- if (load_buffer == NULL)
- if ((load_buffer = kalloc(BLOCK_SIZE)) == NULL)
+ if (load_buffer == NULL) {
+ load_buffer = kalloc(BLOCK_SIZE);
+ if (load_buffer == NULL) {
+ ERROR("Could not allocate user load buffer");
return 1;
+ }
+ }
+ TRACE("Loading %u elf segments", pcb->n_elf_segments);
for (int i = 0; i < pcb->n_elf_segments; i++)
- if ((ret = user_load_segment(pcb, disk, i)))
+ if ((ret = user_load_segment(pcb, file, i)))
return ret;
if (pcb->heap_start == NULL) {
@@ -107,12 +125,12 @@ static int validate_elf_hdr(struct pcb *pcb)
Elf64_Ehdr *ehdr = &pcb->elf_header;
if (strncmp((const char *)ehdr->e_ident, ELFMAG, SELFMAG)) {
- WARN("Invalid ELF File.");
+ ERROR("Invalid ELF File.");
return 1;
}
if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) {
- WARN("Unsupported ELF Class.");
+ ERROR("Unsupported ELF Class.");
return 1;
}
@@ -122,17 +140,17 @@ static int validate_elf_hdr(struct pcb *pcb)
}
if (ehdr->e_machine != EM_X86_64) {
- WARN("Unsupported ELF File target.");
+ ERROR("Unsupported ELF File target.");
return 1;
}
if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
- WARN("Unsupported ELF File version.");
+ ERROR("Unsupported ELF File version.");
return 1;
}
if (ehdr->e_phnum > N_ELF_SEGMENTS) {
- WARN("Too many ELF segments.");
+ ERROR("Too many ELF segments.");
return 1;
}
@@ -144,35 +162,90 @@ static int validate_elf_hdr(struct pcb *pcb)
return 0;
}
-static int user_load_elf(struct pcb *pcb, struct disk *disk)
+static int user_load_elf(struct pcb *pcb, struct file *file)
{
int ret = 0;
- ret = disk_read(disk, 0, sizeof(Elf64_Ehdr), &pcb->elf_header);
- if (ret < 0)
+ if (file->seek(file, 0, SEEK_SET) < 0) {
+ ERROR("Cannot read ELF header.");
return 1;
+ }
+ ret = file->read(file, &pcb->elf_header, sizeof(Elf64_Ehdr));
+ if (ret < 0) {
+ ERROR("Cannot read ELF header.");
+ return 1;
+ }
if (validate_elf_hdr(pcb))
return 1;
pcb->n_elf_segments = pcb->elf_header.e_phnum;
- ret = disk_read(disk, pcb->elf_header.e_phoff,
- sizeof(Elf64_Phdr) * pcb->elf_header.e_phnum,
- &pcb->elf_segments);
- if (ret < 0)
+ if (file->seek(file, pcb->elf_header.e_phoff, SEEK_SET) < 0) {
+ ERROR("Cannot read ELF segemts");
return 1;
+ }
+ ret = file->read(file, &pcb->elf_segments,
+ sizeof(Elf64_Phdr) * pcb->elf_header.e_phnum);
+ if (ret < 0) {
+ ERROR("Cannot read ELF segemts");
+ return 1;
+ }
return 0;
}
-static int user_setup_stack(struct pcb *pcb)
+static int user_setup_stack(struct pcb *pcb, const char **args,
+ mem_ctx_t args_ctx)
{
- // allocate stack
+ /* args */
+ int argbytes = 0;
+ int argc = 0;
+
+ mem_ctx_switch(args_ctx);
+
+ while (args[argc] != NULL) {
+ int n = strlen(args[argc]) + 1;
+ if ((argbytes + n) > USER_STACK_LEN) {
+ // oops - ignore this and any others
+ break;
+ }
+ argbytes += n;
+ argc++;
+ }
+
+ // round to nearest multiple of 8
+ argbytes = (argbytes + 7) & 0xfffffffffffffff8;
+
+ // allocate arg strings on kernel stack
+ char argstrings[argbytes];
+ char *argv[argc + 1];
+ memset(argstrings, 0, sizeof(argstrings));
+ memset(argv, 0, sizeof(argv));
+
+ // Next, duplicate the argument strings, and create pointers to
+ // each one in our argv.
+ char *tmp = argstrings;
+ for (int i = 0; i < argc; ++i) {
+ int nb = strlen(args[i]) + 1;
+ strcpy(tmp, args[i]);
+ argv[i] = tmp;
+ tmp += nb;
+ }
+
+ // trailing NULL pointer
+ argv[argc] = NULL;
+
+ mem_ctx_switch(kernel_mem_ctx);
+
+ /* stack */
if (mem_alloc_pages_at(pcb->memctx, USER_STACK_LEN / PAGE_SIZE,
(void *)(USER_STACK_TOP - USER_STACK_LEN),
- F_WRITEABLE | F_UNPRIVILEGED) == NULL)
+ F_WRITEABLE | F_UNPRIVILEGED) == NULL) {
+ ERROR("Could not allocate user stack");
return 1;
+ }
+ /* regs */
memset(&pcb->regs, 0, sizeof(struct cpu_regs));
// pgdir
@@ -183,7 +256,7 @@ static int user_setup_stack(struct pcb *pcb)
pcb->regs.es = USER_DATA | RING3;
pcb->regs.ds = USER_DATA | RING3;
// registers
- pcb->regs.rdi = 0; // argc
+ pcb->regs.rdi = argc; // argc
pcb->regs.rsi = 0; // argv
// intruction pointer
pcb->regs.rip = pcb->elf_header.e_entry;
@@ -199,10 +272,11 @@ static int user_setup_stack(struct pcb *pcb)
return 0;
}
-int user_load(struct pcb *pcb, struct disk *disk)
+int user_load(struct pcb *pcb, struct file *file, const char **args,
+ mem_ctx_t args_ctx)
{
// check inputs
- if (pcb == NULL || disk == NULL)
+ if (pcb == NULL || file == NULL)
return 1;
// allocate memory context
@@ -211,15 +285,15 @@ int user_load(struct pcb *pcb, struct disk *disk)
goto fail;
// load elf information
- if (user_load_elf(pcb, disk))
+ if (user_load_elf(pcb, file))
goto fail;
// load segments into memory
- if (user_load_segments(pcb, disk))
+ if (user_load_segments(pcb, file))
goto fail;
// setup process stack
- if (user_setup_stack(pcb))
+ if (user_setup_stack(pcb, args, args_ctx))
goto fail;
// success
diff --git a/user/include/stdio.h b/user/include/stdio.h
index fe29c9d..bb57c6d 100644
--- a/user/include/stdio.h
+++ b/user/include/stdio.h
@@ -252,7 +252,7 @@ extern size_t fwrite(const void *restrict ptr, size_t size, size_t n,
* @param stream - the stream to seek
* @param off - the offset from whence
* @param whence - where to seek from (SEEK_SET, SEEK_CUR, SEEK_END)
- * @returns 0 on success, -1 on error setting errno
+ * @returns new offset on success, -1 on error
*/
extern int fseek(FILE *stream, long int off, int whence);
@@ -260,9 +260,9 @@ extern int fseek(FILE *stream, long int off, int whence);
* return the current position of stream
*
* @param stream - the stream to tell
- * @return the position on success, -1 on error setting errno
+ * @returns new offset on success, -1 on error
*/
-extern long int ftell(FILE *stream);
+extern long ftell(FILE *stream);
/**
* rewing to the begining of a stream
diff --git a/user/include/sys/types.h b/user/include/sys/types.h
new file mode 100644
index 0000000..f1b3266
--- /dev/null
+++ b/user/include/sys/types.h
@@ -0,0 +1,15 @@
+/**
+ * @file types.h
+ *
+ * @author Freya Murphy <freya@freyacat.org>
+ *
+ * System types
+ */
+
+#ifndef _TYPES_H
+#define _TYPES_H
+
+typedef long int off_t;
+typedef unsigned short pid_t;
+
+#endif /* types.h */
diff --git a/user/include/unistd.h b/user/include/unistd.h
index e817c84..c54cd20 100644
--- a/user/include/unistd.h
+++ b/user/include/unistd.h
@@ -11,6 +11,7 @@
#include <stdint.h>
#include <stddef.h>
+#include <sys/types.h>
/* System Call Definitions */
@@ -33,7 +34,7 @@ enum {
O_RDONLY = 0x02,
O_WRONLY = 0x04,
O_APPEND = 0x08,
- O_RDWR = O_RDONLY | O_WRONLY,
+ O_RDWR = 0x010,
};
/**
@@ -73,11 +74,9 @@ extern int fork(void);
*
* @param prog - program table index of the program to exec
* @param args - the command-line argument vector
- *
- * Does not return if it succeeds; if it returns, something has
- * gone wrong.
+ * @returns error code on failure
*/
-extern void exec(const char *filename, char **args);
+extern int exec(const char *filename, const char **args);
/**
* open a stream with a given filename
@@ -91,8 +90,9 @@ extern int open(const char *filename, int flags);
* closes a stream with the given file descriptior
*
* @param fd - the file descriptior of the open stream
+ * @returns 0 on success, error code on invalid fd
*/
-extern void close(int fd);
+extern int close(int fd);
/**
* read into a buffer from a stream
@@ -122,7 +122,7 @@ extern int write(int fd, const void *buffer, size_t nbytes);
* @param whence - whence to seek
* @return 0 on success, or an error code
*/
-extern int seek(int fd, long int off, int whence);
+extern off_t seek(int fd, off_t off, int whence);
/**
* gets the pid of the calling process
diff --git a/user/init.c b/user/init.c
new file mode 100644
index 0000000..51d8f92
--- /dev/null
+++ b/user/init.c
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <unistd.h>
+
+#define MAX_ARGS 4
+
+static long running = 0;
+
+struct proc {
+ pid_t pid;
+ const char *filename;
+ const char *args[MAX_ARGS];
+};
+
+static struct proc spawn_table[] = {
+ // apple
+ { 0, "bin/apple", { NULL } },
+ // end,
+ { 0, NULL, { NULL } },
+};
+
+static int spawn(const char *filename, const char **args)
+{
+ int ret;
+
+ // fork init
+ if ((ret = fork()) != 0)
+ return ret;
+
+ // call exec
+ if ((ret = exec(filename, args)))
+ exit(ret);
+
+ // should not happen!
+ exit(1);
+}
+
+static void spawn_proc(struct proc *proc)
+{
+ int ret;
+
+ // update running on respawn
+ if (proc->pid)
+ running--;
+
+ // attempt to fork / exec
+ ret = spawn(proc->filename, proc->args);
+
+ // handle result
+ if (ret < 0) {
+ printf("init: cannot exec '%s': %d\n", proc->filename, ret);
+ proc->pid = 0;
+ } else {
+ running++;
+ proc->pid = ret;
+ }
+}
+
+static void spawn_proc_loop(struct proc *proc)
+{
+ while (proc->pid == 0)
+ spawn_proc(proc);
+}
+
+static void spawn_all(void)
+{
+ struct proc *proc;
+ for (proc = spawn_table; proc->filename != NULL; proc++) {
+ spawn_proc_loop(proc);
+ }
+}
+
+static struct proc *get_proc(pid_t pid)
+{
+ struct proc *proc;
+ for (proc = spawn_table; proc->filename != NULL; proc++) {
+ if (proc->pid == pid)
+ return proc;
+ }
+ return NULL;
+}
+
+int main(void)
+{
+ // spawn our processes
+ spawn_all();
+
+ // clean up dead on restart ours
+ while (1) {
+ struct proc *proc;
+ int pid, status;
+
+ // dont wait if nothing running
+ if (running) {
+ pid = waitpid(0, &status);
+ // ???
+ if (pid < 0)
+ continue;
+ } else {
+ spawn_all();
+ continue;
+ }
+
+ printf("init: pid %d exited with %d\n", pid, status);
+
+ // figure out if this is one of ours
+ proc = get_proc(pid);
+ if (proc == NULL)
+ continue;
+
+ spawn_proc_loop(proc);
+ }
+
+ // failed to launch anythingvery very bad!
+ return 1;
+}
diff --git a/user/lib/entry.S b/user/lib/entry.S
index 40570b5..efaa652 100644
--- a/user/lib/entry.S
+++ b/user/lib/entry.S
@@ -5,7 +5,6 @@
.section .text
.code64
_start:
- call main
- subq $16, %rsp # ???
- pushq %rax
+ call main
+ movq %rax, %rdi
call exit
diff --git a/user/lib/fclose.c b/user/lib/fclose.c
new file mode 100644
index 0000000..be31421
--- /dev/null
+++ b/user/lib/fclose.c
@@ -0,0 +1,10 @@
+#include <stdio.h>
+#include <unistd.h>
+
+void fclose(FILE *stream)
+{
+ int fd;
+
+ fd = (uintptr_t)stream;
+ close(fd);
+}
diff --git a/user/lib/fseek.c b/user/lib/fseek.c
new file mode 100644
index 0000000..a7a3377
--- /dev/null
+++ b/user/lib/fseek.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+#include <unistd.h>
+
+int fseek(FILE *stream, long off, int whence)
+{
+ int fd;
+ fd = (uintptr_t)stream;
+ return seek(fd, off, whence);
+}
+
+long ftell(FILE *stream)
+{
+ int fd;
+ fd = (uintptr_t)stream;
+ return seek(fd, 0, SEEK_CUR);
+}
diff --git a/user/lib/syscall.S b/user/lib/syscall.S
index 93b7daa..c45f641 100644
--- a/user/lib/syscall.S
+++ b/user/lib/syscall.S
@@ -13,6 +13,8 @@ SYSCALL exit SYS_exit
SYSCALL waitpid SYS_waitpid
SYSCALL fork SYS_fork
SYSCALL exec SYS_exec
+SYSCALL open SYS_open
+SYSCALL close SYS_close
SYSCALL read SYS_read
SYSCALL write SYS_write
SYSCALL getpid SYS_getpid
@@ -27,6 +29,7 @@ SYSCALL sbrk SYS_sbrk
SYSCALL poweroff SYS_poweroff
SYSCALL drm SYS_drm
SYSCALL ticks SYS_ticks
+SYSCALL seek SYS_seek
SYSCALL allocshared SYS_allocshared
SYSCALL popsharedmem SYS_popsharedmem
SYSCALL keypoll SYS_keypoll