diff options
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 = ¤t_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 = ¤t_task->read_list; + struct list *write_list = ¤t_task->write_list; + struct list *disconnect_list = ¤t_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 = ¤t_task->event_queue; + list_add(list, q, id); + return 1; +} + +struct event_queue *get_event_queue(u32 id) { + const struct list *list = ¤t_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 = ¤t_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 = ¤t_task->tcp_listen; + int index; + list_add(listen_list, listener, &index); + return index; +} + +struct TcpConnection *tcp_get_connection(u32 socket) { + const struct list *connections = ¤t_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 = ¤t_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 = ¤t_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(); |