--- /dev/null
+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) $<
--- /dev/null
+; 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
--- /dev/null
+#include <string.h>
+
+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;
+}
--- /dev/null
+#include <string.h>
+
+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;
+}
--- /dev/null
+#include <string.h>
+
+void *memset(void *s, int c, size_t n) {
+ unsigned char *p = (unsigned char *)s;
+
+ while (n--) {
+ *p++ = (unsigned char)c;
+ }
+
+ return s;
+}
--- /dev/null
+#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
+}
--- /dev/null
+#ifndef KERNEL_DS_H_
+#define KERNEL_DS_H_ 1
+
+#include <stdint.h>
+
+#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
--- /dev/null
+/* adapted from http://www.efgh.com/software/gprintf.htm */
+/* public domain */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#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;
+}
--- /dev/null
+#ifndef PRINTK_H_
+#define PRINTK_H_
+
+#include <stdint.h>
+
+void terminal_putchar(int ch);
+int printk(const char *fmt, ...);
+
+#endif
--- /dev/null
+#include <string.h>
+
+char *strcat(char *s1, const char *s2) {
+ char *rc = s1;
+ if (*s1) {
+ while(*++s1);
+ }
+ while ( (*s1++ = *s2++) );
+ return rc;
+}
--- /dev/null
+#include <string.h>
+
+int strcmp(const char *s1, const char *s2) {
+ while ( *s1 && (*s1 == *s2) ) {
+ ++s1;
+ ++s2;
+ }
+ return *(unsigned char *)s1 - *(unsigned char *)s2;
+}
--- /dev/null
+#include <string.h>
+
+char *strcpy(char *s1, const char *s2) {
+ char *rc = s1;
+ while ( ( *s1++ = *s2++ ) );
+ return rc;
+}
--- /dev/null
+#include <string.h>
+
+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;
+}
--- /dev/null
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+char *strdup(const char *s) {\r
+ char *ns = NULL;\r
+ size_t len;\r
+\r
+ if (s) {\r
+ len = strlen(s) + 1;\r
+ ns = malloc(len);\r
+ if (ns)\r
+ strncpy(ns, s, len);\r
+ }\r
+ return ns;\r
+}\r
--- /dev/null
+#ifndef _STRING_H
+#define _STRING_H
+
+#include <stddef.h>
+
+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
--- /dev/null
+#include <string.h>
+
+size_t strlen(const char *s) {
+ size_t rc = 0;
+
+ while (s[rc]) {
+ ++rc;
+ }
+
+ return rc;
+}
--- /dev/null
+#include <string.h>
+
+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;
+}
--- /dev/null
+#include <string.h>
+
+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;
+}