diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | build.zig | 118 | ||||
-rw-r--r-- | compile_flags.txt | 2 | ||||
-rw-r--r-- | config/gdbinit (renamed from util/gdbinit) | 0 | ||||
-rw-r--r-- | config/grub.cfg (renamed from grub.cfg) | 0 | ||||
-rw-r--r-- | config/kernel.ld (renamed from kernel/kernel.ld) | 0 | ||||
-rw-r--r-- | config/user.ld (renamed from user/user.ld) | 0 | ||||
-rw-r--r-- | include/lib.h | 8 | ||||
-rw-r--r-- | include/limits.h | 12 | ||||
-rw-r--r-- | include/stdbool.h | 17 | ||||
-rw-r--r-- | include/time.h | 63 | ||||
-rw-r--r-- | kernel/cpu/idt.c | 90 | ||||
-rw-r--r-- | kernel/drivers/clock.c | 150 | ||||
-rw-r--r-- | kernel/drivers/drivers.c | 3 | ||||
-rw-r--r-- | kernel/drivers/pci.c | 6 | ||||
-rw-r--r-- | kernel/drivers/tty.c | 8 | ||||
-rw-r--r-- | kernel/include/comus/drivers/tty.h | 2 | ||||
l--------- | kernel/include/comus/error.h | 1 | ||||
-rw-r--r-- | kernel/include/comus/fs.h | 5 | ||||
-rw-r--r-- | kernel/include/comus/memory.h | 54 | ||||
-rw-r--r-- | kernel/include/comus/time.h | 39 | ||||
-rw-r--r-- | kernel/include/lib.h | 20 | ||||
-rw-r--r-- | kernel/include/lib/kctype.h | 22 | ||||
-rw-r--r-- | kernel/include/lib/kio.h | 91 | ||||
-rw-r--r-- | kernel/include/lib/klib.h | 196 | ||||
-rw-r--r-- | kernel/include/lib/kstring.h | 154 | ||||
-rw-r--r-- | kernel/lib/atox.c | 29 | ||||
-rw-r--r-- | kernel/lib/bound.c | 12 | ||||
-rw-r--r-- | kernel/lib/btoa.c | 43 | ||||
-rw-r--r-- | kernel/lib/ctoi.c | 14 | ||||
-rw-r--r-- | kernel/lib/fputc.c | 10 | ||||
-rw-r--r-- | kernel/lib/isdigit.c | 6 | ||||
-rw-r--r-- | kernel/lib/isspace.c | 16 | ||||
-rw-r--r-- | kernel/lib/itoc.c | 10 | ||||
-rw-r--r-- | kernel/lib/kalloc.c | 210 | ||||
-rw-r--r-- | kernel/lib/kprintf.c | 576 | ||||
-rw-r--r-- | kernel/lib/memcmp.c | 9 | ||||
-rw-r--r-- | kernel/lib/memcpy.c | 10 | ||||
-rw-r--r-- | kernel/lib/memcpyv.c (renamed from lib/memcpyv.c) | 2 | ||||
-rw-r--r-- | kernel/lib/memmove.c | 20 | ||||
-rw-r--r-- | kernel/lib/memmovev.c (renamed from lib/memmovev.c) | 2 | ||||
-rw-r--r-- | kernel/lib/memset.c | 10 | ||||
-rw-r--r-- | kernel/lib/memsetv.c (renamed from lib/memsetv.c) | 2 | ||||
-rw-r--r-- | kernel/lib/panic.c | 6 | ||||
-rw-r--r-- | kernel/lib/stpcpy.c | 9 | ||||
-rw-r--r-- | kernel/lib/stpncpy.c | 10 | ||||
-rw-r--r-- | kernel/lib/strcat.c | 7 | ||||
-rw-r--r-- | kernel/lib/strcpy.c | 9 | ||||
-rw-r--r-- | kernel/lib/strlen.c | 9 | ||||
-rw-r--r-- | kernel/lib/strncmp.c | 11 | ||||
-rw-r--r-- | kernel/lib/strncpy.c | 10 | ||||
-rw-r--r-- | kernel/lib/strtoux.c | 43 | ||||
-rw-r--r-- | kernel/lib/strtox.c | 52 | ||||
-rw-r--r-- | kernel/lib/uxtoa.c | 27 | ||||
-rw-r--r-- | kernel/lib/xtoa.c | 31 | ||||
-rw-r--r-- | kernel/main.c (renamed from kernel/kernel.c) | 11 | ||||
-rw-r--r-- | kernel/mboot/mmap.c | 6 | ||||
-rw-r--r-- | kernel/memory/paging.c | 15 | ||||
-rw-r--r-- | kernel/memory/physalloc.c | 17 | ||||
-rw-r--r-- | kernel/memory/virtalloc.c | 4 | ||||
-rw-r--r-- | user/include/ctype.h (renamed from include/ctype.h) | 0 | ||||
-rw-r--r-- | user/include/elf.h (renamed from include/elf.h) | 0 | ||||
-rw-r--r-- | user/include/error.h (renamed from include/error.h) | 0 | ||||
-rw-r--r-- | user/include/stdio.h (renamed from include/stdio.h) | 16 | ||||
-rw-r--r-- | user/include/stdlib.h (renamed from include/stdlib.h) | 32 | ||||
-rw-r--r-- | user/include/string.h (renamed from include/string.h) | 32 | ||||
-rw-r--r-- | user/include/unistd.h (renamed from include/unistd.h) | 92 | ||||
-rw-r--r-- | user/lib/alloc.c (renamed from lib/alloc.c) | 4 | ||||
-rw-r--r-- | user/lib/atox.c (renamed from lib/atox.c) | 0 | ||||
-rw-r--r-- | user/lib/bound.c (renamed from lib/bound.c) | 0 | ||||
-rw-r--r-- | user/lib/btoa.c (renamed from lib/btoa.c) | 0 | ||||
-rw-r--r-- | user/lib/ctoi.c (renamed from lib/ctoi.c) | 0 | ||||
-rw-r--r-- | user/lib/delay.c (renamed from lib/delay.c) | 0 | ||||
-rw-r--r-- | user/lib/entry.S (renamed from ulib/entry.S) | 0 | ||||
-rw-r--r-- | user/lib/isdigit.c (renamed from lib/isdigit.c) | 0 | ||||
-rw-r--r-- | user/lib/isspace.c (renamed from lib/isspace.c) | 0 | ||||
-rw-r--r-- | user/lib/itoc.c (renamed from lib/itoc.c) | 0 | ||||
-rw-r--r-- | user/lib/memcmp.c (renamed from lib/memcmp.c) | 0 | ||||
-rw-r--r-- | user/lib/memcpy.c (renamed from lib/memcpy.c) | 0 | ||||
-rw-r--r-- | user/lib/memmove.c (renamed from lib/memmove.c) | 0 | ||||
-rw-r--r-- | user/lib/memset.c (renamed from lib/memset.c) | 0 | ||||
-rw-r--r-- | user/lib/printf.c (renamed from lib/printf.c) | 0 | ||||
-rw-r--r-- | user/lib/spawn.c (renamed from ulib/spawn.c) | 0 | ||||
-rw-r--r-- | user/lib/stpcpy.c (renamed from lib/stpcpy.c) | 0 | ||||
-rw-r--r-- | user/lib/stpncpy.c (renamed from lib/stpncpy.c) | 0 | ||||
-rw-r--r-- | user/lib/strcat.c (renamed from lib/strcat.c) | 0 | ||||
-rw-r--r-- | user/lib/strcpy.c (renamed from lib/strcpy.c) | 0 | ||||
-rw-r--r-- | user/lib/strlen.c (renamed from lib/strlen.c) | 0 | ||||
-rw-r--r-- | user/lib/strncmp.c (renamed from lib/strncmp.c) | 0 | ||||
-rw-r--r-- | user/lib/strncpy.c (renamed from lib/strncpy.c) | 0 | ||||
-rw-r--r-- | user/lib/strtoux.c (renamed from lib/strtoux.c) | 0 | ||||
-rw-r--r-- | user/lib/strtox.c (renamed from lib/strtox.c) | 0 | ||||
-rw-r--r-- | user/lib/syscall.S (renamed from ulib/syscall.S) | 0 | ||||
-rw-r--r-- | user/lib/timetostr.c (renamed from lib/timetostr.c) | 0 | ||||
-rw-r--r-- | user/lib/uxtoa.c (renamed from lib/uxtoa.c) | 0 | ||||
-rw-r--r-- | user/lib/xtoa.c (renamed from lib/xtoa.c) | 0 | ||||
-rw-r--r-- | util/BuildImage.c | 420 | ||||
-rw-r--r-- | util/default.ld | 247 | ||||
-rw-r--r-- | util/listblob.c | 240 | ||||
-rw-r--r-- | util/mkblob.c | 321 |
100 files changed, 1954 insertions, 1773 deletions
@@ -19,7 +19,7 @@ qemu-gdb: bin/os.iso $(QEMU) $(QEMUOPTS) -S -gdb tcp::1337 gdb: - gdb -q -n -x util/gdbinit + gdb -q -n -x config/gdbinit clean: rm -fr .zig-cache @@ -30,7 +30,7 @@ build: bin/os.iso: build mkdir -p bin/iso/boot/grub - cp grub.cfg bin/iso/boot/grub + cp config/grub.cfg bin/iso/boot/grub cp bin/kernel bin/iso/boot grub-mkrescue -o bin/os.iso bin/iso 2>/dev/null @@ -20,11 +20,9 @@ const c_flags = &[_][]const u8{ "-ggdb", }; -const boot_src = &[_][]const u8{"boot/boot.S"}; - const kernel_src = &[_][]const u8{ "kernel/entry.S", // must be first - "kernel/kernel.c", // main function + "kernel/main.c", // main function "kernel/cpu/cpu.c", "kernel/cpu/fpu.c", "kernel/cpu/idt.c", @@ -36,8 +34,34 @@ const kernel_src = &[_][]const u8{ "kernel/drivers/tty.c", "kernel/drivers/uart.c", "kernel/fs/fs.c", - "kernel/lib/fputc.c", + "kernel/lib/atox.c", + "kernel/lib/bound.c", + "kernel/lib/btoa.c", + "kernel/lib/ctoi.c", + "kernel/lib/isdigit.c", + "kernel/lib/isspace.c", + "kernel/lib/itoc.c", + "kernel/lib/kalloc.c", + "kernel/lib/kprintf.c", + "kernel/lib/memcmp.c", + "kernel/lib/memcpy.c", + "kernel/lib/memcpyv.c", + "kernel/lib/memmove.c", + "kernel/lib/memmovev.c", + "kernel/lib/memset.c", + "kernel/lib/memsetv.c", "kernel/lib/panic.c", + "kernel/lib/stpcpy.c", + "kernel/lib/stpncpy.c", + "kernel/lib/strcat.c", + "kernel/lib/strcpy.c", + "kernel/lib/strlen.c", + "kernel/lib/strncmp.c", + "kernel/lib/strncpy.c", + "kernel/lib/strtoux.c", + "kernel/lib/strtox.c", + "kernel/lib/uxtoa.c", + "kernel/lib/xtoa.c", "kernel/mboot/mboot.c", "kernel/mboot/mmap.c", "kernel/memory/memory.c", @@ -46,61 +70,11 @@ const kernel_src = &[_][]const u8{ "kernel/memory/virtalloc.c", }; -const lib_src = &[_][]const u8{ - "lib/alloc.c", - "lib/atox.c", - "lib/bound.c", - "lib/btoa.c", - "lib/ctoi.c", - "lib/delay.c", - "lib/isdigit.c", - "lib/isspace.c", - "lib/itoc.c", - "lib/memcmp.c", - "lib/memcpy.c", - "lib/memcpyv.c", - "lib/memmove.c", - "lib/memmovev.c", - "lib/memset.c", - "lib/memsetv.c", - "lib/printf.c", - "lib/stpcpy.c", - "lib/stpncpy.c", - "lib/strcat.c", - "lib/strcpy.c", - "lib/strlen.c", - "lib/strncmp.c", - "lib/strncpy.c", - "lib/strtoux.c", - "lib/strtox.c", - "lib/timetostr.c", - "lib/uxtoa.c", - "lib/xtoa.c", -}; - const Prog = struct { name: []const u8, source: []const []const u8, }; -const util_progs = &[_]Prog{ - // mkblob - Prog{ - .name = "mkblob", - .source = &[_][]const u8{"util/mkblob.c"}, - }, - // listblob - Prog{ - .name = "listblob", - .source = &[_][]const u8{"util/listblob.c"}, - }, - // BuildImage - Prog{ - .name = "BuildImage", - .source = &[_][]const u8{"util/BuildImage.c"}, - }, -}; - const AddSourcesOpts = struct { exe: *std.Build.Step.Compile, sources: []const []const []const u8, c_flags: []const []const u8 }; fn add_sources(b: *std.Build, opts: AddSourcesOpts) void { @@ -138,8 +112,7 @@ fn build_kern_binary(b: *std.Build, opts: BuildKernBinaryOpts) void { .strip = opts.strip, }); - // add include paths - exe.addIncludePath(b.path("include/")); + // add include path if (opts.include != null) { exe.addIncludePath(b.path(opts.include.?)); } @@ -198,12 +171,6 @@ fn build_native_binary(b: *std.Build, opts: BuildNativeBinaryOpts) void { pub fn build(b: *std.Build) !void { // context - const target32 = std.Build.resolveTargetQuery(b, .{ - .cpu_arch = std.Target.Cpu.Arch.x86, - .os_tag = std.Target.Os.Tag.freestanding, - .abi = std.Target.Abi.gnu, - .ofmt = std.Target.ObjectFormat.elf, - }); const target64 = std.Build.resolveTargetQuery(b, .{ .cpu_arch = std.Target.Cpu.Arch.x86_64, .os_tag = std.Target.Os.Tag.freestanding, @@ -212,19 +179,6 @@ pub fn build(b: *std.Build) !void { }); const optimize = std.builtin.OptimizeMode.ReleaseFast; - // boot - build_kern_binary(b, .{ - .name = "boot", - .target = target32, - .optimize = optimize, - .sources = &.{ - boot_src, - }, - .linker = "boot/boot.ld", - .entry = "bootentry", - .include = "boot/include", - }); - // kernel build_kern_binary(b, .{ .name = "kernel", @@ -232,20 +186,8 @@ pub fn build(b: *std.Build) !void { .optimize = optimize, .sources = &.{ kernel_src, - lib_src, }, - .linker = "kernel/kernel.ld", + .linker = "config/kernel.ld", .include = "kernel/include", }); - - // util_progs - for (util_progs) |prog| { - build_native_binary(b, .{ - .name = prog.name, - .optimize = optimize, - .sources = &.{ - prog.source, - }, - }); - } } diff --git a/compile_flags.txt b/compile_flags.txt index 18bbfbc..611c77e 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1,7 +1,7 @@ -c -std=c11 --Iinclude -Ikernel/include +-Iuser/include -ffreestanding -fno-builtin -Wall diff --git a/util/gdbinit b/config/gdbinit index ca2c885..ca2c885 100644 --- a/util/gdbinit +++ b/config/gdbinit diff --git a/grub.cfg b/config/grub.cfg index 6cedb28..6cedb28 100644 --- a/grub.cfg +++ b/config/grub.cfg diff --git a/kernel/kernel.ld b/config/kernel.ld index 0806257..0806257 100644 --- a/kernel/kernel.ld +++ b/config/kernel.ld diff --git a/user/user.ld b/config/user.ld index 9e31dff..9e31dff 100644 --- a/user/user.ld +++ b/config/user.ld diff --git a/include/lib.h b/include/lib.h deleted file mode 100644 index e8e921d..0000000 --- a/include/lib.h +++ /dev/null @@ -1,8 +0,0 @@ -#include <ctype.h> -#include <error.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> -#include <string.h> -#include <limits.h> diff --git a/include/limits.h b/include/limits.h deleted file mode 100644 index d4a3190..0000000 --- a/include/limits.h +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @file limits.h - * - * @author Freya Murphy <freya@freyacat.org> - * - * System limits - */ - -#define MAX_FILE_NAME_LEN 256 -#define MAX_OPEN_FILES 256 - -#define MAX_DISKS 8 diff --git a/include/stdbool.h b/include/stdbool.h deleted file mode 100644 index dddf1c9..0000000 --- a/include/stdbool.h +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file stdbool.h - * @author Freya Murphy <freya@freyacat.org> - * @author Warren R. Carithers - * - * Boolean definitions. - */ - -#ifndef _STDBOOL_H -#define _STDBOOL_H - -// Boolean values -typedef _Bool bool; -#define true 1 -#define false 0 - -#endif /* stdbool.h */ diff --git a/include/time.h b/include/time.h deleted file mode 100644 index 4d339a0..0000000 --- a/include/time.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file time.h - * - * @author Freya Murphy <freya@freyacat.org> - * - * System time structure - */ - -#ifndef TIME_H_ -#define TIME_H_ - -#include <stddef.h> - -typedef struct { - int sec; /// Seconds [0,59] - int min; /// Minutes [0,59] - int hour; /// Hour [0,23] - int mday; /// Day of month [1,31] - int mon; /// Month of year [0,11] - int year; /// Years since 1900 - int wday; /// Day of week [0,6] (Sunday = 0) - int yday; /// Day of year [0,365] - int yn; /// Year number [0,99] - int cen; /// Century [19,20] - int leap; /// If year is a leap year (True == 1) -} time_t; - -typedef enum { - TZ_UTC = 0, - TZ_EST = -5, - TZ_EDT = -4, -} timezone_t; - -/** - * Sets the current timezone - */ -extern void set_timezone(timezone_t tz); - -/** - * Returns current time in UTC - */ -extern time_t get_utctime(void); - -/** - * Returns current time from current Timezone - */ -extern time_t get_localtime(void); - -/** - * Return the time on the system clock - */ -extern size_t get_systemtime(void); - -/** - * Converts the time into a string format - * - * @param time - the current time - * @param format - see manpage for date - * @param buf - the buffer to store it in - */ -extern void timetostr(time_t *time, char *format, char *buf, size_t n); - -#endif /* time.h */ diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c index 748826c..51fb125 100644 --- a/kernel/cpu/idt.c +++ b/kernel/cpu/idt.c @@ -72,63 +72,63 @@ void idt_init(void) static void isr_print_regs(regs_t *regs) { - printf("rax: %#016lx (%lu)\n", regs->rax, regs->rax); - printf("rbx: %#016lx (%lu)\n", regs->rbx, regs->rbx); - printf("rcx: %#016lx (%lu)\n", regs->rcx, regs->rcx); - printf("rdx: %#016lx (%lu)\n", regs->rdx, regs->rdx); - printf("rsi: %#016lx (%lu)\n", regs->rsi, regs->rsi); - printf("rdi: %#016lx (%lu)\n", regs->rdi, regs->rdi); - printf("rsp: %#016lx (%lu)\n", regs->rsp, regs->rsp); - printf("rbp: %#016lx (%lu)\n", regs->rbp, regs->rbp); - printf("r8 : %#016lx (%lu)\n", regs->r8, regs->r8); - printf("r9 : %#016lx (%lu)\n", regs->r9, regs->r9); - printf("r10: %#016lx (%lu)\n", regs->r10, regs->r10); - printf("r11: %#016lx (%lu)\n", regs->r11, regs->r11); - printf("r12: %#016lx (%lu)\n", regs->r12, regs->r12); - printf("r13: %#016lx (%lu)\n", regs->r13, regs->r13); - printf("r14: %#016lx (%lu)\n", regs->r14, regs->r14); - printf("r15: %#016lx (%lu)\n", regs->r15, regs->r15); - printf("rip: %#016lx (%lu)\n", regs->rip, regs->rip); - printf("rflags: %#016lx (%lu)\n", (uint64_t)regs->rflags.raw, + kprintf("rax: %#016lx (%lu)\n", regs->rax, regs->rax); + kprintf("rbx: %#016lx (%lu)\n", regs->rbx, regs->rbx); + kprintf("rcx: %#016lx (%lu)\n", regs->rcx, regs->rcx); + kprintf("rdx: %#016lx (%lu)\n", regs->rdx, regs->rdx); + kprintf("rsi: %#016lx (%lu)\n", regs->rsi, regs->rsi); + kprintf("rdi: %#016lx (%lu)\n", regs->rdi, regs->rdi); + kprintf("rsp: %#016lx (%lu)\n", regs->rsp, regs->rsp); + kprintf("rbp: %#016lx (%lu)\n", regs->rbp, regs->rbp); + kprintf("r8 : %#016lx (%lu)\n", regs->r8, regs->r8); + kprintf("r9 : %#016lx (%lu)\n", regs->r9, regs->r9); + kprintf("r10: %#016lx (%lu)\n", regs->r10, regs->r10); + kprintf("r11: %#016lx (%lu)\n", regs->r11, regs->r11); + kprintf("r12: %#016lx (%lu)\n", regs->r12, regs->r12); + kprintf("r13: %#016lx (%lu)\n", regs->r13, regs->r13); + kprintf("r14: %#016lx (%lu)\n", regs->r14, regs->r14); + kprintf("r15: %#016lx (%lu)\n", regs->r15, regs->r15); + kprintf("rip: %#016lx (%lu)\n", regs->rip, regs->rip); + kprintf("rflags: %#016lx (%lu)\n", (uint64_t)regs->rflags.raw, (uint64_t)regs->rflags.raw); - puts("rflags: "); + kputs("rflags: "); if (regs->rflags.cf) - puts("CF "); + kputs("CF "); if (regs->rflags.pf) - puts("PF "); + kputs("PF "); if (regs->rflags.af) - puts("AF "); + kputs("AF "); if (regs->rflags.zf) - puts("ZF "); + kputs("ZF "); if (regs->rflags.sf) - puts("SF "); + kputs("SF "); if (regs->rflags.tf) - puts("TF "); + kputs("TF "); if (regs->rflags.if_) - puts("IF "); + kputs("IF "); if (regs->rflags.df) - puts("DF "); + kputs("DF "); if (regs->rflags.of) - puts("OF "); + kputs("OF "); if (regs->rflags.iopl) - puts("IOPL "); + kputs("IOPL "); if (regs->rflags.nt) - puts("NT "); + kputs("NT "); if (regs->rflags.md) - puts("MD "); + kputs("MD "); if (regs->rflags.rf) - puts("RF "); + kputs("RF "); if (regs->rflags.vm) - puts("VM "); + kputs("VM "); if (regs->rflags.ac) - puts("AC "); + kputs("AC "); if (regs->rflags.vif) - puts("VIF "); + kputs("VIF "); if (regs->rflags.vip) - puts("VIP "); + kputs("VIP "); if (regs->rflags.id) - puts("ID "); - puts("\n"); + kputs("ID "); + kputs("\n"); } #define EX_DEBUG 0x01 @@ -179,23 +179,23 @@ void idt_exception_handler(uint64_t exception, uint64_t code, regs_t *state) case EX_PAGE_FAULT: // page faults store the offending address in cr2 __asm__ volatile("mov %%cr2, %0" : "=r"(cr2)); - if (!load_page((void *)cr2)) + if (!kload_page((void *)cr2)) return; } - puts("\n\n!!! EXCEPTION !!!\n"); - printf("%#02lX %s\n", exception, EXCEPTIONS[exception]); - printf("Error code %#lX\n", code); + kputs("\n\n!!! EXCEPTION !!!\n"); + kprintf("%#02lX %s\n", exception, EXCEPTIONS[exception]); + kprintf("Error code %#lX\n", code); if (exception == EX_PAGE_FAULT) { - printf("Page fault address: %#016lx\n", cr2); + kprintf("Page fault address: %#016lx\n", cr2); } - puts("\n"); + kputs("\n"); isr_print_regs(state); - puts("\n"); + kputs("\n"); while (1) { halt(); diff --git a/kernel/drivers/clock.c b/kernel/drivers/clock.c index dd229dc..fadd938 100644 --- a/kernel/drivers/clock.c +++ b/kernel/drivers/clock.c @@ -1,6 +1,6 @@ #include <lib.h> -#include <time.h> #include <comus/asm.h> +#include <comus/time.h> #include <comus/drivers/clock.h> #define CMOS_WRITE_PORT 0x70 @@ -15,18 +15,6 @@ #define CMOS_REG_YEAR 0x09 #define CMOS_REG_CEN 0x32 -// Live buffers to work on data -static time_t time; -static time_t localtime; - -// Front buffers so interupts dont request data that is half done -static time_t curr_time; -static time_t curr_localtime; - -// Current set time Zone -static timezone_t curr_timezone = TZ_UTC; -static timezone_t last_timezone = TZ_UTC; - static uint8_t cmos_read(uint8_t reg) { uint8_t hex, ret; @@ -43,124 +31,40 @@ static uint8_t cmos_read(uint8_t reg) static int mday_offset[12] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; -static int month_days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - -static void update_localtime(void) -{ - int change, max; - - // set localtime - localtime = time; - - // if tz is UTC, we dont need to do anythin - if (last_timezone == TZ_UTC) - return; - - localtime.hour += last_timezone; - - // check if day rolled over - change = localtime.hour < 0 ? -1 : localtime.hour >= 24 ? 1 : 0; - if (!change) - return; - - // roll over day - localtime.hour = (localtime.hour + 24) % 24; - localtime.wday = (localtime.wday + change + 7) % 7; - localtime.mday += change; - localtime.yday += change; - - // check if month rolled over - max = month_days[localtime.mon]; - if (localtime.leap && localtime.mon == 1) - max++; - change = localtime.mday < 0 ? -1 : localtime.mday >= max ? 1 : 0; - if (!change) - return; - - // roll over month - localtime.mon = (localtime.mon + change + 12) % 12; - - // check if year rolled over - max = localtime.leap ? 366 : 365; - change = localtime.yday < 0 ? -1 : localtime.yday >= max ? 1 : 0; - if (!change) - return; - - // roll over year - localtime.yn += change; - - // check if cen rolled over - change = localtime.yn < 0 ? -1 : localtime.yn >= 100 ? 1 : 0; - if (!change) - goto year; - - // roll over cen - localtime.cen += change; - -year: - - localtime.year = localtime.yn + localtime.cen * 100; - localtime.leap = localtime.year % 4 == 0 && localtime.year % 100 != 0; - - if (localtime.leap && localtime.yday == -1) - localtime.yday = 365; - else if (localtime.yday == -1) - localtime.yday = 364; - else - localtime.yday = 0; - - localtime.year -= 1900; -} - -void clock_update(void) +void gettime(struct time *time) { - time.sec = cmos_read(CMOS_REG_SEC); - time.min = cmos_read(CMOS_REG_MIN); - time.hour = cmos_read(CMOS_REG_HOUR); - time.wday = cmos_read(CMOS_REG_WDAY) - 1; - time.mday = cmos_read(CMOS_REG_MDAY); - time.mon = cmos_read(CMOS_REG_MON) - 1; - time.yn = cmos_read(CMOS_REG_YEAR); - time.cen = 20; - - time.year = time.yn + time.cen * 100; - - time.leap = time.year % 4 == 0 && time.year % 100 != 0; + time->sec = cmos_read(CMOS_REG_SEC); + time->min = cmos_read(CMOS_REG_MIN); + time->hour = cmos_read(CMOS_REG_HOUR); + time->wday = cmos_read(CMOS_REG_WDAY) - 1; + time->mday = cmos_read(CMOS_REG_MDAY); + time->mon = cmos_read(CMOS_REG_MON) - 1; + time->yn = cmos_read(CMOS_REG_YEAR); + time->cen = 20; - time.yday = mday_offset[time.mon] + time.mday; + time->year = time->yn + time->cen * 100; - if (time.leap && time.mon > 2) - time.yday++; + time->leap = time->year % 4 == 0 && time->year % 100 != 0; - time.year -= 1900; + time->yday = mday_offset[time->mon] + time->mday; - update_localtime(); + if (time->leap && time->mon > 2) + time->yday++; - curr_time = time; - curr_localtime = localtime; + time->year -= 1900; } -void set_timezone(timezone_t tz) +uint64_t unixtime(void) { - curr_timezone = tz; -} - -time_t get_utctime(void) -{ - return curr_time; -} + struct time time; + gettime(&time); -time_t get_localtime(void) -{ - if (curr_timezone != last_timezone) { - last_timezone = curr_timezone; - update_localtime(); - curr_localtime = localtime; - } - return curr_localtime; -} - -size_t get_systemtime(void) -{ - return 0; + // FIXME: probably wrong + uint64_t unix = 0; + unix += time.sec; + unix += time.min * 60; + unix += time.hour * 60 * 60; + unix += time.yday * 60 * 60 * 24; + unix += time.year * 60 * 60 * 24 * 365; + return unix; } diff --git a/kernel/drivers/drivers.c b/kernel/drivers/drivers.c index 00ee247..9b90eb8 100644 --- a/kernel/drivers/drivers.c +++ b/kernel/drivers/drivers.c @@ -1,12 +1,9 @@ #include <comus/drivers.h> #include <comus/drivers/uart.h> -#include <comus/drivers/tty.h> #include <comus/drivers/pci.h> -#include <comus/drivers/clock.h> void drivers_init(void) { uart_init(); pci_init(); - clock_update(); } diff --git a/kernel/drivers/pci.c b/kernel/drivers/pci.c index 83c47f1..e84ca11 100644 --- a/kernel/drivers/pci.c +++ b/kernel/drivers/pci.c @@ -34,7 +34,7 @@ uint32_t pci_rcfg_d(struct pci_device dev, uint8_t offset) static void print_device(struct pci_table_entry *entry) { - printf( + kprintf( "BUS: %#-4x DEV: %#-4x FUNC: %#-4x ID: %04x:%04x CLASS: %02x:%02x:%02x REV: %#02x\n", entry->device.bus, entry->device.device, entry->device.function, entry->vendor_id, entry->device_id, entry->class, entry->subclass, @@ -134,11 +134,11 @@ void pci_init(void) } } } - printf("PCI DEVICES\n"); + kprintf("PCI DEVICES\n"); for (size_t i = 0; i < pci_table_next; i++) { print_device(&pci_table[i]); } - printf("\n"); + kprintf("\n"); } bool pci_findby_class(struct pci_device *dest, uint8_t class, uint8_t subclass, diff --git a/kernel/drivers/tty.c b/kernel/drivers/tty.c index 5a231cd..e9d3e50 100644 --- a/kernel/drivers/tty.c +++ b/kernel/drivers/tty.c @@ -2,8 +2,6 @@ #include <comus/drivers/tty.h> #include <comus/asm.h> #include <comus/memory.h> -#include <stdint.h> -#include <stdio.h> #define VGA_ADDR 0xB8000 @@ -99,3 +97,9 @@ void tty_out(char c) outb(0x3D4, 0x0E); outb(0x3D5, (uint8_t)((pos >> 8) & 0xFF)); } + +void tty_out_str(const char *str) +{ + while (*str) + tty_out(*str++); +} diff --git a/kernel/include/comus/drivers/tty.h b/kernel/include/comus/drivers/tty.h index 4f8a5f1..55aec64 100644 --- a/kernel/include/comus/drivers/tty.h +++ b/kernel/include/comus/drivers/tty.h @@ -17,6 +17,6 @@ void tty_out(char c); /** * Output a string to the terminal */ -void tty_out_str(char *str); +void tty_out_str(const char *str); #endif /* tty.h */ diff --git a/kernel/include/comus/error.h b/kernel/include/comus/error.h new file mode 120000 index 0000000..9367cab --- /dev/null +++ b/kernel/include/comus/error.h @@ -0,0 +1 @@ +../../../user/include/error.h
\ No newline at end of file diff --git a/kernel/include/comus/fs.h b/kernel/include/comus/fs.h index 67c74e3..fe335ca 100644 --- a/kernel/include/comus/fs.h +++ b/kernel/include/comus/fs.h @@ -11,7 +11,10 @@ #include <stdint.h> #include <stddef.h> -#include <limits.h> + +// FIXME: aaaa +#define MAX_DISKS 8 +#define MAX_FILE_NAME_LEN 256 struct disk { /// set to 1 in array to state that fs is defined diff --git a/kernel/include/comus/memory.h b/kernel/include/comus/memory.h index 411c039..294c795 100644 --- a/kernel/include/comus/memory.h +++ b/kernel/include/comus/memory.h @@ -13,6 +13,7 @@ #include <stddef.h> #define MMAP_MAX_ENTRY 64 +#define PAGE_SIZE 4096 struct memory_segment { uint64_t addr; @@ -54,14 +55,39 @@ uint64_t memory_used(void); * @param writable - if this memory should be writable * @param user - if this memory should be user writable */ -void *mapaddr(void *addr, size_t len); +void *kmapaddr(void *addr, size_t len); /** * Unmaps mapped address from the mmap function * @param addr - the address returned from mmap * @param len - the length allocated */ -void unmapaddr(void *addr); +void kunmapaddr(void *addr); + +/** + * Allocates size_t bytes in memory + * + * @param size - the amount of bytes to allocate + * @returns the address allocated or NULL on failure + */ +void *kalloc(size_t size); + +/** + * Rellocates a given allocated ptr to a new size of bytes in memory. + * If ptr is NULL it will allocate new memory. + * + * @param ptr - the pointer to reallocate + * @param size - the amount of bytes to reallocate to + * @returns the address allocated or NULL on failure + */ +void *krealloc(void *ptr, size_t size); + +/** + * Frees an allocated pointer in memory + * + * @param ptr - the pointer to free + */ +void kfree(void *ptr); /** * Attemps to load a mapped but not yet allocated page. @@ -70,6 +96,28 @@ void unmapaddr(void *addr); * * @returns 0 on success and a negative error code on failure. */ -int load_page(void *virt_addr); +int kload_page(void *virt_addr); + +/** + * Allocate a single page of memory + * + * @returns the address allocated or NULL on failure + */ +void *kalloc_page(void); + +/** + * Allocate size_t amount of contiguous virtual pages + * + * @param count - the number of pages to allocate + * @returns the address allocated or NULL on failure + */ +void *kalloc_pages(size_t count); + +/** + * Free allocated pages. + * + * @param ptr - the pointer provided by alloc_page or alloc_pages + */ +void kfree_pages(void *ptr); #endif /* memory.h */ diff --git a/kernel/include/comus/time.h b/kernel/include/comus/time.h new file mode 100644 index 0000000..6ecb2b7 --- /dev/null +++ b/kernel/include/comus/time.h @@ -0,0 +1,39 @@ +/** + * @file time.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * System time structure + */ + +#ifndef _TIME_H +#define _TIME_H + +#include <stddef.h> +#include <stdint.h> + +struct time { + int sec; /// Seconds [0,59] + int min; /// Minutes [0,59] + int hour; /// Hour [0,23] + int mday; /// Day of month [1,31] + int mon; /// Month of year [0,11] + int year; /// Years since 1900 + int wday; /// Day of week [0,6] (Sunday = 0) + int yday; /// Day of year [0,365] + int yn; /// Year number [0,99] + int cen; /// Century [19,20] + int leap; /// If year is a leap year (True == 1) +}; + +/** + * Return the current time in the system + */ +void gettime(struct time *time); + +/** + * Return current UTC time + */ +uint64_t unixtime(void); + +#endif /* time.h */ diff --git a/kernel/include/lib.h b/kernel/include/lib.h new file mode 100644 index 0000000..be4e739 --- /dev/null +++ b/kernel/include/lib.h @@ -0,0 +1,20 @@ +/** + * @file lib.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * Kernel C Library + */ + +#ifndef _LIB_H +#define _LIB_H + +#include <stdint.h> +#include <stddef.h> +#include <stdbool.h> +#include <lib/kctype.h> +#include <lib/kio.h> +#include <lib/klib.h> +#include <lib/kstring.h> + +#endif /* lib.h */ diff --git a/kernel/include/lib/kctype.h b/kernel/include/lib/kctype.h new file mode 100644 index 0000000..6d090c6 --- /dev/null +++ b/kernel/include/lib/kctype.h @@ -0,0 +1,22 @@ +/** + * @file kctype.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * Kernel C type libaray functions + */ + +#ifndef _KCTYPE_H +#define _KCTYPE_H + +/** + * @returns 1 if c is a space + */ +int isspace(int c); + +/** + * @returns 1 if c is a digit (0 - 9) + */ +int isdigit(int c); + +#endif /* kctype.h */ diff --git a/kernel/include/lib/kio.h b/kernel/include/lib/kio.h new file mode 100644 index 0000000..652a85b --- /dev/null +++ b/kernel/include/lib/kio.h @@ -0,0 +1,91 @@ +/** + * @file kio.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * Kernel I/O definitions. + */ + +#ifndef _KIO_H +#define _KIO_H + +#include <stddef.h> +#include <stdarg.h> + +/** + * Prints out a char + * + * @param c - the char + */ +void kputc(char c); + +/** + * Prints out a null terminated string + * + * @param s - the string + */ +void kputs(const char *s); + +/** + * prints out a formatted string + * + * @param format - the format string + * @param ... - variable args for the format + */ +__attribute__((format(printf, 1, 2))) void kprintf(const char *format, ...); + +/** + * prints out a formatted string to a buffer + * + * @param s - the string to write to + * @param format - the format string + * @param ... - variable args for the format + * @returns number of bytes written + */ +__attribute__((format(printf, 2, 3))) size_t ksprintf(char *restrict s, + const char *format, ...); + +/** + * prints out a formatted string to a buffer with a given max length + * + * @param s - the string to write to + * @param maxlen - the max len of the buffer + * @param format - the format string + * @param ... - variable args for the format + * @returns number of bytes written + */ +__attribute__((format(printf, 3, 4))) size_t ksnprintf(char *restrict s, + size_t maxlen, + const char *format, ...); + +/** + * prints out a formatted string + * + * @param format - the format string + * @param args - variable arg list for the format + */ +void kvprintf(const char *format, va_list args); + +/** + * prints out a formatted string to a buffer + * + * @param s - the string to write to + * @param format - the format string + * @param args - variable arg list for the format + * @returns number of bytes written + */ +size_t kvsprintf(char *restrict s, const char *format, va_list args); + +/** + * prints out a formatted string to a buffer with a given max length + * + * @param s - the string to write to + * @param maxlen - the max len of the buffer + * @param format - the format string + * @param args - variable arg list for the format + * @returns number of bytes written + */ +size_t kvsnprintf(char *restrict s, size_t maxlen, const char *format, + va_list args); + +#endif /* kio.h */ diff --git a/kernel/include/lib/klib.h b/kernel/include/lib/klib.h new file mode 100644 index 0000000..c67e57d --- /dev/null +++ b/kernel/include/lib/klib.h @@ -0,0 +1,196 @@ +/** + * @file klib.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * Kernel libaray functions + */ + +#ifndef _KLIB_H +#define _KLIB_H + +#include <stddef.h> + +/** + * converts single digit int to base 36 + * @param i - int + * @returns c - base 36 char + */ +char itoc(int i); + +/** + * converts single base 36 chat into int + * @param c - base 36 char + * @returns i - int, or -1 if the char was invalid + */ +int ctoi(char c); + +/** + * Converts the initial portiion of the string pointed to by s to int. + * @param s - the string to convert + * @returns the number inside s or 0 on error + */ +int atoi(const char *s); + +/** + * Converts the initial portiion of the string pointed to by s to long. + * @param s - the string to convert + * @returns the number inside s or 0 on error + */ +long int atol(const char *s); + +/** + * Converts the initial portiion of the string pointed to by s to long long. + * @param s - the string to convert + * @returns the number inside s or 0 on error + */ +long long int atoll(const char *s); + +/** + * Converts a integer to asci inside a string with a given radix (base). + * @param n - the number to convert + * @param buffer - the string buffer + * @param radix - the base to convert + */ +char *itoa(int n, char *buffer, int radix); + +/** + * Converts a long to asci inside a string with a given radix (base). + * @param n - the number to convert + * @param buffer - the string buffer + * @param radix - the base to convert + */ +char *ltoa(long int n, char *buffer, int radix); + +/** + * Converts a long long to asci inside a string with a given radix (base). + * @param n - the number to conver + * @param buffer - the string buffer + * @param radix - the base to convert + */ +char *lltoa(long long int n, char *buffer, int radix); + +/** + * Converts a unsigned integer to asci inside a string with a given radix (base). + * @param n - the number to convert + * @param buffer - the string buffer + * @param radix - the base to convert + */ +char *utoa(unsigned int n, char *buffer, int radix); + +/** + * Converts a unsigned long to asci inside a string with a given radix (base). + * @param n - the number to convert + * @param buffer - the string buffer + * @param radix - the base to convert + */ +char *ultoa(unsigned long int n, char *buffer, int radix); + +/** + * Converts a unsigned long long to asci inside a string with a given radix (base). + * @param n - the number to conver + * @param buffer - the string buffer + * @param radix - the base to convert + */ +char *ulltoa(unsigned long long int n, char *buffer, int radix); + +/** + * Converts the string in str to an int value based on the given base. + * The endptr is updated to where the string was no longer valid. + * @param str - the string buffer + * @param endptr - the endptr + * @param base - the base to convert to + * @returns 0 on error or success, error if endptr is still equal to str + */ +int strtoi(const char *str, char **endptr, int base); + +/** + * Converts the string in str to a long value based on the given base. + * The endptr is updated to where the string was no longer valid. + * @param str - the string buffer + * @param endptr - the endptr + * @param base - the base to convert to + * @returns 0 on error or success, error if endptr is still equal to str + */ +long int strtol(const char *str, char **endptr, int base); + +/** + * Converts the string in str to a long long value based on the given base. + * The endptr is updated to where the string was no longer valid. + * @param str - the string buffer + * @param endptr - the endptr + * @param base - the base to convert to + * @returns 0 on error or success, error if endptr is still equal to str + */ +long long int strtoll(const char *str, char **endptr, int base); + +/** + * Converts the string in str to an unsigned int value based on the given base. + * The endptr is updated to where the string was no longer valid. + * @param str - the string buffer + * @param endptr - the endptr + * @param base - the base to convert to + * @returns 0 on error or success, error if endptr is still equal to str + */ +unsigned int strtoui(const char *str, char **endptr, int base); + +/** + * Converts the string in str to an unsigned long value based on the given base. + * The endptr is updated to where the string was no longer valid. + * @param str - the string buffer + * @param endptr - the endptr + * @param base - the base to convert to + * @returns 0 on error or success, error if endptr is still equal to str + */ +unsigned long int strtoul(const char *str, char **endptr, int base); + +/** + * Converts the string in str to an unsigned long long value based on the given base. + * The endptr is updated to where the string was no longer valid. + * @param str - the string buffer + * @param endptr - the endptr + * @param base - the base to convert to + * @returns 0 on error or success, error if endptr is still equal to str + */ +unsigned long long int strtoull(const char *str, char **endptr, int base); + +/** + * Converts a byte count to a human readable file size of at most four characters + * using binary suffixes. + * + * The following rules are applied: + * - If the byte count is less than 1024, the count is written in decimal + * and no suffix is applied + * - Otherwise, repeatedly divide by 1024 until the value is under 1000. + * - If the value has two or three decimal digits, print it followed by the + * approprate suffix. + * - If the value has one decimal digit, print it along with a single fractional + * digit. This also applies if the value is zero. + * + * @param bytes - the bytes to convert + * @param buf - a pointer to the buffer to store it in (which must be at least five + * bytes long) + * @returns - buf + */ +char *btoa(size_t bytes, char *buf); + +/** + * This function confines an argument within specified bounds. + * + * @param min - lower bound + * @param value - value to be constrained + * @param max - upper bound + * + * @returns the constrained value + */ +unsigned int bound(unsigned int min, unsigned int value, unsigned int max); + +/** + * Abort the kernel with a given message. + * + * @param format - the format string + * @param ... - variable args for the format + */ +__attribute__((noreturn)) void panic(const char *format, ...); + +#endif /* klib.h */ diff --git a/kernel/include/lib/kstring.h b/kernel/include/lib/kstring.h new file mode 100644 index 0000000..50334b4 --- /dev/null +++ b/kernel/include/lib/kstring.h @@ -0,0 +1,154 @@ +/** + * @file kstring.h + * + * @author Freya Murphy <freya@freyacat.org> + * + * Kernel String libaray functions + */ + +#ifndef _KSTRING_H +#define _KSTRING_H + +#include <stddef.h> + +/** + * Compare the first n bytes (interpreted as unsigned char) of the memory areas s1 and s2 + * @param s1 - the first memory area + * @param s2 - the second memory area + * @param n - the byte count + * @returns an interger less than, equal to, or greater than 0 if the first n bytes + * of s1 are less than, equal to, or greater than s2. + */ +int memcmp(const void *restrict s1, const void *restrict s2, size_t n); + +/** + * Copy the first n bytes from memory area src to memory area dest. The memory + * areas must not overlap. + * @param dest - the destination + * @param src - the source + * @param n - the byte count + * @returns a pointer to dest + */ +void *memcpy(void *restrict dest, const void *restrict src, size_t n); + +/** + * Copy the first n bytes from memory area src to memory area dest. The memory + * areas may overlap; memmove behaves as though the bytes are first copied to a + * temporary array. + * @param dest - the destination + * @param src - the source + * @param n - the byte count + * @returns a pointer to dest + */ +void *memmove(void *restrict dest, const void *restrict src, size_t n); + +/** + * Fill the first n bytes of the memory region dest with the constant byte c. + * @param dest - the destination + * @param c - the byte to write + * @param n - the byte count + * @returns a pointer to dest + */ +void *memset(void *restrict dest, int c, size_t n); + +/** + * Copy the first n bytes from memory area src to memory area dest. The memory + * areas must not overlap. + * @param dest - the destination + * @param src - the source + * @param n - the byte count + * @returns a pointer to dest + */ +volatile void *memcpyv(volatile void *restrict dest, + const volatile void *restrict src, size_t n); + +/** + * Copy the first n bytes from memory area src to memory area dest. The memory + * areas may overlap; memmove behaves as though the bytes are first copied to a + * temporary array. + * @param dest - the destination + * @param src - the source + * @param n - the byte count + * @returns a pointer to dest + */ +volatile void *memmovev(volatile void *restrict dest, + const volatile void *restrict src, size_t n); + +/** + * Fill the first n bytes of the memory region dest with the constant byte c. + * @param dest - the destination + * @param c - the byte to write + * @param n - the byte count + * @returns a pointer to dest + */ +volatile void *memsetv(volatile void *restrict dest, int c, size_t n); + +/** + * Calculates the length of the string pointed to by str, excluding + * the terminating null byte + * @param str - the string pointer + * @returns the length of the string in bytes + */ +size_t strlen(const char *str); + +/** + * Compare null terminated string s1 and s2. The comparison is done using + * unsigned characters. + * @param s1 - a pointer to the first string + * @param s2 - a pointer to the second string + * @returns an interger less than, equal to, or greater than 0 if s1 compares less + * than, equal to, or greater than s2 + */ +int strcmp(const char *restrict s1, const char *restrict s2, size_t n); + +/** + * Compare at most the first n bytes of the strings s1 and s2. The comparison is + * done using unsigned characters. + * @param s1 - a pointer to the first string + * @param s2 - a pointer to the second string + * @param n - the maximum number of bytes + * @returns an interger less than, equal to, or greater than 0 if s1 compares less + * than, equal to, or greater than s2 + */ +int strncmp(const char *restrict s1, const char *restrict s2, size_t n); + +/** + * Copies the string pointed to by src into the buffer pointer to by dest. + * The dest buffer must be long enough to hold src. + * @param dest - the destination + * @param src - the source + * @returns a pointer to dest + */ +char *strcpy(char *restrict dest, const char *restrict src); + +/** + * Copies the string pointed to by src into the buffer pointer to by dest. + * The dest buffer must be long enough to hold src or size n. + * @param dest - the destination + * @param src - the source + * @param n - the maximum number of bytes + * @returns a pointer to dest + */ +char *strncpy(char *restrict dest, const char *restrict src, size_t n); + +/** + * Copies the string pointed to by src into the buffer pointed to by dest. + * The dest buffer must be long enough to hold src. + * @param dest - the destination + * @param src - the source + * @param n - the maximum number of bytes + * @returns a pointer to the terminating null byte + */ +char *stpcpy(char *restrict dest, const char *restrict src); + +/** + * Copies the string pointed to by src into the buffer pointed to by dest. + * The dest buffer must be long enough to hold src or size n. + * @param dest - the destination + * @param src - the source + * @param n - the maximum number of bytes + * @returns a pointer to the byte after the last character copied + */ +char *stpncpy(char *restrict dest, const char *restrict src, size_t n); + +#endif /* kstring.h */ diff --git a/kernel/lib/atox.c b/kernel/lib/atox.c new file mode 100644 index 0000000..6d3d4cc --- /dev/null +++ b/kernel/lib/atox.c @@ -0,0 +1,29 @@ +#include <lib.h> + +#define ATOX(name, type) \ + type name(const char *s) \ + { \ + for (; isspace(*s); s++) \ + ; \ + int neg = 0; \ + switch (*s) { \ + case '-': \ + neg = 1; \ + /* fallthrough */ \ + case '+': \ + s++; \ + break; \ + } \ + type num = 0; \ + for (; *s == '0'; s++) \ + ; \ + for (; isdigit(*s); s++) { \ + num *= 10; \ + num += *s - '0'; \ + } \ + return num * (neg ? -1 : 1); \ + } + +ATOX(atoi, int) +ATOX(atol, long int) +ATOX(atoll, long long int) diff --git a/kernel/lib/bound.c b/kernel/lib/bound.c new file mode 100644 index 0000000..5a3c9fa --- /dev/null +++ b/kernel/lib/bound.c @@ -0,0 +1,12 @@ +#include <lib.h> + +unsigned int bound(unsigned int min, unsigned int value, unsigned int max) +{ + if (value < min) { + value = min; + } + if (value > max) { + value = max; + } + return value; +} diff --git a/kernel/lib/btoa.c b/kernel/lib/btoa.c new file mode 100644 index 0000000..96a60ef --- /dev/null +++ b/kernel/lib/btoa.c @@ -0,0 +1,43 @@ +#include <lib.h> + +static char suffixes[] = { 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q' }; + +char *btoa(size_t bytes, char *buf) +{ + // no suffix if under 1K, print up to four digits + if (bytes < 1024) { + ultoa(bytes, buf, 10); + return buf; + } + + // store one digit of remainder for decimal + unsigned int remainder; + // power of 1024 + int power = 0; + + // iterate until remaining bytes fits in three digits + while (bytes >= 1000) { + remainder = (bytes % 1024) * 10 / 1024; + bytes /= 1024; + power += 1; + } + + // end of number + char *end; + + if (bytes >= 10) { + // no decimal + end = ultoa(bytes, buf, 10); + } else { + // decimal + end = ultoa(bytes, buf, 10); + end[0] = '.'; + end = ultoa(remainder, end + 1, 10); + } + + // add suffix + end[0] = suffixes[power - 1]; + end[1] = '\0'; + + return buf; +} diff --git a/kernel/lib/ctoi.c b/kernel/lib/ctoi.c new file mode 100644 index 0000000..09a9f10 --- /dev/null +++ b/kernel/lib/ctoi.c @@ -0,0 +1,14 @@ +#include <lib.h> + +int ctoi(char c) +{ + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'A' && c <= 'Z') { + return c - 'A' + 10; + } else if (c >= 'a' && c <= 'z') { + return c - 'a' + 10; + } else { + return -1; + } +} diff --git a/kernel/lib/fputc.c b/kernel/lib/fputc.c deleted file mode 100644 index 0d47cb5..0000000 --- a/kernel/lib/fputc.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <lib.h> -#include <comus/drivers/tty.h> -#include <comus/drivers/uart.h> - -void fputc(FILE *stream, char c) -{ - (void)stream; // TODO: manage stream - uart_out(c); - tty_out(c); -} diff --git a/kernel/lib/isdigit.c b/kernel/lib/isdigit.c new file mode 100644 index 0000000..f645093 --- /dev/null +++ b/kernel/lib/isdigit.c @@ -0,0 +1,6 @@ +#include <lib.h> + +int isdigit(int c) +{ + return c >= '0' && c <= '9'; +} diff --git a/kernel/lib/isspace.c b/kernel/lib/isspace.c new file mode 100644 index 0000000..5196d0c --- /dev/null +++ b/kernel/lib/isspace.c @@ -0,0 +1,16 @@ +#include <lib.h> + +int isspace(int c) +{ + switch (c) { + case ' ': + case '\t': + case '\v': + case '\f': + case '\r': + case '\n': + return 1; + default: + return 0; + } +} diff --git a/kernel/lib/itoc.c b/kernel/lib/itoc.c new file mode 100644 index 0000000..493b66e --- /dev/null +++ b/kernel/lib/itoc.c @@ -0,0 +1,10 @@ +#include <lib.h> + +char itoc(int i) +{ + if (i < 10) { + return '0' + i; + } else { + return 'a' + (i - 10); + } +} diff --git a/kernel/lib/kalloc.c b/kernel/lib/kalloc.c new file mode 100644 index 0000000..9845a62 --- /dev/null +++ b/kernel/lib/kalloc.c @@ -0,0 +1,210 @@ +#include <lib.h> +#include <comus/memory.h> + +#define MAGIC 0xBEEFCAFE + +struct page_header { + struct page_header *next; + struct page_header *prev; + size_t + node_number; // all headers on the same page alloc have the same node number (so they can be merged) + size_t + free; // free space after the node (if its the last node in the alloc block) + size_t used; // how much space this allocation is using + uint64_t magic; +}; + +static const size_t header_len = sizeof(struct page_header); +static struct page_header *start_header = NULL; +static struct page_header *end_header = NULL; + +static struct page_header *get_header(void *ptr) +{ + struct page_header *header = + (struct page_header *)((uintptr_t)ptr - header_len); + + // PERF: do we want to make sure this pointer is paged + // before reading it??? + if (header->magic != MAGIC) { + return NULL; // invalid pointer + } + + return header; +} + +static void *alloc_new(size_t size) +{ + size_t pages = ((size + header_len) / PAGE_SIZE) + 1; + + void *addr = kalloc_pages(pages); + void *mem = (char *)addr + header_len; + + size_t total = pages * PAGE_SIZE; + size_t free = total - (size + header_len); + + if (addr == NULL) { + return NULL; + } + + size_t node; + if (end_header != NULL) { + node = end_header->node_number + 1; + } else { + node = 0; + } + + struct page_header *header = addr; + header->magic = 0xBEEFCAFE; + header->used = size; + header->free = free; + header->prev = end_header; + header->next = NULL; + header->node_number = node; + + if (start_header == NULL) { + start_header = header; + } + + if (end_header != NULL) { + end_header->next = header; + } else { + end_header = header; + } + + return mem; +} + +static void *alloc_block(size_t size, struct page_header *block) +{ + struct page_header *header = + (struct page_header *)((char *)block + block->used + header_len); + + size_t free = block->free - (size + header_len); + block->free = 0; + + header->magic = MAGIC; + header->used = size; + header->free = free; + header->prev = block; + header->next = block->next; + block->next = header; + header->node_number = block->node_number; + + void *mem = (char *)header + header_len; + + return mem; +} + +void *kalloc(size_t size) +{ + struct page_header *header = start_header; + + for (; header != NULL; header = header->next) { + size_t free = header->free; + if (free < header_len) + continue; + if (size <= + (free - header_len)) { // we must be able to fit data + header + break; + } + } + + if (header != NULL) { + return alloc_block(size, header); + } else { + return alloc_new(size); + } +} + +void *krealloc(void *src, size_t dst_len) +{ + struct page_header *header; + size_t src_len; + void *dst; + + // realloc of 0 means free pointer + if (dst_len == 0) { + kfree(src); + return NULL; + } + + // NULL src means allocate ptr + if (src == NULL) { + dst = kalloc(dst_len); + return dst; + } + + header = get_header(src); + + if (header == NULL) + return NULL; + + src_len = header->used; + + if (src_len == 0) + return NULL; + + dst = kalloc(dst_len); + + if (dst == NULL) + return NULL; // allocation failed + + if (dst_len < src_len) + src_len = dst_len; + + memcpy(dst, src, src_len); + kfree(src); + + return dst; +} + +void kfree(void *ptr) +{ + struct page_header *header; + + if (ptr == NULL) + return; + + header = get_header(ptr); + + if (header == NULL) + return; + + header->free += header->used; + header->used = 0; + + struct page_header *neighbor; + + // merge left + for (neighbor = header->prev; neighbor != NULL; neighbor = neighbor->prev) { + if (neighbor->node_number != header->node_number) + break; + if (neighbor->used && header->used) + break; + neighbor->free += header->free + header_len; + neighbor->next = header->next; + header = neighbor; + } + + // merge right + for (neighbor = header->next; neighbor != NULL; neighbor = neighbor->next) { + if (neighbor->node_number != header->node_number) + break; + if (neighbor->used) + break; + header->free += neighbor->free + header_len; + header->next = neighbor->next; + } + + if ((header->next == NULL || + header->next->node_number != header->node_number) && + (header->prev == NULL || + header->prev->node_number != header->node_number) && + header->used == 0) { + if (header->next) + header->next->prev = header->prev; + if (header->prev) + header->prev->next = header->next; + kfree_pages(header); + } +} diff --git a/kernel/lib/kprintf.c b/kernel/lib/kprintf.c new file mode 100644 index 0000000..a76036f --- /dev/null +++ b/kernel/lib/kprintf.c @@ -0,0 +1,576 @@ +#include <lib.h> +#include <comus/drivers/uart.h> +#include <comus/drivers/tty.h> + +#define PRINTF_NUMERIC_BUF_LEN 50 + +typedef union { + unsigned long long int u; + signed long long int i; + char *str; + char c; +} data_t; + +/// options that can be set inside a specifier +/// flags, width, precision, length, and data type +typedef struct { + /* flags */ + /// left justify content + uint8_t left : 1; + /// force sign (+/-) on numeric output + uint8_t sign : 1; + /// leave space if no printed sign on numeric output + uint8_t space : 1; + /// preceed hex/octal output with '0x' + uint8_t hash : 1; + /// left pads numeric output with zeros + uint8_t zero : 1; + uint8_t : 3; + + /* width & precision */ + /// minimum number of characters to be printed (padding if origonal is less) + int width; + /// digit precision used when printing numerical answers + int precision; + /// if a fixed minimum width has been provided + uint8_t width_set : 1; + /// if the provided minimum width is in the next variable argument + uint8_t width_varies : 1; + /// if a fixed digit precision has been provided + uint8_t precision_set : 1; + /// if the provided digit precision is in the next variable argument + uint8_t precision_varies : 1; + uint8_t : 4; + + /* length */ + /// what size to read argument as + enum printf_len { + PRINTF_LEN_CHAR, + PRINTF_LEN_SHORT_INT, + PRINTF_LEN_INT, + PRINTF_LEN_LONG_INT, + PRINTF_LEN_LONG_LONG_INT, + PRINTF_LEN_SIZE_T, + } len; + + /* other */ + /// radix to print the numerical answers as + uint8_t radix; + /// case to print hexadecimal values as + bool is_uppercase; +} options_t; + +typedef struct { + /* input */ + /// the origonal format string + const char *format; + /// maximum allowed output length + size_t max_len; + /// if a maximum output length is set + bool has_max_len; + + /* output */ + size_t written_len; + bool sprintf; + char *sprintf_buf; + + /* pass 2 */ + char *output; +} context_t; + +static void printf_putc(context_t *ctx, char c) +{ + // bounds check + if (ctx->has_max_len) + if (ctx->written_len >= ctx->max_len) + return; + + // write to correct + if (ctx->sprintf) + *(ctx->sprintf_buf++) = c; + else + kputc(c); + + ctx->written_len++; +} + +static int parse_flag(const char **res, options_t *opts) +{ + const char *fmt = *res; + switch (*(fmt++)) { + case '-': + opts->left = 1; + break; + case '+': + opts->sign = 1; + break; + case ' ': + opts->space = 1; + break; + case '#': + opts->hash = 1; + break; + case '0': + opts->zero = 1; + break; + default: + return 0; + } + + *res = fmt; + return 1; +} + +static void parse_width(const char **res, options_t *opts) +{ + const char *fmt = *res; + char *end = NULL; + + // check varies + if (*fmt == '*') { + opts->width_varies = true; + *res = fmt++; + return; + } + + // parse num + long width = strtol(fmt, &end, 10); + if (end != NULL) { + opts->width_set = 1; + opts->width = width; + *res = end; + return; + } +} + +static void parse_precision(const char **res, options_t *opts) +{ + const char *fmt = *res; + char *end = NULL; + + // check for dot + if (*(fmt++) != '.') + return; + + // check varies + if (*fmt == '*') { + opts->precision_varies = true; + *res = fmt++; + return; + } + + // parse num + long precision = strtol(fmt, &end, 10); + if (end != NULL) { + opts->precision_set = 1; + opts->precision = precision; + *res = end; + return; + } +} + +static void parse_length(const char **res, options_t *opts) +{ + const char *fmt = *res; + + switch (*(fmt++)) { + // half + case 'h': + if (*fmt == 'h') { + opts->len = PRINTF_LEN_CHAR; + fmt++; + } else { + opts->len = PRINTF_LEN_SHORT_INT; + } + break; + // long + case 'l': + if (*fmt == 'l') { + opts->len = PRINTF_LEN_LONG_LONG_INT; + fmt++; + } else { + opts->len = PRINTF_LEN_LONG_INT; + } + break; + // size_t + case 'z': + opts->len = PRINTF_LEN_SIZE_T; + break; + default: + opts->len = PRINTF_LEN_INT; + return; + } + + *res = fmt; +} + +static void get_radix(char spec, options_t *opts) +{ + switch (spec) { + case 'x': + case 'X': + opts->radix = 16; + break; + case 'o': + opts->radix = 8; + break; + default: + opts->radix = 10; + break; + } +} + +static void get_case(char spec, options_t *opts) +{ + if (spec == 'X') + opts->is_uppercase = 1; +} + +static char printf_itoc(int uppercase, int i) +{ + // decimal + if (i < 10) { + return i + '0'; + } + // hex + if (uppercase) { + return (i - 10) + 'A'; + } else { + return (i - 10) + 'a'; + } +} + +static int printf_lltoa(char *buf, options_t *opts, bool is_neg, + unsigned long long int num) +{ + int precision = 0; + char *start = buf; + + // get width of number + int len = 0; + unsigned long long int temp = num; + if (temp == 0) + len = 1; + while (temp) { + if (opts->precision_set && precision++ >= opts->precision) + break; + temp /= opts->radix; + len++; + } + precision = 0; + + // sign + if (is_neg) { + *(buf++) = '-'; + } else if (opts->sign) { + *(buf++) = '+'; + } else if (opts->space) { + *(buf++) = ' '; + } + + // radix specifier + if (opts->hash) { + if (opts->radix == 8) { + *(buf++) = '0'; + *(buf++) = 'o'; + } + if (opts->radix == 16) { + *(buf++) = '0'; + *(buf++) = 'x'; + } + } + + // print zeros if needed + if (opts->width_set && len < opts->width && opts->zero) { + while (len++ < opts->width) + *(buf++) = '0'; + } + + // write number + if (num == 0) { + *(buf++) = '0'; + } + while (num) { + if (opts->precision_set && precision++ >= opts->precision) + break; + *(buf++) = printf_itoc(opts->is_uppercase, num % opts->radix); + num /= opts->radix; + } + *(buf++) = '\0'; + + return buf - start; +} + +static void handle_int_specifier(context_t *ctx, options_t *const opts, + bool has_sign_bit, data_t num) +{ + bool is_neg = false; + + // get sign if possible neg + if (has_sign_bit) { + if (num.i < 0) { + num.i = -num.i; + is_neg = true; + } + } + + // get length of number and number + char buf[PRINTF_NUMERIC_BUF_LEN]; + int buf_len = printf_lltoa(buf, opts, is_neg, num.u); + + // get needed padding + int padding = 0; + if (opts->width_set && (buf_len < opts->width)) + padding = opts->width - buf_len; + + /* print */ + // left padding + if (opts->left == 0) { + for (int i = 0; i < padding; i++) + printf_putc(ctx, opts->zero ? '0' : ' '); + } + // number + for (int i = 0; i < buf_len; i++) + printf_putc(ctx, buf[i]); + // right padding + if (opts->left == 1) { + for (int i = 0; i < padding; i++) + printf_putc(ctx, opts->zero ? '0' : ' '); + } +} + +static void handle_char_specifier(context_t *ctx, data_t c) +{ + printf_putc(ctx, c.c); +} + +static void handle_string_specifier(context_t *ctx, options_t *opts, + data_t data) +{ + char *str = data.str; + int str_len = 0; + + // get length of string + if (opts->precision_set) + str_len = opts->precision; + else + str_len = strlen(str); + + // get needed padding + int padding = 0; + if (opts->width_set && (str_len < opts->width)) + padding = opts->width - str_len; + + /* print */ + // left padding + if (opts->left == 0) { + for (int i = 0; i < padding; i++) + printf_putc(ctx, ' '); + } + // string + for (int i = 0; i < str_len; i++) + printf_putc(ctx, str[i]); + // right padding + if (opts->left == 1) { + for (int i = 0; i < padding; i++) + printf_putc(ctx, ' '); + } +} + +static void do_printf(context_t *ctx, va_list args) +{ + const char *fmt = ctx->format; + + char c; + while (c = *fmt++, c != '\0') { + // save start of fmt for current iteration + const char *start = fmt - 1; + + // ignore if not % + if (c != '%') { + printf_putc(ctx, c); + continue; + } + + // read opts + options_t opts = { 0 }; + while (parse_flag(&fmt, &opts)) + ; + parse_width(&fmt, &opts); + parse_precision(&fmt, &opts); + parse_length(&fmt, &opts); + + // read specifier + char spec = *fmt++; + get_radix(spec, &opts); + get_case(spec, &opts); + + // read varied width / precision + if (opts.width_varies) { + opts.width_set = 1; + opts.width = va_arg(args, int); + } + if (opts.precision_varies) { + opts.precision_set = 1; + opts.precision = va_arg(args, int); + } + // read data from args + data_t data; + switch (spec) { + case 'p': + opts.len = PRINTF_LEN_SIZE_T; + opts.width_set = true; + opts.radix = 16; + opts.hash = true; + opts.zero = true; + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + // read number from arg + switch (opts.len) { + case PRINTF_LEN_CHAR: + data.u = va_arg(args, unsigned int); // char + break; + case PRINTF_LEN_SHORT_INT: + data.u = va_arg(args, unsigned int); // short int + break; + case PRINTF_LEN_INT: + data.u = va_arg(args, unsigned int); + break; + case PRINTF_LEN_LONG_INT: + data.u = va_arg(args, unsigned long int); + break; + case PRINTF_LEN_LONG_LONG_INT: + data.u = va_arg(args, unsigned long long int); + break; + case PRINTF_LEN_SIZE_T: + data.u = va_arg(args, size_t); + break; + } + break; + // end int + case 's': + // read string + data.str = va_arg(args, void *); + break; + // end string + case 'c': + // read char + data.c = va_arg(args, int); + break; + // end char + } + + switch (spec) { + // signed int + case 'd': + case 'i': + handle_int_specifier(ctx, &opts, true, data); + break; + // unsigned int + case 'p': + case 'u': + case 'o': + case 'x': + case 'X': + handle_int_specifier(ctx, &opts, false, data); + break; + // character + case 'c': + handle_char_specifier(ctx, data); + break; + // string + case 's': + handle_string_specifier(ctx, &opts, data); + break; + // unknown + default: + // print from % to current + for (; start < fmt; start++) + printf_putc(ctx, *start); + break; + } + } +} + +void kprintf(const char *format, ...) +{ + va_list args; + va_start(args, format); + kvprintf(format, args); + va_end(args); +} + +size_t ksprintf(char *restrict s, const char *format, ...) +{ + va_list args; + size_t amt; + va_start(args, format); + amt = kvsprintf(s, format, args); + va_end(args); + return amt; +} + +size_t snprintf(char *restrict s, size_t maxlen, const char *format, ...) +{ + va_list args; + size_t amt; + va_start(args, format); + amt = kvsnprintf(s, maxlen, format, args); + va_end(args); + return amt; +} + +void kvprintf(const char *format, va_list args) +{ + // create context + context_t ctx = { 0 }; + ctx.format = format; + // print + do_printf(&ctx, args); +} + +size_t kvsprintf(char *restrict s, const char *format, va_list args) +{ + // create context + context_t ctx = { 0 }; + ctx.format = format; + // sprintf buffer + ctx.sprintf_buf = s; + ctx.sprintf = 1; + // print + do_printf(&ctx, args); + return ctx.written_len; +} + +size_t kvsnprintf(char *restrict s, size_t maxlen, const char *format, + va_list args) +{ + // create context + context_t ctx = { 0 }; + ctx.format = format; + // sprintf buffer + ctx.sprintf_buf = s; + ctx.sprintf = 1; + // sprintf max_len + ctx.has_max_len = 1; + ctx.max_len = maxlen; + // print + do_printf(&ctx, args); + return ctx.written_len; +} + +void kputc(char c) +{ + tty_out(c); + uart_out(c); +} + +void kputs(const char *str) +{ + tty_out_str(str); + uart_out_str(str); +} diff --git a/kernel/lib/memcmp.c b/kernel/lib/memcmp.c new file mode 100644 index 0000000..f938d0a --- /dev/null +++ b/kernel/lib/memcmp.c @@ -0,0 +1,9 @@ +#include <lib.h> + +int memcmp(const void *restrict vl, const void *restrict vr, size_t n) +{ + const unsigned char *l = vl, *r = vr; + for (; n && *l == *r; n--, l++, r++) + ; + return n ? *l - *r : 0; +} diff --git a/kernel/lib/memcpy.c b/kernel/lib/memcpy.c new file mode 100644 index 0000000..e848cef --- /dev/null +++ b/kernel/lib/memcpy.c @@ -0,0 +1,10 @@ +#include <lib.h> + +void *memcpy(void *restrict dest, const void *restrict src, size_t n) +{ + char *d = dest; + const char *s = src; + for (; n; n--) + *d++ = *s++; + return dest; +} diff --git a/lib/memcpyv.c b/kernel/lib/memcpyv.c index 610daf2..bc95807 100644 --- a/lib/memcpyv.c +++ b/kernel/lib/memcpyv.c @@ -1,4 +1,4 @@ -#include <string.h> +#include <lib.h> volatile void *memcpyv(volatile void *restrict dest, const volatile void *restrict src, size_t n) diff --git a/kernel/lib/memmove.c b/kernel/lib/memmove.c new file mode 100644 index 0000000..55be66d --- /dev/null +++ b/kernel/lib/memmove.c @@ -0,0 +1,20 @@ +#include <lib.h> + +void *memmove(void *dest, const void *src, size_t n) +{ + char *d = dest; + const char *s = src; + + if (d == s) + return d; + + if (d < s) { + for (; n; n--) + *d++ = *s++; + } else { + while (n) + n--, d[n] = s[n]; + } + + return dest; +} diff --git a/lib/memmovev.c b/kernel/lib/memmovev.c index 0b21d25..56684a5 100644 --- a/lib/memmovev.c +++ b/kernel/lib/memmovev.c @@ -1,4 +1,4 @@ -#include <string.h> +#include <lib.h> volatile void *memmovev(volatile void *dest, const volatile void *src, size_t n) { diff --git a/kernel/lib/memset.c b/kernel/lib/memset.c new file mode 100644 index 0000000..d1c2a5e --- /dev/null +++ b/kernel/lib/memset.c @@ -0,0 +1,10 @@ +#include <lib.h> + +void *memset(void *dest, int c, size_t n) +{ + unsigned char *d = dest; + for (; n; n--) { + *d++ = c; + }; + return dest; +} diff --git a/lib/memsetv.c b/kernel/lib/memsetv.c index 91fe6a1..647847f 100644 --- a/lib/memsetv.c +++ b/kernel/lib/memsetv.c @@ -1,4 +1,4 @@ -#include <string.h> +#include <lib.h> volatile void *memsetv(volatile void *dest, int c, size_t n) { diff --git a/kernel/lib/panic.c b/kernel/lib/panic.c index 403418f..5381041 100644 --- a/kernel/lib/panic.c +++ b/kernel/lib/panic.c @@ -7,9 +7,9 @@ __attribute__((noreturn)) void panic(const char *format, ...) cli(); va_list list; va_start(list, format); - printf("\n\n!!! PANIC !!!\n"); - vprintf(format, list); - printf("\n\n"); + kprintf("\n\n!!! PANIC !!!\n"); + kvprintf(format, list); + kprintf("\n\n"); while (1) halt(); diff --git a/kernel/lib/stpcpy.c b/kernel/lib/stpcpy.c new file mode 100644 index 0000000..1a7c5bf --- /dev/null +++ b/kernel/lib/stpcpy.c @@ -0,0 +1,9 @@ +#include <lib.h> + +char *stpcpy(char *restrict dest, const char *restrict src) +{ + char *d = dest; + for (; (*d = *src); d++, src++) + ; + return d; +} diff --git a/kernel/lib/stpncpy.c b/kernel/lib/stpncpy.c new file mode 100644 index 0000000..87f9838 --- /dev/null +++ b/kernel/lib/stpncpy.c @@ -0,0 +1,10 @@ +#include <lib.h> + +char *stpncpy(char *restrict dest, const char *restrict src, size_t n) +{ + char *d = dest; + for (; (*d = *src) && n; d++, src++, n--) + ; + memset(d, 0, n); + return d; +} diff --git a/kernel/lib/strcat.c b/kernel/lib/strcat.c new file mode 100644 index 0000000..fcfa463 --- /dev/null +++ b/kernel/lib/strcat.c @@ -0,0 +1,7 @@ +#include <lib.h> + +char *strcat(char *restrict dest, const char *restrict src) +{ + strcpy(dest + strlen(dest), src); + return dest; +} diff --git a/kernel/lib/strcpy.c b/kernel/lib/strcpy.c new file mode 100644 index 0000000..d74e68d --- /dev/null +++ b/kernel/lib/strcpy.c @@ -0,0 +1,9 @@ +#include <lib.h> + +char *strcpy(char *restrict dest, const char *restrict src) +{ + char *d = dest; + for (; (*d = *src); d++, src++) + ; + return dest; +} diff --git a/kernel/lib/strlen.c b/kernel/lib/strlen.c new file mode 100644 index 0000000..6d31f2f --- /dev/null +++ b/kernel/lib/strlen.c @@ -0,0 +1,9 @@ +#include <lib.h> + +size_t strlen(const char *str) +{ + const char *p; + for (p = str; *p != 0; p++) { + } + return p - str; +} diff --git a/kernel/lib/strncmp.c b/kernel/lib/strncmp.c new file mode 100644 index 0000000..0cf5837 --- /dev/null +++ b/kernel/lib/strncmp.c @@ -0,0 +1,11 @@ +#include <lib.h> + +int strncmp(const char *restrict lhs, const char *restrict rhs, size_t n) +{ + const unsigned char *l = (void *)lhs, *r = (void *)rhs; + if (!n--) + return 0; + for (; *l && *r && n && *l == *r; l++, r++, n--) + ; + return *l - *r; +} diff --git a/kernel/lib/strncpy.c b/kernel/lib/strncpy.c new file mode 100644 index 0000000..f691191 --- /dev/null +++ b/kernel/lib/strncpy.c @@ -0,0 +1,10 @@ +#include <lib.h> + +char *strncpy(char *restrict dest, const char *restrict src, size_t n) +{ + char *d = dest; + for (; (*d = *src) && n; d++, src++, n--) + ; + memset(d, 0, n); + return dest; +} diff --git a/kernel/lib/strtoux.c b/kernel/lib/strtoux.c new file mode 100644 index 0000000..e8f828b --- /dev/null +++ b/kernel/lib/strtoux.c @@ -0,0 +1,43 @@ +#include <lib.h> + +#define STRTOUX(name, type) \ + type name(const char *restrict s, char **restrict endptr, int radix) \ + { \ + const char *s_start = s; \ + for (; isspace(*s); s++) \ + ; \ + \ + if ((radix == 0 || radix == 16) && \ + (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))) { \ + radix = 16; \ + s += 2; \ + } else if (radix == 0) { \ + if (*s == '0') { \ + radix = 8; \ + s++; \ + } else { \ + radix = 10; \ + } \ + } \ + \ + type num = 0; \ + int has_digit = 0; \ + \ + while (1) { \ + int n = ctoi(*s++); \ + if (n < 0 || n >= radix) \ + break; \ + has_digit = 1; \ + num = num * radix + n; \ + } \ + \ + if (endptr != NULL) { \ + *endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \ + } \ + \ + return num; \ + } + +STRTOUX(strtoui, unsigned int) +STRTOUX(strtoul, unsigned long int) +STRTOUX(strtoull, unsigned long long int) diff --git a/kernel/lib/strtox.c b/kernel/lib/strtox.c new file mode 100644 index 0000000..620b8d3 --- /dev/null +++ b/kernel/lib/strtox.c @@ -0,0 +1,52 @@ +#include <lib.h> + +#define STRTOX(name, type) \ + type name(const char *restrict s, char **restrict endptr, int radix) \ + { \ + const char *s_start = s; \ + for (; isspace(*s); s++) \ + ; \ + \ + int sign = 0; \ + switch (*s) { \ + case '-': \ + sign = 1; /* fallthrough */ \ + case '+': \ + s++; \ + break; \ + } \ + \ + if ((radix == 0 || radix == 16) && \ + (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))) { \ + radix = 16; \ + s += 2; \ + } else if (radix == 0) { \ + if (*s == '0') { \ + radix = 8; \ + s++; \ + } else { \ + radix = 10; \ + } \ + } \ + \ + type num = 0; \ + int has_digit = 0; \ + \ + while (1) { \ + int n = ctoi(*s++); \ + if (n < 0 || n >= radix) \ + break; \ + has_digit = 1; \ + num = num * radix + n; \ + } \ + \ + if (endptr != NULL) { \ + *endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \ + } \ + \ + return sign ? -num : num; \ + } + +STRTOX(strtoi, int) +STRTOX(strtol, long int) +STRTOX(strtoll, long long int) diff --git a/kernel/lib/uxtoa.c b/kernel/lib/uxtoa.c new file mode 100644 index 0000000..9133d29 --- /dev/null +++ b/kernel/lib/uxtoa.c @@ -0,0 +1,27 @@ +#include <lib.h> + +#define UXTOA(type, name) \ + char *name(unsigned type n, char *buffer, int radix) \ + { \ + if (n == 0) { \ + buffer[0] = '0'; \ + buffer[1] = '\0'; \ + return buffer + 1; \ + } \ + char *start = buffer; \ + for (; n; n /= radix) { \ + *buffer++ = itoc(n % radix); \ + } \ + char *buf_end = buffer; \ + *buffer-- = '\0'; \ + while (buffer > start) { \ + char tmp = *start; \ + *start++ = *buffer; \ + *buffer-- = tmp; \ + } \ + return buf_end; \ + } + +UXTOA(int, utoa) +UXTOA(long int, ultoa) +UXTOA(long long int, ulltoa) diff --git a/kernel/lib/xtoa.c b/kernel/lib/xtoa.c new file mode 100644 index 0000000..bd3a367 --- /dev/null +++ b/kernel/lib/xtoa.c @@ -0,0 +1,31 @@ +#include <lib.h> + +#define XTOA(type, name) \ + char *name(type n, char *buffer, int radix) \ + { \ + if (n == 0) { \ + buffer[0] = '0'; \ + buffer[1] = '\0'; \ + return buffer + 1; \ + } \ + if (n < 0) { \ + *buffer++ = '-'; \ + n = -n; \ + } \ + char *start = buffer; \ + for (; n; n /= radix) { \ + *buffer++ = itoc(n % radix); \ + } \ + char *buf_end = buffer; \ + *buffer-- = '\0'; \ + while (buffer > start) { \ + char tmp = *start; \ + *start++ = *buffer; \ + *buffer-- = tmp; \ + } \ + return buf_end; \ + } + +XTOA(int, itoa) +XTOA(long int, ltoa) +XTOA(long long int, lltoa) diff --git a/kernel/kernel.c b/kernel/main.c index 7382a7d..5b06ae2 100644 --- a/kernel/kernel.c +++ b/kernel/main.c @@ -4,8 +4,6 @@ #include <comus/drivers.h> #include <comus/fs.h> #include <lib.h> -#include <stdio.h> -#include <time.h> struct memory_map mmap; @@ -29,13 +27,6 @@ void main(long magic, volatile void *mboot) // load file systems fs_init(); - // print current time - char date[40]; - set_timezone(TZ_EDT); - time_t time = get_localtime(); - timetostr(&time, "%a %b %d %Y %H:%M:%S", date, 40); - printf("The date is: %s\n\n", date); - // halt - printf("halting...\n"); + kprintf("halting...\n"); } diff --git a/kernel/mboot/mmap.c b/kernel/mboot/mmap.c index ff38771..8a5f549 100644 --- a/kernel/mboot/mmap.c +++ b/kernel/mboot/mmap.c @@ -2,8 +2,6 @@ #include <comus/mboot.h> #include "mboot.h" -#include <stdint.h> -#include <stdio.h> static const char *segment_type[] = { "Reserved", "Free", "Reserved", "ACPI Reserved", @@ -17,7 +15,7 @@ void mboot_load_mmap(volatile void *mboot, struct memory_map *res) int idx = 0; uintptr_t i = (uintptr_t)mmap->entries; - printf("MEMORY MAP\n"); + kprintf("MEMORY MAP\n"); char buf[20]; for (; i < (uintptr_t)mmap->entries + mmap->size; i += mmap->entry_size, idx++) { @@ -27,7 +25,7 @@ void mboot_load_mmap(volatile void *mboot, struct memory_map *res) type = segment_type[6]; else type = segment_type[seg->type]; - printf("ADDR: %16p LEN: %4s TYPE: %s (%d)\n", (void *)seg->addr, + kprintf("ADDR: %16p LEN: %4s TYPE: %s (%d)\n", (void *)seg->addr, btoa(seg->len, buf), type, seg->type); if (seg->type != 1 || seg->len < 1) continue; diff --git a/kernel/memory/paging.c b/kernel/memory/paging.c index d10cf6d..5c4fa5c 100644 --- a/kernel/memory/paging.c +++ b/kernel/memory/paging.c @@ -514,7 +514,7 @@ static inline void *page_align(void *addr) return (void *)a; } -void *mapaddr(void *addr, size_t len) +void *kmapaddr(void *addr, size_t len) { void *phys = page_align(addr); ptrdiff_t error = (char *)addr - (char *)phys; @@ -531,7 +531,7 @@ void *mapaddr(void *addr, size_t len) return (char *)virt + error; } -void unmapaddr(void *addr) +void kunmapaddr(void *addr) { long pages = virtaddr_free(addr); if (pages < 1) @@ -539,7 +539,7 @@ void unmapaddr(void *addr) unmap_pages(kernel_pml4, addr, pages); } -void *alloc_pages(size_t count) +void *kalloc_pages(size_t count) { void *virt = virtaddr_alloc(count); if (virt == NULL) @@ -559,13 +559,12 @@ void *alloc_pages(size_t count) return virt; } -void free_page(void *virt) +void *kalloc_page(void) { - (void)virt; - panic("free_page is not yet implemented"); + return kalloc_pages(1); } -void free_pages(void *virt) +void kfree_pages(void *virt) { long pages = virtaddr_free(virt); if (pages < 1) @@ -573,7 +572,7 @@ void free_pages(void *virt) unmap_pages(kernel_pml4, virt, pages); } -int load_page(void *virt_addr) +int kload_page(void *virt_addr) { volatile struct pte *page = get_page(kernel_pml4, virt_addr); if (page == NULL) diff --git a/kernel/memory/physalloc.c b/kernel/memory/physalloc.c index 53f8aaf..a907077 100644 --- a/kernel/memory/physalloc.c +++ b/kernel/memory/physalloc.c @@ -185,9 +185,9 @@ void physalloc_init(struct memory_map *map) memory_start = page_align((uintptr_t)page_area_addr + page_area_size); - bitmap = mapaddr(bitmap, bitmap_size); + bitmap = kmapaddr(bitmap, bitmap_size); memset(bitmap, 0, bitmap_size); - page_area_addr = mapaddr(page_area_addr, page_area_size); + page_area_addr = kmapaddr(page_area_addr, page_area_size); memset(page_area_addr, 0, page_area_size); page_start = (struct memory_segment *)page_area_addr; @@ -210,15 +210,10 @@ void physalloc_init(struct memory_map *map) free_memory = page_count * PAGE_SIZE; char buf[20]; - printf("\nMEMORY USAGE\n"); - printf("mem total: %s\n", btoa(memory_total(), buf)); - printf("mem free: %s\n", btoa(memory_free(), buf)); - printf("mem used: %s\n\n", btoa(memory_used(), buf)); -} - -void *alloc_page(void) -{ - return alloc_pages(1); + kprintf("\nMEMORY USAGE\n"); + kprintf("mem total: %s\n", btoa(memory_total(), buf)); + kprintf("mem free: %s\n", btoa(memory_free(), buf)); + kprintf("mem used: %s\n\n", btoa(memory_used(), buf)); } uint64_t memory_total(void) diff --git a/kernel/memory/virtalloc.c b/kernel/memory/virtalloc.c index 2b64b72..6b7fd20 100644 --- a/kernel/memory/virtalloc.c +++ b/kernel/memory/virtalloc.c @@ -64,11 +64,11 @@ static struct addr_node *get_node(void) if (new_alloc < 8) new_alloc = 8; struct addr_node *new_nodes; - new_nodes = malloc(sizeof(struct addr_node) * new_alloc); + new_nodes = kalloc(sizeof(struct addr_node) * new_alloc); if (new_nodes == NULL) panic("virt addr alloc nodes is null"); update_node_ptrs(alloc_nodes, new_nodes, alloc_node_count, new_alloc); - free(alloc_nodes); + kfree(alloc_nodes); alloc_nodes = new_nodes; alloc_node_count = new_alloc; is_allocating = false; diff --git a/include/ctype.h b/user/include/ctype.h index c5f92b4..c5f92b4 100644 --- a/include/ctype.h +++ b/user/include/ctype.h diff --git a/include/elf.h b/user/include/elf.h index b7e6059..b7e6059 100644 --- a/include/elf.h +++ b/user/include/elf.h diff --git a/include/error.h b/user/include/error.h index b9265b4..b9265b4 100644 --- a/include/error.h +++ b/user/include/error.h diff --git a/include/stdio.h b/user/include/stdio.h index d335968..9e60f55 100644 --- a/include/stdio.h +++ b/user/include/stdio.h @@ -12,19 +12,13 @@ #include <stdarg.h> #include <stddef.h> +// TODO: implement typedef void FILE; -/// standard input -#define stdin ((FILE *)1) -/// standard output -#define stdout ((FILE *)2) -/// standard error -#define stderr ((FILE *)3) - -/// console output -#define stdcon ((FILE *)4) -/// serial output -#define stduart ((FILE *)5) +extern FILE *stdin; +extern FILE *stdout; +#define stdin stdin +#define stdout stdout /** * Prints out a char diff --git a/include/stdlib.h b/user/include/stdlib.h index 1455a1f..40bffde 100644 --- a/include/stdlib.h +++ b/user/include/stdlib.h @@ -11,8 +11,6 @@ #include <stddef.h> -#define PAGE_SIZE 4096 - /** * converts single digit int to base 36 * @param i - int @@ -221,34 +219,4 @@ extern void *realloc(void *ptr, size_t size); */ extern void free(void *ptr); -/** - * Allocate a single page of memory - * - * @returns the address allocated or NULL on failure - */ -extern void *alloc_page(void); - -/** - * Allocate size_t amount of contiguous virtual pages - * - * @param count - the number of pages to allocate - * @returns the address allocated or NULL on failure - */ -extern void *alloc_pages(size_t count); - -/** - * Free allocated pages. - * - * @param ptr - the pointer provided by alloc_page or alloc_pages - */ -extern void free_pages(void *ptr); - -/** - * Abort the current process with a given message. - * - * @param format - the format string - * @param ... - variable args for the format - */ -__attribute__((noreturn)) extern void panic(const char *format, ...); - #endif /* stlib.h */ diff --git a/include/string.h b/user/include/string.h index f966981..4d32f57 100644 --- a/include/string.h +++ b/user/include/string.h @@ -52,38 +52,6 @@ extern void *memmove(void *restrict dest, const void *restrict src, size_t n); extern void *memset(void *restrict dest, int c, size_t n); /** - * Copy the first n bytes from memory area src to memory area dest. The memory - * areas must not overlap. - * @param dest - the destination - * @param src - the source - * @param n - the byte count - * @returns a pointer to dest - */ -extern volatile void *memcpyv(volatile void *restrict dest, - const volatile void *restrict src, size_t n); - -/** - * Copy the first n bytes from memory area src to memory area dest. The memory - * areas may overlap; memmove behaves as though the bytes are first copied to a - * temporary array. - * @param dest - the destination - * @param src - the source - * @param n - the byte count - * @returns a pointer to dest - */ -extern volatile void *memmovev(volatile void *restrict dest, - const volatile void *restrict src, size_t n); - -/** - * Fill the first n bytes of the memory region dest with the constant byte c. - * @param dest - the destination - * @param c - the byte to write - * @param n - the byte count - * @returns a pointer to dest - */ -extern volatile void *memsetv(volatile void *restrict dest, int c, size_t n); - -/** * Calculates the length of the string pointed to by str, excluding * the terminating null byte * @param str - the string pointer diff --git a/include/unistd.h b/user/include/unistd.h index f9838f1..1f83abc 100644 --- a/include/unistd.h +++ b/user/include/unistd.h @@ -6,29 +6,29 @@ * Universial system definitions for userspace. */ -#ifndef _UNISTD_H -#define _UNISTD_H +#ifndef UNISTD_H_ +#define UNISTD_H_ #include <stdint.h> #include <stddef.h> /* System Call Definitions */ -typedef uint_t pid_t; +typedef unsigned short pid_t; /** - * Terminates the calling process and does not return. + * terminates the calling process and does not return. + * * @param status - the status code to exit with */ -__attribute__((noreturn)) extern void exit(int32_t status); +__attribute__((noreturn)) extern void exit(int status); /** - * Sleeps current process until a child process terminates + * sleeps current process until a child process terminates * * @param pid - pid of the desired child, or 0 for any child - * @param status - Pointer to int32_t into which the child's status is placed, + * @param status - pointer to int32_t into which the child's status is placed, * or NULL - * * @return The pid of the terminated child, or an error code * * If there are no children in the system, returns an error code (*status @@ -38,18 +38,18 @@ __attribute__((noreturn)) extern void exit(int32_t status); * terminated but hasn't yet been cleaned up, cleans up that process and * returns its information; otherwise, blocks until a child terminates. */ -extern int waitpid(pid_t pid, int32_t *status); +extern int waitpid(pid_t pid, int *status); /** - * Create a duplicate of the calling process + * create a duplicate of the calling process * - * @return parent - the pid of the new child, or an error code - * child - 0 + * @return parent - the pid of the new child, or an error code + * child - 0 */ extern int fork(void); /** - * Replace the memory image of the calling process + * replace the memory image of the calling process * * @param prog - program table index of the program to exec * @param args - the command-line argument vector @@ -57,126 +57,124 @@ extern int fork(void); * Does not return if it succeeds; if it returns, something has * gone wrong. */ -extern void exec(uint_t prog, char **args); +extern void exec(const char *filename, char **args); /** - * Open a stream with a given filename + * open a stream with a given filename * * @param filename - the name of the file to open * @return the file descriptior of the open file or a negative error code. - * TODO: fmurphy implement */ -extern int open(char *filename); +extern int open(const char *filename); /** - * Closes a stream with the given file descriptior + * closes a stream with the given file descriptior + * * @param fd - the file descriptior of the open stream - * TODO: fmurphy implement */ extern void close(int fd); /** - * Read into a buffer from a stream + * read into a buffer from a stream * * @param fd - file stream to read from * @param buf - buffer to read into * @param nbytes - maximum capacity of the buffer - * * @return - The count of bytes transferred, or an error code - * TODO: fmurphy FD */ extern int read(int fd, void *buffer, size_t nbytes); /** - * Write from a buffer to a stream + * write from a buffer to a stream * * @param fd - file stream to write to * @param buf - buffer to write from * @param nbytes - maximum capacity of the buffer - * * @return - The count of bytes transferred, or an error code - * TODO: fmurphy FD */ extern int write(int fd, const void *buffer, size_t nbytes); /** - * Gets the pid of the calling process + * gets the pid of the calling process * * @return the pid of this process */ extern pid_t getpid(void); /** - * Gets the parent pid of the current process + * gets the parent pid of the current process * * @return the parent pid of the current process, or 0 if init */ extern pid_t getppid(void); /** - * Gets the current system time + * gets the current system time * * @return the system time - * TODO: CHANGE TIME TO 64bits!! */ -extern ulong_t gettime(void); +extern unsigned long gettime(void); /** - * Gets the scheduling priority of the calling process + * gets the scheduling priority of the calling process * * @return the process' priority */ -extern uint_t getprio(void); +extern unsigned int getprio(void); /** - * Sets the scheduling priority of the calling process + * sets the scheduling priority of the calling process * * @param new - the desired new priority - * * @return the old priority value */ -extern uint_t setprio(uint_t new); +extern unsigned int setprio(unsigned int new); /** - * Terminates a process + * terminates a process * * @param pid - the pid of the process to kill - * * @return 0 on success, else an error code */ -extern int32_t kill(pid_t pid); +extern int kill(pid_t pid); /** - * Put the current process to sleep for some length of time + * put the current process to sleep for some length of time * * @param ms - desired sleep time (in ms), or 0 to yield the CPU - * * @return the time the process spent sleeping (in ms) */ -extern int sleep(uint32_t ms); +extern int sleep(unsigned long ms); /** * Wait for any child to exit * - * @param status - Pointer to int32_t into which the child's status is placed, + * @param status - pointer to int32_t into which the child's status is placed, * or NULL - * * @return The pid of the terminated child, or an error code * * Analogous to waitpid(0,status) */ -extern int wait(int32_t *status); +extern int wait(int *status); /** * Spawn a new process running a different program * * @param prog - program table index of the program to spawn * @param args - the command-line argument vector for the process - * - * @return The pid of the child, or an error code + * @return the pid of the child, or an error code * * Analogous to calling fork and exec */ -extern int spawn(uint_t prog, char **args); +extern int spawn(pid_t prog, char **args); + +/** + * Increment the program's data space by increment bytes. + * + * @param increment - the amount in bytes to increment the heap + * @return the previos program break on success, or NULL on failure + * + */ +extern void *sbrk(intptr_t increment); #endif /* unistd.h */ diff --git a/lib/alloc.c b/user/lib/alloc.c index dfa2df5..49c762b 100644 --- a/lib/alloc.c +++ b/user/lib/alloc.c @@ -1,8 +1,10 @@ #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #define MAGIC 0xBEEFCAFE +#define PAGE_SIZE 4096 struct page_header { struct page_header *next; @@ -37,6 +39,7 @@ static void *alloc_new(size_t size) { size_t pages = ((size + header_len) / PAGE_SIZE) + 1; + // FIXME: use brk/sbrk void *addr = alloc_pages(pages); void *mem = (char *)addr + header_len; @@ -206,6 +209,7 @@ void free(void *ptr) header->next->prev = header->prev; if (header->prev) header->prev->next = header->next; + // FIXME: use brk/sbrk free_pages(header); } } diff --git a/lib/atox.c b/user/lib/atox.c index c4bef59..c4bef59 100644 --- a/lib/atox.c +++ b/user/lib/atox.c diff --git a/lib/bound.c b/user/lib/bound.c index 072a41a..072a41a 100644 --- a/lib/bound.c +++ b/user/lib/bound.c diff --git a/lib/btoa.c b/user/lib/btoa.c index fe5e275..fe5e275 100644 --- a/lib/btoa.c +++ b/user/lib/btoa.c diff --git a/lib/ctoi.c b/user/lib/ctoi.c index efe4fec..efe4fec 100644 --- a/lib/ctoi.c +++ b/user/lib/ctoi.c diff --git a/lib/delay.c b/user/lib/delay.c index ff5ccc4..ff5ccc4 100644 --- a/lib/delay.c +++ b/user/lib/delay.c diff --git a/ulib/entry.S b/user/lib/entry.S index 87ad9c7..87ad9c7 100644 --- a/ulib/entry.S +++ b/user/lib/entry.S diff --git a/lib/isdigit.c b/user/lib/isdigit.c index aa93ced..aa93ced 100644 --- a/lib/isdigit.c +++ b/user/lib/isdigit.c diff --git a/lib/isspace.c b/user/lib/isspace.c index 9e89d76..9e89d76 100644 --- a/lib/isspace.c +++ b/user/lib/isspace.c diff --git a/lib/itoc.c b/user/lib/itoc.c index c19d814..c19d814 100644 --- a/lib/itoc.c +++ b/user/lib/itoc.c diff --git a/lib/memcmp.c b/user/lib/memcmp.c index 7f3dc01..7f3dc01 100644 --- a/lib/memcmp.c +++ b/user/lib/memcmp.c diff --git a/lib/memcpy.c b/user/lib/memcpy.c index ec56537..ec56537 100644 --- a/lib/memcpy.c +++ b/user/lib/memcpy.c diff --git a/lib/memmove.c b/user/lib/memmove.c index 81f00fe..81f00fe 100644 --- a/lib/memmove.c +++ b/user/lib/memmove.c diff --git a/lib/memset.c b/user/lib/memset.c index ddf42f8..ddf42f8 100644 --- a/lib/memset.c +++ b/user/lib/memset.c diff --git a/lib/printf.c b/user/lib/printf.c index 4a85956..4a85956 100644 --- a/lib/printf.c +++ b/user/lib/printf.c diff --git a/ulib/spawn.c b/user/lib/spawn.c index 78b1a53..78b1a53 100644 --- a/ulib/spawn.c +++ b/user/lib/spawn.c diff --git a/lib/stpcpy.c b/user/lib/stpcpy.c index 1586a37..1586a37 100644 --- a/lib/stpcpy.c +++ b/user/lib/stpcpy.c diff --git a/lib/stpncpy.c b/user/lib/stpncpy.c index 4e0def6..4e0def6 100644 --- a/lib/stpncpy.c +++ b/user/lib/stpncpy.c diff --git a/lib/strcat.c b/user/lib/strcat.c index 33f749b..33f749b 100644 --- a/lib/strcat.c +++ b/user/lib/strcat.c diff --git a/lib/strcpy.c b/user/lib/strcpy.c index 70cd1ca..70cd1ca 100644 --- a/lib/strcpy.c +++ b/user/lib/strcpy.c diff --git a/lib/strlen.c b/user/lib/strlen.c index 6c4cc86..6c4cc86 100644 --- a/lib/strlen.c +++ b/user/lib/strlen.c diff --git a/lib/strncmp.c b/user/lib/strncmp.c index e890517..e890517 100644 --- a/lib/strncmp.c +++ b/user/lib/strncmp.c diff --git a/lib/strncpy.c b/user/lib/strncpy.c index 264fd9d..264fd9d 100644 --- a/lib/strncpy.c +++ b/user/lib/strncpy.c diff --git a/lib/strtoux.c b/user/lib/strtoux.c index 7c2d7ee..7c2d7ee 100644 --- a/lib/strtoux.c +++ b/user/lib/strtoux.c diff --git a/lib/strtox.c b/user/lib/strtox.c index 5f786f1..5f786f1 100644 --- a/lib/strtox.c +++ b/user/lib/strtox.c diff --git a/ulib/syscall.S b/user/lib/syscall.S index 46fcb89..46fcb89 100644 --- a/ulib/syscall.S +++ b/user/lib/syscall.S diff --git a/lib/timetostr.c b/user/lib/timetostr.c index fa77362..fa77362 100644 --- a/lib/timetostr.c +++ b/user/lib/timetostr.c diff --git a/lib/uxtoa.c b/user/lib/uxtoa.c index 8d4e0e1..8d4e0e1 100644 --- a/lib/uxtoa.c +++ b/user/lib/uxtoa.c diff --git a/lib/xtoa.c b/user/lib/xtoa.c index bf02236..bf02236 100644 --- a/lib/xtoa.c +++ b/user/lib/xtoa.c diff --git a/util/BuildImage.c b/util/BuildImage.c deleted file mode 100644 index f43f0b0..0000000 --- a/util/BuildImage.c +++ /dev/null @@ -1,420 +0,0 @@ -/** -** SCCS ID: @(#)BuildImage.c 2.2 1/16/25 -** -** @file BuildImage.c -** -** @author K. Reek -** @author Jon Coles -** @author Warren R. Carithers -** @author Garrett C. Smith -** -** Modify the bootstrap image to include the information -** on the programs to be loaded, and produce the file -** that contains the concatenation of these programs. -** -*/ - -#define _POSIX_C_SOURCE 200809L - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> - -#define TRUE 1 -#define FALSE 0 - -#define DRIVE_FLOPPY 0x00 -#define DRIVE_USB 0x80 - -#define SECT_SIZE 512 - -char *progname; /* invocation name of this program */ -char *bootstrap_filename; /* path of file holding bootstrap program */ -char *output_filename; /* path of disk image file */ -FILE *out; /* output stream for disk image file */ -short drive = DRIVE_USB; /* boot drive */ - -/* -** Array into which program information will be stored, starting at the -** end and moving back toward the front. The array is the same size as -** a sector, which is guaranteed to be larger than the maximum possible -** space available for this stuff in the bootstrap image. Thus, the -** bootstrap image itself (and the amount of space available on the -** device) are the only limiting factors on how many program sections -** can be loaded. -*/ - -#define N_INFO (SECT_SIZE / sizeof(short)) - -short info[N_INFO]; -int n_info = N_INFO; - -/** -** quit with an appropriate message -** -** @param msg NULL, or a message to be printed to stderr -** @param call_perror non-zero if perror() should be used; else, -** fprintf() will be used -** -** does not return -*/ -void quit(char *msg, int call_perror) -{ - if (msg != NULL) { - // preserve the error code in case we need it - int err_num = errno; - fprintf(stderr, "%s: ", progname); - errno = err_num; - if (call_perror) { - perror(msg); - } else { - fprintf(stderr, "%s\n", msg); - } - } - if (output_filename != NULL) { - unlink(output_filename); - } - exit(EXIT_FAILURE); - // NOTREACHED -} - -const char usage_error_msg[] = - "\nUsage: %s [ -d drive ] -b bootfile -o outfile { progfile loadpt } ...\n\n" - "\t'drive' is either 'floppy' or 'usb' (default 'usb')\n\n" - "\tThere must be at least one program file and load point.\n\n" - "\tLoad points may be specified either as 32-bit quantities in hex,\n" - "\tdecimal or octal (e.g. 0x10c00, 68608, 0206000 are all equivalent),\n" - "\tor as an explicit segment:offset pair whose digits are always\n" - "\tinterpreted as hexadecimal values (e.g. 10c0:0000, 1000:0c00 are\n" - "\tboth equivalent to the previous examples).\n\n"; - -/** -** print a usage message and then call quit() -** -** does not return -*/ -void usage_error(void) -{ - fprintf(stderr, usage_error_msg, progname); - quit(NULL, FALSE); - // NOTREACHED -} - -/** -** copy the contents of a binary file into the output file, padding the -** last sector with NUL bytes -** -** @param in open FILE to be read -** @return the number of sectors copied from the file -*/ -int copy_file(FILE *in) -{ - int n_sectors = 0; - char buf[SECT_SIZE]; - int n_bytes; - int i; - - /* - ** Copy the file to the output, being careful that the - ** last sector is padded with null bytes out to the - ** sector size. - */ - n_sectors = 0; - while ((n_bytes = fread(buf, 1, sizeof(buf), in)) > 0) { - // pad this sector out to block size - if (n_bytes < sizeof(buf)) { - int i; - - for (i = n_bytes; i < sizeof(buf); i += 1) { - buf[i] = '\0'; - } - } - if (fwrite(buf, 1, sizeof(buf), out) != sizeof(buf)) { - quit("Write failed or was wrong size", FALSE); - } - n_sectors += 1; - } - return n_sectors; -} - -/** -** process a file whose contents should be at a specific' -** address in memory when the program is loaded -** -** @param name path to the file to be copied -** @param addr string containing the load address -*/ -void process_file(char *name, char *addr) -{ - long address; - short segment, offset; - int n_bytes; - - /* - ** Open the input file. - */ - FILE *in = fopen(name, "rb"); - if (in == NULL) { - quit(name, TRUE); - } - - /* - ** Copy the file to the output, being careful that the - ** last block is padded with null bytes. - */ - int n_sectors = copy_file(in); - fclose(in); - - /* - ** Decode the address they gave us. We'll accept two forms: - ** "nnnn:nnnn" for a segment:offset value (assumed to be hex), - ** "nnnnnnn" for a decimal, hex, or octal value - */ - int valid_address = FALSE; - char *cp = strchr(addr, ':'); - if (cp != NULL) { - // must be in nnnn:nnnn form exactly - if (strlen(addr) == 9 && cp == addr + 4) { - char *ep1, *ep2; - int a1, a2; - - segment = strtol(addr, &ep1, 16); - offset = strtol(addr + 5, &ep2, 16); - address = (segment << 4) + offset; - valid_address = *ep1 == '\0' && *ep2 == '\0'; - } else { - fprintf(stderr, "Bad address format - '%s'\n", addr); - quit(NULL, FALSE); - } - } else { - // just a number, possibly hex or octal - char *ep; - - address = strtol(addr, &ep, 0); - segment = (short)(address >> 4); - offset = (short)(address & 0xf); - valid_address = *ep == '\0' && address <= 0x0009ffff; - } - - if (!valid_address) { - fprintf(stderr, "%s: Invalid address: %s\n", progname, addr); - quit(NULL, FALSE); - } - - /* - ** Make sure the program will fit! - */ - if (address + n_sectors * SECT_SIZE > 0x0009ffff) { - fprintf(stderr, "Program %s too large to start at 0x%08x\n", name, - (unsigned int)address); - quit(NULL, FALSE); - } - - if (n_info < 3) { - quit("Too many programs!", FALSE); - } - - /* - ** Looks good: report and store the information. - */ - fprintf(stderr, " %s: %d sectors, loaded at 0x%x\n", name, n_sectors, - (unsigned int)address); - - info[--n_info] = n_sectors; - info[--n_info] = segment; - info[--n_info] = offset; -} - -/* -** Global variables set by getopt() -*/ - -extern int optind, optopt; -extern char *optarg; - -/** -** process the command-line arguments -** -** @param ac the count of entries in av -** @param av the argument vector -*/ -void process_args(int ac, char **av) -{ - int c; - - while ((c = getopt(ac, av, ":d:o:b:")) != EOF) { - switch (c) { - case ':': /* missing arg value */ - fprintf(stderr, "missing operand after -%c\n", optopt); - /* FALL THROUGH */ - - case '?': /* error */ - usage_error(); - /* NOTREACHED */ - - case 'b': /* -b bootstrap_file */ - bootstrap_filename = optarg; - break; - - case 'd': /* -d drive */ - switch (*optarg) { - case 'f': - drive = DRIVE_FLOPPY; - break; - case 'u': - drive = DRIVE_USB; - break; - default: - usage_error(); - } - break; - - case 'o': /* -o output_file */ - output_filename = optarg; - break; - - default: - usage_error(); - } - } - - if (!bootstrap_filename) { - fprintf(stderr, "%s: no bootstrap file specified\n", progname); - exit(2); - } - - if (!output_filename) { - fprintf(stderr, "%s: no disk image file specified\n", progname); - exit(2); - } - - /* - ** Must have at least two remaining arguments (file to load, - ** address at which it should be loaded), and must have an - ** even number of remaining arguments. - */ - int remain = ac - optind; - if (remain < 2 || (remain & 1) != 0) { - usage_error(); - } -} - -/** -** build a bootable image file from one or more binary files -** -** usage: -** BuildImage [ -d drive ] -b bootfile -o outfile { binfile1 loadpt1 } ... ] -** -** @param ac command-line argument count -** @param av command-line argument vector -** @return EXIT_SUCCESS or EXIT_FAILURE -*/ -int main(int ac, char **av) -{ - FILE *bootimage; - int bootimage_size; - int n_bytes, n_words; - short existing_data[N_INFO]; - int i; - - /* - ** Save the program name for error messages - */ - progname = strrchr(av[0], '/'); - if (progname != NULL) { - progname++; - } else { - progname = av[0]; - } - - /* - ** Process arguments - */ - process_args(ac, av); - - /* - ** Open the output file - */ - - out = fopen(output_filename, "wb+"); - if (out == NULL) { - quit(output_filename, TRUE); - } - - /* - ** Open the bootstrap file and copy it to the output image. - */ - bootimage = fopen(bootstrap_filename, "rb"); - if (bootimage == NULL) { - quit(bootstrap_filename, TRUE); - } - - /* - ** Remember the size of the bootstrap for later, as we - ** need to patch some things into it - */ - int n_sectors = copy_file(bootimage); - fclose(bootimage); - - bootimage_size = n_sectors * SECT_SIZE; - fprintf(stderr, " %s: %d sectors\n", bootstrap_filename, n_sectors); - - /* - ** Process the programs one by one - */ - ac -= optind; - av += optind; - while (ac >= 2) { - process_file(av[0], av[1]); - ac -= 2; - av += 2; - } - - /* - ** Check for oddball leftover argument - */ - if (ac > 0) { - usage_error(); - } - - /* - ** Seek to where the array of module data must begin and read - ** what's already there. - */ - n_words = (N_INFO - n_info); - n_bytes = n_words * sizeof(info[0]); - fseek(out, bootimage_size - n_bytes, SEEK_SET); - if (fread(existing_data, sizeof(info[0]), n_words, out) != n_words) { - quit("Read from boot image failed or was too short", FALSE); - } - - /* - ** If that space is non-zero, we have a problem - */ - for (i = 0; i < n_words; i += 1) { - if (existing_data[i] != 0) { - quit("Too many programs to load!", FALSE); - } - } - - /* - ** We know that we're only overwriting zeros at the end of - ** the bootstrap image, so it is ok to go ahead and do it. - */ - fseek(out, bootimage_size - n_bytes, SEEK_SET); - if (fwrite(info + n_info, sizeof(info[0]), n_words, out) != n_words) { - quit("Write to boot image failed or was too short", FALSE); - } - - /* - ** Write the drive index to the image. - */ - fseek(out, 508, SEEK_SET); - fwrite((void *)&drive, sizeof(drive), 1, out); - - fclose(out); - - return EXIT_SUCCESS; -} diff --git a/util/default.ld b/util/default.ld deleted file mode 100644 index 0c600e4..0000000 --- a/util/default.ld +++ /dev/null @@ -1,247 +0,0 @@ -GNU ld (GNU Binutils for Ubuntu) 2.30 - Supported emulations: - elf_x86_64 - elf32_x86_64 - elf_i386 - elf_iamcu - i386linux - elf_l1om - elf_k1om - i386pep - i386pe -using internal linker script: -================================================== -/* Script for -z combreloc: combine and sort reloc sections */ -/* Copyright (C) 2014-2018 Free Software Foundation, Inc. - Copying and distribution of this script, with or without modification, - are permitted in any medium without royalty provided the copyright - notice and this notice are preserved. */ -OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", - "elf64-x86-64") -OUTPUT_ARCH(i386:x86-64) -ENTRY(_start) -SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib"); -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS; - .interp : { *(.interp) } - .note.gnu.build-id : { *(.note.gnu.build-id) } - .hash : { *(.hash) } - .gnu.hash : { *(.gnu.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rela.dyn : - { - *(.rela.init) - *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) - *(.rela.fini) - *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) - *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) - *(.rela.ctors) - *(.rela.dtors) - *(.rela.got) - *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) - *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*) - *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*) - *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*) - *(.rela.ifunc) - } - .rela.plt : - { - *(.rela.plt) - PROVIDE_HIDDEN (__rela_iplt_start = .); - *(.rela.iplt) - PROVIDE_HIDDEN (__rela_iplt_end = .); - } - .init : - { - KEEP (*(SORT_NONE(.init))) - } - .plt : { *(.plt) *(.iplt) } -.plt.got : { *(.plt.got) } -.plt.sec : { *(.plt.sec) } - .text : - { - *(.text.unlikely .text.*_unlikely .text.unlikely.*) - *(.text.exit .text.exit.*) - *(.text.startup .text.startup.*) - *(.text.hot .text.hot.*) - *(.text .stub .text.* .gnu.linkonce.t.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } - .fini : - { - KEEP (*(SORT_NONE(.fini))) - } - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } - .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) } - .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table - .gcc_except_table.*) } - .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } - /* These sections are generated by the Sun/Oracle C++ compiler. */ - .exception_ranges : ONLY_IF_RO { *(.exception_ranges - .exception_ranges*) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); - /* Exception handling */ - .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } - .gnu_extab : ONLY_IF_RW { *(.gnu_extab) } - .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } - .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } - /* Thread Local Storage sections */ - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - .preinit_array : - { - PROVIDE_HIDDEN (__preinit_array_start = .); - KEEP (*(.preinit_array)) - PROVIDE_HIDDEN (__preinit_array_end = .); - } - .init_array : - { - PROVIDE_HIDDEN (__init_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) - KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) - PROVIDE_HIDDEN (__init_array_end = .); - } - .fini_array : - { - PROVIDE_HIDDEN (__fini_array_start = .); - KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) - KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) - PROVIDE_HIDDEN (__fini_array_end = .); - } - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin.o(.ctors)) - KEEP (*crtbegin?.o(.ctors)) - /* We don't want to include the .ctor section from - the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } - .dtors : - { - KEEP (*crtbegin.o(.dtors)) - KEEP (*crtbegin?.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } - .jcr : { KEEP (*(.jcr)) } - .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) } - .dynamic : { *(.dynamic) } - .got : { *(.got) *(.igot) } - . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .); - .got.plt : { *(.got.plt) *(.igot.plt) } - .data : - { - *(.data .data.* .gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - } - .data1 : { *(.data1) } - _edata = .; PROVIDE (edata = .); - . = .; - __bss_start = .; - .bss : - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. - FIXME: Why do we need it? When there is no .bss section, we don't - pad the .data section. */ - . = ALIGN(. != 0 ? 64 / 8 : 1); - } - .lbss : - { - *(.dynlbss) - *(.lbss .lbss.* .gnu.linkonce.lb.*) - *(LARGE_COMMON) - } - . = ALIGN(64 / 8); - . = SEGMENT_START("ldata-segment", .); - .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : - { - *(.lrodata .lrodata.* .gnu.linkonce.lr.*) - } - .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) : - { - *(.ldata .ldata.* .gnu.linkonce.l.*) - . = ALIGN(. != 0 ? 64 / 8 : 1); - } - . = ALIGN(64 / 8); - _end = .; PROVIDE (end = .); - . = DATA_SEGMENT_END (.); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /* DWARF 3 */ - .debug_pubtypes 0 : { *(.debug_pubtypes) } - .debug_ranges 0 : { *(.debug_ranges) } - /* DWARF Extension. */ - .debug_macro 0 : { *(.debug_macro) } - .debug_addr 0 : { *(.debug_addr) } - .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } - /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } -} - - -================================================== diff --git a/util/listblob.c b/util/listblob.c deleted file mode 100644 index e6266a3..0000000 --- a/util/listblob.c +++ /dev/null @@ -1,240 +0,0 @@ -/** -** @file listblob.c -** -** @author Warren R. Carithers -** -** Examine a binary blob of ELF files. -*/ -#define _DEFAULT_SOURCE -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <unistd.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <elf.h> -#include <ctype.h> - -/* -** Blob file organization -** -** The file begins with a four-byte magic number and a four-byte integer -** indicating the number of ELF files contained in the blob. This is -** followed by an array of 32-byte file entries, and then the contents -** of the ELF files in the order they appear in the program file table. -** -** Bytes Contents -** ----- ---------------------------- -** 0 - 3 File magic number ("BLB\0") -** 4 - 7 Number of ELF files in blob ("n") -** 8 - n*32+8 Program file table -** n*32+9 - ? ELF file contents -** -** Each program file table entry contains the following information: -** -** name File name (up to 19 characters long) -** offset Byte offset to the ELF header for this file -** size Size of this ELF file, in bytes -** flags Flags related to this file -*/ - -// blob header: 8 bytes -typedef struct header_s { - char magic[4]; - uint32_t num; -} header_t; - -// The program table entry is 32 bytes long. To accomplish this, the -// name field is 20 bytes long, which allows file names of 19 characters -// (followed by a trailing NUL byte). -// -// If that field is made longer, it should be incremented in multiples -// of four to avoid the insertion of padding bytes. -#define NAMELEN 20 - -// program descriptor: 32 bytes -typedef struct prog_s { - char name[NAMELEN]; // truncated name (19 chars plus NUL) - uint32_t offset; // offset from the beginning of the blob - uint32_t size; // size of this ELF module - uint32_t flags; // miscellaneous flags -} prog_t; - -// modules must be written as multiples of eight bytes -#define FL_ROUNDUP 0x00000001 - -// mask for mod 8 checking -#define FSIZE_MASK 0x00000007 - -// program list entry -typedef struct node_s { - prog_t *data; - struct node_s *next; -} node_t; - -node_t *progs, *last_prog; // list pointers -uint32_t n_progs; // number of files being copied -uint32_t offset; // current file area offset -bool defs = false; // print CPP #defines? -bool enums = false; // print C enums? - -// header string for the userids.h file -const char header[] = - "/**\n" - "** @file userids.h\n" - "**\n" - "** @author Warren R. Carithers\n" - "**\n" - "** @brief IDs for user-level programs\n" - "**\n" - "** NOTE: this file is automatically generated when the user.img file\n" - "** is created. Do not edit this manually!\n" - "*/\n" - "\n" - "#ifndef USERIDS_H_\n" - "#define USERIDS_H_\n" - "\n" - "#ifndef ASM_SRC\n" - "/*\n" - "** These IDs are used to identify the various user programs.\n" - "** Each call to exec() will provide one of these as the first\n" - "** argument.\n" - "**\n" - "** This list should be updated if/when the collection of\n" - "** user processes changes.\n" - "*/\n" - "enum users_e {"; - -// trailer string for the userids.h file -const char trailer[] = "\n\t// sentinel\n\t, N_USERS\n" - "};\n" - "#endif /* !ASM_SRC */\n" - "\n" - "#endif"; - -/** -** Name: process -** -** Process a program list entry -** -** @param num Program list index -** @param prog Pointer to the program list entry -*/ -void process(uint32_t num, prog_t *prog) -{ - if (defs || enums) { - char *slash = strrchr(prog->name, '/'); - if (slash == NULL) { - slash = prog->name; - } else { - ++slash; - } - - slash[0] = toupper(slash[0]); - - if (defs) { - // just printing #define statements - printf("#define %-15s %2d\n", prog->name, num); - - } else { - // printing a new userids.h file - if (num == 0) { - // first one, so print the file header - puts(header); - putchar('\t'); - } else { - // second or later entry; limit to 8 per line - fputs(((num & 0x7) == 0) ? ",\n\t" : ", ", stdout); - } - printf("%s", prog->name); - } - - } else { - // just printing information - printf("Entry %2d: ", num); - printf("%-s,", prog->name); - printf(" offset 0x%x, size 0x%x, flags %08x\n", prog->offset, - prog->size, prog->flags); - } -} - -void usage(char *name) -{ - fprintf(stderr, "usage: %s [-d | -e] blob_name\n", name); -} - -int main(int argc, char *argv[]) -{ - if (argc < 2 || argc > 3) { - usage(argv[0]); - exit(1); - } - - int nameix = 1; - - // could use getopt() for this, but this is easy enough - if (argc == 3) { - if (strcmp(argv[1], "-d") == 0) { - defs = true; - } else if (strcmp(argv[1], "-e") == 0) { - enums = true; - } else { - usage(argv[0]); - exit(1); - } - nameix = 2; - } - - char *name = argv[nameix]; - - int fd = open(name, O_RDONLY); - if (fd < 0) { - perror(name); - exit(1); - } - - header_t hdr; - - int n = read(fd, &hdr, sizeof(header_t)); - if (n != sizeof(header_t)) { - fprintf(stderr, "%s: header read returned only %d bytes\n", name, n); - close(fd); - exit(1); - } - - if (strcmp(hdr.magic, "BLB") != 0) { - fprintf(stderr, "%s: bad magic number\n", name); - close(fd); - exit(1); - } - - if (hdr.num < 1) { - fprintf(stderr, "%s: no programs in blob?\n", name); - close(fd); - exit(1); - } - - prog_t progs[hdr.num]; - - n = read(fd, progs, hdr.num * sizeof(prog_t)); - if (n != (int)(hdr.num * sizeof(prog_t))) { - fprintf(stderr, "%s: prog table only %d bytes, expected %lu\n", name, n, - hdr.num * sizeof(prog_t)); - close(fd); - exit(1); - } - - for (uint32_t i = 0; i < hdr.num; ++i) { - process(i, &progs[i]); - } - - if (enums) { - // print the file trailer - puts(trailer); - } - - close(fd); - return 0; -} diff --git a/util/mkblob.c b/util/mkblob.c deleted file mode 100644 index ea6a946..0000000 --- a/util/mkblob.c +++ /dev/null @@ -1,321 +0,0 @@ -/** -** @file mkblob.c -** -** @author Warren R. Carithers -** -** Create a binary blob from a collection of ELF files. -*/ -#define _DEFAULT_SOURCE - -#include <stdio.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <elf.h> - -/* -** Blob file organization -** -** The file begins with a four-byte magic number and a four-byte integer -** indicating the number of ELF files contained in the blob. This is -** followed by an array of 32-byte file table entries, and then the contents -** of the ELF files in the order they appear in the program file table. -** -** Bytes Contents -** ----- ---------------------------- -** 0 - 3 File magic number ("BLB\0") -** 4 - 7 Number of ELF files in blob ("n") -** 8 - n*32+8 Program file table -** n*32+9 - ? ELF file contents -** -** Each program file table entry contains the following information: -** -** name File name (up to 19 characters long) -** offset Byte offset to the ELF header for this file -** size Size of this ELF file, in bytes -** flags Flags related to this file -*/ - -// blob header -typedef struct header_s { - char magic[4]; - uint32_t num; -} header_t; - -// length of the file name field -#define NAMELEN 20 - -// program descriptor -typedef struct prog_s { - char name[NAMELEN]; // truncated name (15 chars) - uint32_t offset; // offset from the beginning of the blob - uint32_t size; // size of this ELF module - uint32_t flags; // miscellaneous flags -} prog_t; - -// modules must be written as multiples of eight bytes -#define FL_ROUNDUP 0x00000001 - -// mask for mod 8 checking -#define FSIZE_MASK 0x00000007 - -// program list entry -typedef struct node_s { - prog_t *data; - char *fullname; - struct node_s *next; -} node_t; - -node_t *progs, *last_prog; // list pointers -uint32_t n_progs; // number of files being copied -uint32_t offset; // current file area offset - -/** -** Name: process -** -** Do the initial processing for an ELF file -** -** @param name The name of the file -*/ -void process(const char *name) -{ - struct stat info; - - // check the name length - if (strlen(name) >= NAMELEN) { - fprintf(stderr, "%s: name exceeds length limit (%d)\n", name, - NAMELEN - 1); - return; - } - - // does it exist? - if (stat(name, &info) < 0) { - perror(name); - return; - } - - // is it a regular file? - if (!S_ISREG(info.st_mode)) { - fprintf(stderr, "%s: not a regular file\n", name); - return; - } - - // open it and check the file header - int fd = open(name, O_RDONLY); - if (fd < 0) { - perror(name); - return; - } - - // read and check the ELF header - Elf32_Ehdr hdr; - int n = read(fd, &hdr, sizeof(Elf32_Ehdr)); - close(fd); - - if (n != sizeof(Elf32_Ehdr)) { - fprintf(stderr, "%s: header read was short - only %d\n", name, n); - return; - } - - if (hdr.e_ident[EI_MAG0] != ELFMAG0 || hdr.e_ident[EI_MAG1] != ELFMAG1 || - hdr.e_ident[EI_MAG2] != ELFMAG2 || hdr.e_ident[EI_MAG3] != ELFMAG3) { - fprintf(stderr, "%s: bad ELF magic number\n", name); - return; - } - - // ok, it's a valid ELF file - create the prog list entry - prog_t *new = calloc(1, sizeof(prog_t)); - if (new == NULL) { - fprintf(stderr, "%s: calloc prog returned NULL\n", name); - return; - } - - node_t *node = calloc(1, sizeof(node_t)); - if (node == NULL) { - free(new); - fprintf(stderr, "%s: calloc node returned NULL\n", name); - return; - } - - node->data = new; - node->fullname = strdup(name); - - // copy in the name - - // only want the last component - const char *slash = strrchr(name, '/'); - if (slash == NULL) { - // only the file name - slash = name; - } else { - // skip the slash - ++slash; - } - - strncpy(new->name, slash, sizeof(new->name) - 1); - new->offset = offset; - new->size = info.st_size; - - // bump our counters - ++n_progs; - offset += info.st_size; - - // make sure it's a multiple of eight bytes long - if ((info.st_size & FSIZE_MASK) != 0) { - // nope, so we must round it up when we write it out - new->flags |= FL_ROUNDUP; - // increases the offset to the next file - offset += 8 - (info.st_size & FSIZE_MASK); - } - - // add to the list - if (progs == NULL) { - // first entry - progs = node; - } else { - // add to the end - if (last_prog == NULL) { - fprintf(stderr, "%s: progs ! NULL, last_prog is NULL\n", name); - free(new); - free(node->fullname); - free(node); - return; - } - last_prog->next = node; - } - last_prog = node; -} - -/** -** Name: copy -** -** Copy the contents of a program list entry into the blob -** -** @param ofd The output FILE* to be written -** @param prog Pointer to the program list entry for the file -*/ -void copy(FILE *ofd, node_t *node) -{ - prog_t *prog = node->data; - - // open it so we can copy it - int fd = open(node->fullname, O_RDONLY); - if (fd < 0) { - perror(node->fullname); - return; - } - - uint8_t buf[512]; - - // copy it block-by-block - do { - int n = read(fd, buf, 512); - // no bytes --> we're done - if (n < 1) { - break; - } - // copy it, and verify the copy count - int k = fwrite(buf, 1, n, ofd); - if (k != n) { - fprintf(stderr, "%s: write of %d returned %d\n", prog->name, n, k); - } - } while (1); - - printf("%s: copied %d", prog->name, prog->size); - - // do we need to round up? - if ((prog->flags & FL_ROUNDUP) != 0) { - // we'll fill with NUL bytes - uint64_t filler = 0; - - // how many filler bytes do we need? - int nbytes = 8 - (prog->size & FSIZE_MASK); - - // do it, and check the transfer count to be sure - int n = fwrite(&filler, 1, nbytes, ofd); - if (n != nbytes) { - fprintf(stderr, "%s: fill write of %d returned %d\n", prog->name, - nbytes, n); - } - - // report that we added some filler bytes - printf("(+%d)", n); - } - puts(" bytes"); - - // all done! - close(fd); -} - -int main(int argc, char *argv[]) -{ - // construct program list - for (int i = 1; i < argc; ++i) { - process(argv[i]); - } - - if (n_progs < 1) { - fputs("Nothing to do... exiting.", stderr); - exit(0); - } - - // create the output file - FILE *ofd; - ofd = fopen("user.img", "wb"); - if (ofd == NULL) { - perror("user.img"); - exit(1); - } - - printf("Processing %d ELF files\n", n_progs); - - // we need to adjust the offset values so they are relative to the - // start of the blob, not relative to the start of the file area. - // do this by adding the sum of the file header and program entries - // to each offset field. - - uint32_t hlen = sizeof(header_t) + n_progs * sizeof(prog_t); - node_t *curr = progs; - while (curr != NULL) { - curr->data->offset += hlen; - curr = curr->next; - } - - // write out the blob header - header_t hdr = { "BLB", n_progs }; - if (fwrite(&hdr, sizeof(header_t), 1, ofd) != 1) { - perror("blob header"); - fclose(ofd); - exit(1); - } - - // next, the program entries - curr = progs; - while (curr != NULL) { - if (fwrite(curr->data, sizeof(prog_t), 1, ofd) != 1) { - perror("blob prog entry write"); - fclose(ofd); - exit(1); - } - curr = curr->next; - } - - // finally, copy the files - curr = progs; - while (curr != NULL) { - prog_t *prog = curr->data; - copy(ofd, curr); - node_t *tmp = curr; - curr = curr->next; - free(tmp->data); - free(tmp->fullname); - free(tmp); - } - - fclose(ofd); - - return 0; -} |