From 5c0e560e481e2e97b793f7574e849a5882781df9 Mon Sep 17 00:00:00 2001 From: Nathan Wagner Date: Mon, 24 Oct 2016 20:27:31 -0500 Subject: [PATCH] klib and makefile --- Makefile | 129 ++++++++++++++++++ klib/bitops.s | 10 ++ klib/memcpy.c | 10 ++ klib/memmove.c | 18 +++ klib/memset.c | 11 ++ klib/objlist.c | 52 +++++++ klib/objlist.h | 17 +++ klib/printk.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++ klib/printk.h | 9 ++ klib/strcat.c | 10 ++ klib/strcmp.c | 9 ++ klib/strcpy.c | 7 + klib/strcspn.c | 17 +++ klib/strdup.c | 15 +++ klib/string.h | 43 ++++++ klib/strlen.c | 11 ++ klib/strncpy.c | 17 +++ klib/strtok.c | 52 +++++++ 18 files changed, 796 insertions(+) create mode 100644 Makefile create mode 100644 klib/bitops.s create mode 100644 klib/memcpy.c create mode 100644 klib/memmove.c create mode 100644 klib/memset.c create mode 100644 klib/objlist.c create mode 100644 klib/objlist.h create mode 100644 klib/printk.c create mode 100644 klib/printk.h create mode 100644 klib/strcat.c create mode 100644 klib/strcmp.c create mode 100644 klib/strcpy.c create mode 100644 klib/strcspn.c create mode 100644 klib/strdup.c create mode 100644 klib/string.h create mode 100644 klib/strlen.c create mode 100644 klib/strncpy.c create mode 100644 klib/strtok.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e4cab80 --- /dev/null +++ b/Makefile @@ -0,0 +1,129 @@ +AFLAGS=-felf64 +AS=yasm $(AFLAGS) +CFLAGS= -ffreestanding -mno-red-zone -mcmodel=large +CFLAGS= -Wall -Iinclude -Ipci -Iklib -I. -std=c99 -nostdlibinc -Wno-parentheses -ffreestanding -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fomit-frame-pointer +LDFLAGS= -L. -Tlink64.ld +CFLAGS32= -ffreestanding -mno-red-zone -mno-mmx -mno-sse -mno-sse2 +OS=$(shell uname -s) + +DIS= objdump -M intel -d + +LIBSRC=$(wildcard klib/*.c) +#LIBOBJS:=$(addsuffix .o,$(basename, $(wildcard klib/*.c))) +LIBOBJS:=$(addsuffix .o, $(basename $(wildcard klib/*.c))) +#LIBOBJS:=$(addprefix klib/, $(LIBOBJS)) + +#PATH:=/home/nw/src/kernel/cc/sysroot/bin:$(PATH) +#export PATH + +CC=clang -target amd64-elf-zos +LD=ld +OBJCOPY=objcopy + +ifeq ($(OS),Darwin) +# CC=/opt/local/libexec/llvm-3.9/bin/clang + LD=x86_64-elf-ld + AR=x86_64-elf-ar + OBJCOPY=x86_64-elf-objcopy +endif + +zos: zos64 + $(OBJCOPY) $< -O elf32-i386 $@ + +usermode.o: usermode.c + $(CC) $(CFLAGS) -fpic -c -o $@ $< + +include/errno.h: include/errno.in tools/mkerrno + tools/mkerrno $< > $@ + +libklib.a: CFLAGS+=-D_PDCLIB_restrict=restrict +libklib.a: $(LIBOBJS) + $(AR) rcu $@ $(LIBOBJS) + +vfs/vfs.o: vfs/vfs.c vfs/vfs.h | include/errno.h +vfs/pipes.o: vfs/pipes.c vfs/vfs.h | include/errno.h + +libvfs.a: vfs/pipes.o vfs/vfs.o + $(AR) rcu $@ $+ + +pci/func.o: pci/func.c + +libpci.a: pci/pci.o pci/func.o + $(AR) rcu $@ $+ + +pic.o: pic.h interrupt.h + +zos64: libklib.a +zos64: link64.ld + +KOBJS= boot32.o bootz.o kernel.o interrupt.o idt.o \ + pic.o ioport.o timer.o tty.o mem.o \ + memx64.o spinlock.o process.o taskx64.o kbd.o \ + cpu.o syscalls.o smp.o \ + usermain.o +KLIBS=libpci.a libklib.a + +zos64: $(KOBJS) $(KLIBS) link64.ld + $(LD) $(LDFLAGS) -z max-page-size=0x1000 -nostdlib $(KOBJS) $(KLIBS) -o $@ + +zemu: zos + #qemu-system-x86_64 -d in_asm,op -m 512M -kernel $< -vnc :0 + qemu-system-x86_64 -monitor stdio -m 256MB -kernel $< -vnc :0 -append 'mboot hb' \ + -drive file=rdisk.img,if=none,id=mydisk \ + -device ich9-ahci,id=ahci \ + -device ide-drive,drive=mydisk,bus=ahci.0 + #-device ide-hd,drive=mydisk +cemu: zos + #qemu-system-x86_64 -d in_asm,op -m 512M -kernel $< -vnc :0 + qemu-system-x86_64 -monitor stdio -m 256MB -kernel $< -display curses -append 'mboot hb' \ + -drive file=rdisk.img,if=none,id=mydisk \ + -device ich9-ahci,id=ahci \ + -device ide-drive,drive=mydisk,bus=ahci.0 + #-device ide-hd,drive=mydisk + +rdisk.img: + qemu-img create -f qcow2 $@ 1G + +mem.o: mem.c mem.h multiboot.h +interrupt.o: interrupt.c interrupt.h +process.o: process.c process.h + +# -initrd TODO +memu: zos rdisk.img + #qemu-system-x86_64 -d in_asm,op -m 512M -kernel $< -vnc :0 + qemu-system-x86_64 $(SMP) -d cpu_reset -monitor stdio -m 256MB \ + -kernel $< -append 'mboot hb' \ + -drive file=rdisk.img,if=none,id=mydisk \ + -device ich9-ahci,id=ahci \ + -device ide-drive,drive=mydisk,bus=ahci.0 + #-device ide-hd,drive=mydisk + +cemu2: zos + qemu-system-x86_64 -display curses -m 512M -kernel $< -append 'mboot hb' + +kernel.o: kernel.c multiboot.h + $(CC) $(CFLAGS) -o $@ -c $< + +clean: + rm -f *.o *.a zos64 zos klib/*.o vfs/*.o pci/*.o ahci/*.o + +%.o%.s: + $(AS) -o $@ $< + +%.o%.c: + $(CC) $(CFLAGS) -c -o $@ $< + +tprintk.o: printk.c + cc -Wall -Wno-parentheses -I. -c -o $@ $+ + +test: t/t_printk tprintk.o + t/t_printk + +t/t_printk.o: t/t_printk.c + cc -Wall -I. -c -o $@ $+ + +t/t_printk: tprintk.o t/t_printk.o + cc -Wall -o $@ $+ + +%.d%.o: + $(DIS) $< diff --git a/klib/bitops.s b/klib/bitops.s new file mode 100644 index 0000000..2771bcb --- /dev/null +++ b/klib/bitops.s @@ -0,0 +1,10 @@ +; round up to a power of two +logtwoup: + xor eax, eax + bsr rsi, rdi ; rsi has the log 2 rounded down + bts rax, rsi + cmp rax, rdi + jz .done + shr rax, 1 +.done: + ret diff --git a/klib/memcpy.c b/klib/memcpy.c new file mode 100644 index 0000000..fc5e053 --- /dev/null +++ b/klib/memcpy.c @@ -0,0 +1,10 @@ +#include + +void *memcpy(void *restrict s1, const void *restrict s2, size_t n) { + char *dest = (char *)s1; + const char *src = (const char *)s2; + while (n--) { + *dest++ = *src++; + } + return s1; +} diff --git a/klib/memmove.c b/klib/memmove.c new file mode 100644 index 0000000..b372945 --- /dev/null +++ b/klib/memmove.c @@ -0,0 +1,18 @@ +#include + +void *memmove(void *s1, const void *s2, size_t n) { + char *dest = (char *)s1; + const char *src = (const char *)s2; + if (dest <= src) { + while (n--) { + *dest++ = *src++; + } + } else { + src += n; + dest += n; + while (n--) { + *--dest = *--src; + } + } + return s1; +} diff --git a/klib/memset.c b/klib/memset.c new file mode 100644 index 0000000..afa52a7 --- /dev/null +++ b/klib/memset.c @@ -0,0 +1,11 @@ +#include + +void *memset(void *s, int c, size_t n) { + unsigned char *p = (unsigned char *)s; + + while (n--) { + *p++ = (unsigned char)c; + } + + return s; +} diff --git a/klib/objlist.c b/klib/objlist.c new file mode 100644 index 0000000..ce3bd0d --- /dev/null +++ b/klib/objlist.c @@ -0,0 +1,52 @@ +#include "objlist.h" + +#include "mem.h" + +/* + * how to have an empty list + */ +struct kobj_list *list_init() { + struct kobj_list *list; + list = koalloc(sizeof *list); + list->next = 0; + list->prev = 0; + list->flags = 0; + return list; +} + +/* add an object pointer to the end of the list */ +void list_push(struct kobj_list *list, void *obj) { + +} + +void *list_pop(struct kobj_list *list, void *obj) { + return 0; +} + +void *list_shift(struct kobj_list *list, void *obj) { + return 0; +} + +void list_unshift(struct kobj_list *list, void *obj) { +} + +void list_free(struct kobj_list *list, void *obj) { +} + +#if 0 +for (cur = list; cur != list; cur = cur->next) { + +} +#endif +void *list_elem(struct kobj_list *list, uint64_t elem) { + return 0; +#if 0 + if (elem > list->elements) return 0; + + while (elem > KOLIST_MAX_INDEX) { + list = list->next; + elem -= KOLIST_MAX_INDEX+1; + } + return list->obj[elem]; +#endif +} diff --git a/klib/objlist.h b/klib/objlist.h new file mode 100644 index 0000000..dacfad4 --- /dev/null +++ b/klib/objlist.h @@ -0,0 +1,17 @@ +#ifndef KERNEL_DS_H_ +#define KERNEL_DS_H_ 1 + +#include + +#define KOLIST_MAX_INDEX 507 +/* an empty list has next and prev pointers null */ +/* or, use one as a sentinel? could store an object count in the flags then */ +struct kobj_list { + struct kobj_list *next; + struct kobj_list *prev; + void *obj; /* a pointer to where a new object would go */ + /* we've got room for 32 bytes, might as well have some flags */ + uint64_t flags; +}; + +#endif diff --git a/klib/printk.c b/klib/printk.c new file mode 100644 index 0000000..5df47ab --- /dev/null +++ b/klib/printk.c @@ -0,0 +1,359 @@ +/* adapted from http://www.efgh.com/software/gprintf.htm */ +/* public domain */ + +#include +#include +#include + +#include "kernel.h" +#include "tty.h" + +#define BITS_PER_BYTE 8 + +#define F_THOUSANDS 0x1 +#define F_LEFTJUSTIFY 0x2 +#define F_USESIGN 0x4 +#define F_SPACE 0x8 +#define F_ALTERNATE 0x10 +#define F_ZEROPAD 0x20 +#define F_CAPITAL 0x40 +/* F_PRECISION set if precision specified in format */ +#define F_PRECISION 0x80 + +#if 0 +static unsigned char digits[17] = "01234567890abcdef"; +static unsigned char capdigits[17] = "01234567890ABCDEF"; +#endif + +struct parameters { + int n; /* number of output chars */ + unsigned flags; + int width; + int precision; + int modifier; + + short len; + int (*output_function)(void *, int); + void *output_pointer; + char *str; + char buf[BITS_PER_BYTE * sizeof(uintmax_t) + 1]; +}; + +static int strlenk(char *s) { + int len = 0; + while (*s++) { + len++; + } + return len; +} + +static void output(struct parameters *p, char *s) { + int justify = p->width - p->len; + char jc = ' '; + + if (justify < 0) { + justify = 0; + } + + if (justify && p->flags & F_ZEROPAD) { + jc = '0'; + } + + if (justify && !(p->flags & F_LEFTJUSTIFY)) { + while (justify--) { + terminal.putchar(jc); + p->n++; + } + } + + while (p->len--) { + terminal.putchar(*s++); + p->n++; + } + + while (justify-- > 0) { + terminal.putchar(' '); + p->n++; + } +} + +static inline int get_decimal(const char *str, int *val) { + int ans = 0; + int used = 0; + int neg = 0; + char digit; + + if (*str == '-') { + str++; + neg = 1; + used++; + } + + while (digit = *str++) { + if (digit >= '0' && digit <= '9') { + ans *= 10; + ans += (digit - '0'); + used++; + } else { + break; + } + } + if (neg) { + ans = -ans; + } + *val = ans; + return used; +} + +int printk(const char *fmt, ...) { + va_list ap; + int n; + va_start(ap, fmt); + n = printkv(fmt, ap); + va_end(ap); + return n; +} + +int printkv(const char *fmt, va_list ap) { + struct parameters p = { 0 }; + struct parameters z = { 0 }; + unsigned char fc; + int get_flags; + + while (fc = *fmt++) { + if (fc != '%') { + terminal.putchar(fc); + p.n++; + continue; + } + p = z; + + /* it's a conversion, get flags */ + get_flags = 1; + while (get_flags) { + fc = *fmt++; + switch (fc) { + case 0: + /* we're done */ + /* this is an error though */ + return p.n; + break; + case '#': + p.flags |= F_ALTERNATE; + break; + case '0': + p.flags |= F_ZEROPAD; + break; + case '-': + p.flags |= F_LEFTJUSTIFY; + break; + case ' ': + p.flags |= F_SPACE; + break; + case '+': + p.flags |= F_USESIGN; + break; + /* posix, not C, so maybe need a define */ + case '.': + p.flags |= F_THOUSANDS; + break; + default: + fmt--; + get_flags = 0; + break; + } + } + + /* get minimum field width */ + if (fc >= '1' && fc <= '9') { + fmt += get_decimal(fmt, &p.width); + } else if (*fmt == '*') { + fmt++; + if (*fmt >= '1' && *fmt <= '9') { + int lenarg = 0; + fmt += get_decimal(fmt, &lenarg); + if (*fmt != '$') { + /* TODO ERROR */ + } + fmt++; /* skip past the $ */ + } else { + p.width = va_arg(ap, int); + if (p.width < 0) { + p.width = -p.width; + p.flags |= F_LEFTJUSTIFY; + } + } + } + + /* get precision */ + if (*fmt == '.') { + fmt++; + p.precision = 0; + p.flags |= F_PRECISION; + + if (fc >= '0' && fc <= '9') { + fmt += get_decimal(fmt, &p.width); + } else if (*fmt == '*') { + fmt++; + if (*fmt >= '1' && *fmt <= '9') { + int arg = 0; + fmt += get_decimal(fmt, &arg); + if (*fmt != '$') { + /* TODO ERROR */ + } + fmt++; /* skip past the $ */ + } else { + p.precision = va_arg(ap, int); + if (p.precision < 0) { + p.precision = 0; + p.flags &= ~F_PRECISION; + } + } + } + } + + /* get length modifier */ + switch (*fmt) { + case 'L': + case 'j': + case 'z': + case 't': + p.modifier = *fmt++; + break; + case 'h': + p.modifier = *fmt++; + if (*fmt == 'h') { + fmt++; + p.modifier = 'H'; + } + break; + case 'l': + p.modifier = *fmt++; + if (*fmt == 'l') { + fmt++; + p.modifier = 'L'; + } + break; + default: + break; + } + + /* conversion specifier */ + int base = 2; + uintmax_t i; + union { + uintmax_t uim; + int i; + char c; + unsigned u; + unsigned char uc; + unsigned short us; + unsigned long ul; + unsigned long long ull; + size_t size; + ptrdiff_t pd; + } arg; + + switch (*fmt) { + case '%': + terminal.putchar('%'); + p.n++; + fmt++; + break; + case 'c': + if (p.modifier == 'l') { + /* wide int wint_t */ + break; + } + arg.i = va_arg(ap, int); + p.buf[0] = (unsigned char) arg.i; + p.len = 1; + output(&p, p.buf); + fmt++; + break; + case 's': + p.str = va_arg(ap, char *); + /* TODO may not be properly terminated if precision is given */ + p.len = strlenk(p.str); + /* precision, if given, is maximum characters + * for an 's' conversion */ + if (p.flags & F_PRECISION && p.len > p.precision) { + p.len = p.precision; + } + /* TODO don't zero pad strings */ + output(&p, p.str); + fmt++; + break; + case 'X': + p.flags |= F_CAPITAL; + case 'x': + base += 6; + case 'u': + base += 2; + case 'o': + base += 6; + switch (p.modifier) { + case 'H': + arg.u = va_arg(ap, unsigned int); + i = (uintmax_t) (unsigned char) arg.uc; + break; + case 'h': + arg.u = va_arg(ap, unsigned int); + i = (uintmax_t) (unsigned short) arg.us; + break; + case 'l': + arg.ul = va_arg(ap, unsigned long); + i = (uintmax_t) arg.ul; + break; + case 'L': + arg.ull = va_arg(ap, unsigned long long); + i = (uintmax_t) arg.ull; + break; + case 'j': + i = va_arg(ap, uintmax_t); + break; + case 'z': + arg.size = va_arg(ap, size_t); + i = (uintmax_t) arg.size; + break; + case 't': + arg.pd = va_arg(ap, ptrdiff_t); + i = (uintmax_t) arg.pd; + break; + default: + arg.u = va_arg(ap, unsigned); + i = (uintmax_t) arg.u; + break; + } + p.str = p.buf + sizeof(p.buf) - 1; + *p.str = 0; + p.str--; + do { + int c; + c = i % base + '0'; + if (c > '9') { + if (p.flags & F_CAPITAL) + c += 'A'-'9'-1; + else + c += 'a'-'9'-1; + } + *p.str-- = c; + p.len++; + } while ( i /= base); + output(&p, p.str+1); + fmt++; + break; + case 'd': + case 'i': + base = 10; + + default: + break; + } + /* output number here ? */ + + } + terminal.update_cursor(); + + return p.n; +} diff --git a/klib/printk.h b/klib/printk.h new file mode 100644 index 0000000..436dbf9 --- /dev/null +++ b/klib/printk.h @@ -0,0 +1,9 @@ +#ifndef PRINTK_H_ +#define PRINTK_H_ + +#include + +void terminal_putchar(int ch); +int printk(const char *fmt, ...); + +#endif diff --git a/klib/strcat.c b/klib/strcat.c new file mode 100644 index 0000000..33e2648 --- /dev/null +++ b/klib/strcat.c @@ -0,0 +1,10 @@ +#include + +char *strcat(char *s1, const char *s2) { + char *rc = s1; + if (*s1) { + while(*++s1); + } + while ( (*s1++ = *s2++) ); + return rc; +} diff --git a/klib/strcmp.c b/klib/strcmp.c new file mode 100644 index 0000000..6d46c95 --- /dev/null +++ b/klib/strcmp.c @@ -0,0 +1,9 @@ +#include + +int strcmp(const char *s1, const char *s2) { + while ( *s1 && (*s1 == *s2) ) { + ++s1; + ++s2; + } + return *(unsigned char *)s1 - *(unsigned char *)s2; +} diff --git a/klib/strcpy.c b/klib/strcpy.c new file mode 100644 index 0000000..75d9d85 --- /dev/null +++ b/klib/strcpy.c @@ -0,0 +1,7 @@ +#include + +char *strcpy(char *s1, const char *s2) { + char *rc = s1; + while ( ( *s1++ = *s2++ ) ); + return rc; +} diff --git a/klib/strcspn.c b/klib/strcspn.c new file mode 100644 index 0000000..8970175 --- /dev/null +++ b/klib/strcspn.c @@ -0,0 +1,17 @@ +#include + +size_t strcspn(const char *s1, const char *s2) { + size_t len = 0; + const char *p; + + while (s1[len]) { + p = s2; + while (*p) { + if (s1[len] == *p++) { + return len; + } + } + ++len; + } + return len; +} diff --git a/klib/strdup.c b/klib/strdup.c new file mode 100644 index 0000000..b921b85 --- /dev/null +++ b/klib/strdup.c @@ -0,0 +1,15 @@ +#include +#include + +char *strdup(const char *s) { + char *ns = NULL; + size_t len; + + if (s) { + len = strlen(s) + 1; + ns = malloc(len); + if (ns) + strncpy(ns, s, len); + } + return ns; +} diff --git a/klib/string.h b/klib/string.h new file mode 100644 index 0000000..3b01407 --- /dev/null +++ b/klib/string.h @@ -0,0 +1,43 @@ +#ifndef _STRING_H +#define _STRING_H + +#include + +void *memccpy(void *, const void *, int, size_t); +void *memchr(const void *, int, size_t); +void *memrchr(const void *, int, size_t); +int memcmp(const void *, const void *, size_t); +void *memcpy(void *, const void *, size_t); +void *memmove(void *, const void *, size_t); +void *memset(void *, int, size_t); +void *memmem(const void *, size_t, const void *, size_t); +void memswap(void *, void *, size_t); +void bzero(void *, size_t); +int strcasecmp(const char *, const char *); +int strncasecmp(const char *, const char *, size_t); +char *strcat(char *, const char *); +char *strchr(const char *, int); +char *index(const char *, int); +char *strrchr(const char *, int); +char *rindex(const char *, int); +int strcmp(const char *, const char *); +char *strcpy(char *, const char *); +size_t strcspn(const char *, const char *); +char *strdup(const char *); +char *strndup(const char *, size_t); +char *strerror(int); +char *strsignal(int); +size_t strlen(const char *); +size_t strnlen(const char *, size_t); +char *strncat(char *, const char *, size_t); +size_t strlcat(char *, const char *, size_t); +int strncmp(const char *, const char *, size_t); +char *strncpy(char *, const char *, size_t); +size_t strlcpy(char *, const char *, size_t); +char *strpbrk(const char *, const char *); +size_t strspn(const char *, const char *); +char *strstr(const char *, const char *); +char *strtok(char *, const char *); +char *strtok_r(char *, const char *, char **); + +#endif diff --git a/klib/strlen.c b/klib/strlen.c new file mode 100644 index 0000000..861f843 --- /dev/null +++ b/klib/strlen.c @@ -0,0 +1,11 @@ +#include + +size_t strlen(const char *s) { + size_t rc = 0; + + while (s[rc]) { + ++rc; + } + + return rc; +} diff --git a/klib/strncpy.c b/klib/strncpy.c new file mode 100644 index 0000000..e674420 --- /dev/null +++ b/klib/strncpy.c @@ -0,0 +1,17 @@ +#include + +char *strncpy(char *s1, const char *s2, size_t n) { + char * rc = s1; + while ( (n > 0) && (*s1++ = *s2++) ) { + /* Cannot do "n--" in the conditional as size_t is unsigned and we have + * to check it again for >0 in the next loop below, so we must not risk + * underflow. + */ + --n; + } + /* Checking against 1 as we missed the last --n in the loop above. */ + while (n-- > 1) { + *s1++ = '\0'; + } + return rc; +} diff --git a/klib/strtok.c b/klib/strtok.c new file mode 100644 index 0000000..d3595a3 --- /dev/null +++ b/klib/strtok.c @@ -0,0 +1,52 @@ +#include + +char *strtok(char *s1, const char *s2) { + static char *tmp = NULL; + const char *p = s2; + + if (s1 != NULL) { + /* new string */ + tmp = s1; + } else { + /* old string continued */ + if (tmp == NULL) { + /* No old string, no new string, nothing to do */ + return NULL; + } + s1 = tmp; + } + + /* skipping leading s2 characters */ + while (*p && *s1) { + if ( *s1 == *p ) { + /* found seperator; skip and start over */ + ++s1; + p = s2; + continue; + } + ++p; + } + + if (!*s1) { + /* no more to parse */ + return ( tmp = NULL ); + } + + /* skipping non-s2 characters */ + tmp = s1; + while (*tmp) { + p = s2; + while (*p) { + if (*tmp == *p++) { + /* found seperator; overwrite with '\0', position tmp, return */ + *tmp++ = '\0'; + return s1; + } + } + ++tmp; + } + + /* parsed to end of string */ + tmp = NULL; + return s1; +} -- 2.40.0