summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/typedefs.h8
-rw-r--r--kernel/Makefile10
-rw-r--r--kernel/arch/i386/mmu.c6
-rw-r--r--kernel/cpu/idt.c8
-rw-r--r--kernel/cpu/int_syscall.s1
-rw-r--r--kernel/cpu/syscall.c56
-rw-r--r--kernel/drivers/mouse.c2
-rw-r--r--kernel/drivers/rtl8139.c5
-rw-r--r--kernel/fs/ext2.c4
-rw-r--r--kernel/fs/fifo.c4
-rw-r--r--kernel/fs/tmpfs.c8
-rw-r--r--kernel/fs/vfs.c33
-rw-r--r--kernel/includes/mmu.h4
-rw-r--r--kernel/includes/syscalls.h5
-rw-r--r--kernel/init/kernel.c60
-rw-r--r--kernel/ipc.c19
-rw-r--r--kernel/kmalloc.c12
-rw-r--r--kernel/lib/list.c5
-rw-r--r--kernel/lib/list.h2
-rw-r--r--kernel/lib/stack.c1
-rw-r--r--kernel/libc/exit/assert.c1
-rw-r--r--kernel/libc/string/copy.c2
-rw-r--r--kernel/log.c4
-rw-r--r--kernel/network/arp.c23
-rw-r--r--kernel/network/arp.h1
-rw-r--r--kernel/network/ethernet.c1
-rw-r--r--kernel/network/tcp.c9
-rw-r--r--kernel/poll.c24
-rw-r--r--kernel/queue.c81
-rw-r--r--kernel/queue.h25
-rw-r--r--kernel/sched/scheduler.c67
-rw-r--r--kernel/sched/scheduler.h9
-rw-r--r--kernel/socket.c178
-rw-r--r--kernel/syscalls/getcwd.c4
-rw-r--r--kernel/syscalls/install_irq.c2
-rw-r--r--kernel/syscalls/msleep.c2
-rw-r--r--kernel/syscalls/queue.c14
-rwxr-xr-xmeta/userland.sh2
-rw-r--r--userland/libc/include/syscall.h8
-rw-r--r--userland/terminal/term.c130
40 files changed, 647 insertions, 193 deletions
diff --git a/include/typedefs.h b/include/typedefs.h
index e2226fd..c10482c 100644
--- a/include/typedefs.h
+++ b/include/typedefs.h
@@ -1,3 +1,5 @@
+#ifndef TYPEDEFS_H
+#define TYPEDEFS_H
#include <stdint.h>
typedef uint8_t u8;
@@ -10,4 +12,10 @@ typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
+typedef union {
+ u8 a[4];
+ u32 d;
+} ipv4_t;
+
#define U32_MAX 4294967295
+#endif
diff --git a/kernel/Makefile b/kernel/Makefile
index 8f2cd3d..71ea761 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -1,11 +1,13 @@
CC="i686-sb-gcc"
AS="i686-sb-as"
-OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o ipc.o syscalls/ipc.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o
-#CFLAGS = -std=c99 -Ofast -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
-CFLAGS = -std=c99 -Ofast -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
+OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o ipc.o syscalls/ipc.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o arch/i386/interrupts.o cpu/isr.o lib/stack.o lib/buffered_write.o lib/list.o cpu/arch_inst.o cpu/int_syscall.o queue.o syscalls/queue.o
+CFLAGS = -std=c99 -Ofast -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
+#CFLAGS = -std=c99 -Ofast -flto -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
+#CFLAGS = -std=c99 -O0 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
+#CFLAGS = -std=c99 -Ofast -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
#CFLAGS = -Ofast -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
#CFLAGS = -O0 -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
-LDFLAGS=-flto -Ofast
+#LDFLAGS=-flto -Ofast
LDFLAGS=
INCLUDE=-I./includes/ -I../include/ -I./libc/include/
diff --git a/kernel/arch/i386/mmu.c b/kernel/arch/i386/mmu.c
index 240c9ea..ad415a6 100644
--- a/kernel/arch/i386/mmu.c
+++ b/kernel/arch/i386/mmu.c
@@ -530,12 +530,12 @@ void move_stack(u32 new_stack_address, u32 size) {
// C strings have a unknown length so it does not makes sense to check
// for a size on the pointer. Instead we check whether the page it
// resides in is accessible to the user.
-void *is_valid_user_c_string(const char *ptr, size_t *size) {
+void *mmu_is_valid_user_c_string(const char *ptr, size_t *size) {
void *r = (void *)ptr;
size_t s = 0;
for (; ((u32)ptr - (u32)r) < 0x1000;) {
void *page = (void *)((uintptr_t)ptr & (uintptr_t)(~(PAGE_SIZE - 1)));
- if (!is_valid_userpointer(page, PAGE_SIZE)) {
+ if (!mmu_is_valid_userpointer(page, PAGE_SIZE)) {
return NULL;
}
if (!((uintptr_t)ptr & (PAGE_SIZE - 1))) {
@@ -556,7 +556,7 @@ void *is_valid_user_c_string(const char *ptr, size_t *size) {
return NULL;
}
-void *is_valid_userpointer(const void *ptr, size_t s) {
+void *mmu_is_valid_userpointer(const void *ptr, size_t s) {
uintptr_t t = (uintptr_t)ptr;
size_t num_pages = (uintptr_t)align_page((void *)s) / 0x1000;
for (size_t i = 0; i < num_pages; i++, t += 0x1000) {
diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c
index 805eb20..0d031f3 100644
--- a/kernel/cpu/idt.c
+++ b/kernel/cpu/idt.c
@@ -74,9 +74,9 @@ void page_fault(reg_t *regs) {
}
klog("Page Fault", LOG_ERROR);
kprintf("CR2: %x\n", cr2);
- if (get_current_task()) {
- kprintf("PID: %x\n", get_current_task()->pid);
- kprintf("Name: %s\n", get_current_task()->program_name);
+ if (current_task) {
+ kprintf("PID: %x\n", current_task->pid);
+ kprintf("Name: %s\n", current_task->program_name);
}
kprintf("Error Code: %x\n", regs->error_code);
kprintf("Instruction Pointer: %x\n", regs->eip);
@@ -101,7 +101,7 @@ void page_fault(reg_t *regs) {
kprintf("Attempted instruction fetch\n");
}
- dump_backtrace(12);
+ dump_backtrace(8);
halt();
}
diff --git a/kernel/cpu/int_syscall.s b/kernel/cpu/int_syscall.s
index 5fff75b..4d0ef2e 100644
--- a/kernel/cpu/int_syscall.s
+++ b/kernel/cpu/int_syscall.s
@@ -2,7 +2,6 @@
.global int_syscall
.extern syscall_functions
int_syscall:
-sti
push ebp
mov ebp,esp
push edi
diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c
index 193367e..c982648 100644
--- a/kernel/cpu/syscall.c
+++ b/kernel/cpu/syscall.c
@@ -9,6 +9,7 @@
#include <interrupts.h>
#include <kmalloc.h>
#include <network/ethernet.h>
+#include <socket.h>
#include <string.h>
#include <syscalls.h>
#include <typedefs.h>
@@ -73,22 +74,24 @@ void syscall_exit(int status) {
void syscall_wait(int *status) {
disable_interrupts();
- if (!get_current_task()->child) {
+ if (!current_task->child) {
if (status) {
*status = -1;
}
return;
}
- if (get_current_task()->child->dead) {
+ if (current_task->child->dead) {
if (status) {
- *status = get_current_task()->child_rc;
+ *status = current_task->child_rc;
}
return;
}
- get_current_task()->halts[WAIT_CHILD_HALT] = 1;
- switch_task();
+ do {
+ current_task->halts[WAIT_CHILD_HALT] = 1;
+ switch_task();
+ } while (current_task->halts[WAIT_CHILD_HALT]);
if (status) {
- *status = get_current_task()->child_rc;
+ *status = current_task->child_rc;
}
}
@@ -97,25 +100,24 @@ int syscall_fork(void) {
}
int syscall_getpid(void) {
- return get_current_task()->pid;
+ return current_task->pid;
}
void *align_page(void *a);
int syscall_brk(void *addr) {
- void *end = get_current_task()->data_segment_end;
+ void *end = current_task->data_segment_end;
if (!mmu_allocate_region(end, addr - end, MMU_FLAG_RW, NULL)) {
return -ENOMEM;
}
- get_current_task()->data_segment_end = align_page(addr);
+ current_task->data_segment_end = align_page(addr);
return 0;
}
void *syscall_sbrk(uintptr_t increment) {
disable_interrupts();
- void *rc = get_current_task()->data_segment_end;
- void *n =
- (void *)((uintptr_t)(get_current_task()->data_segment_end) + increment);
+ void *rc = current_task->data_segment_end;
+ void *n = (void *)((uintptr_t)(current_task->data_segment_end) + increment);
int rc2;
if (0 > (rc2 = syscall_brk(n))) {
return (void *)rc2;
@@ -128,11 +130,26 @@ int syscall_close(int fd) {
}
int syscall_openpty(SYS_OPENPTY_PARAMS *args) {
- assert(is_valid_userpointer(args, sizeof(SYS_OPENPTY_PARAMS)));
+ assert(mmu_is_valid_userpointer(args, sizeof(SYS_OPENPTY_PARAMS)));
return openpty(args->amaster, args->aslave, args->name, args->termp,
args->winp);
}
+u32 syscall_tcp_connect(u32 ip, u16 port, int *error) {
+ // TODO: Make sure error is a user address
+ return tcp_connect_ipv4(ip, port, error);
+}
+
+int syscall_tcp_write(u32 socket, const u8 *buffer, u32 len, u64 *out) {
+ // TODO: Make sure out is a user address
+ return tcp_write(socket, buffer, len, out);
+}
+
+int syscall_tcp_read(u32 socket, u8 *buffer, u32 buffer_size, u64 *out) {
+ // TODO: Make sure out is a user address
+ return tcp_read(socket, buffer, buffer_size, out);
+}
+
int (*syscall_functions[])() = {
(void(*))syscall_open,
(void(*))syscall_read,
@@ -180,14 +197,17 @@ int (*syscall_functions[])() = {
(void(*))syscall_virtual_to_physical,
(void(*))syscall_install_irq,
(void(*))syscall_tmp_handle_packet,
+
+ (void(*))syscall_tcp_connect,
+ (void(*))syscall_tcp_write,
+ (void(*))syscall_tcp_read,
+
+ (void(*))syscall_queue_create,
+ (void(*))syscall_queue_add,
+ (void(*))syscall_queue_wait,
};
void int_syscall(reg_t *r);
-void syscall_function_handler(u32 eax, u32 arg1, u32 arg2, u32 arg3, u32 arg4,
- u32 arg5, u32 ebp, u32 esp) {
- assert(eax < sizeof(syscall_functions) / sizeof(syscall_functions[0]));
- syscall_functions[eax](arg1, arg2, arg3, arg4, arg5);
-}
void syscalls_init(void) {
install_handler(int_syscall, INT_32_INTERRUPT_GATE(0x3), 0x80);
diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c
index af4f22e..a829318 100644
--- a/kernel/drivers/mouse.c
+++ b/kernel/drivers/mouse.c
@@ -43,7 +43,7 @@ void add_mouse(void) {
// Don't look at this
int fd = vfs_open("/dev/mouse", O_RDWR, 0);
mouse_fd = get_vfs_fd(fd);
- get_current_task()->file_descriptors[fd] = NULL;
+ current_task->file_descriptors[fd] = NULL;
}
void what(registers_t *r) {
diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c
index b22bb8a..5a11e74 100644
--- a/kernel/drivers/rtl8139.c
+++ b/kernel/drivers/rtl8139.c
@@ -111,8 +111,7 @@ void rtl8139_send_data(u8 *data, u16 data_size) {
data_size -= 0x1000;
return rtl8139_send_data(data, data_size);
}
- ipc_write(0, data, data_size);
- /*
+ // ipc_write(0, data, data_size);
const struct PCI_DEVICE *device = &rtl8139;
// FIXME: It should block or fail if there is too little space for the
// buffer
@@ -129,7 +128,7 @@ void rtl8139_send_data(u8 *data, u16 data_size) {
outl(device->gen.base_mem_io + 0x20 + send_buffers_loop * 4,
(u32)virtual_to_physical(send_buffers[send_buffers_loop], NULL));
outl(device->gen.base_mem_io + 0x10 + send_buffers_loop * 4, data_size);
- send_buffers_loop += 1;*/
+ send_buffers_loop += 1;
}
void get_mac_address(u8 mac[6]) {
diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c
index ccf2fdf..9017b82 100644
--- a/kernel/fs/ext2.c
+++ b/kernel/fs/ext2.c
@@ -802,8 +802,8 @@ vfs_inode_t *ext2_mount(void) {
cache = kcalloc(3000, sizeof(struct BLOCK_CACHE));
// TODO: Can this be done better? Maybe create a seperate function in
// the VFS?
- mount_fd = get_current_task()->file_descriptors[fd];
- get_current_task()->file_descriptors[fd] = NULL;
+ mount_fd = current_task->file_descriptors[fd];
+ current_task->file_descriptors[fd] = NULL;
parse_superblock();
return vfs_create_inode(0 /*inode_num*/, 0 /*type*/, 0 /*has_data*/,
0 /*can_write*/, 0 /*is_open*/,
diff --git a/kernel/fs/fifo.c b/kernel/fs/fifo.c
index 5563f76..7c286db 100644
--- a/kernel/fs/fifo.c
+++ b/kernel/fs/fifo.c
@@ -58,12 +58,12 @@ FIFO_FILE *create_fifo_object(void) {
int create_fifo(void) {
int fd_n = 0;
- for (; get_current_task()->file_descriptors[fd_n]; fd_n++)
+ for (; current_task->file_descriptors[fd_n]; fd_n++)
;
vfs_fd_t *fd = kmalloc(sizeof(vfs_fd_t));
fd->flags = O_RDWR | O_NONBLOCK;
- get_current_task()->file_descriptors[fd_n] = fd;
+ current_task->file_descriptors[fd_n] = fd;
fd->inode = kmalloc(sizeof(vfs_inode_t));
fd->inode->internal_object = (void *)create_fifo_object();
diff --git a/kernel/fs/tmpfs.c b/kernel/fs/tmpfs.c
index bdb0dfb..75de1cd 100644
--- a/kernel/fs/tmpfs.c
+++ b/kernel/fs/tmpfs.c
@@ -56,8 +56,8 @@ void dual_pipe(int fd[2]) {
fd[i] = vfs_create_fd(O_RDWR | O_NONBLOCK, 0, 0 /*is_tty*/, inode, &fd_ptr);
assert(-1 != fd[i]);
}
- vfs_inode_t *f_inode = get_current_task()->file_descriptors[fd[0]]->inode;
- vfs_inode_t *s_inode = get_current_task()->file_descriptors[fd[1]]->inode;
+ vfs_inode_t *f_inode = current_task->file_descriptors[fd[0]]->inode;
+ vfs_inode_t *s_inode = current_task->file_descriptors[fd[1]]->inode;
tmp_inode *f_pipe = f_inode->internal_object;
tmp_inode *s_pipe = s_inode->internal_object;
f_pipe->read_inode = s_inode;
@@ -86,8 +86,8 @@ void pipe(int fd[2]) {
fd[i] = vfs_create_fd(O_RDWR, 0, 0 /*is_tty*/, inode, &fd_ptr);
assert(-1 != fd[i]);
}
- vfs_inode_t *f_inode = get_current_task()->file_descriptors[fd[0]]->inode;
- vfs_inode_t *s_inode = get_current_task()->file_descriptors[fd[1]]->inode;
+ vfs_inode_t *f_inode = current_task->file_descriptors[fd[0]]->inode;
+ vfs_inode_t *s_inode = current_task->file_descriptors[fd[1]]->inode;
tmp_inode *f_pipe = f_inode->internal_object;
tmp_inode *s_pipe = s_inode->internal_object;
f_pipe->read_inode = s_inode;
diff --git a/kernel/fs/vfs.c b/kernel/fs/vfs.c
index 2a072e9..76e6778 100644
--- a/kernel/fs/vfs.c
+++ b/kernel/fs/vfs.c
@@ -19,7 +19,7 @@ vfs_fd_t *get_vfs_fd(int fd) {
dump_backtrace(12);
return NULL;
}
- return get_current_task()->file_descriptors[fd];
+ return current_task->file_descriptors[fd];
}
vfs_inode_t *vfs_create_inode(
@@ -56,7 +56,7 @@ vfs_inode_t *vfs_create_inode(
int vfs_create_fd(int flags, int mode, int is_tty, vfs_inode_t *inode,
vfs_fd_t **fd) {
- process_t *p = (process_t *)get_current_task();
+ process_t *p = (process_t *)current_task;
int i;
for (i = 0; i < 100; i++) {
if (!p->file_descriptors[i]) {
@@ -194,7 +194,7 @@ char *vfs_resolve_path(const char *file, char *resolved_path) {
assert(vfs_clean_path(file, resolved_path));
return resolved_path;
}
- const char *cwd = get_current_task()->current_working_directory;
+ const char *cwd = current_task->current_working_directory;
size_t l = strlen(cwd);
assert(l > 0);
assert('/' == cwd[l - 1]);
@@ -230,10 +230,10 @@ int vfs_chdir(const char *path) {
}
vfs_close(tmp_fd);
}
- strcpy(get_current_task()->current_working_directory, resolved_path);
+ strcpy(current_task->current_working_directory, resolved_path);
if ('/' != resolved_path[strlen(resolved_path)] &&
strlen(resolved_path) != 1) {
- strcat(get_current_task()->current_working_directory, "/");
+ strcat(current_task->current_working_directory, "/");
}
return 0;
}
@@ -297,7 +297,7 @@ int vfs_close(int fd) {
assert(0 < fd_ptr->reference_count);
// Remove process reference
fd_ptr->reference_count--;
- get_current_task()->file_descriptors[fd] = 0;
+ current_task->file_descriptors[fd] = 0;
// If no references left then free the contents
if (0 == fd_ptr->reference_count) {
if (fd_ptr->inode->close) {
@@ -326,7 +326,7 @@ int vfs_pread(int fd, void *buf, u64 count, u64 offset) {
kprintf("EBADF : %x\n", fd);
return -EBADF;
}
- vfs_fd_t *vfs_fd = get_current_task()->file_descriptors[fd];
+ vfs_fd_t *vfs_fd = current_task->file_descriptors[fd];
if (!vfs_fd) {
return -EBADF;
}
@@ -334,10 +334,15 @@ int vfs_pread(int fd, void *buf, u64 count, u64 offset) {
if (-EAGAIN == rc && count > 0) {
if (!(vfs_fd->flags & O_NONBLOCK)) {
struct pollfd fds;
- fds.fd = fd;
- fds.events = POLLIN;
- fds.revents = 0;
- poll(&fds, 1, 0);
+ do {
+ fds.fd = fd;
+ fds.events = POLLIN;
+ fds.revents = 0;
+ int rc = poll(&fds, 1, 0);
+ if (-EINTR == rc) {
+ return -EINTR;
+ }
+ } while (!(fds.revents & POLLIN));
return vfs_pread(fd, buf, count, offset);
}
}
@@ -372,9 +377,9 @@ vfs_vm_object_t *vfs_get_vm_object(int fd, u64 length, u64 offset) {
}
int vfs_dup2(int org_fd, int new_fd) {
- get_current_task()->file_descriptors[new_fd] =
- get_current_task()->file_descriptors[org_fd];
- get_current_task()->file_descriptors[new_fd]->reference_count++;
+ current_task->file_descriptors[new_fd] =
+ current_task->file_descriptors[org_fd];
+ current_task->file_descriptors[new_fd]->reference_count++;
return 1;
}
diff --git a/kernel/includes/mmu.h b/kernel/includes/mmu.h
index 49b4886..68fd134 100644
--- a/kernel/includes/mmu.h
+++ b/kernel/includes/mmu.h
@@ -45,6 +45,8 @@ void mmu_map_physical(void *dst, PageDirectory *d, void *physical,
size_t length);
void mmu_free_pages(void *a, u32 n);
void *mmu_map_user_frames(void *const ptr, size_t s);
+void *mmu_is_valid_userpointer(const void *ptr, size_t s);
+void *mmu_is_valid_user_c_string(const char *ptr, size_t *size);
void flush_tlb(void);
void paging_init(u64 memsize);
@@ -54,8 +56,6 @@ void switch_page_directory(PageDirectory *directory);
void *allocate_frame(Page *page, int rw, int is_kernel);
PageDirectory *clone_directory(PageDirectory *original);
void *virtual_to_physical(void *address, PageDirectory *directory);
-void *is_valid_userpointer(const void *const p, size_t s);
-void *is_valid_user_c_string(const char *ptr, size_t *size);
void *ksbrk(size_t s);
void *ksbrk_physical(size_t s, void **physical);
diff --git a/kernel/includes/syscalls.h b/kernel/includes/syscalls.h
index ee3e417..a0be694 100644
--- a/kernel/includes/syscalls.h
+++ b/kernel/includes/syscalls.h
@@ -6,11 +6,16 @@
#include <time.h>
#include <typedefs.h>
#include <types.h>
+#include <queue.h>
void syscall_outw(u16 port, u16 word);
u32 syscall_inl(u16 port);
void syscall_outl(u16 port, u32 l);
+int syscall_queue_create(u32 *id);
+int syscall_queue_add(u32 queue_id, struct event *ev, u32 size);
+int syscall_queue_wait(u32 queue_id);
+
int syscall_ipc_register_endpoint(u32 endpoint);
int syscall_ipc_read(u8 *buffer, u32 length, u32 *sender_pid);
int syscall_ipc_write(int ipc_id, u8 *buffer, u32 length);
diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c
index 55c65b2..edff4f1 100644
--- a/kernel/init/kernel.c
+++ b/kernel/init/kernel.c
@@ -20,6 +20,7 @@
#include <log.h>
#include <mmu.h>
#include <multiboot.h>
+#include <network/arp.h>
#include <random.h>
#include <sched/scheduler.h>
#include <stdbool.h>
@@ -67,7 +68,7 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
klog("Syscalls Initalized", LOG_SUCCESS);
pit_install();
- set_pit_count(100);
+ set_pit_count(1000);
klog("PIT driver installed", LOG_SUCCESS);
ata_init();
@@ -95,8 +96,60 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
add_keyboard();
add_mouse();
- // rtl8139_init();
+ ////////
+ rtl8139_init();
+ enable_interrupts();
+
+ /*
+ u32 ip = gen_ipv4(10, 0, 2, 2);
+ int err;
+ u32 listen_socket = tcp_listen_ipv4(ip, 6000, &err);
+ assert(!err);
+ u32 socket = tcp_accept(listen_socket, &err);
+ assert(!err);
+
+ kprintf("socket: %x\n", socket);
+
+ u64 out;
+ char buffer[256];
+ assert(tcp_read(socket, buffer, 256, &out));
+ kprintf("got %x bytes\n", out);
+ for (int i = 0; i < out; i++) {
+ kprintf("%c", buffer[i]);
+ }
+ */
+
+ ipv4_t gateway;
+ gateway.d = gen_ipv4(10, 0, 2, 2);
+ ipv4_t bitmask;
+ bitmask.d = gen_ipv4(255, 255, 255, 0);
+ setup_network(gateway, bitmask);
+
+ /*
+ // u32 ip = gen_ipv4(10, 0, 2, 2);
+ u32 ip = gen_ipv4(93, 184, 216, 34);
+ int err;
+ u32 socket = tcp_connect_ipv4(ip, 80, &err);
+ assert(!err);
+ kprintf("socket: %x\n", socket);
+ u64 out;
+ char *http_request = "GET /\r\n\r\n";
+ assert(tcp_write(socket, http_request, strlen(http_request), &out));
+ kprintf("sent: %x over the tcp socket\n", out);
+
+ for (;;) {
+ char buffer[256];
+ assert(tcp_read(socket, buffer, 256, &out));
+ kprintf("got %x bytes\n", out);
+ for (int i = 0; i < out; i++) {
+ kprintf("%c", buffer[i]);
+ }
+ }
+
+ for (;;)
+ ;
+ */
display_driver_init(mb);
add_vbe_device();
int pid;
@@ -107,7 +160,8 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
}
}
for (;;) {
- get_current_task()->sleep_until = pit_num_ms() + 100000000;
+ current_task->sleep_until = pit_num_ms() + 100000000;
+ // enable_interrupts();
switch_task();
}
}
diff --git a/kernel/ipc.c b/kernel/ipc.c
index eb7c1b7..a3e1160 100644
--- a/kernel/ipc.c
+++ b/kernel/ipc.c
@@ -20,7 +20,7 @@ bool ipc_register_endpoint(u32 endpoint) {
return false;
}
ipc_endpoints[endpoint].in_use = 1;
- ipc_endpoints[endpoint].pid = get_current_task()->pid;
+ ipc_endpoints[endpoint].pid = current_task->pid;
return true;
}
@@ -46,7 +46,7 @@ int ipc_get_mailbox(u32 id, struct IpcMailbox **out) {
int ipc_has_data(process_t *p) {
if (!p) {
- p = get_current_task();
+ p = current_task;
}
struct IpcMailbox *handler = &p->ipc_mailbox;
u32 read_ptr = handler->read_ptr;
@@ -55,28 +55,29 @@ int ipc_has_data(process_t *p) {
}
int ipc_read(u8 *buffer, u32 length, u32 *sender_pid) {
- struct IpcMailbox *handler = &get_current_task()->ipc_mailbox;
+ struct IpcMailbox *handler = &current_task->ipc_mailbox;
u32 read_ptr = handler->read_ptr;
struct IpcMessage *ipc_message = &handler->data[read_ptr];
for (;;) {
if (!ipc_message->is_used) {
- if (get_current_task()->is_interrupted) {
- get_current_task()->is_interrupted = 0;
- get_current_task()->is_halted = 0;
+ if (current_task->is_interrupted) {
+ current_task->is_interrupted = 0;
+ current_task->is_halted = 0;
return 0;
}
- get_current_task()->is_halted = 1;
+ current_task->is_halted = 1;
switch_task();
continue;
}
break;
}
- get_current_task()->is_halted = 0;
+ current_task->is_halted = 0;
disable_interrupts();
ipc_message->is_used = 0;
// TODO: Verify sender_pid is a valid address
if (sender_pid) {
+ assert(mmu_is_valid_userpointer(sender_pid, sizeof(ipc_message->sender_pid)));
*sender_pid = ipc_message->sender_pid;
}
@@ -100,7 +101,7 @@ int ipc_write_to_process(int pid, u8 *buffer, u32 length) {
struct IpcMessage *ipc_message = &handler->data[write_ptr];
ipc_message->is_used = 1;
u32 len = min(IPC_BUFFER_SIZE, length);
- ipc_message->sender_pid = get_current_task()->pid;
+ ipc_message->sender_pid = current_task->pid;
ipc_message->size = len;
memcpy(ipc_message->buffer, buffer, len);
diff --git a/kernel/kmalloc.c b/kernel/kmalloc.c
index f362f6b..f75ab33 100644
--- a/kernel/kmalloc.c
+++ b/kernel/kmalloc.c
@@ -62,7 +62,11 @@ int add_heap_memory(size_t min_desired) {
MallocHeader *next_header(MallocHeader *a) {
assert(a->magic == 0xdde51ab9410268b1);
if (a->n) {
- assert(a->n->magic == 0xdde51ab9410268b1);
+ if (a->n->magic != 0xdde51ab9410268b1) {
+ kprintf("Real magic value is: %x\n", a->n->magic);
+ kprintf("location: %x\n", &(a->n->magic));
+ assert(0);
+ }
return a->n;
}
return NULL;
@@ -124,6 +128,7 @@ void merge_headers(MallocHeader *b) {
}
void *kmalloc(size_t s) {
+ s += 0x1000;
size_t n = s;
MallocHeader *free_entry = find_free_entry(s);
if (!free_entry) {
@@ -154,7 +159,10 @@ void *kmalloc(size_t s) {
free_entry->flags = 0;
free_entry->n = new_entry;
free_entry->magic = 0xdde51ab9410268b1;
- get_fast_insecure_random((void *)rc, s);
+ for (int i = 0; i < s; i++) {
+ *(char *)rc = 'A';
+ }
+ // get_fast_insecure_random((void *)rc, s);
return rc;
}
diff --git a/kernel/lib/list.c b/kernel/lib/list.c
index 12104d8..9cdcd01 100644
--- a/kernel/lib/list.c
+++ b/kernel/lib/list.c
@@ -16,13 +16,16 @@ void list_reset(struct list *list) {
list->tail_index = -1;
}
-int list_add(struct list *list, void *entry) {
+int list_add(struct list *list, void *entry, int *index) {
if (list->tail_index > 100 - 1) {
kprintf("Error: list has run out of space\n");
assert(0);
}
list->tail_index++;
list->entries[list->tail_index] = entry;
+ if(index) {
+ *index = list->tail_index;
+ }
return 1;
}
diff --git a/kernel/lib/list.h b/kernel/lib/list.h
index 8c3cce4..6ab9e0b 100644
--- a/kernel/lib/list.h
+++ b/kernel/lib/list.h
@@ -8,6 +8,6 @@ struct list {
int list_init(struct list *list);
void list_reset(struct list *list);
void list_free(struct list *list);
-int list_add(struct list *list, void *entry);
+int list_add(struct list *list, void *entry, int *index);
int list_get(const struct list *list, int index, void **out);
#endif
diff --git a/kernel/lib/stack.c b/kernel/lib/stack.c
index 7f31867..7283b35 100644
--- a/kernel/lib/stack.c
+++ b/kernel/lib/stack.c
@@ -1,3 +1,4 @@
+#include <interrupts.h>
#include <kmalloc.h>
#include <lib/stack.h>
#include <stddef.h>
diff --git a/kernel/libc/exit/assert.c b/kernel/libc/exit/assert.c
index 47c0704..89aa863 100644
--- a/kernel/libc/exit/assert.c
+++ b/kernel/libc/exit/assert.c
@@ -8,4 +8,5 @@ __attribute__((__noreturn__)) void aFailed(char *f, int l) {
kprintf("%s : %d\n", f, l);
dump_backtrace(10);
halt();
+ kprintf("after halt?\n");
}
diff --git a/kernel/libc/string/copy.c b/kernel/libc/string/copy.c
index 166924b..11cd664 100644
--- a/kernel/libc/string/copy.c
+++ b/kernel/libc/string/copy.c
@@ -14,7 +14,7 @@ char *copy_and_allocate_string(const char *s) {
char *copy_and_allocate_user_string(const char *s) {
size_t len;
- if (!is_valid_user_c_string(s, &len)) {
+ if (!mmu_is_valid_user_c_string(s, &len)) {
return NULL;
}
size_t real_len = strlen(s);
diff --git a/kernel/log.c b/kernel/log.c
index 8f72b3a..ff6f45b 100644
--- a/kernel/log.c
+++ b/kernel/log.c
@@ -14,8 +14,8 @@ void dump_backtrace(u32 max_frames) {
kprintf(" 0x%x\n", stk->eip);
stk = stk->ebp;
}
- if (get_current_task()) {
- kprintf(" PID: %x\n", get_current_task()->pid);
+ if (current_task) {
+ kprintf(" PID: %x\n", current_task->pid);
}
}
diff --git a/kernel/network/arp.c b/kernel/network/arp.c
index bd3cd24..576a09a 100644
--- a/kernel/network/arp.c
+++ b/kernel/network/arp.c
@@ -5,6 +5,15 @@
#include <network/ethernet.h>
#include <stdio.h>
#include <string.h>
+#include <interrupts.h>
+
+ipv4_t gateway;
+ipv4_t bitmask;
+
+void setup_network(ipv4_t _gateway, ipv4_t _bitmask) {
+ gateway = _gateway;
+ bitmask = _bitmask;
+}
struct ARP_DATA {
u16 htype; // Hardware type
@@ -84,7 +93,20 @@ void send_arp_request(const u8 ip[4]) {
send_ethernet_packet(broadcast, 0x0806, (u8 *)&data, sizeof(data));
}
+int ip_inside_network(const ipv4_t ip) {
+ if ((ip.d & bitmask.d) == (gateway.d & bitmask.d)) {
+ return 1;
+ }
+ return 0;
+}
+
int get_mac_from_ip(const u8 ip[4], u8 mac[6]) {
+ ipv4_t tmp_ip;
+ memcpy(tmp_ip.a, ip, sizeof(u8[4]));
+ if (!ip_inside_network(tmp_ip)) {
+ return get_mac_from_ip(gateway.a, mac);
+ }
+
for (int i = 0; i < 10; i++) {
if (0 != memcmp(arp_table[i].ip, ip, sizeof(u8[4]))) {
continue;
@@ -93,6 +115,7 @@ int get_mac_from_ip(const u8 ip[4], u8 mac[6]) {
return 1;
}
klog("ARP cache miss", LOG_NOTE);
+ enable_interrupts();
send_arp_request(ip);
// TODO: Maybe wait a bit?
for (int i = 0; i < 10; i++) {
diff --git a/kernel/network/arp.h b/kernel/network/arp.h
index 6e53fd9..3795a62 100644
--- a/kernel/network/arp.h
+++ b/kernel/network/arp.h
@@ -1,5 +1,6 @@
#include <typedefs.h>
+void setup_network(ipv4_t _gateway, ipv4_t _bitmask);
int get_mac_from_ip(const u8 ip[4], u8 mac[6]);
void send_arp_request(const u8 ip[4]);
void handle_arp(const u8 *payload);
diff --git a/kernel/network/ethernet.c b/kernel/network/ethernet.c
index 4fe6a94..9fa5ef8 100644
--- a/kernel/network/ethernet.c
+++ b/kernel/network/ethernet.c
@@ -73,6 +73,7 @@ void send_ethernet_packet(u8 mac_dst[6], u16 type, u8 *payload,
u64 buffer_size =
sizeof(struct ETHERNET_HEADER) + payload_length + sizeof(u32);
u8 *buffer = kmalloc(buffer_size);
+ memset(buffer, 0, buffer_size);
u8 *buffer_start = buffer;
struct ETHERNET_HEADER *eth_header = (struct ETHERNET_HEADER *)buffer;
buffer += sizeof(struct ETHERNET_HEADER);
diff --git a/kernel/network/tcp.c b/kernel/network/tcp.c
index 717c7db..fb3c052 100644
--- a/kernel/network/tcp.c
+++ b/kernel/network/tcp.c
@@ -190,6 +190,7 @@ void handle_tcp(u8 src_ip[4], const u8 *payload, u32 payload_length) {
}
struct TcpConnection *incoming_connection = tcp_find_connection(dst_port);
+ kprintf("dst_port: %d\n", dst_port);
if (incoming_connection) {
incoming_connection->unhandled_packet = 1;
if (0 != (flags & RST)) {
@@ -212,9 +213,9 @@ void handle_tcp(u8 src_ip[4], const u8 *payload, u32 payload_length) {
tcp_send_ack(incoming_connection);
}
- if (0 != (flags & PSH)) {
- u16 tcp_payload_length =
- payload_length - header->data_offset * sizeof(u32);
+ // if (0 != (flags & PSH)) {
+ u16 tcp_payload_length = payload_length - header->data_offset * sizeof(u32);
+ if (tcp_payload_length > 0) {
int len = fifo_object_write(
(u8 *)(payload + header->data_offset * sizeof(u32)), 0,
tcp_payload_length, incoming_connection->data_file);
@@ -232,7 +233,7 @@ void handle_tcp(u8 src_ip[4], const u8 *payload, u32 payload_length) {
// is closed.
}
} else {
- assert(NULL);
+ return;
}
}
/*
diff --git a/kernel/poll.c b/kernel/poll.c
index 276b592..8174657 100644
--- a/kernel/poll.c
+++ b/kernel/poll.c
@@ -1,3 +1,4 @@
+#include <errno.h>
#include <fs/vfs.h>
#include <interrupts.h>
#include <lib/list.h>
@@ -10,9 +11,9 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
disable_interrupts();
- struct list *read_list = &get_current_task()->read_list;
- struct list *write_list = &get_current_task()->write_list;
- struct list *disconnect_list = &get_current_task()->disconnect_list;
+ struct list *read_list = &current_task->read_list;
+ struct list *write_list = &current_task->write_list;
+ struct list *disconnect_list = &current_task->disconnect_list;
for (size_t i = 0; i < nfds; i++) {
if (fds[i].fd < 0) {
continue;
@@ -23,13 +24,13 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
}
if (fds[i].events & POLLIN) {
- list_add(read_list, f->inode);
+ list_add(read_list, f->inode, NULL);
}
if (fds[i].events & POLLOUT) {
- list_add(write_list, f->inode);
+ list_add(write_list, f->inode, NULL);
}
if (fds[i].events & POLLHUP) {
- list_add(disconnect_list, f->inode);
+ list_add(disconnect_list, f->inode, NULL);
}
}
@@ -39,6 +40,11 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
list_reset(read_list);
list_reset(write_list);
list_reset(disconnect_list);
+ if (current_task->is_interrupted) {
+ current_task->is_interrupted = 0;
+ current_task->is_halted = 0;
+ return -EINTR;
+ }
for (size_t i = 0; i < nfds; i++) {
if (0 > fds[i].fd) {
@@ -60,9 +66,9 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
if (!(f->inode->is_open) && fds[i].events & POLLHUP) {
fds[i].revents |= POLLHUP;
}
- if (fds[i].revents) {
- rc++;
- }
+ }
+ if (fds[i].revents) {
+ rc++;
}
}
enable_interrupts();
diff --git a/kernel/queue.c b/kernel/queue.c
new file mode 100644
index 0000000..0f2f645
--- /dev/null
+++ b/kernel/queue.c
@@ -0,0 +1,81 @@
+#include <kmalloc.h>
+#include <queue.h>
+#include <sched/scheduler.h>
+#include <stdio.h>
+
+int queue_create(u32 *id) {
+ struct event_queue *q = kcalloc(1, sizeof(struct event_queue));
+ q->wait = 0;
+ list_init(&q->events);
+
+ struct list *list = &current_task->event_queue;
+ list_add(list, q, id);
+ return 1;
+}
+
+struct event_queue *get_event_queue(u32 id) {
+ const struct list *list = &current_task->event_queue;
+ struct event_queue *q;
+ if (!list_get(list, id, (void **)&q)) {
+ return NULL;
+ }
+ return q;
+}
+
+int queue_add(u32 queue_id, struct event *ev, u32 size) {
+ struct event_queue *q = get_event_queue(queue_id);
+ if (!q) {
+ return 0;
+ }
+ for (u32 i = 0; i < size; i++) {
+ // TODO: Should it be a copy or could it be kept in userland to
+ // improve performance?
+ struct event *new_ev = kmalloc(sizeof(struct event));
+ memcpy(new_ev, ev, sizeof(struct event));
+ list_add(&q->events, new_ev, NULL);
+ }
+ return 1;
+}
+
+int queue_should_block(struct event_queue *q, int *is_empty) {
+ if (!q->wait) {
+ return 0;
+ }
+ *is_empty = 1;
+ for (int i = 0;; i++) {
+ struct event *ev;
+ if (!list_get(&q->events, i, (void **)&ev)) {
+ break;
+ }
+ kprintf("wait %d\n", i);
+ *is_empty = 0;
+ if (EVENT_TYPE_FD == ev->type) {
+ kprintf("found fd: %d\n", ev->internal_id);
+ vfs_fd_t *fd = get_vfs_fd(ev->internal_id);
+ kprintf("fd->inode->has_data: %x\n", fd->inode->has_data);
+ if (!fd) {
+ kprintf("queue: Invalid fd given\n");
+ continue;
+ }
+ if (fd->inode->has_data) {
+ kprintf("no block\n");
+ return 0;
+ }
+ } else if (EVENT_TYPE_TCP_SOCKET == ev->type) {
+ kprintf("tcp socket wait\n");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int queue_wait(u32 queue_id) {
+ struct event_queue *q = get_event_queue(queue_id);
+ if (!q) {
+ return 0;
+ }
+ q->wait = 1;
+ switch_task();
+ q->wait = 0;
+ return 1;
+}
diff --git a/kernel/queue.h b/kernel/queue.h
new file mode 100644
index 0000000..74c7ab8
--- /dev/null
+++ b/kernel/queue.h
@@ -0,0 +1,25 @@
+#ifndef QUEUE_H
+#define QUEUE_H
+#include <lib/list.h>
+#include <stddef.h>
+#include <string.h>
+#include <typedefs.h>
+
+#define EVENT_TYPE_FD 0
+#define EVENT_TYPE_TCP_SOCKET 1
+
+struct event {
+ u8 type; // File descriptor | Socket
+ u32 internal_id;
+};
+
+struct event_queue {
+ struct list events;
+ int wait;
+};
+
+int queue_create(u32 *id);
+int queue_add(u32 queue_id, struct event *ev, u32 size);
+int queue_wait(u32 queue_id);
+int queue_should_block(struct event_queue *q, int *is_empty);
+#endif
diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c
index 949cdf2..cbb28fa 100644
--- a/kernel/sched/scheduler.c
+++ b/kernel/sched/scheduler.c
@@ -6,6 +6,7 @@
#include <errno.h>
#include <fs/vfs.h>
#include <interrupts.h>
+#include <queue.h>
// FIXME: Use the process_t struct instead or keep this contained in it.
TCB *current_task_TCB;
@@ -27,6 +28,10 @@ process_t *get_current_task(void) {
return current_task;
}
+process_t *get_ready_queue(void) {
+ return ready_queue;
+}
+
void process_push_restore_context(process_t *p, reg_t r) {
if (!p) {
p = current_task;
@@ -115,6 +120,11 @@ process_t *create_process(process_t *p, u32 esp, u32 eip) {
list_init(&r->write_list);
list_init(&r->disconnect_list);
+ list_init(&r->tcp_sockets);
+ list_init(&r->tcp_listen);
+
+ list_init(&r->event_queue);
+
// Temporarily switch to the page directory to be able to place the
// "entry_instruction_pointer" onto the stack.
@@ -178,7 +188,7 @@ void tasking_init(void) {
int i = 0;
void free_process(void) {
- process_t *p = get_current_task();
+ process_t *p = current_task;
kprintf("pid: %x\n", p->pid);
kprintf("Exiting process: %s\n", p->program_name);
// free_process() will purge all contents such as allocated frames
@@ -324,9 +334,10 @@ int fork(void) {
return new_task->pid;
}
-int isset_fdhalt(process_t *p) {
+int isset_fdhalt(process_t *p, int *empty) {
+ *empty = 1;
if (NULL == p) {
- p = get_current_task();
+ p = current_task;
}
int blocked = 0;
struct list *read_list = &p->read_list;
@@ -338,6 +349,7 @@ int isset_fdhalt(process_t *p) {
if (!list_get(read_list, i, (void **)&inode)) {
break;
}
+ *empty = 0;
if (inode->has_data) {
return 0;
}
@@ -348,6 +360,7 @@ int isset_fdhalt(process_t *p) {
if (!list_get(write_list, i, (void **)&inode)) {
break;
}
+ *empty = 0;
if (inode->can_write) {
return 0;
}
@@ -358,7 +371,9 @@ int isset_fdhalt(process_t *p) {
if (!list_get(disconnect_list, i, (void **)&inode)) {
break;
}
- if (inode->is_open) {
+ *empty = 0;
+ if (!inode->is_open) {
+ kprintf("is_open\n");
return 0;
}
blocked = 1;
@@ -375,11 +390,35 @@ int is_halted(process_t *process) {
if (process->is_halted) {
if (ipc_has_data(process)) {
+ kprintf("ipc had data\n");
return 0;
}
}
- if (isset_fdhalt(process)) {
+ int queue_block = 1;
+ int wait_empty = 1;
+ for (int i = 0;; i++) {
+ struct event_queue *q;
+ if (!list_get(&process->event_queue, i, (void **)&q)) {
+ break;
+ }
+ int is_empty;
+ int rc = queue_should_block(q, &is_empty);
+ if (is_empty) {
+ wait_empty = 0;
+ continue;
+ }
+ if (0 == rc) {
+ queue_block = 0;
+ }
+ }
+ if (!queue_block && !wait_empty) {
+ kprintf("skip because queue_wait has data\n");
+ return 0;
+ }
+
+ int fd_empty;
+ if (isset_fdhalt(process, &fd_empty) && !fd_empty) {
return 1;
}
return 0;
@@ -387,9 +426,10 @@ int is_halted(process_t *process) {
extern PageDirectory *active_directory;
-process_t *next_task(process_t *c) {
- for (;;) {
- c = c->next;
+process_t *next_task(process_t *s) {
+ process_t *c = s;
+ c = c->next;
+ for (;; c = c->next) {
if (!c) {
c = ready_queue;
}
@@ -430,8 +470,9 @@ void switch_task() {
return;
}
- disable_interrupts();
+ enable_interrupts();
current_task = next_task((process_t *)current_task);
+ disable_interrupts();
active_directory = current_task->cr3;
switch_to_task(current_task->tcb);
@@ -448,11 +489,11 @@ MemoryMap **get_free_map(void) {
}
void *get_free_virtual_memory(size_t length) {
- void *n = (void *)((uintptr_t)(get_current_task()->data_segment_end) +
- length + 0x1000);
+ void *n =
+ (void *)((uintptr_t)(current_task->data_segment_end) + length + 0x1000);
- void *rc = get_current_task()->data_segment_end;
- get_current_task()->data_segment_end = align_page(n);
+ void *rc = current_task->data_segment_end;
+ current_task->data_segment_end = align_page(n);
return rc;
}
diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h
index ff38034..175f3ce 100644
--- a/kernel/sched/scheduler.h
+++ b/kernel/sched/scheduler.h
@@ -14,6 +14,9 @@ typedef struct Process process_t;
#define KEYBOARD_HALT 0
#define WAIT_CHILD_HALT 1
+extern process_t *current_task;
+extern process_t *ready_queue;
+
int fork(void);
int exec(const char *filename, char **argv);
void switch_task(void);
@@ -63,6 +66,11 @@ struct Process {
struct list write_list;
struct list disconnect_list;
+ struct list tcp_sockets;
+ struct list tcp_listen;
+
+ struct list event_queue;
+
struct stack restore_context_stack;
struct stack signal_stack;
@@ -87,7 +95,6 @@ struct Process {
};
bool get_task_from_pid(u32 pid, process_t **out);
-process_t *get_current_task(void);
int get_free_fd(process_t *p, int allocate);
void free_process(void);
void *get_free_virtual_memory(size_t length);
diff --git a/kernel/socket.c b/kernel/socket.c
index 9cb8763..e13a845 100644
--- a/kernel/socket.c
+++ b/kernel/socket.c
@@ -11,51 +11,71 @@
// FIXME: Make these more dynamic
OPEN_UNIX_SOCKET *un_sockets[100] = {0};
-struct TcpConnection *tcp_sockets[100];
-struct TcpListen *tcp_listen[100];
+// struct TcpConnection *tcp_sockets[100];
+// struct TcpListen *tcp_listen[100];
u32 gen_ipv4(u8 i1, u8 i2, u8 i3, u8 i4) {
return i4 << (32 - 8) | i3 << (32 - 16) | i2 << (32 - 24) | i1 << (32 - 32);
}
struct TcpConnection *tcp_find_connection(u16 port) {
- for (int i = 0; i < 100; i++) {
- if (port == tcp_sockets[i]->incoming_port) {
- return tcp_sockets[i];
+ process_t *p = current_task;
+ process_t *s = p;
+ p = p->next;
+ for (; p != s; p = p->next) {
+ if (!p) {
+ p = ready_queue;
+ }
+ struct list *connections = &p->tcp_sockets;
+ for (int i = 0;; i++) {
+ struct TcpConnection *c;
+ if (!list_get(connections, i, (void **)&c)) {
+ break;
+ }
+ kprintf("got port: %d\n", c->incoming_port);
+ if (c->incoming_port == port) {
+ return c;
+ }
}
}
return NULL;
}
-struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
- u32 dst_ip, u16 dst_port) {
- u32 i = 0;
- for (; i < 100; i++) {
- if (!tcp_listen[i]) {
- continue;
+
+struct TcpListen *tcp_find_listen(u16 port) {
+ process_t *p = current_task;
+ process_t *s = p;
+ p = p->next;
+ for (; p != s; p = p->next) {
+ if (!p) {
+ p = ready_queue;
}
- if (dst_port == tcp_listen[i]->port) {
- break;
+ struct list *listen_list = &p->tcp_listen;
+ for (int i = 0;; i++) {
+ struct TcpListen *c;
+ if (!list_get(listen_list, i, (void **)&c)) {
+ break;
+ }
+ if (c->port == port) {
+ return c;
+ }
}
}
- if (!tcp_listen[i] || dst_port != tcp_listen[i]->port) {
- return NULL;
- }
- struct TcpListen *listen = tcp_listen[i];
- u32 listen_id = i;
+ return NULL;
+}
- i = 0;
- for (; i < 100; i++) {
- if (!tcp_sockets[i]) {
- break;
- }
- }
- if (tcp_sockets[i]) {
+struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
+ u32 dst_ip, u16 dst_port) {
+ struct TcpListen *listen = tcp_find_listen(dst_port);
+ if (!listen) {
return NULL;
}
- tcp_sockets[i] = kcalloc(1, sizeof(struct TcpConnection));
- struct TcpConnection *con = tcp_sockets[i];
- u32 con_id = i;
+ struct TcpConnection *con = kcalloc(1, sizeof(struct TcpConnection));
+
+ int connection_id;
+ struct list *connections = &current_task->tcp_sockets;
+ list_add(connections, con, &connection_id);
+
con->outgoing_ip = src_ip;
con->outgoing_port = src_port;
// con->incoming_ip = dst_ip;
@@ -63,39 +83,38 @@ struct TcpConnection *internal_tcp_incoming(u32 src_ip, u16 src_port,
// connection
con->data_file = create_fifo_object();
- kprintf("pushing the connection\n");
- kprintf("listen_id: %x\n", listen_id);
- stack_push(&listen->incoming_connections, (void *)con_id);
- kprintf("listen->incoming_connections->head: %x\n",
- (&listen->incoming_connections)->head);
- kprintf("root: %x\n", &listen->incoming_connections);
+ stack_push(&listen->incoming_connections, (void *)connection_id);
return con;
}
u32 tcp_listen_ipv4(u32 ip, u16 port, int *error) {
*error = 0;
- u32 i = 0;
- for (; i < 100; i++) {
- if (!tcp_listen[i]) {
- break;
- }
- }
- if (tcp_listen[i]) {
- *error = 1;
- return 0;
- }
- tcp_listen[i] = kcalloc(1, sizeof(struct TcpListen));
- tcp_listen[i]->ip = ip;
- tcp_listen[i]->port = port;
- stack_init(&tcp_listen[i]->incoming_connections);
- return i;
+ struct TcpListen *listener = kcalloc(1, sizeof(struct TcpListen));
+ listener->ip = ip;
+ listener->port = port;
+ stack_init(&listener->incoming_connections);
+
+ struct list *listen_list = &current_task->tcp_listen;
+ int index;
+ list_add(listen_list, listener, &index);
+ return index;
+}
+
+struct TcpConnection *tcp_get_connection(u32 socket) {
+ const struct list *connections = &current_task->tcp_sockets;
+ struct TcpConnection *con;
+ if (!list_get(connections, socket, (void **)&con)) {
+ return NULL;
+ }
+ return con;
}
u32 tcp_accept(u32 listen_socket, int *error) {
*error = 0;
- struct TcpListen *l = tcp_listen[listen_socket];
- if (NULL == l) {
+ struct list *listen_list = &current_task->tcp_listen;
+ struct TcpListen *l;
+ if (!list_get(listen_list, listen_socket, (void **)&l)) {
*error = 1;
return 0;
}
@@ -110,20 +129,12 @@ u32 tcp_accept(u32 listen_socket, int *error) {
}
u32 tcp_connect_ipv4(u32 ip, u16 port, int *error) {
+ struct list *connections = &current_task->tcp_sockets;
*error = 0;
- u32 i = 0;
- for (; i < 100; i++) {
- if (!tcp_sockets[i]) {
- break;
- }
- }
- if (tcp_sockets[i]) {
- *error = 1;
- return 0;
- }
- tcp_sockets[i] = kcalloc(1, sizeof(struct TcpConnection));
- struct TcpConnection *con = tcp_sockets[i];
+ struct TcpConnection *con = kcalloc(1, sizeof(struct TcpConnection));
+ int index;
+ list_add(connections, con, &index);
con->incoming_port = 1337; // TODO
con->outgoing_ip = ip;
@@ -144,33 +155,50 @@ u32 tcp_connect_ipv4(u32 ip, u16 port, int *error) {
}
}
- return i;
+ return index;
}
int tcp_write(u32 socket, const u8 *buffer, u64 len, u64 *out) {
- struct TcpConnection *con = tcp_sockets[socket];
- if (con->dead) {
+ if (out) {
*out = 0;
+ }
+ struct TcpConnection *con = tcp_get_connection(socket);
+ if (!con) {
+ return 0;
+ }
+ if (con->dead) {
return 0;
}
send_tcp_packet(con, buffer, len);
- *out = len;
+ if (out) {
+ *out = len;
+ }
return 1;
}
int tcp_read(u32 socket, u8 *buffer, u64 buffer_size, u64 *out) {
- struct TcpConnection *con = tcp_sockets[socket];
- if (con->dead) {
+ if (out) {
*out = 0;
+ }
+ struct TcpConnection *con = tcp_get_connection(socket);
+ if (!con) {
+ return 0;
+ }
+ if (con->dead) {
return 0;
}
int rc = 0;
for (; rc <= 0;) {
rc = fifo_object_read(buffer, 0, buffer_size, con->data_file);
+ if(rc <= 0) {
+ switch_task();
+ }
+ }
+ if (out) {
+ *out = rc;
}
- *out = rc;
return 1;
}
@@ -210,7 +238,7 @@ int uds_open(const char *path) {
fifo_object_write((u8 *)&c, 1, 0, s->fifo_file);
s->ptr_socket_fd->inode->has_data = 1;
- s->incoming_fd = get_current_task()->file_descriptors[fd[1]];
+ s->incoming_fd = current_task->file_descriptors[fd[1]];
// vfs_close(fd[1]);
return fd[0];
}
@@ -218,7 +246,7 @@ int uds_open(const char *path) {
int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
(void)address;
(void)address_len;
- vfs_inode_t *inode = get_current_task()->file_descriptors[socket]->inode;
+ vfs_inode_t *inode = current_task->file_descriptors[socket]->inode;
SOCKET *s = (SOCKET *)inode->internal_object;
if (NULL == s->incoming_fd) {
@@ -231,10 +259,10 @@ int accept(int socket, struct sockaddr *address, socklen_t *address_len) {
}
int n = 0;
- for (; get_current_task()->file_descriptors[n]; n++)
+ for (; current_task->file_descriptors[n]; n++)
;
- get_current_task()->file_descriptors[n] = s->incoming_fd;
- get_current_task()->file_descriptors[n]->reference_count++;
+ current_task->file_descriptors[n] = s->incoming_fd;
+ current_task->file_descriptors[n]->reference_count++;
s->incoming_fd = NULL;
// for (char c; 0 < vfs_pread(s->fifo_fd, &c, 1, 0);)
// ;
diff --git a/kernel/syscalls/getcwd.c b/kernel/syscalls/getcwd.c
index df370fb..c279428 100644
--- a/kernel/syscalls/getcwd.c
+++ b/kernel/syscalls/getcwd.c
@@ -4,8 +4,8 @@
char *syscall_getcwd(char *buf, size_t size) {
kprintf("syscall_getcwd\n");
- const char *cwd = get_current_task()->current_working_directory;
+ const char *cwd = current_task->current_working_directory;
size_t len = min(size, strlen(cwd));
- strlcpy(buf, get_current_task()->current_working_directory, len);
+ strlcpy(buf, current_task->current_working_directory, len);
return buf;
}
diff --git a/kernel/syscalls/install_irq.c b/kernel/syscalls/install_irq.c
index 4c990ee..5ad2ee6 100644
--- a/kernel/syscalls/install_irq.c
+++ b/kernel/syscalls/install_irq.c
@@ -16,7 +16,7 @@ void test_handler(reg_t *regs) {
int syscall_install_irq(void (*irq_handler)(), u8 irq) {
// TODO: This should be able to fail if the handler is already set
- tmp = get_current_task();
+ tmp = current_task;
handler = irq_handler;
install_handler(test_handler, INT_32_INTERRUPT_GATE(0x0), 0x20 + irq);
return 1;
diff --git a/kernel/syscalls/msleep.c b/kernel/syscalls/msleep.c
index a752d94..d2c8b59 100644
--- a/kernel/syscalls/msleep.c
+++ b/kernel/syscalls/msleep.c
@@ -4,6 +4,6 @@
#include <syscalls.h>
void syscall_msleep(u32 ms) {
- get_current_task()->sleep_until = pit_num_ms() + ms;
+ current_task->sleep_until = pit_num_ms() + ms;
switch_task();
}
diff --git a/kernel/syscalls/queue.c b/kernel/syscalls/queue.c
new file mode 100644
index 0000000..94f7960
--- /dev/null
+++ b/kernel/syscalls/queue.c
@@ -0,0 +1,14 @@
+#include <queue.h>
+#include <syscalls.h>
+
+int syscall_queue_create(u32 *id) {
+ return queue_create(id);
+}
+
+int syscall_queue_add(u32 queue_id, struct event *ev, u32 size) {
+ return queue_add(queue_id, ev, size);
+}
+
+int syscall_queue_wait(u32 queue_id) {
+ return queue_wait(queue_id);
+}
diff --git a/meta/userland.sh b/meta/userland.sh
index 98aaa74..c8eb1ac 100755
--- a/meta/userland.sh
+++ b/meta/userland.sh
@@ -17,6 +17,7 @@ make -C ./userland/minibox
make -C ./userland/libppm
make -C ./userland/rtl8139
make -C ./userland/smol_http
+make -C ./userland/irc
mkdir sysroot
sudo cp ./userland/rtl8139/rtl8139 ./sysroot/rtl8139
@@ -29,6 +30,7 @@ sudo cp ./userland/windowserver/ws ./sysroot/ws
sudo cp ./userland/test/test ./sysroot/test
sudo cp ./userland/minibox/minibox ./sysroot/minibox
sudo cp ./userland/smol_http/smol_http ./sysroot/smol_http
+sudo cp ./userland/irc/irc ./sysroot/irc
cd ./sysroot
rm ./init
diff --git a/userland/libc/include/syscall.h b/userland/libc/include/syscall.h
index 72f781d..5e0e567 100644
--- a/userland/libc/include/syscall.h
+++ b/userland/libc/include/syscall.h
@@ -53,6 +53,14 @@
#define SYS_INSTALL_IRQ 44
#define SYS_TMP_KERNEL_HANDLE_PACKET 45
+#define SYS_TCP_CONNECT 46
+#define SYS_TCP_WRITE 47
+#define SYS_TCP_READ 48
+
+#define SYS_QUEUE_CREATE 49
+#define SYS_QUEUE_ADD 50
+#define SYS_QUEUE_WAIT 51
+
int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx,
uint32_t esi, uint32_t edi);
int s_syscall(int sys);
diff --git a/userland/terminal/term.c b/userland/terminal/term.c
index 2bc4a02..62aaa55 100644
--- a/userland/terminal/term.c
+++ b/userland/terminal/term.c
@@ -19,6 +19,8 @@ uint32_t screen_pos_x = 0;
uint32_t screen_pos_y = 0;
int serial_fd;
+int raw_mode = 0;
+
void execsh(void) {
char *argv[] = {NULL};
execv("/sh", argv);
@@ -27,7 +29,7 @@ void execsh(void) {
uint32_t cursor_pos_x = 0;
uint32_t cursor_pos_y = 0;
-void screen_remove_old_cursor() {
+void screen_remove_old_cursor(void) {
GUI_OverwriteFont(global_w, cursor_pos_x, cursor_pos_y, TERM_BACKGROUND);
}
@@ -38,6 +40,11 @@ void screen_update_cursor() {
}
void screen_putchar(uint32_t c) {
+ if (raw_mode) {
+ GUI_DrawFont(global_w, screen_pos_x, screen_pos_y, c);
+ screen_remove_old_cursor();
+ return;
+ }
if (c == '\n') {
screen_pos_x = 0;
screen_pos_y += 8;
@@ -77,9 +84,11 @@ void screen_delete_char(void) {
void screen_print(const unsigned char *s, int l) {
for (; l; l--, s++) {
- if ('\b' == *s) {
- screen_delete_char();
- continue;
+ if (!raw_mode) {
+ if ('\b' == *s) {
+ screen_delete_char();
+ continue;
+ }
}
screen_putchar((uint32_t)*s);
}
@@ -112,6 +121,103 @@ void writetty(const char *b, size_t len) {
}
}
+// VT100 escape codes
+void handle_escape_codes_or_print(char *buffer, int len) {
+ static int inside_escape_code = 0;
+ static int second_stage = 0;
+
+ if (!inside_escape_code) {
+ for (; len > 0; len--, buffer++) {
+ if ('\033' == *buffer) {
+ inside_escape_code = 1;
+ buffer++;
+ len--;
+ break;
+ }
+ screen_print(buffer, 1);
+ }
+ if (0 == len) {
+ return;
+ }
+ }
+ assert(inside_escape_code);
+ if (!second_stage) {
+ if ('[' == *buffer) {
+ second_stage = 1;
+ buffer++;
+ len--;
+ } else {
+ // TODO: Implement the rest.
+ inside_escape_code = 0;
+ buffer++;
+ len--;
+ handle_escape_codes_or_print(buffer, len);
+ }
+ }
+
+ static int in_second_argument = 0;
+ static int first_argument = 0;
+ if (!in_second_argument) {
+ // Parse the first argument(number)
+ for (; len > 0; len--, buffer++) {
+ if (!isdigit(*buffer)) {
+ break;
+ }
+ first_argument *= 10;
+ first_argument += *buffer - '0';
+ }
+ if (0 == len) {
+ return;
+ }
+ }
+ if (';' == *buffer) {
+ in_second_argument = 1;
+ buffer++;
+ len--;
+ }
+ static int second_argument = 0;
+ if (in_second_argument) {
+ for (; len > 0; len--, buffer++) {
+ if (!isdigit(*buffer)) {
+ break;
+ }
+ second_argument *= 10;
+ second_argument += *buffer - '0';
+ }
+ if (0 == len) {
+ return;
+ }
+ }
+
+ if ('H' == *buffer) {
+ assert(in_second_argument);
+ screen_pos_x = first_argument * 8;
+ screen_pos_y = second_argument * 8;
+ screen_remove_old_cursor();
+ buffer++;
+ len--;
+ } else if ('J' == *buffer) {
+ // clearscreen ED2 Clear entire screen ^[[2J
+ if (!in_second_argument && 2 == first_argument) {
+ for (int i = 0; i < 250 * 150 * 4 * 4; i++) {
+ global_w->bitmap_ptr[i] = TERM_BACKGROUND;
+ }
+ buffer++;
+ len--;
+ }
+ } else if ('X' == *buffer) {
+ raw_mode = 1;
+ buffer++;
+ len--;
+ }
+ inside_escape_code = 0;
+ second_stage = 0;
+ in_second_argument = 0;
+ first_argument = 0;
+ second_argument = 0;
+ handle_escape_codes_or_print(buffer, len);
+}
+
void run() {
char buffer[4096];
struct pollfd fds[2];
@@ -126,19 +232,22 @@ void run() {
if (fds[0].revents & POLLIN) {
int rc;
if ((rc = read(cmdfd, buffer, 4096))) {
- screen_print(buffer, rc);
+ handle_escape_codes_or_print(buffer, rc);
GUI_UpdateWindow(global_w);
}
}
if (fds[1].revents & POLLIN) {
WS_EVENT e;
int rc;
- if (0 >= (rc = read(global_w->ws_socket, &e, sizeof(e))))
+ if (0 >= (rc = read(global_w->ws_socket, &e, sizeof(e)))) {
+ continue;
+ }
+ if (1 == e.ev.release) {
continue;
- if (1 == e.ev.release)
- continue;
- if (0 == e.ev.c)
+ }
+ if (0 == e.ev.c) {
continue;
+ }
write(cmdfd, &e.ev.c, 1);
}
}
@@ -150,8 +259,9 @@ int main(void) {
global_w = GUI_CreateWindow(20, 20, 250 * 4, 150 * 4);
assert(global_w);
- for (int i = 0; i < 250 * 150 * 4 * 4; i++)
+ for (int i = 0; i < 250 * 150 * 4 * 4; i++) {
global_w->bitmap_ptr[i] = TERM_BACKGROUND;
+ }
// memset(global_w->bitmap_ptr, 0x0, 50 * 50);
GUI_UpdateWindow(global_w);
newtty();