From 35f72ac032922022d09bca1c35c79b169ff6666e Mon Sep 17 00:00:00 2001 From: Rhett Date: Sun, 1 Jul 2012 16:39:35 -0700 Subject: [PATCH] Moved from Google Code to github --- COPYRIGHT | 17 + GNUmakefile | 85 ++++ README.md | 4 - arcanos.kdev4 | 3 + boot/pad | Bin 0 -> 408 bytes boot/post_pad | Bin 0 -> 4919483 bytes boot/stage1 | Bin 0 -> 512 bytes boot/stage2 | Bin 0 -> 121960 bytes gpl-3.0.txt | 674 +++++++++++++++++++++++++++ inc/COPYRIGHT | 121 +++++ inc/console.h | 21 + inc/elf.h | 65 +++ inc/idt.h | 31 ++ inc/info.h | 8 + inc/memlayout.h | 36 ++ inc/memmgr.h | 36 ++ inc/mmu.h | 259 ++++++++++ inc/multiboot.h | 225 +++++++++ inc/pic.h | 33 ++ inc/stdarg.h | 19 + inc/string.h | 9 + inc/stringformat.h | 21 + inc/types.h | 72 +++ inc/x86.h | 283 +++++++++++ kern/COPYRIGHT | 41 ++ kern/Makefrag | 66 +++ kern/boot.S | 30 ++ kern/console.c | 116 +++++ kern/entry.S | 126 +++++ kern/init.c | 148 ++++++ kern/interrupts/COPYRIGHT | 2 + kern/interrupts/idt.c | 73 +++ kern/interrupts/interrupt_handlers.c | 90 ++++ kern/interrupts/interrupts.S | 194 ++++++++ kern/interrupts/pic.c | 85 ++++ kern/kernel.ld | 84 ++++ kern/layout_image_file.py | 31 ++ kern/memmgr.c | 460 ++++++++++++++++++ kern/stringformat.c | 125 +++++ lib/string.c | 226 +++++++++ 40 files changed, 3915 insertions(+), 4 deletions(-) create mode 100644 COPYRIGHT create mode 100644 GNUmakefile delete mode 100644 README.md create mode 100644 arcanos.kdev4 create mode 100644 boot/pad create mode 100644 boot/post_pad create mode 100644 boot/stage1 create mode 100644 boot/stage2 create mode 100644 gpl-3.0.txt create mode 100644 inc/COPYRIGHT create mode 100644 inc/console.h create mode 100644 inc/elf.h create mode 100644 inc/idt.h create mode 100644 inc/info.h create mode 100644 inc/memlayout.h create mode 100644 inc/memmgr.h create mode 100644 inc/mmu.h create mode 100644 inc/multiboot.h create mode 100644 inc/pic.h create mode 100644 inc/stdarg.h create mode 100644 inc/string.h create mode 100644 inc/stringformat.h create mode 100644 inc/types.h create mode 100644 inc/x86.h create mode 100644 kern/COPYRIGHT create mode 100644 kern/Makefrag create mode 100644 kern/boot.S create mode 100644 kern/console.c create mode 100644 kern/entry.S create mode 100644 kern/init.c create mode 100644 kern/interrupts/COPYRIGHT create mode 100644 kern/interrupts/idt.c create mode 100644 kern/interrupts/interrupt_handlers.c create mode 100644 kern/interrupts/interrupts.S create mode 100644 kern/interrupts/pic.c create mode 100644 kern/kernel.ld create mode 100755 kern/layout_image_file.py create mode 100644 kern/memmgr.c create mode 100644 kern/stringformat.c create mode 100644 lib/string.c diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..26ff21e --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,17 @@ +A considerable portion of the initial check-in of ArcanOS is based directly +off the operating systems coursework labs of Dr. Lorenzo Alvisi +(http://userweb.cs.utexas.edu/~lorenzo/), and I owe him a debt of gratitude for +producing and distributing material to help bridge the gap between a simple +"Hello World" bootloader and a functioning kernel. I believe Dr. Alvisi has +released his code under an MIT license, which is GPL compatible. + +Some materials from the initial drop contain header files documented as under +a BSD license which may not be fully GPL-compatible. Since the conflicting +clause under this license is related to advertising of products, I believe +that a hobby project such as ArcanOS will not produce any conflict. I am +endeavoring to locate more GPL-compatible source for these files. + +Concerned parties should contact me at roadriverrail@gmail.com + +Unless explicity specified otherwise, materials in this project are copyright +J. Rhett Aultman (c) 2010 and are released under the terms of the GPL v3. diff --git a/GNUmakefile b/GNUmakefile new file mode 100644 index 0000000..52150b7 --- /dev/null +++ b/GNUmakefile @@ -0,0 +1,85 @@ +# +# This makefile system follows the structuring conventions +# recommended by Peter Miller in his excellent paper: +# +# Recursive Make Considered Harmful +# http://aegis.sourceforge.net/auug97.pdf +# +OBJDIR := obj + +TOP = . + +# Cross-compiler jos toolchain +# +# This Makefile will automatically use the cross-compiler toolchain +# installed as 'i386-jos-elf-*', if one exists. If the host tools ('gcc', +# 'objdump', and so forth) compile for a 32-bit x86 ELF target, that will +# be detected as well. If you have the right compiler toolchain installed +# using a different name, set GCCPREFIX explicitly in conf/env.mk + +# try to infer the correct GCCPREFIX +ifndef GCCPREFIX +GCCPREFIX := $(shell if objdump -i 2>&1 | grep 'elf32-i386' >/dev/null 2>&1; \ + then echo ''; \ + else echo "***" 1>&2; \ + echo "*** Error: Couldn't find an i386-*-elf version of GCC/binutils." 1>&2; \ + echo "*** Is the directory with i386-*-elf-gcc in your PATH?" 1>&2; \ + echo "***" 1>&2; exit 1; fi) +endif + +CC := $(GCCPREFIX)gcc -pipe +GCC_LIB := $(shell $(CC) -print-libgcc-file-name) +AS := $(GCCPREFIX)as +AR := $(GCCPREFIX)ar +LD := $(GCCPREFIX)ld +OBJCOPY := $(GCCPREFIX)objcopy +OBJDUMP := $(GCCPREFIX)objdump +NM := $(GCCPREFIX)nm + +# Native commands +NCC := gcc $(CC_VER) -pipe +TAR := gtar +PERL := perl + +# Compiler flags +# -fno-builtin is required to avoid refs to undefined functions in the kernel. +# Only optimize to -O1 to discourage inlining, which complicates backtraces. +CFLAGS := $(CFLAGS) $(DEFS) $(LABDEFS) -O -fno-builtin -I$(TOP) -MD -Wall -Wno-format -Wno-unused -Werror -gstabs -fno-stack-protector + +# Lists that the */Makefrag makefile fragments will add to +OBJDIRS := + +# Make sure that 'all' is the first target +all: + +# Eliminate default suffix rules +.SUFFIXES: + +# Delete target files if there is an error (or make is interrupted) +.DELETE_ON_ERROR: + +# make it so that no intermediate .o files are ever deleted +.PRECIOUS: %.o $(OBJDIR)/boot/%.o $(OBJDIR)/kern/%.o \ + $(OBJDIR)/lib/%.o $(OBJDIR)/fs/%.o $(OBJDIR)/user/%.o + +KERN_CFLAGS := $(CFLAGS) -DARCANOS_KERNEL -gstabs +USER_CFLAGS := $(CFLAGS) -DARCANOS_USER -gstabs + + + + +# Include Makefrags for subdirectories +include kern/Makefrag + + +IMAGES = $(OBJDIR)/kern/bochs.img + +# For deleting the build +clean: + rm -rf $(OBJDIR) + +always: + @: + +.PHONY: all always \ + clean diff --git a/README.md b/README.md deleted file mode 100644 index be3ac9a..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -arcanos -======= - -A hobby/vanity operating system \ No newline at end of file diff --git a/arcanos.kdev4 b/arcanos.kdev4 new file mode 100644 index 0000000..875be81 --- /dev/null +++ b/arcanos.kdev4 @@ -0,0 +1,3 @@ +[Project] +Manager=KDevCustomMakeManager +Name=arcanos diff --git a/boot/pad b/boot/pad new file mode 100644 index 0000000000000000000000000000000000000000..7a3d28a869767bff812abbdade509f6283b9f1a6 GIT binary patch literal 408 NcmZQz7zKkd1ONe;00961 literal 0 HcmV?d00001 diff --git a/boot/post_pad b/boot/post_pad new file mode 100644 index 0000000000000000000000000000000000000000..1ccbecfb2359deae890630b476825b5c1275fd62 GIT binary patch literal 4919483 zcmeFtfdBvi0Dz$VsTV1P3IhfV7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjxE(r>0RR91802q#kFO9i zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK zfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5 zV8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM z7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b* z1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA Lz<>b*1_lEG6(9fs literal 0 HcmV?d00001 diff --git a/boot/stage1 b/boot/stage1 new file mode 100644 index 0000000000000000000000000000000000000000..b5ed85dece20c410412fb5e27cef48a85baf04e3 GIT binary patch literal 512 zcmaFuF@b@6z|8cYfuVsBWB|vn*X-X8HIy=KYIqe{!@yv8pzlWCg*^-kzZW>v*!(YH z>NpexlrIU{;<$TN=vm>Ypd!!4-=V8YofkOPv>Yg9ZGOmDVxHFRBe0LP=9tTW#3z-I%7DFyRb17q!}LQbYV&Bbm7_JbXK^CbvHx7>)I_GXN8NofX4H; zd|-Il%K$Ng0jRd)g9A`4i{Yh?QwJY0b-d{K;?U{B0TjP*;004!CrjEwmzp%gOKIOt zIzqU>j1rcP5N@FH)-D{iHeDgS2OhC?`EdO^$Z@eNhbOA5gd1pM-(kbsI~bXO_G|SV z?ql<)Ns!ygz}R=&@SEZPKcAP%C;nG+s@Ydr`@)LhHQ&Cv+80I)ui5r>)V|PS*w{a-%# J2QxHu6#!Glvcv!Y literal 0 HcmV?d00001 diff --git a/boot/stage2 b/boot/stage2 new file mode 100644 index 0000000000000000000000000000000000000000..58a481949962083d68e93c58738dd3916891e85e GIT binary patch literal 121960 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

&AQT64vc=%_( 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 literal 0 HcmV?d00001 diff --git a/gpl-3.0.txt b/gpl-3.0.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/gpl-3.0.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/inc/COPYRIGHT b/inc/COPYRIGHT new file mode 100644 index 0000000..a2146cf --- /dev/null +++ b/inc/COPYRIGHT @@ -0,0 +1,121 @@ +The files in this directory are: + +elf.h, memlayout.h, mmu.h, and x86.h are: + + +/* + * Copyright (C) 1997 Massachusetts Institute of Technology + * + * This software is being provided by the copyright holders under the + * following license. By obtaining, using and/or copying this software, + * you agree that you have read, understood, and will comply with the + * following terms and conditions: + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose and without fee or royalty is + * hereby granted, provided that the full text of this NOTICE appears on + * ALL copies of the software and documentation or portions thereof, + * including modifications, that you make. + * + * THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO + * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, + * BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR + * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR + * THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY + * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT + * HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR + * DOCUMENTATION. + * + * The name and trademarks of copyright holders may NOT be used in + * advertising or publicity pertaining to the software without specific, + * written prior permission. Title to copyright in this software and any + * associated documentation will at all times remain with copyright + * holders. See the file AUTHORS which should have accompanied this software + * for a list of all copyright holders. + * + * This file may be derived from previously copyrighted software. This + * copyright applies only to those changes made by the copyright + * holders listed in the AUTHORS file. The rest of this file is covered by + * the copyright notices, if any, listed below. + */ + + +stdarg.h is: + +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)stdarg.h 8.1 (Berkeley) 6/10/93 + */ + +types.h is: + +/*- + * Copyright (c) 1982, 1986, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.4 (Berkeley) 1/21/94 + */ + diff --git a/inc/console.h b/inc/console.h new file mode 100644 index 0000000..2b49ab7 --- /dev/null +++ b/inc/console.h @@ -0,0 +1,21 @@ +#include + +void blank_screen(); + +void buffer_to_screen(); + +void console_init(); + +void printchar(char c); + +void next_line(); + +void update_cursor(); +int8_t move_to (uint8_t x, uint8_t y); + + +void print_string_helper(char* string); + +void print_string(char* string); + +void print_line(char* string); diff --git a/inc/elf.h b/inc/elf.h new file mode 100644 index 0000000..66add42 --- /dev/null +++ b/inc/elf.h @@ -0,0 +1,65 @@ +#ifndef ARCANOS_INC_ELF_H +#define ARCANOS_INC_ELF_H + +#define ELF_MAGIC 0x464C457FU /* "\x7FELF" in little endian */ + +struct Elf { + uint32_t e_magic; // must equal ELF_MAGIC + uint8_t e_elf[12]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + uint32_t e_phoff; + uint32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +}; + +struct Proghdr { + uint32_t p_type; + uint32_t p_offset; + uint32_t p_va; + uint32_t p_pa; + uint32_t p_filesz; + uint32_t p_memsz; + uint32_t p_flags; + uint32_t p_align; +}; + +struct Secthdr { + uint32_t sh_name; + uint32_t sh_type; + uint32_t sh_flags; + uint32_t sh_addr; + uint32_t sh_offset; + uint32_t sh_size; + uint32_t sh_link; + uint32_t sh_info; + uint32_t sh_addralign; + uint32_t sh_entsize; +}; + +// Values for Proghdr::p_type +#define ELF_PROG_LOAD 1 + +// Flag bits for Proghdr::p_flags +#define ELF_PROG_FLAG_EXEC 1 +#define ELF_PROG_FLAG_WRITE 2 +#define ELF_PROG_FLAG_READ 4 + +// Values for Secthdr::sh_type +#define ELF_SHT_NULL 0 +#define ELF_SHT_PROGBITS 1 +#define ELF_SHT_SYMTAB 2 +#define ELF_SHT_STRTAB 3 + +// Values for Secthdr::sh_name +#define ELF_SHN_UNDEF 0 + +#endif /* !ARCANOS_INC_ELF_H */ diff --git a/inc/idt.h b/inc/idt.h new file mode 100644 index 0000000..8ce5c51 --- /dev/null +++ b/inc/idt.h @@ -0,0 +1,31 @@ +#include +#include + +typedef struct _IDTDescr{ + uint16_t offset_1; // offset bits 0..15 + uint16_t selector; // a code segment selector in GDT or LDT + uint8_t zero; // unused, set to 0 + uint8_t type_attr; // type and attributes, see below + uint16_t offset_2; // offset bits 16..31 +}__attribute__((__packed__)) IDTDescr; + +typedef struct _IDT{ + uint16_t limit; + uint32_t base; +}__attribute__((__packed__)) IDT; + +IDTDescr idt[256]; +IDT idt_struct; +IDT* idtp; +IDT* phys_idtp; + +#define UNUSED_TYPE_ATTR 0x00 +#define INTERRUPT_GATE_TYPE_ATTR 0x8E +#define TRAP_GATE_TYPE_ATTR 0x8F + +#define HIGH_OFFSET(x) ((x >> 16)) +#define LOW_OFFSET(x) ((x & 0x0000FFFF)) + +void reset_idt(); +void set_idt_entry(uint8_t number, void (*handler)(), uint16_t type); +void load_idt(); diff --git a/inc/info.h b/inc/info.h new file mode 100644 index 0000000..727d894 --- /dev/null +++ b/inc/info.h @@ -0,0 +1,8 @@ +#ifndef ARCANOS_INC_INFO_H +#define ARCANOS_INC_INFO_H + +#include + +#define ARCANOS_VERSION "PRE-MAGUS" + +#endif diff --git a/inc/memlayout.h b/inc/memlayout.h new file mode 100644 index 0000000..487a934 --- /dev/null +++ b/inc/memlayout.h @@ -0,0 +1,36 @@ +#ifndef ARCANOS_INC_MEMLAYOUT_H +#define ARCANOS_INC_MEMLAYOUT_H + +#ifndef __ASSEMBLER__ +#include +//#include +#include +#endif /* not __ASSEMBLER__ */ + +/* + * This file contains definitions for memory management in our OS, + * which are relevant to both the kernel and user-mode software. + */ + +// Global descriptor numbers +#define GD_KT 0x08 // kernel text +#define GD_KD 0x10 // kernel data +#define GD_UT 0x18 // user text +#define GD_UD 0x20 // user data +#define GD_TSS 0x28 // Task segment selector + +// All physical memory mapped at this address +#define KERNBASE 0xC0000000 + +#define INITIAL_PDE 0x09D000 + +// At IOPHYSMEM (640K) there is a 384K hole for I/O. From the kernel, +// IOPHYSMEM can be addressed at KERNBASE + IOPHYSMEM. The hole ends +// at physical address EXTPHYSMEM. +#define IOPHYSMEM 0x0A0000 +#define EXTPHYSMEM 0x100000 + +#define KSTACKTOP VPT +#define KSTKSIZE (8*PGSIZE) // size of a kernel stack + +#endif /* !ARCANOS_INC_MEMLAYOUT_H */ diff --git a/inc/memmgr.h b/inc/memmgr.h new file mode 100644 index 0000000..3690700 --- /dev/null +++ b/inc/memmgr.h @@ -0,0 +1,36 @@ +#ifndef __ARCANOS_KERN_MEMMGR_H__ +#define __ARCANOS_KERN_MEMMGR_H__ + +#include + +#define PAGE_PRESENT 0x1 +#define PAGE_RW 0x2 +#define PAGE_USER 0x4 + +#define PAGE_SIZE 4096 + +//4GB / 4kb page size / 1 bit per page +#define PHYS_MEM_MAP_SIZE 131072 + +//Bitmap of memory. +uint8_t phys_mem_map [PHYS_MEM_MAP_SIZE]; + +typedef struct _kmemdesc { + void* data_ptr; + unsigned int size; + struct _kmemdesc* next; +} kmemdesc; + +void init_paging(); + +void frame_allocator_init(multiboot_info_t* mbi, uint32_t kernel_base, uint32_t kernel_end); +void mark_frame(uint32_t base, uint8_t status); +void* get_frame(); +void* get_page(); +void memmgr_init(); +void* memmgr_allocate(unsigned int size); +void memmgr_free(void* ptr); + +void map_page(void* physaddr, void* virtualaddr, unsigned int flags); + +#endif diff --git a/inc/mmu.h b/inc/mmu.h new file mode 100644 index 0000000..62ae3c4 --- /dev/null +++ b/inc/mmu.h @@ -0,0 +1,259 @@ +#ifndef ARCANOS_INC_MMU_H +#define ARCANOS_INC_MMU_H + +/* + * This file contains definitions for the x86 memory management unit (MMU), + * including paging- and segmentation-related data structures and constants, + * the %cr0, %cr4, and %eflags registers, and traps. + */ + +/* + * + * Part 1. Paging data structures and constants. + * + */ + +#ifndef __ASSEMBLER__ + +typedef uint32_t pdentry; +typedef uint32_t ptentry; + +#endif + +// A linear address 'la' has a three-part structure as follows: +// +// +--------10------+-------10-------+---------12----------+ +// | Page Directory | Page Table | Offset within Page | +// | Index | Index | | +// +----------------+----------------+---------------------+ +// \--- PDX(la) --/ \--- PTX(la) --/ \---- PGOFF(la) ----/ +// \----------- PPN(la) -----------/ +// +// The PDX, PTX, PGOFF, and PPN macros decompose linear addresses as shown. +// To construct a linear address la from PDX(la), PTX(la), and PGOFF(la), +// use PGADDR(PDX(la), PTX(la), PGOFF(la)). + +// page number field of address +#define PPN(la) (((uintptr_t) (la)) >> PTXSHIFT) +#define VPN(la) PPN(la) // used to index into vpt[] + +// page directory index +#define PDX(la) ((((uintptr_t) (la)) >> PDXSHIFT) & 0x3FF) +#define VPD(la) PDX(la) // used to index into vpd[] + +// page table index +#define PTX(la) ((((uintptr_t) (la)) >> PTXSHIFT) & 0x3FF) + +// offset in page +#define PGOFF(la) (((uintptr_t) (la)) & 0xFFF) + +// construct linear address from indexes and offset +#define PGADDR(d, t, o) ((void*) ((d) << PDXSHIFT | (t) << PTXSHIFT | (o))) + +// Page directory and page table constants. +#define NPDENTRIES 1024 // page directory entries per page directory +#define NPTENTRIES 1024 // page table entries per page table + +#define PGSIZE 4096 // bytes mapped by a page +#define PGSHIFT 12 // log2(PGSIZE) + +#define PTSIZE (PGSIZE*NPTENTRIES) // bytes mapped by a page directory entry +#define PTSHIFT 22 // log2(PTSIZE) + +#define PTXSHIFT 12 // offset of PTX in a linear address +#define PDXSHIFT 22 // offset of PDX in a linear address + +// Page table/directory entry flags. +#define PTE_P 0x001 // Present +#define PTE_W 0x002 // Writeable +#define PTE_U 0x004 // User +#define PTE_PWT 0x008 // Write-Through +#define PTE_PCD 0x010 // Cache-Disable +#define PTE_A 0x020 // Accessed +#define PTE_D 0x040 // Dirty +#define PTE_PS 0x080 // Page Size +#define PTE_MBZ 0x180 // Bits must be zero + +// The PTE_AVAIL bits aren't used by the kernel or interpreted by the +// hardware, so user processes are allowed to set them arbitrarily. +#define PTE_AVAIL 0xE00 // Available for software use + +// Only flags in PTE_USER may be used in system calls. +#define PTE_USER (PTE_AVAIL | PTE_P | PTE_W | PTE_U) + +// address in page table entry +#define PTE_ADDR(pte) ((physaddr_t) (pte) & ~0xFFF) + +// Control Register flags +#define CR0_PE 0x00000001 // Protection Enable +#define CR0_MP 0x00000002 // Monitor coProcessor +#define CR0_EM 0x00000004 // Emulation +#define CR0_TS 0x00000008 // Task Switched +#define CR0_ET 0x00000010 // Extension Type +#define CR0_NE 0x00000020 // Numeric Errror +#define CR0_WP 0x00010000 // Write Protect +#define CR0_AM 0x00040000 // Alignment Mask +#define CR0_NW 0x20000000 // Not Writethrough +#define CR0_CD 0x40000000 // Cache Disable +#define CR0_PG 0x80000000 // Paging + +#define CR4_PCE 0x00000100 // Performance counter enable +#define CR4_MCE 0x00000040 // Machine Check Enable +#define CR4_PSE 0x00000010 // Page Size Extensions +#define CR4_DE 0x00000008 // Debugging Extensions +#define CR4_TSD 0x00000004 // Time Stamp Disable +#define CR4_PVI 0x00000002 // Protected-Mode Virtual Interrupts +#define CR4_VME 0x00000001 // V86 Mode Extensions + +// Eflags register +#define FL_CF 0x00000001 // Carry Flag +#define FL_PF 0x00000004 // Parity Flag +#define FL_AF 0x00000010 // Auxiliary carry Flag +#define FL_ZF 0x00000040 // Zero Flag +#define FL_SF 0x00000080 // Sign Flag +#define FL_TF 0x00000100 // Trap Flag +#define FL_IF 0x00000200 // Interrupt Flag +#define FL_DF 0x00000400 // Direction Flag +#define FL_OF 0x00000800 // Overflow Flag +#define FL_IOPL_MASK 0x00003000 // I/O Privilege Level bitmask +#define FL_IOPL_0 0x00000000 // IOPL == 0 +#define FL_IOPL_1 0x00001000 // IOPL == 1 +#define FL_IOPL_2 0x00002000 // IOPL == 2 +#define FL_IOPL_3 0x00003000 // IOPL == 3 +#define FL_NT 0x00004000 // Nested Task +#define FL_RF 0x00010000 // Resume Flag +#define FL_VM 0x00020000 // Virtual 8086 mode +#define FL_AC 0x00040000 // Alignment Check +#define FL_VIF 0x00080000 // Virtual Interrupt Flag +#define FL_VIP 0x00100000 // Virtual Interrupt Pending +#define FL_ID 0x00200000 // ID flag + +// Page fault error codes +#define FEC_PR 0x1 // Page fault caused by protection violation +#define FEC_WR 0x2 // Page fault caused by a write +#define FEC_U 0x4 // Page fault occured while in user mode + + +/* + * + * Part 2. Segmentation data structures and constants. + * + */ + +#ifdef __ASSEMBLER__ + +/* + * Macros to build GDT entries in assembly. + */ +#define SEG_NULL \ + .word 0, 0; \ + .byte 0, 0, 0, 0 +#define SEG(type,base,lim) \ + .word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ + .byte (((base) >> 16) & 0xff), (0x90 | (type)), \ + (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) + +#else // not __ASSEMBLER__ + +#include + +// Segment Descriptors +struct Segdesc { + unsigned sd_lim_15_0 : 16; // Low bits of segment limit + unsigned sd_base_15_0 : 16; // Low bits of segment base address + unsigned sd_base_23_16 : 8; // Middle bits of segment base address + unsigned sd_type : 4; // Segment type (see STS_ constants) + unsigned sd_s : 1; // 0 = system, 1 = application + unsigned sd_dpl : 2; // Descriptor Privilege Level + unsigned sd_p : 1; // Present + unsigned sd_lim_19_16 : 4; // High bits of segment limit + unsigned sd_avl : 1; // Unused (available for software use) + unsigned sd_rsv1 : 1; // Reserved + unsigned sd_db : 1; // 0 = 16-bit segment, 1 = 32-bit segment + unsigned sd_g : 1; // Granularity: limit scaled by 4K when set + unsigned sd_base_31_24 : 8; // High bits of segment base address +}; +// Null segment +#define SEG_NULL (struct Segdesc){ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +// Segment that is loadable but faults when used +#define SEG_FAULT (struct Segdesc){ 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0 } +// Normal segment +#define SEG(type, base, lim, dpl) (struct Segdesc) \ +{ ((lim) >> 12) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ + type, 1, dpl, 1, (unsigned) (lim) >> 28, 0, 0, 1, 1, \ + (unsigned) (base) >> 24 } +#define SEG16(type, base, lim, dpl) (struct Segdesc) \ +{ (lim) & 0xffff, (base) & 0xffff, ((base) >> 16) & 0xff, \ + type, 1, dpl, 1, (unsigned) (lim) >> 16, 0, 0, 1, 0, \ + (unsigned) (base) >> 24 } + +#endif /* !__ASSEMBLER__ */ + +// Application segment type bits +#define STA_X 0x8 // Executable segment +#define STA_E 0x4 // Expand down (non-executable segments) +#define STA_C 0x4 // Conforming code segment (executable only) +#define STA_W 0x2 // Writeable (non-executable segments) +#define STA_R 0x2 // Readable (executable segments) +#define STA_A 0x1 // Accessed + +// System segment type bits +#define STS_T16A 0x1 // Available 16-bit TSS +#define STS_LDT 0x2 // Local Descriptor Table +#define STS_T16B 0x3 // Busy 16-bit TSS +#define STS_CG16 0x4 // 16-bit Call Gate +#define STS_TG 0x5 // Task Gate / Coum Transmitions +#define STS_IG16 0x6 // 16-bit Interrupt Gate +#define STS_TG16 0x7 // 16-bit Trap Gate +#define STS_T32A 0x9 // Available 32-bit TSS +#define STS_T32B 0xB // Busy 32-bit TSS +#define STS_CG32 0xC // 32-bit Call Gate +#define STS_IG32 0xE // 32-bit Interrupt Gate +#define STS_TG32 0xF // 32-bit Trap Gate + +#ifndef __ASSEMBLER__ + +// Task state segment format (as described by the Pentium architecture book) +struct Taskstate { + uint32_t ts_link; // Old ts selector + uintptr_t ts_esp0; // Stack pointers and segment selectors + uint16_t ts_ss0; // after an increase in privilege level + uint16_t ts_padding1; + uintptr_t ts_esp1; + uint16_t ts_ss1; + uint16_t ts_padding2; + uintptr_t ts_esp2; + uint16_t ts_ss2; + uint16_t ts_padding3; + physaddr_t ts_cr3; // Page directory base + uintptr_t ts_eip; // Saved state from last task switch + uint32_t ts_eflags; + uint32_t ts_eax; // More saved state (registers) + uint32_t ts_ecx; + uint32_t ts_edx; + uint32_t ts_ebx; + uintptr_t ts_esp; + uintptr_t ts_ebp; + uint32_t ts_esi; + uint32_t ts_edi; + uint16_t ts_es; // Even more saved state (segment selectors) + uint16_t ts_padding4; + uint16_t ts_cs; + uint16_t ts_padding5; + uint16_t ts_ss; + uint16_t ts_padding6; + uint16_t ts_ds; + uint16_t ts_padding7; + uint16_t ts_fs; + uint16_t ts_padding8; + uint16_t ts_gs; + uint16_t ts_padding9; + uint16_t ts_ldt; + uint16_t ts_padding10; + uint16_t ts_t; // Trap on task switch + uint16_t ts_iomb; // I/O map base address +}; + +#endif /* !__ASSEMBLER__ */ + +#endif /* !ARCANOS_INC_MMU_H */ diff --git a/inc/multiboot.h b/inc/multiboot.h new file mode 100644 index 0000000..a592058 --- /dev/null +++ b/inc/multiboot.h @@ -0,0 +1,225 @@ +/* multiboot.h - Multiboot header file. */ +/* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to +* deal in the Software without restriction, including without limitation the +* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +* sell copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY +* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef ARCANOS_MULTIBOOT_HEADER +#define ARCANOS_MULTIBOOT_HEADER 1 + +/* How many bytes from the start of the file we search for the header. */ +#define MULTIBOOT_SEARCH 8192 + +/* The magic field should contain this. */ +#define MULTIBOOT_HEADER_MAGIC 0x1BADB002 + +/* This should be in %eax. */ +#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 + +/* The bits in the required part of flags field we don't support. */ +#define MULTIBOOT_UNSUPPORTED 0x0000fffc + +/* Alignment of multiboot modules. */ +#define MULTIBOOT_MOD_ALIGN 0x00001000 + +/* Alignment of the multiboot info structure. */ +#define MULTIBOOT_INFO_ALIGN 0x00000004 + +/* Flags set in the 'flags' member of the multiboot header. */ + +/* Align all boot modules on i386 page (4KB) boundaries. */ +#define MULTIBOOT_PAGE_ALIGN 0x00000001 + +/* Must pass memory information to OS. */ +#define MULTIBOOT_MEMORY_INFO 0x00000002 + +/* Must pass video information to OS. */ +#define MULTIBOOT_VIDEO_MODE 0x00000004 + +/* This flag indicates the use of the address fields in the header. */ +#define MULTIBOOT_AOUT_KLUDGE 0x00010000 + +/* Flags to be set in the 'flags' member of the multiboot info structure. */ + +/* is there basic lower/upper memory information? */ +#define MULTIBOOT_INFO_MEMORY 0x00000001 +/* is there a boot device set? */ +#define MULTIBOOT_INFO_BOOTDEV 0x00000002 +/* is the command-line defined? */ +#define MULTIBOOT_INFO_CMDLINE 0x00000004 +/* are there modules to do something with? */ +#define MULTIBOOT_INFO_MODS 0x00000008 + +/* These next two are mutually exclusive */ + +/* is there a symbol table loaded? */ +#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 +/* is there an ELF section header table? */ +#define MULTIBOOT_INFO_ELF_SHDR 0X00000020 + +/* is there a full memory map? */ +#define MULTIBOOT_INFO_MEM_MAP 0x00000040 + +/* Is there drive info? */ +#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 + +/* Is there a config table? */ +#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 + +/* Is there a boot loader name? */ +#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 + +/* Is there a APM table? */ +#define MULTIBOOT_INFO_APM_TABLE 0x00000400 + +/* Is there video information? */ +#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800 + +#ifndef ASM_FILE + +typedef unsigned short multiboot_uint16_t; +typedef unsigned int multiboot_uint32_t; +typedef unsigned long long multiboot_uint64_t; + +struct multiboot_header +{ + /* Must be MULTIBOOT_MAGIC - see above. */ + multiboot_uint32_t magic; + + /* Feature flags. */ + multiboot_uint32_t flags; + + /* The above fields plus this one must equal 0 mod 2^32. */ + multiboot_uint32_t checksum; + + /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ + multiboot_uint32_t header_addr; + multiboot_uint32_t load_addr; + multiboot_uint32_t load_end_addr; + multiboot_uint32_t bss_end_addr; + multiboot_uint32_t entry_addr; + + /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ + multiboot_uint32_t mode_type; + multiboot_uint32_t width; + multiboot_uint32_t height; + multiboot_uint32_t depth; +}; + +/* The symbol table for a.out. */ +struct multiboot_aout_symbol_table +{ + multiboot_uint32_t tabsize; + multiboot_uint32_t strsize; + multiboot_uint32_t addr; + multiboot_uint32_t reserved; +}; +typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; + +/* The section header table for ELF. */ +struct multiboot_elf_section_header_table +{ + multiboot_uint32_t num; + multiboot_uint32_t size; + multiboot_uint32_t addr; + multiboot_uint32_t shndx; +}; +typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; + +struct multiboot_info +{ + /* Multiboot info version number */ + multiboot_uint32_t flags; + + /* Available memory from BIOS */ + multiboot_uint32_t mem_lower; + multiboot_uint32_t mem_upper; + + /* "root" partition */ + multiboot_uint32_t boot_device; + + /* Kernel command line */ + multiboot_uint32_t cmdline; + + /* Boot-Module list */ + multiboot_uint32_t mods_count; + multiboot_uint32_t mods_addr; + + union + { + multiboot_aout_symbol_table_t aout_sym; + multiboot_elf_section_header_table_t elf_sec; + } u; + + /* Memory Mapping buffer */ + multiboot_uint32_t mmap_length; + multiboot_uint32_t mmap_addr; + + /* Drive Info buffer */ + multiboot_uint32_t drives_length; + multiboot_uint32_t drives_addr; + + /* ROM configuration table */ + multiboot_uint32_t config_table; + + /* Boot Loader Name */ + multiboot_uint32_t boot_loader_name; + + /* APM table */ + multiboot_uint32_t apm_table; + + /* Video */ + multiboot_uint32_t vbe_control_info; + multiboot_uint32_t vbe_mode_info; + multiboot_uint16_t vbe_mode; + multiboot_uint16_t vbe_interface_seg; + multiboot_uint16_t vbe_interface_off; + multiboot_uint16_t vbe_interface_len; +}; +typedef struct multiboot_info multiboot_info_t; + +struct multiboot_mmap_entry +{ + multiboot_uint32_t size; + multiboot_uint32_t addr_low; + multiboot_uint32_t addr_high; + multiboot_uint32_t len_low; + multiboot_uint32_t len_high; + #define MULTIBOOT_MEMORY_AVAILABLE 1 + #define MULTIBOOT_MEMORY_RESERVED 2 + multiboot_uint32_t type; +} __attribute__((packed)); +typedef struct multiboot_mmap_entry multiboot_memory_map_t; + +struct multiboot_mod_list +{ + /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ + multiboot_uint32_t mod_start; + multiboot_uint32_t mod_end; + + /* Module command line */ + multiboot_uint32_t cmdline; + + /* padding to take it to 16 bytes (must be zero) */ + multiboot_uint32_t pad; +}; +typedef struct multiboot_mod_list multiboot_module_t; + +#endif /* ! ASM_FILE */ + +#endif /* ! MULTIBOOT_HEADER */ diff --git a/inc/pic.h b/inc/pic.h new file mode 100644 index 0000000..4d7dd85 --- /dev/null +++ b/inc/pic.h @@ -0,0 +1,33 @@ + +/** + * Credit where credit is due-- I have to thank the osdev.org community + * for their excellent Wiki, which has given me incredibly useful code + * samples for working with the PIC. + */ + +#define PIC1 0x20 /* IO base address for master PIC */ +#define PIC2 0xA0 /* IO base address for slave PIC */ +#define PIC1_COMMAND PIC1 +#define PIC1_DATA (PIC1+1) +#define PIC2_COMMAND PIC2 +#define PIC2_DATA (PIC2+1) + +#define PIC_EOI 0x20 /* End-of-interrupt command code */ + +#define ICW1_ICW4 0x01 /* ICW4 (not) needed */ +#define ICW1_SINGLE 0x02 /* Single (cascade) mode */ +#define ICW1_INTERVAL4 0x04 /* Call address interval 4 (8) */ +#define ICW1_LEVEL 0x08 /* Level triggered (edge) mode */ +#define ICW1_INIT 0x10 /* Initialization - required! */ + +#define ICW4_8086 0x01 /* 8086/88 (MCS-80/85) mode */ +#define ICW4_AUTO 0x02 /* Auto (normal) EOI */ +#define ICW4_BUF_SLAVE 0x08 /* Buffered mode/slave */ +#define ICW4_BUF_MASTER 0x0C /* Buffered mode/master */ +#define ICW4_SFNM 0x10 /* Special fully nested (not) */ + +void PIC_remap(int offset1, int offset2); +void PIC_sendEOI(unsigned char irq); +void PIC_clear_masks(); +void PIC_set_mask(uint8_t irq, uint8_t value); + diff --git a/inc/stdarg.h b/inc/stdarg.h new file mode 100644 index 0000000..006da79 --- /dev/null +++ b/inc/stdarg.h @@ -0,0 +1,19 @@ +/* $NetBSD: stdarg.h,v 1.12 1995/12/25 23:15:31 mycroft Exp $ */ + +#ifndef STDARG_H +#define STDARG_H + +typedef char *va_list; + +#define __va_size(type) \ + (((sizeof(type) + sizeof(long) - 1) / sizeof(long)) * sizeof(long)) + +#define va_start(ap, last) \ + ((ap) = (va_list)&(last) + __va_size(last)) + +#define va_arg(ap, type) \ + (*(type *)((ap) += __va_size(type), (ap) - __va_size(type))) + +#define va_end(ap) ((void)0) + +#endif /* !STDARG_H */ diff --git a/inc/string.h b/inc/string.h new file mode 100644 index 0000000..56d3302 --- /dev/null +++ b/inc/string.h @@ -0,0 +1,9 @@ +#ifndef ARCANOS_INC_STRING_H +#define ARCANOS_INC_STRING_H + +#include + +int strlen(const char *s); +void * memset(void *dst, int c, size_t len); + +#endif /* not ARCANOS_INC_STRING_H */ diff --git a/inc/stringformat.h b/inc/stringformat.h new file mode 100644 index 0000000..be48b14 --- /dev/null +++ b/inc/stringformat.h @@ -0,0 +1,21 @@ +/* + * stringformat.h + * + * Created on: Aug 30, 2010 + * Author: rhett + */ + +#ifndef STRINGFORMAT_H_ +#define STRINGFORMAT_H_ + +#include + +void reverse(char*); + +void print_int_dec(unsigned int i); +void print_int_hex(unsigned int i); +void print_substring(char* i); +void print_escape_char(char c); + +void _kern_print(const char* fmt_string, ...); +#endif /* STRINGFORMAT_H_ */ diff --git a/inc/types.h b/inc/types.h new file mode 100644 index 0000000..e50fba1 --- /dev/null +++ b/inc/types.h @@ -0,0 +1,72 @@ +#ifndef ARCANOS_INC_TYPES_H +#define ARCANOS_INC_TYPES_H + +#ifndef NULL +#define NULL ((void*) 0) +#endif + +// Represents true-or-false values +typedef int bool; + +// Explicitly-sized versions of integer types +typedef __signed char int8_t; +typedef unsigned char uint8_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef long long int64_t; +typedef unsigned long long uint64_t; + +// Pointers and addresses are 32 bits long. +// We use pointer types to represent virtual addresses, +// uintptr_t to represent the numerical values of virtual addresses, +// and physaddr_t to represent physical addresses. +typedef int32_t intptr_t; +typedef uint32_t uintptr_t; +typedef uint32_t physaddr_t; + +// Page numbers are 32 bits long. +typedef uint32_t ppn_t; + +// size_t is used for memory object sizes. +typedef uint32_t size_t; +// ssize_t is a signed version of ssize_t, used in case there might be an +// error return. +typedef int32_t ssize_t; + +// off_t is used for file offsets and lengths. +typedef int32_t off_t; + +// Efficient min and max operations +#define MIN(_a, _b) \ +({ \ + typeof(_a) __a = (_a); \ + typeof(_b) __b = (_b); \ + __a <= __b ? __a : __b; \ +}) +#define MAX(_a, _b) \ +({ \ + typeof(_a) __a = (_a); \ + typeof(_b) __b = (_b); \ + __a >= __b ? __a : __b; \ +}) + +// Rounding operations (efficient when n is a power of 2) +// Round down to the nearest multiple of n +#define ROUNDDOWN(a, n) \ +({ \ + uint32_t __a = (uint32_t) (a); \ + (typeof(a)) (__a - __a % (n)); \ +}) +// Round up to the nearest multiple of n +#define ROUNDUP(a, n) \ +({ \ + uint32_t __n = (uint32_t) (n); \ + (typeof(a)) (ROUNDDOWN((uint32_t) (a) + __n - 1, __n)); \ +}) + +// Return the offset of 'member' relative to the beginning of a struct type +#define offsetof(type, member) ((size_t) (&((type*)0)->member)) + +#endif /* !ARCANOS_INC_TYPES_H */ diff --git a/inc/x86.h b/inc/x86.h new file mode 100644 index 0000000..e6b19ea --- /dev/null +++ b/inc/x86.h @@ -0,0 +1,283 @@ +#ifndef ARCANOS_INC_X86_H +#define ARCANOS_INC_X86_H + +#include + +static __inline void breakpoint(void) __attribute__((always_inline)); +static __inline uint8_t inb(int port) __attribute__((always_inline)); +static __inline void insb(int port, void *addr, int cnt) __attribute__((always_inline)); +static __inline uint16_t inw(int port) __attribute__((always_inline)); +static __inline void insw(int port, void *addr, int cnt) __attribute__((always_inline)); +static __inline uint32_t inl(int port) __attribute__((always_inline)); +static __inline void insl(int port, void *addr, int cnt) __attribute__((always_inline)); +static __inline void outb(int port, uint8_t data) __attribute__((always_inline)); +static __inline void outsb(int port, const void *addr, int cnt) __attribute__((always_inline)); +static __inline void outw(int port, uint16_t data) __attribute__((always_inline)); +static __inline void outsw(int port, const void *addr, int cnt) __attribute__((always_inline)); +static __inline void outsl(int port, const void *addr, int cnt) __attribute__((always_inline)); +static __inline void outl(int port, uint32_t data) __attribute__((always_inline)); +static __inline void invlpg(void *addr) __attribute__((always_inline)); +static __inline void lidt(void *p) __attribute__((always_inline)); +static __inline void lldt(uint16_t sel) __attribute__((always_inline)); +static __inline void ltr(uint16_t sel) __attribute__((always_inline)); +static __inline void lcr0(uint32_t val) __attribute__((always_inline)); +static __inline uint32_t rcr0(void) __attribute__((always_inline)); +static __inline uint32_t rcr2(void) __attribute__((always_inline)); +static __inline void lcr3(uint32_t val) __attribute__((always_inline)); +static __inline uint32_t rcr3(void) __attribute__((always_inline)); +static __inline void lcr4(uint32_t val) __attribute__((always_inline)); +static __inline uint32_t rcr4(void) __attribute__((always_inline)); +static __inline void tlbflush(void) __attribute__((always_inline)); +static __inline uint32_t read_eflags(void) __attribute__((always_inline)); +static __inline void write_eflags(uint32_t eflags) __attribute__((always_inline)); +static __inline uint32_t read_ebp(void) __attribute__((always_inline)); +static __inline uint32_t read_esp(void) __attribute__((always_inline)); +static __inline void cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp); +static __inline uint64_t read_tsc(void) __attribute__((always_inline)); +static __inline void io_wait(void) __attribute__((always_inline)); + +static __inline void +breakpoint(void) +{ + __asm __volatile("int3"); +} + +static __inline uint8_t +inb(int port) +{ + uint8_t data; + __asm __volatile("inb %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insb(int port, void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\tinsb" : + "=D" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "memory", "cc"); +} + +static __inline uint16_t +inw(int port) +{ + uint16_t data; + __asm __volatile("inw %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insw(int port, void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\tinsw" : + "=D" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "memory", "cc"); +} + +static __inline uint32_t +inl(int port) +{ + uint32_t data; + __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port)); + return data; +} + +static __inline void +insl(int port, void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\tinsl" : + "=D" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "memory", "cc"); +} + +static __inline void +outb(int port, uint8_t data) +{ + __asm __volatile("outb %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsb(int port, const void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\toutsb" : + "=S" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "cc"); +} + +static __inline void +outw(int port, uint16_t data) +{ + __asm __volatile("outw %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +outsw(int port, const void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\toutsw" : + "=S" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "cc"); +} + +static __inline void +outsl(int port, const void *addr, int cnt) +{ + __asm __volatile("cld\n\trepne\n\toutsl" : + "=S" (addr), "=c" (cnt) : + "d" (port), "0" (addr), "1" (cnt) : + "cc"); +} + +static __inline void +outl(int port, uint32_t data) +{ + __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port)); +} + +static __inline void +invlpg(void *addr) +{ + __asm __volatile("invlpg (%0)" : : "r" (addr) : "memory"); +} + +static __inline void +lidt(void *p) +{ + __asm __volatile("lidt (%0)" : : "r" (p)); +} + +static __inline void +lldt(uint16_t sel) +{ + __asm __volatile("lldt %0" : : "r" (sel)); +} + +static __inline void +ltr(uint16_t sel) +{ + __asm __volatile("ltr %0" : : "r" (sel)); +} + +static __inline void +lcr0(uint32_t val) +{ + __asm __volatile("movl %0,%%cr0" : : "r" (val)); +} + +static __inline uint32_t +rcr0(void) +{ + uint32_t val; + __asm __volatile("movl %%cr0,%0" : "=r" (val)); + return val; +} + +static __inline uint32_t +rcr2(void) +{ + uint32_t val; + __asm __volatile("movl %%cr2,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr3(uint32_t val) +{ + __asm __volatile("movl %0,%%cr3" : : "r" (val)); +} + +static __inline uint32_t +rcr3(void) +{ + uint32_t val; + __asm __volatile("movl %%cr3,%0" : "=r" (val)); + return val; +} + +static __inline void +lcr4(uint32_t val) +{ + __asm __volatile("movl %0,%%cr4" : : "r" (val)); +} + +static __inline uint32_t +rcr4(void) +{ + uint32_t cr4; + __asm __volatile("movl %%cr4,%0" : "=r" (cr4)); + return cr4; +} + +static __inline void +tlbflush(void) +{ + uint32_t cr3; + __asm __volatile("movl %%cr3,%0" : "=r" (cr3)); + __asm __volatile("movl %0,%%cr3" : : "r" (cr3)); +} + +static __inline uint32_t +read_eflags(void) +{ + uint32_t eflags; + __asm __volatile("pushfl; popl %0" : "=r" (eflags)); + return eflags; +} + +static __inline void +write_eflags(uint32_t eflags) +{ + __asm __volatile("pushl %0; popfl" : : "r" (eflags)); +} + +static __inline uint32_t +read_ebp(void) +{ + uint32_t ebp; + __asm __volatile("movl %%ebp,%0" : "=r" (ebp)); + return ebp; +} + +static __inline uint32_t +read_esp(void) +{ + uint32_t esp; + __asm __volatile("movl %%esp,%0" : "=r" (esp)); + return esp; +} + +static __inline void +cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp) +{ + uint32_t eax, ebx, ecx, edx; + asm volatile("cpuid" + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) + : "a" (info)); + if (eaxp) + *eaxp = eax; + if (ebxp) + *ebxp = ebx; + if (ecxp) + *ecxp = ecx; + if (edxp) + *edxp = edx; +} + +static __inline uint64_t +read_tsc(void) +{ + uint64_t tsc; + __asm __volatile("rdtsc" : "=A" (tsc)); + return tsc; +} + +static __inline void io_wait(void) { + asm volatile("outb %%al, $0x80" : : "a"(0)); +} + + +#endif /* !ARCANOS_INC_X86_H */ diff --git a/kern/COPYRIGHT b/kern/COPYRIGHT new file mode 100644 index 0000000..dce201f --- /dev/null +++ b/kern/COPYRIGHT @@ -0,0 +1,41 @@ +Unless otherwise stated, all source is Copyright (c) 2010 J. Rhett Aultman +and under the GPL v3. + +entry.S is derived from the Exokernel, which is: + +/* + * Copyright (C) 1997 Massachusetts Institute of Technology + * + * This software is being provided by the copyright holders under the + * following license. By obtaining, using and/or copying this software, + * you agree that you have read, understood, and will comply with the + * following terms and conditions: + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose and without fee or royalty is + * hereby granted, provided that the full text of this NOTICE appears on + * ALL copies of the software and documentation or portions thereof, + * including modifications, that you make. + * + * THIS SOFTWARE IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO + * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, + * BUT NOT LIMITATION, COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR + * WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR + * THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY + * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. COPYRIGHT + * HOLDERS WILL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE OR + * DOCUMENTATION. + * + * The name and trademarks of copyright holders may NOT be used in + * advertising or publicity pertaining to the software without specific, + * written prior permission. Title to copyright in this software and any + * associated documentation will at all times remain with copyright + * holders. See the file AUTHORS which should have accompanied this software + * for a list of all copyright holders. + * + * This file may be derived from previously copyrighted software. This + * copyright applies only to those changes made by the copyright + * holders listed in the AUTHORS file. The rest of this file is covered by + * the copyright notices, if any, listed below. + */ + diff --git a/kern/Makefrag b/kern/Makefrag new file mode 100644 index 0000000..8f17fdb --- /dev/null +++ b/kern/Makefrag @@ -0,0 +1,66 @@ +OBJDIRS += kern + +KERN_LDFLAGS := $(LDFLAGS) -T kern/kernel.ld -nostdlib + +# entry.S must be first, so that it's the first code in the text segment!!! +# +# We also snatch the use of a couple handy source files +# from the lib directory, to avoid gratuitous code duplication. +KERN_SRCFILES := kern/entry.S \ + kern/init.c \ + kern/console.c \ + lib/string.c \ + kern/stringformat.c \ + kern/memmgr.c \ + kern/interrupts/interrupts.S \ + kern/interrupts/interrupt_handlers.c \ + kern/interrupts/idt.c \ + kern/interrupts/pic.c + +# Only build files if they exist. +KERN_SRCFILES := $(wildcard $(KERN_SRCFILES)) + +KERN_BINFILES := + +KERN_OBJFILES := $(patsubst %.c, $(OBJDIR)/%.o, $(KERN_SRCFILES)) +KERN_OBJFILES := $(patsubst %.S, $(OBJDIR)/%.o, $(KERN_OBJFILES)) +KERN_OBJFILES := $(patsubst obj/lib/%, obj/kern/%, $(KERN_OBJFILES)) + +KERN_BINFILES := $(patsubst %, $(OBJDIR)/%, $(KERN_BINFILES)) + +# How to build kernel object files +$(OBJDIR)/kern/%.o: kern/%.c + @echo + cc $< + @mkdir -p $(@D) + $(V)$(CC) -nostdinc $(KERN_CFLAGS) -c -o $@ $< + +$(OBJDIR)/kern/%.o: kern/%.S + @echo + as $< + @mkdir -p $(@D) + $(V)$(CC) -nostdinc $(KERN_CFLAGS) -c -o $@ $< + +$(OBJDIR)/kern/%.o: kern/interrupts/%.S + @echo + as $< + @mkdir -p $(@D) + $(V)$(CC) -nostdinc $(KERN_CFLAGS) -c -o $@ $< + +$(OBJDIR)/kern/%.o: lib/%.c + @echo + cc $< + @mkdir -p $(@D) + $(V)$(CC) -nostdinc $(KERN_CFLAGS) -c -o $@ $< + +# How to build the kernel itself +$(OBJDIR)/kern/kernel: $(KERN_OBJFILES) $(KERN_BINFILES) kern/kernel.ld + @echo + ld $@ + $(V)$(LD) -o $@ $(KERN_LDFLAGS) $(KERN_OBJFILES) $(GCC_LIB) -b binary $(KERN_BINFILES) + $(V)$(OBJDUMP) -S $@ > $@.asm + $(V)$(NM) -n $@ > $@.sym + +# How to build the Bochs disk image +$(OBJDIR)/kern/bochs.img: $(OBJDIR)/kern/kernel + @echo + mk $@ + kern/layout_image_file.py + $(V)cat boot/stage1 boot/stage2 boot/pad $(OBJDIR)/kern/kernel boot/post_pad > $(OBJDIR)/kern/bochs.img + +all: $(OBJDIR)/kern/bochs.img + diff --git a/kern/boot.S b/kern/boot.S new file mode 100644 index 0000000..922c0ff --- /dev/null +++ b/kern/boot.S @@ -0,0 +1,30 @@ +.global loader # making entry point visible to linker +.extern kernel_main + +# setting up the Multiboot header - see GRUB docs for details +.set ALIGN, 1<<0 # align loaded modules on page boundaries +.set MEMINFO, 1<<1 # provide memory map +.set FLAGS, ALIGN | MEMINFO # this is the Multiboot 'flag' field +.set MAGIC, 0x1BADB002 # 'magic number' lets bootloader find the header +.set CHECKSUM, -(MAGIC + FLAGS) # checksum required + +.align 4 +.long MAGIC +.long FLAGS +.long CHECKSUM + +# reserve initial kernel stack space +.set STACKSIZE, 0x4000 # that is, 16k. +.comm stack, STACKSIZE, 32 # reserve 16k stack on a quadword boundary + +loader: + mov $(stack + STACKSIZE), %esp # set up the stack + push %eax # Multiboot magic number + push %ebx # Multiboot data structure + + call kernel_main # call kernel proper + + cli +hang: + hlt # halt machine should kernel return + jmp hang diff --git a/kern/console.c b/kern/console.c new file mode 100644 index 0000000..752c50a --- /dev/null +++ b/kern/console.c @@ -0,0 +1,116 @@ +#include +#include +#include + +#include + +#define SCREEN_WIDTH 80 +#define SCREEN_HEIGHT 25 +#define X 0 +#define Y 1 + +volatile uint8_t* textmode_base = (volatile uint8_t*)(0xB8000); +uint8_t current_color = (uint8_t)0x2a; +uint8_t current_loc[2] = {0,0}; +char screen_buffer[SCREEN_WIDTH*SCREEN_HEIGHT]; + +void blank_screen() { + int i=0; + for (i=0; i<(SCREEN_WIDTH*SCREEN_HEIGHT*2); i=i+2) { + *(textmode_base+i) = ' '; + *(textmode_base+i+1) = current_color; + screen_buffer[i/2] = ' '; + } + current_loc[X] = 0; + current_loc[Y] = 0; +} + +void buffer_to_screen() { + int i=0; + for (i=0; i<(SCREEN_WIDTH*SCREEN_HEIGHT*2); i=i+2) { + *(textmode_base+i) = screen_buffer[i/2]; + *(textmode_base+i+1) = current_color; + } +} + +void console_init() { + blank_screen(); + update_cursor(); +} + +void printchar(char c) { + unsigned int offset = ((current_loc[Y]*SCREEN_WIDTH)+current_loc[X])*2; + *(textmode_base+offset) = c; + screen_buffer[(current_loc[Y]*SCREEN_WIDTH)+current_loc[X]] = c; + *(textmode_base+offset+1) = current_color; + current_loc[X]++; + if (current_loc[X] >= SCREEN_WIDTH) { + next_line(); + } +} + +void next_line() { + current_loc[X] = 0; + current_loc[Y] = current_loc[Y] + 1; + if (current_loc[Y] == SCREEN_HEIGHT) { + int x=0; + int y=0; + //copy everything in the buffer one line down + move_to(0,0); + for (y=1; y<=SCREEN_HEIGHT; y++) { + for (x=0; x>8)&0xFF)); +} + +int8_t move_to (uint8_t x, uint8_t y) { + if (x >= SCREEN_WIDTH || y >= SCREEN_HEIGHT) { + return -1; + } + current_loc[X] = x; + current_loc[Y] = y; + return 0; +} + + + +void print_string_helper(char* string) { + while (*string != '\0') { + printchar(*string); + string++; + } +} + +void print_string(char* string) { + print_string_helper(string); + update_cursor(); +} + +void print_line(char* string) { + print_string_helper(string); + next_line(); + update_cursor(); +} diff --git a/kern/entry.S b/kern/entry.S new file mode 100644 index 0000000..2532d04 --- /dev/null +++ b/kern/entry.S @@ -0,0 +1,126 @@ +/* See COPYRIGHT for copyright information. */ + +#include +#include + +# Shift Right Logical +#define SRL(val, shamt) (((val) >> (shamt)) & ~(-1 << (32 - (shamt)))) + + +################################################################### +# The kernel (this code) is linked at address ~(KERNBASE + 1 Meg), +# but the bootloader loads it at address ~1 Meg. +# +# RELOC(x) maps a symbol x from its link address to its actual +# location in physical memory (its load address). +################################################################### + +#define RELOC(x) ((x) - KERNBASE) + + +.set CODE_SEL,0x8 # index of code seg within mygdt +.set DATA_SEL,0x10 # index of data seg within mygdt + +#define MULTIBOOT_PAGE_ALIGN (1<<0) +#define MULTIBOOT_MEMORY_INFO (1<<1) +#define MULTIBOOT_HEADER_MAGIC (0x1BADB002) +#define MULTIBOOT_HEADER_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN) +#define CHECKSUM (-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS)) + +################################################################### +# entry point +################################################################### + +.text + +# The Multiboot header +.align 4 +.long MULTIBOOT_HEADER_MAGIC +.long MULTIBOOT_HEADER_FLAGS +.long CHECKSUM + +.globl _start +_start: + movw $0x1234,0x472 # warm boot + + # Clear the frame pointer register (EBP) + # so that once we get into debugging C code, + # stack backtraces will be terminated properly. + movl $0x0,%ebp # nuke frame pointer + + # Set the stack pointer + movl $(RELOC(bootstacktop)),%esp + + #preserve the GRUB magic info + push %eax + push %ebx + + movl $(RELOC(init_paging)), %edx + call %edx + + #okay...in theory, paging is ready to go, so enable paging + + mov $INITIAL_PDE, %eax + mov %eax, %cr3 + + mov %cr0, %eax + or $0x80000000, %eax + mov %eax, %cr0 + + #get the info back off the stack before we NEWK it! + pop %ebx + pop %eax + + # Perform a long jump to a symbol the linker has provided. This + # will move the program counter register into the address space + # ArcanOS is linked to. + + ljmp $CODE_SEL,$relocated +relocated: + + # Clear the frame pointer register (EBP) + # so that once we get into debugging C code, + # stack backtraces will be terminated properly. + movl $0x0,%ebp # nuke frame pointer + + # Set the stack pointer + movl $(bootstacktop),%esp + + push %eax #push the multiboot magic number on the stack + push %ebx #push the multipoot pointer on the stack + + # now to C code + call kernel_main + + # Should never get here, but in case we do, just spin. +spin: jmp spin + +################################################################### +# boot stack +################################################################### + .p2align PGSHIFT # force page alignment + .globl bootstack +bootstack: + .space KSTKSIZE + .globl bootstacktop +bootstacktop: + +################################################################### +# setup the GDT +################################################################### + .p2align 2 # force 4 byte alignment +mygdt: + SEG_NULL # null seg + SEG(STA_X|STA_R, -KERNBASE, 0xffffffff) # code seg + SEG(STA_W, -KERNBASE, 0xffffffff) # data seg +mygdtdesc: + .word 0x17 # sizeof(mygdt) - 1 + .long RELOC(mygdt) # address mygdt + +mygdt_flat: + SEG_NULL # null seg + SEG(STA_X|STA_R, 0, 0xffffffff) # code seg + SEG(STA_W, 0, 0xffffffff) # data seg +mygdtdesc_flat: + .word 0x17 # sizeof(mygdt_flat) - 1 + .long RELOC(mygdt_flat) # address mygdt_flat diff --git a/kern/init.c b/kern/init.c new file mode 100644 index 0000000..fb14f92 --- /dev/null +++ b/kern/init.c @@ -0,0 +1,148 @@ +/* See COPYRIGHT for copyright information. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Check if the bit BIT in FLAGS is set. */ +#define CHECK_FLAG(flags,bit) ((flags) & (1 << (bit))) + +extern void keyboard_isr(); +void i386_init(multiboot_info_t* mbi); + +void kernel_main( void* mbd, unsigned int magic ) +{ + if ( magic != 0x2BADB002 ) + { + /* Something went not according to specs. Print an error */ + /* message and halt, but do *not* rely on the multiboot */ + /* data structure. */ + _kern_print("BROKEN MULTIBOOT HEADER! Bailing out!"); + while(1); + } + mbd = KERNBASE + mbd; + i386_init((multiboot_info_t*)mbd); +} + +void +i386_init(multiboot_info_t* mbi) +{ + extern char etext[], edata[], end[], kern_textbase[], kern_textend[]; + extern char kern_robase[], kern_roend[]; + extern char kern_stabbase[], kern_stabend[]; + extern char kern_stabstrbase[], kern_stabstrend[]; + extern char kern_database[], kern_dataend[]; + extern char kern_bssbase[], kern_bssend[]; + extern char end[]; + extern char load_start[], load_end[]; + + int i; + int j; + + console_init(); + _kern_print("Arcanos version %s\n", ARCANOS_VERSION); + _kern_print("Kernel mapped to address 0x%x\n", KERNBASE); + + /* Print out the flags. */ + _kern_print("multiboot info address = 0x%x\n", mbi); + _kern_print("flags = 0x%x\n", (unsigned) mbi->flags); + + /* Are mem_* valid? */ + if (CHECK_FLAG (mbi->flags, 0)) + _kern_print("mem_lower = %uKB, mem_upper = %uKB\n", + (unsigned) mbi->mem_lower, (unsigned) mbi->mem_upper); + + /* Is boot_device valid? */ + if (CHECK_FLAG (mbi->flags, 1)) + _kern_print("boot_device = 0x%x\n", (unsigned) mbi->boot_device); + + /* Is the command line passed? */ + if (CHECK_FLAG (mbi->flags, 2)) { + _kern_print("cmdline = %s\n", (char *) (mbi->cmdline)); + } + + + /* Are mods_* valid? */ + if (CHECK_FLAG (mbi->flags, 3)) + { + multiboot_module_t *mod; + int i; + + _kern_print("mods_count = %d, mods_addr = 0x%x\n", + (int) mbi->mods_count, (int) (mbi->mods_addr)); + for (i = 0, mod = (multiboot_module_t *) (mbi->mods_addr); + i < mbi->mods_count; + i++, mod++) + _kern_print(" mod_start = 0x%x, mod_end = 0x%x, cmdline = %s\n", + (unsigned) (mod->mod_start), + (unsigned) (mod->mod_end), + (char *) (mod->cmdline)); + } + + + /* Bits 4 and 5 are mutually exclusive! */ + if (CHECK_FLAG (mbi->flags, 4) && CHECK_FLAG (mbi->flags, 5)) + { + _kern_print("Both bits 4 and 5 are set.\n"); + return; + } + + /* Is the symbol table of a.out valid? */ + if (CHECK_FLAG (mbi->flags, 4)) + { + multiboot_aout_symbol_table_t *multiboot_aout_sym = &(mbi->u.aout_sym); + + _kern_print("multiboot_aout_symbol_table: tabsize = 0x%0x, " + "strsize = 0x%x, addr = 0x%x\n", + (unsigned) multiboot_aout_sym->tabsize, + (unsigned) multiboot_aout_sym->strsize, + (unsigned) multiboot_aout_sym->addr); + } + + /* Is the section header table of ELF valid? */ + if (CHECK_FLAG (mbi->flags, 5)) + { + multiboot_elf_section_header_table_t *multiboot_elf_sec = &(mbi->u.elf_sec); + + _kern_print("multiboot_elf_sec: num = %u, size = 0x%x," + " addr = 0x%x, shndx = 0x%x\n", + (unsigned) multiboot_elf_sec->num, (unsigned) multiboot_elf_sec->size, + (unsigned) (multiboot_elf_sec->addr), (unsigned) multiboot_elf_sec->shndx); + } + + /* Are mmap_* valid? */ + if (CHECK_FLAG (mbi->flags, 6)) + { + multiboot_memory_map_t *mmap; + + frame_allocator_init(mbi, (uint32_t)load_start, (uint32_t)load_end); + } + + //void* init_addr = memmgr_init(end); + //_kern_print("Mem mgr initialized and using address %x\n", init_addr); + asm("cli"); + reset_idt(); + load_idt(); + PIC_clear_masks(); + PIC_remap(32, 40); //PIC1 - 32-39, PIC2 - 40-47; + set_idt_entry(33, keyboard_isr, INTERRUPT_GATE_TYPE_ATTR); + PIC_set_mask(1, 0); + load_idt(); + asm("sti"); //Interrupts are on now, bitches. + _kern_print("Interrupts enabled.\n"); + //I think that it might actually be necessary to forcibly run the + //keyboard ISR to perhaps...process any lingering key presses? + asm("int $33"); + memmgr_init(); + + char* yaay = memmgr_allocate(1024); +//stop here for now + _kern_print("Entering kernel idle loop.\n"); + asm("hlt"); + while (1); +} diff --git a/kern/interrupts/COPYRIGHT b/kern/interrupts/COPYRIGHT new file mode 100644 index 0000000..40c0755 --- /dev/null +++ b/kern/interrupts/COPYRIGHT @@ -0,0 +1,2 @@ +Unless otherwise stated, all source is Copyright (c) 2010 J. Rhett Aultman +and under the GPL v3. diff --git a/kern/interrupts/idt.c b/kern/interrupts/idt.c new file mode 100644 index 0000000..c51b4f6 --- /dev/null +++ b/kern/interrupts/idt.c @@ -0,0 +1,73 @@ +#include +#include +#include + +extern void isr_0(); +extern void isr_1(); +extern void isr_2(); +extern void isr_3(); +extern void isr_4(); +extern void isr_5(); +extern void isr_6(); +extern void isr_7(); +extern void isr_8(); +extern void isr_9(); +extern void isr_10(); +extern void isr_11(); +extern void isr_12(); +extern void isr_13(); +extern void isr_14(); +extern void isr_16(); +extern void isr_17(); +extern void isr_18(); +extern void isr_19(); +extern void isr_30(); + +void reset_idt() { + memset(idt, 0, sizeof(IDTDescr)*256); + //The base of the table must be a linear address (which is + //currently the same as the physical address) + idt_struct.base = (uint32_t)idt-KERNBASE; + idt_struct.limit = 256*(sizeof(IDTDescr)-1); + idtp = &idt_struct; + phys_idtp = (IDT*)(((uint32_t)idtp) - KERNBASE); + _kern_print("IDTP: %x PHYS_IDTP %x\n", ((uint32_t)idtp), ((uint32_t)phys_idtp)); + //Set default exception handlers. There's no compelling reason + //to change them, but kernel code can by making its own + //set_idt_entry calls. + set_idt_entry(0, isr_0, TRAP_GATE_TYPE_ATTR); + set_idt_entry(1,isr_1, TRAP_GATE_TYPE_ATTR); + set_idt_entry(2,isr_2, INTERRUPT_GATE_TYPE_ATTR); + set_idt_entry(3,isr_3, TRAP_GATE_TYPE_ATTR); + set_idt_entry(4,isr_4, TRAP_GATE_TYPE_ATTR); + set_idt_entry(5,isr_5, TRAP_GATE_TYPE_ATTR); + set_idt_entry(6,isr_6, TRAP_GATE_TYPE_ATTR); + set_idt_entry(7,isr_7, TRAP_GATE_TYPE_ATTR); + set_idt_entry(8,isr_8, TRAP_GATE_TYPE_ATTR); + set_idt_entry(9,isr_9, TRAP_GATE_TYPE_ATTR); + set_idt_entry(10,isr_10, TRAP_GATE_TYPE_ATTR); + set_idt_entry(11,isr_11, TRAP_GATE_TYPE_ATTR); + set_idt_entry(12,isr_12, TRAP_GATE_TYPE_ATTR); + set_idt_entry(13,isr_13, TRAP_GATE_TYPE_ATTR); + set_idt_entry(14,isr_14, TRAP_GATE_TYPE_ATTR); + set_idt_entry(16,isr_16, TRAP_GATE_TYPE_ATTR); + set_idt_entry(17,isr_17, TRAP_GATE_TYPE_ATTR); + set_idt_entry(18,isr_18, TRAP_GATE_TYPE_ATTR); + set_idt_entry(19,isr_19, TRAP_GATE_TYPE_ATTR); + set_idt_entry(30,isr_30, TRAP_GATE_TYPE_ATTR); + +} + +void set_idt_entry(uint8_t number, void (*handler)(), uint16_t type) { + uint32_t handler_addr = (uint32_t)handler - KERNBASE; + handler_addr = handler_addr; + idt[number].offset_1 = LOW_OFFSET(handler_addr); + idt[number].offset_2 = HIGH_OFFSET(handler_addr); + idt[number].selector = GD_KT; + idt[number].type_attr = type; + idt[number].zero = 0; +} + +void load_idt() { + asm volatile("LIDT (%0) ": :"p" (phys_idtp)); +} diff --git a/kern/interrupts/interrupt_handlers.c b/kern/interrupts/interrupt_handlers.c new file mode 100644 index 0000000..d9cffaa --- /dev/null +++ b/kern/interrupts/interrupt_handlers.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +char* exception_messages[32] = { +"Divide-by-zero Error", +"Debug", +"Non-maskable Interrupt", +"Breakpoint", +"Overflow", +"Bound Range Exceeded", +"Invalid Opcode", +"Device Not Available", +"Double Fault", +"Coprocessor Segment Overrun", +"Invalid TSS", +"Segment Not Present", +"Stack-Segment Fault", +"General Protection Fault", +"Page Fault", +"Reserved", +"x87 Floating-Point Exception", +"Alignment Check", +"Machine Check", +"SIMD Floating-Point Exception", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Reserved", +"Security Exception", +"Reserved" +}; + +/** + * Exceptions to handle: + * +Divide-by-zero Error 0 Fault #DE No +Debug 1 Fault/Trap #DB No +Non-maskable Interrupt 2 Interrupt - No +Breakpoint 3 Trap #BP No +Overflow 4 Trap #OF No +Bound Range Exceeded 5 Fault #BR No +Invalid Opcode 6 Fault #UD No +Device Not Available 7 Fault #NM No +Double Fault 8 Abort #DF Yes +Coprocessor Segment Overrun 9 Fault - No +Invalid TSS 10 Fault #TS Yes +Segment Not Present 11 Fault #NP Yes +Stack-Segment Fault 12 Fault #SS Yes +General Protection Fault 13 Fault #GP Yes +Page Fault 14 Fault #PF Yes +Reserved 15 - - No +x87 Floating-Point Exception 16 Fault #MF No +Alignment Check 17 Fault #AC Yes +Machine Check 18 Abort #MC No +SIMD Floating-Point Exception 19 Fault #XM/#XF No +Reserved 20-29 - - No +Security Exception 30 - #SX No +Reserved 31 - - No +Triple Fault - - - No +*/ + +/* filename : interrupt_handlers.c */ +void _interrupt_handler(uint8_t number) +{ + _kern_print("%s exception. Halting.\n", exception_messages[number]); + asm("hlt"); + while(1); +} + +void _keyboard_interrupt() +{ + uint8_t new_scan_code=0; + new_scan_code = inb(0x60); + + /* Do something with the scancode. + * Remember you only get '''one''' byte of the scancode each time the ISR is invoked. + * (Though most of the times the scancode is only one byte.) + */ + _kern_print("Keyboard scancode 0x%x\n", new_scan_code); + /* Acknowledge the IRQ, pretty much tells the PIC that we can accept >=priority IRQs now. */ + PIC_sendEOI(1); //Keyboard is IRQ 1. +} diff --git a/kern/interrupts/interrupts.S b/kern/interrupts/interrupts.S new file mode 100644 index 0000000..fc5c990 --- /dev/null +++ b/kern/interrupts/interrupts.S @@ -0,0 +1,194 @@ +/* filename : interrupts.S */ + +.globl _load_idt +.extern idtp +.extern _interrupt_handler + +.align 4 + +//Divide-by-zero Error +.globl isr_0 +isr_0: + pushal + push $0 + call _interrupt_handler + popal + iret + +//Debug +.globl isr_1 +isr_1: + pushal + push $1 + call _interrupt_handler + popal + iret + +//Non-maskable Interrupt +.globl isr_2 +isr_2: + pushal + push $2 + call _interrupt_handler + popal + iret + +//Breakpoint +.globl isr_3 +isr_3: + pushal + push $3 + call _interrupt_handler + popal + iret + +//Overflow +.globl isr_4 +isr_4: + pushal + push $4 + call _interrupt_handler + popal + iret + +//Bound Range Exceeded +.globl isr_5 +isr_5: + pushal + push $5 + call _interrupt_handler + popal + iret + +//Invalid Opcode +.globl isr_6 +isr_6: + pushal + push $6 + call _interrupt_handler + popal + iret + +//Device Not Available +.globl isr_7 +isr_7: + pushal + push $7 + call _interrupt_handler + popal + iret + +//Double Fault +.globl isr_8 +isr_8: + pushal + push $8 + call _interrupt_handler + popal + iret + +//Coprocessor Segment Overrun +.globl isr_9 +isr_9: + pushal + push $9 + call _interrupt_handler + popal + iret + +//Invalid TSS +.globl isr_10 +isr_10: + pushal + push $10 + call _interrupt_handler + popal + iret + +//Segment Not Present +.globl isr_11 +isr_11: + pushal + push $11 + call _interrupt_handler + popal + iret + +//Stack-Segment Fault +.globl isr_12 +isr_12: + pushal + push $12 + call _interrupt_handler + popal + iret + +//General Protection Fault +.globl isr_13 +isr_13: + pushal + push $13 + call _interrupt_handler + popal + iret + +//Page Fault +.globl isr_14 +isr_14: + pushal + push $14 + call _interrupt_handler + popal + iret + +//x87 Floating-Point Exception +.globl isr_16 +isr_16: + pushal + push $16 + call _interrupt_handler + popal + iret + +//Alignment Check +.globl isr_17 +isr_17: + pushal + push $17 + call _interrupt_handler + popal + iret + +//Machine Check +.globl isr_18 +isr_18: + pushal + push $18 + call _interrupt_handler + popal + iret + +//SIMD Floating-Point Exception +.globl isr_19 +isr_19: + pushal + push $19 + call _interrupt_handler + popal + iret + +//Security Exception +.globl isr_30 +isr_30: + pushal + push $30 + call _interrupt_handler + popal + iret + +.globl keyboard_isr +keyboard_isr: + pushal + call _keyboard_interrupt + popal + iret diff --git a/kern/interrupts/pic.c b/kern/interrupts/pic.c new file mode 100644 index 0000000..1b30b3c --- /dev/null +++ b/kern/interrupts/pic.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include + +/** + * Again, a debt of gratitude to osdev.org for this code. + */ + +void PIC_sendEOI(unsigned char irq) +{ + if(irq >= 8) + outb(PIC2_COMMAND,PIC_EOI); + + outb(PIC1_COMMAND,PIC_EOI); +} + +/* +arguments: + offset1 - vector offset for master PIC + vectors on the master become offset1..offset1+7 + offset2 - same for slave PIC: offset2..offset2+7 +*/ +void PIC_remap(int offset1, int offset2) +{ + uint8_t a1, a2; + + a1 = inb(PIC1_DATA); // save masks + a2 = inb(PIC2_DATA); + + outb(PIC1_COMMAND, ICW1_INIT+ICW1_ICW4); // starts the initialization sequence + io_wait(); + outb(PIC2_COMMAND, ICW1_INIT+ICW1_ICW4); + io_wait(); + outb(PIC1_DATA, offset1); // define the PIC vectors + io_wait(); + outb(PIC2_DATA, offset2); + io_wait(); + outb(PIC1_DATA, 4); //ICW3: Master takes slave on IRQ2 (4 = 100b -- bitmask for IRQ2) + io_wait(); + outb(PIC2_DATA, 2); //ICW3: Slave sends to master on IRQ2 (2 expressed in binary here) + io_wait(); + + outb(PIC1_DATA, ICW4_8086); + io_wait(); + outb(PIC2_DATA, ICW4_8086); + io_wait(); + + outb(PIC1_DATA, a1); // restore saved masks. + outb(PIC2_DATA, a2); +} + +void PIC_clear_masks() { + outb(PIC1_DATA, 0xFF); + outb(PIC2_DATA, 0xFF); +} + +/* + * Set/clear interrupt mask bits. Must specify by IRQ and value is + * 0 to clear and all else to set. + */ +void PIC_set_mask(uint8_t irq, uint8_t value) { + uint8_t mask_bit = 1; + + uint8_t pic_port; + + if(irq >= 8) { + irq = irq-8; + pic_port = PIC2_DATA; + } else { + pic_port = PIC1_DATA; + } + + uint8_t mask; + mask = inb(pic_port); //get current mask + io_wait(); + mask_bit = mask_bit << irq; + if (value) { + mask = mask | mask_bit; //If value is 1, then set the mask bit + } else { + mask = mask & (~mask_bit); //If value is 0, then clear the mask bit + } + outb(pic_port, mask); //set the new mask + io_wait(); +} diff --git a/kern/kernel.ld b/kern/kernel.ld new file mode 100644 index 0000000..289006e --- /dev/null +++ b/kern/kernel.ld @@ -0,0 +1,84 @@ +/* Simple linker script for the Arcanos kernel. + See the GNU ld 'info' manual ("info ld") to learn the syntax. */ + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) + +virt = 0xC0100000; +phys = 0x00100000; +offset = 0xC0000000; + +SECTIONS +{ + .text virt : AT(phys) { + PROVIDE(load_start = phys); + PROVIDE(kern_textbase = .); + *(.text .stub .text.* .gnu.linkonce.t.*) + PROVIDE(kern_textend = .); + } + + PROVIDE(etext = .); + phys = ALIGN(4) - offset; + + .rodata : AT(phys) { + robase = .; + PROVIDE(kern_robase = .); + *(.rodata .rodata.* .gnu.linkonce.r.*) + PROVIDE(kern_roend = .); + + } + + phys = ALIGN(4) - offset; + + /* Include debugging information in kernel memory */ + .stab : AT(phys) { + stabbase = .; + PROVIDE(kern_stabbase = .); + *(.stab); + PROVIDE(kern_stabend = .); + BYTE(0) /* Force the linker to allocate space + for this section */ + } + + phys = ALIGN(1) - offset; + + .stabstr : AT(phys) { + stabstrbase = .; + PROVIDE(kern_stabstrbase = .); + *(.stabstr); + PROVIDE(kern_stabstrend = .); + BYTE(0) /* Force the linker to allocate space + for this section */ + } + + phys = . - offset; + phys = ALIGN(0x1000) - offset; + + /* The data segment */ + .data ALIGN(0x1000) : AT (phys) { + database = .; + PROVIDE(kern_database = .); + *(.data) + PROVIDE(kern_dataend = .); + } + + phys = ALIGN(32) - offset; + + PROVIDE(edata = .); + + .bss : AT (phys) { + bssbase = .; + PROVIDE(kern_bssbase = .); + *(.bss) + PROVIDE(kern_bssend = .); + } + + PROVIDE(end = .); + phys = . - offset; + PROVIDE(load_end = phys); + + /DISCARD/ : { + *(.eh_frame .note.GNU-stack) + } +} diff --git a/kern/layout_image_file.py b/kern/layout_image_file.py new file mode 100755 index 0000000..17f7ec0 --- /dev/null +++ b/kern/layout_image_file.py @@ -0,0 +1,31 @@ +#!/usr/bin/python + +from __future__ import division; +import os; +import math; + + +disk_size = 5120000; + +stage1_size = os.path.getsize("boot/stage1"); +stage2_size = os.path.getsize("boot/stage2"); +pad_size = os.path.getsize("boot/pad"); +kernel_size = os.path.getsize("obj/kern/kernel"); + +print "stage1 size: %d" % stage1_size; +print "stage2 size: %d" % stage2_size; +print "pad size: %d" % pad_size; +print "kernel size: %d" % kernel_size; + +post_pad_size = disk_size - stage1_size - stage2_size - pad_size - kernel_size; + +print "will generate a post_pad of size: %d" % post_pad_size; + +dd_cmd = "dd if=/dev/zero of=boot/post_pad bs=%d count=1" % post_pad_size; + +os.system(dd_cmd); + +kernel_start = math.ceil((stage1_size + stage2_size + pad_size)/512); +kernel_len = math.ceil(kernel_size/512); + +print "GRUB load command: kernel %d+%d" % (kernel_start, kernel_len); diff --git a/kern/memmgr.c b/kern/memmgr.c new file mode 100644 index 0000000..c1b3853 --- /dev/null +++ b/kern/memmgr.c @@ -0,0 +1,460 @@ +#include +#include +#include +#include + +#define CELL_SIZE (PAGE_SIZE*sizeof(uint8_t)*8) +#define FRAME_STATUS_FREE 1 +#define FRAME_STATUS_USED 0 +#define CELL_STATUS_USED 0 +#define PT_ENTRIES 1024 +#define HIGHER_HALF_BASE 768 +#define INVALID_FRAME ((void*)0xFFFFFFFF) + +static kmemdesc* free_list_head; +static kmemdesc* alloc_list_head; +static kmemdesc* free_list_tail; +static kmemdesc* alloc_list_tail; + +static uint32_t* pde = (uint32_t*)INITIAL_PDE; + +int mem_available; + +void flush_tlb(); + +/* + * I can't honestly say if this is the dumbest thing I've done or one + * of my more clever tricks. This function is written to sling together + * some page tables for the kernel. The kernel is higher-half (actually + * it's linked at 0xc0100000) but I just didn't want to write this in + * assembly. Well...nothing in here involves a long jump or a far call + * or refers to global variables ("end" is linker-provided), so the + * code should be location-independent! So, we call this from within + * entry.S when we have nothing set up, and it still works! + * + * Probably shouldn't call this from within the kernel proper, though. + */ + +void init_paging() { + extern char end[]; + + int i; + uint32_t* initial_pde = (uint32_t*)INITIAL_PDE; + uint32_t* firstmeg_table = (uint32_t*)(INITIAL_PDE-PAGE_SIZE); + uint32_t* kernel_table = (uint32_t*)(INITIAL_PDE-(PAGE_SIZE*2)); + + //First, clear the tables + for (i=0; i<1024; ++i) { + *initial_pde=0; + *firstmeg_table = 0; + *kernel_table = 0; + } + + //Identity-page the first 4MB + for (i=0; i<1024; i++) { + uint32_t page_base = i*PAGE_SIZE; + page_base = page_base | PAGE_RW | PAGE_PRESENT; + firstmeg_table[i] = page_base; + } + + initial_pde[0] = ((uint32_t)firstmeg_table) | PAGE_RW | PAGE_PRESENT; + + //Now page in the kernel's space. + uint32_t kernel_page_count = (((uint32_t)end) - KERNBASE) / PAGE_SIZE; + if ((((uint32_t)end) - KERNBASE) % PAGE_SIZE > 0) ++kernel_page_count; + + /* NOTE: this should really map in only enough pages to fit the kernel + * but for now, this is mapping the entire lower 4MB to 0xc0000000 + * in addition to the identity paging above. Why? Because GRUB + * is putting the multiboot header struct in low memory but passing + * it a value that appears to be link-address relative (i.e. it's at + * 0xc00300000 or so) and so the area below the kernel must be mapped + * in, too. We're going to change link addresses before MAGUS is + * over, anyway, so for now we're mapping the same 4MB as both identity + * and into the link-address space of the kernel. */ + + for (i=0; i<1024/*kernel_page_count*/; ++i) { + //Load base is 1MB + uint32_t page_base = (i*PAGE_SIZE)/*+(1024*1024)*/; + page_base = page_base | PAGE_RW | PAGE_PRESENT; + //the link address base is not flat higher half but higher half + //plus 1MB + kernel_table[i] = page_base; + } + + initial_pde[768] = ((uint32_t)kernel_table) | PAGE_RW | PAGE_PRESENT; + + return; + +} + +void frame_allocator_init(multiboot_info_t* mbi, uint32_t kernel_base, uint32_t kernel_end) { + + int i; + int frames_allocated = 0; + for(i=0; i<(PHYS_MEM_MAP_SIZE); i++) { + phys_mem_map[i] = 0; + } + + //_kern_print("mmap_addr = 0x%x, mmap_length = 0x%x\n", + // (unsigned) (mbi->mmap_addr), (unsigned) mbi->mmap_length); + + multiboot_memory_map_t* mmap; + for (mmap = (multiboot_memory_map_t *) (mbi->mmap_addr); + (unsigned long) mmap < (mbi->mmap_addr) + mbi->mmap_length; + mmap = (multiboot_memory_map_t *) ((unsigned long) mmap + + mmap->size + sizeof (mmap->size))) + { + //_kern_print(" size = 0x%x, base_addr = 0x%x%x," + // " length = 0x%x%x, type = 0x%x\n", + // (unsigned) mmap->size, + // mmap->addr_high, + // mmap->addr_low, + // mmap->len_high, + // mmap->len_low, + // (unsigned) mmap->type); + + if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE) { + //Kindly note here that we will *NOT* be making use of the "high" + //fields here. The memory manager is current capped at 4GB, so + //we will deal only with the lower 32-bits of addresses. + + //The goal here is to flip on the bits for available RAM. After + //that, we will flip OFF the bits for the areas where the kernel + //was loaded and where the initial page tables sit. + + //The frame allocator is very happy to fail to mark partial + //frames as "not available." This is a good, safe starting point + //as it means that the only physical memory allocated out will + //"really be there." + + uint32_t base = mmap->addr_low; + uint32_t len = mmap->len_low; + + //First, advance up to the next page frame boundary. + if ((base % PAGE_SIZE) != 0) { + base = base + (PAGE_SIZE - (base % PAGE_SIZE)); + len = len - (PAGE_SIZE - (base % PAGE_SIZE)); + } + + //As long as there is another frame to allocate, allocate it. + while (!(len> bit) & FRAME_STATUS_FREE) { + break; + } else { + continue; + } + } + + //Once we get here, we know we must have an available frame + //As the mem_map entry was not full and so an empty bit was + //found somewhere. + + //Mark it as taken + mark_frame(((i*CELL_SIZE)+(bit*PAGE_SIZE)), FRAME_STATUS_USED); + + //return the address + uint32_t addr = (i*CELL_SIZE)+(bit*PAGE_SIZE); + return (void*)addr; + } + } + //Looks like everything was taken already + _kern_print("ERROR: Could not locate a frame to allocate\n"); + return (void*)INVALID_FRAME; +} + +void* get_page() { + + void* frame = get_frame(); + if (frame == INVALID_FRAME) { + _kern_print("Did not get a frame for the requested page!\n"); + return 0; + } + + //All page addresses returned from here should be higher-half + int pd_entry; + for (pd_entry = HIGHER_HALF_BASE; pd_entry < PT_ENTRIES; pd_entry++) { + if (pde[pd_entry] == 0) { + //Found a blank spot in the page directory, so we will + //create a table and use it. + uint32_t* new_table = (uint32_t*)get_frame(); + if (new_table == INVALID_FRAME) { + _kern_print("Could not allocate a new page table.\n"); + //TODO: RETURN INITIAL FRAME TO POOL TO PREVENT A LEAK + return 0; + } + //Blank the table + int i; + for (i=0; inext = 0; + free_list_head->size = mem_available; + free_list_head->data_ptr = ((char*)free_list_head)+sizeof(kmemdesc); + free_list_tail = free_list_head; + return; +} + +void* memmgr_allocate(unsigned int size) { + + if (size > (PAGE_SIZE - sizeof(kmemdesc))) { + _kern_print("Alloc of sizes greater than %d not supported!\n", + (PAGE_SIZE - sizeof(kmemdesc))); + return 0; + } + //Sweep the free list to find a fit. + kmemdesc* sweep = 0; + kmemdesc* prev = 0; + + if (free_list_head == 0) return 0; + + sweep = free_list_head; + while (sweep != free_list_tail) { + + //_kern_print("Comparing size %d against %d\n",sweep->size, size); + if (sweep->size == size) { + //_kern_print("Comparing size matched object at %x\n",sweep->data_ptr); + + //Found it. If it's the head, then the free list needs + //a new head. Otherwise, suture it out. + //a head == tail case cannot occur inside this loop + if (sweep == free_list_head) { + if (sweep == free_list_tail) { + free_list_head = 0; + free_list_tail = 0; + } else { + free_list_head = sweep->next; + } + } else { + prev->next = sweep->next; + } + + if (alloc_list_tail == 0) { + alloc_list_head = sweep; + alloc_list_tail = sweep; + } else { + alloc_list_tail->next = sweep; + alloc_list_tail = sweep; + } + return sweep->data_ptr; + } + + prev = sweep; + sweep = sweep->next; + } + + //We are here under the following conditions: + //head == tail == sweep , previous == 0 + //sweep == tail, previous != 0 + + //Before proceeding, see if we need to allocate more memory on + //the end. + if (free_list_tail->size < (size+sizeof(kmemdesc))) { + + kmemdesc* next_page = (kmemdesc*)get_page(); + if (!next_page) { + _kern_print("Could not satisfy: no pages available!\n"); + return 0; + } + + int mem_available = PAGE_SIZE; + mem_available -= sizeof(kmemdesc); + next_page->size = mem_available; + next_page->data_ptr = ((char*)next_page)+sizeof(kmemdesc); + + free_list_tail->next = next_page; + free_list_tail = next_page; + free_list_tail = free_list_head; + } + + sweep = (kmemdesc*)(((char*)free_list_tail)+sizeof(kmemdesc)+size); + sweep->data_ptr = ((char*)sweep) + sizeof(kmemdesc); + mem_available = mem_available - size - sizeof(kmemdesc); + sweep->size = mem_available; + sweep->next = 0; + + //free_list_tail is now a kmemdesc describing the allocated space + free_list_tail->size = size; + + if (alloc_list_tail != 0) { + alloc_list_tail->next = free_list_tail; + alloc_list_tail = free_list_tail; + } else { + alloc_list_head = free_list_tail; + alloc_list_tail = free_list_tail; + } + + //sweep is now set to be the new tail + if (free_list_head == free_list_tail) { + free_list_head = sweep; + free_list_tail = sweep; + } else { + prev->next = sweep; + free_list_tail = sweep; + } + + //having moved the former free list tail to the tail of the + //alloc list, return the alloc list tail data pointer + return alloc_list_tail->data_ptr; +} + +void memmgr_free(void* ptr) { + kmemdesc* sweep = 0; + kmemdesc* prev = 0; + + + if (alloc_list_head == 0) return; + + //First, locate the correct kmemdesc in the free list. Keep + //prev updated in case we need to suture the list. + + sweep = alloc_list_head; + while (sweep != alloc_list_tail) { + if (sweep->data_ptr == ptr) { + //Found it. Break the loop. + break; + } + prev = sweep; + sweep = sweep->next; + } + //Conditions that get us to this point: + //-- head == tail == sweep, prev == NULL, sweep data_ptr not checked + if (alloc_list_head == alloc_list_tail) { + if (sweep->data_ptr == ptr) { + alloc_list_head = 0; + alloc_list_tail = 0; + } else { + //ERROR! The only entry on the free list didn't + //have a data pointer that matched the given pointer + //_kern_print("Couldn't match the one item in the free list\n"); + return; + } + } + //-- head == sweep, prev == null, sweep data_ptr matched + else if (sweep == alloc_list_head) { + alloc_list_head = sweep->next; + } + //-- sweep == tail, prev != null, sweep data ptr not checked + else if (sweep == alloc_list_tail) { + if (sweep->data_ptr == ptr) { + //Matched at the tail of the list + alloc_list_tail = prev; + alloc_list_tail->next = 0; + } else { + //ERROR! Traversed the list without a match! + //_kern_print("Traversed the free list in vain\n"); + return; + } + } + //-- prev != null, sweep data_ptr matched + else { + sweep->next = prev->next; + } + + //At this point, sweep points to a kmemdesc that has been removed + //from the alloc list. We will place it at the head of the free + //list. + if (free_list_head == 0) { + free_list_head = sweep; + free_list_tail = sweep; + } else { + sweep->next = free_list_head; + free_list_head = sweep; + } + //_kern_print("Object at address %x freed\n", sweep->data_ptr); + //_kern_print("Free list head now size %d address %x\n", free_list_head->size, free_list_head->data_ptr); +} + +void flush_tlb() { + //Do the super-heavy full TLB flush. We should use invlpg in the + //future. + asm("movl %cr3, %eax; movl %eax, %cr3;"); +} diff --git a/kern/stringformat.c b/kern/stringformat.c new file mode 100644 index 0000000..2ef677c --- /dev/null +++ b/kern/stringformat.c @@ -0,0 +1,125 @@ +/* + * stringformat.c + * + * Created on: Aug 30, 2010 + * Author: rhett + */ + +#include +#include +#include + +void reverse(char* buffer) { + int buflen = 0; + int begin; + int end; + + begin = 0; + end = strlen(buffer)-1; + + if (end<0) return; + if (end == begin) return; + + while(begin < end) { + char swap; + swap = buffer[begin]; + buffer[begin] = buffer[end]; + buffer[end] = swap; + + begin++; + end--; + } + +} + +void print_int_dec(unsigned int i) { + int radix = 10; + //Buffer size is based on a guess at something larger than + //a maxint val + char buffer [(sizeof(int)*3)+1]; + int c=0; + do { + buffer[c++] = i % radix + '0'; + i /= radix; + } while (i>0); + + buffer[c] = '\0'; + reverse(buffer); + print_string(buffer); +} + +void print_int_hex(unsigned int i) { + int radix = 16; + //Buffer size is based on a guess at something larger than + //a maxint val + char buffer [(sizeof(int)*3)+1]; + int c=0; + do { + int hexit = i%radix; + if (hexit<10) { + buffer[c++] = hexit + '0'; + } else { + hexit = hexit-10; + buffer[c++] = hexit + 'a'; + } + i /= radix; + } while (i>0); + + buffer[c] = '\0'; + reverse(buffer); + print_string(buffer); + +} + +void print_substring(char* c) { + print_string(c); +} + +void print_escape_char(char c) { + switch(c) { + case '\n': + next_line(); + update_cursor(); + break; + default: + printchar(c); + } +} + +void _kern_print(const char* fmt_string, ...) { + int i; + int value; + char* s; + va_list args; + + va_start(args,fmt_string); + + for (i=0; fmt_string[i] != '\0'; i++) { + if (fmt_string[i] == '%') { + i++; + switch (fmt_string[i]) { + case 'd': + case 'u': + value = va_arg(args, int); + print_int_dec(value); + break; + case 's': + s = va_arg(args, char*); + print_substring(s); + break; + case 'x': + value = va_arg(args, int); + print_int_hex(value); + break; + case '%': + print_escape_char(fmt_string[i]); + break; + } + } else { + print_escape_char(fmt_string[i]); + } + } + update_cursor(); + + va_end(args); +} diff --git a/lib/string.c b/lib/string.c new file mode 100644 index 0000000..d3818c8 --- /dev/null +++ b/lib/string.c @@ -0,0 +1,226 @@ +// Basic string routines. Not hardware optimized, but not shabby. + +#include + +int +strlen(const char *s) +{ + int n; + + for (n = 0; *s != '\0'; s++) + n++; + return n; +} + +int +strnlen(const char *s, size_t size) +{ + int n; + + for (n = 0; size > 0 && *s != '\0'; s++, size--) + n++; + return n; +} + +char * +strcpy(char *dst, const char *src) +{ + char *ret; + + ret = dst; + while ((*dst++ = *src++) != '\0') + /* do nothing */; + return ret; +} + +char * +strncpy(char *dst, const char *src, size_t size) { + size_t i; + char *ret; + + ret = dst; + for (i = 0; i < size; i++) { + *dst++ = *src; + // If strlen(src) < size, null-pad 'dst' out to 'size' chars + if (*src != '\0') + src++; + } + return ret; +} + +size_t +strlcpy(char *dst, const char *src, size_t size) +{ + char *dst_in; + + dst_in = dst; + if (size > 0) { + while (--size > 0 && *src != '\0') + *dst++ = *src++; + *dst = '\0'; + } + return dst - dst_in; +} + +int +strcmp(const char *p, const char *q) +{ + while (*p && *p == *q) + p++, q++; + return (int) ((unsigned char) *p - (unsigned char) *q); +} + +int +strncmp(const char *p, const char *q, size_t n) +{ + while (n > 0 && *p && *p == *q) + n--, p++, q++; + if (n == 0) + return 0; + else + return (int) ((unsigned char) *p - (unsigned char) *q); +} + +// Return a pointer to the first occurrence of 'c' in 's', +// or a null pointer if the string has no 'c'. +char * +strchr(const char *s, char c) +{ + for (; *s; s++) + if (*s == c) + return (char *) s; + return 0; +} + +// Return a pointer to the first occurrence of 'c' in 's', +// or a pointer to the string-ending null character if the string has no 'c'. +char * +strfind(const char *s, char c) +{ + for (; *s; s++) + if (*s == c) + break; + return (char *) s; +} + + +void * +memset(void *v, int c, size_t n) +{ + char *p; + int m; + + p = v; + m = n; + while (--m >= 0) + *p++ = c; + + return v; +} + +void * +memcpy(void *dst, const void *src, size_t n) +{ + const char *s; + char *d; + + s = src; + d = dst; + while (n-- > 0) + *d++ = *s++; + + return dst; +} + +void * +memmove(void *dst, const void *src, size_t n) +{ + const char *s; + char *d; + + s = src; + d = dst; + if (s < d && s + n > d) { + s += n; + d += n; + while (n-- > 0) + *--d = *--s; + } else + while (n-- > 0) + *d++ = *s++; + + return dst; +} + +int +memcmp(const void *v1, const void *v2, size_t n) +{ + const uint8_t *s1 = (const uint8_t *) v1; + const uint8_t *s2 = (const uint8_t *) v2; + + while (n-- > 0) { + if (*s1 != *s2) + return (int) *s1 - (int) *s2; + s1++, s2++; + } + + return 0; +} + +void * +memfind(const void *s, int c, size_t n) +{ + const void *ends = (const char *) s + n; + for (; s < ends; s++) + if (*(const unsigned char *) s == (unsigned char) c) + break; + return (void *) s; +} + +long +strtol(const char *s, char **endptr, int base) +{ + int neg = 0; + long val = 0; + + // gobble initial whitespace + while (*s == ' ' || *s == '\t') + s++; + + // plus/minus sign + if (*s == '+') + s++; + else if (*s == '-') + s++, neg = 1; + + // hex or octal base prefix + if ((base == 0 || base == 16) && (s[0] == '0' && s[1] == 'x')) + s += 2, base = 16; + else if (base == 0 && s[0] == '0') + s++, base = 8; + else if (base == 0) + base = 10; + + // digits + while (1) { + int dig; + + if (*s >= '0' && *s <= '9') + dig = *s - '0'; + else if (*s >= 'a' && *s <= 'z') + dig = *s - 'a' + 10; + else if (*s >= 'A' && *s <= 'Z') + dig = *s - 'A' + 10; + else + break; + if (dig >= base) + break; + s++, val = (val * base) + dig; + // we don't properly detect overflow! + } + + if (endptr) + *endptr = (char *) s; + return (neg ? -val : val); +} + -- 2.34.1