From 07b2250270fa5253794342c3125a6dacba39be7c Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Fri, 8 Nov 2013 17:22:37 +0100 Subject: [PATCH] add the "smallest" HelloWorld of the world --- .gitignore | 7 + Makefile.example | 86 ++++++ Makefile.inc | 20 ++ NOTICE | 23 ++ README | 28 ++ README.md | 4 - arch/x86/include/asm/io.h | 70 +++++ arch/x86/include/asm/limits.h | 87 ++++++ arch/x86/include/asm/multiboot.h | 142 +++++++++ arch/x86/include/asm/processor.h | 80 +++++ arch/x86/include/asm/stddef.h | 73 +++++ arch/x86/include/asm/string.h | 47 +++ arch/x86/include/asm/vga.h | 46 +++ arch/x86/kernel/Makefile | 5 + arch/x86/kernel/entry.asm | 102 +++++++ arch/x86/kernel/multiboot.c | 41 +++ arch/x86/kernel/vga.c | 235 +++++++++++++++ include/eduos/config.h.example | 49 ++++ include/eduos/processor.h | 43 +++ include/eduos/stdarg.h | 46 +++ include/eduos/stddef.h | 71 +++++ include/eduos/stdio.h | 68 +++++ include/eduos/stdlib.h | 47 +++ include/eduos/string.h | 71 +++++ kernel/Makefile | 4 + kernel/main.c | 67 +++++ libkern/Makefile | 4 + libkern/divdi3.c | 63 ++++ libkern/moddi3.c | 65 +++++ libkern/printf.c | 485 +++++++++++++++++++++++++++++++ libkern/qdivrem.c | 329 +++++++++++++++++++++ libkern/quad.h | 51 ++++ libkern/stdio.c | 55 ++++ libkern/string.c | 137 +++++++++ libkern/udivdi3.c | 53 ++++ libkern/umoddi3.c | 56 ++++ link.ld | 29 ++ 37 files changed, 2885 insertions(+), 4 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile.example create mode 100644 Makefile.inc create mode 100644 NOTICE create mode 100644 README delete mode 100644 README.md create mode 100644 arch/x86/include/asm/io.h create mode 100644 arch/x86/include/asm/limits.h create mode 100644 arch/x86/include/asm/multiboot.h create mode 100644 arch/x86/include/asm/processor.h create mode 100644 arch/x86/include/asm/stddef.h create mode 100644 arch/x86/include/asm/string.h create mode 100644 arch/x86/include/asm/vga.h create mode 100644 arch/x86/kernel/Makefile create mode 100644 arch/x86/kernel/entry.asm create mode 100644 arch/x86/kernel/multiboot.c create mode 100644 arch/x86/kernel/vga.c create mode 100644 include/eduos/config.h.example create mode 100644 include/eduos/processor.h create mode 100644 include/eduos/stdarg.h create mode 100644 include/eduos/stddef.h create mode 100644 include/eduos/stdio.h create mode 100644 include/eduos/stdlib.h create mode 100644 include/eduos/string.h create mode 100644 kernel/Makefile create mode 100644 kernel/main.c create mode 100644 libkern/Makefile create mode 100644 libkern/divdi3.c create mode 100644 libkern/moddi3.c create mode 100644 libkern/printf.c create mode 100644 libkern/qdivrem.c create mode 100644 libkern/quad.h create mode 100644 libkern/stdio.c create mode 100644 libkern/string.c create mode 100644 libkern/udivdi3.c create mode 100644 libkern/umoddi3.c create mode 100644 link.ld diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d81ac8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.o +*.dep +*~ +*.elf +*.sym +Makefile +include/eduos/config.h diff --git a/Makefile.example b/Makefile.example new file mode 100644 index 0000000..8454c92 --- /dev/null +++ b/Makefile.example @@ -0,0 +1,86 @@ +TOPDIR = $(shell pwd) +ARCH = x86 +NAME = eduos +KERNDIRS = libkern kernel arch/$(ARCH)/kernel +SUBDIRS = $(KERNDIRS) + +# Set your own cross compiler tool chain prefix here +CROSSCOMPREFIX = + +CC_FOR_TARGET = $(CROSSCOMPREFIX)gcc +CXX_FOR_TARGET = $(CROSSCOMPREFIX)g++ +GCC_FOR_TARGET = $(CROSSCOMPREFIX)gcc +CPP_FOR_TARGET = $(CROSSCOMPREFIX)cpp +AR_FOR_TARGET = $(CROSSCOMPREFIX)ar +AS_FOR_TARGET = $(CROSSCOMPREFIX)as +LD_FOR_TARGET = $(CROSSCOMPREFIX)ld +NM_FOR_TARGET = $(CROSSCOMPREFIX)nm +OBJDUMP_FOR_TARGET = $(CROSSCOMPREFIX)objdump +OBJCOPY_FOR_TARGET = $(CROSSCOMPREFIX)objcopy +RANLIB_FOR_TARGET = $(CROSSCOMPREFIX)ranlib +STRIP_FOR_TARGET = $(CROSSCOMPREFIX)strip +READELF_FOR_TARGET = $(CROSSCOMPREFIX)readelf +NASM = nasm + +NASMFLAGS = -felf32 -g +INCLUDE = -I$(TOPDIR)/include -I$(TOPDIR)/arch/$(ARCH)/include +# Compiler options for final code +CFLAGS = -g -m32 -march=i586 -Wall -O2 -fno-builtin -fstrength-reduce -fomit-frame-pointer -finline-functions -nostdinc $(INCLUDE) -fno-stack-protector +# Compiler options for debugging +#CFLAGS = -g -O -m32 -march=i586 -Wall -fno-builtin -DWITH_FRAME_POINTER -nostdinc $(INCLUDE) -fno-stack-protector +AR = ar +ARFLAGS = rsv +RM = rm -rf +LDFLAGS = -T link.ld -z max-page-size=4096 --defsym __BUILD_DATE=$(shell date +'%Y%m%d') --defsym __BUILD_TIME=$(shell date +'%H%M%S') +STRIP_DEBUG = --strip-debug +KEEP_DEBUG = --only-keep-debug + +# Prettify output +V = 0 +ifeq ($V,0) + Q = @ + P = > /dev/null +endif + +default: all + +all: $(NAME).elf + +$(NAME).elf: + $Q$(LD_FOR_TARGET) $(LDFLAGS) -o $(NAME).elf $^ + @echo [OBJCOPY] $(NAME).sym + $Q$(OBJCOPY_FOR_TARGET) $(KEEP_DEBUG) $(NAME).elf $(NAME).sym + @echo [OBJCOPY] $(NAME).elf + $Q$(OBJCOPY_FOR_TARGET) $(STRIP_DEBUG) $(NAME).elf + +clean: + $Q$(RM) $(NAME).elf $(NAME).sym *~ + @echo Cleaned. + +veryclean: clean + $Q$(RM) qemu-vlan0.pcap + @echo Very cleaned + +qemu: $(NAME).elf + qemu-system-i386 -monitor stdio -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel $(NAME).elf + +qemu-dbg: $(NAME).elf + qemu-system-i386 -monitor stdio -s -S -smp 2 -net nic,model=rtl8139 -net user,hostfwd=tcp::12345-:7 -net dump -kernel $(NAME).elf + +%.o : %.c + @echo [CC] $@ + $Q$(CC_FOR_TARGET) -c -D__KERNEL__ $(CFLAGS) -o $@ $< + @echo [DEP] $*.dep + $Q$(CC_FOR_TARGET) -MF $*.dep -MT $*.o -MM $(CFLAGS) $< + +%.o : %.asm + @echo [ASM] $@ + $Q$(NASM) $(NASMFLAGS) -o $@ $< + +%.o : %.S + @echo [GCC-ASM] $@ + $Q$(CC_FOR_TARGET) $(CFLAGS) -c -o $@ $< + +.PHONY: default all clean emu gdb newlib tools + +include $(addsuffix /Makefile,$(SUBDIRS)) diff --git a/Makefile.inc b/Makefile.inc new file mode 100644 index 0000000..743cacc --- /dev/null +++ b/Makefile.inc @@ -0,0 +1,20 @@ +C_source-$(MODULE) := $(addprefix $(subst _,/,$(MODULE))/,$(filter %.c,$(C_source))) +ASM_source-$(MODULE) := $(addprefix $(subst _,/,$(MODULE))/,$(filter %.asm,$(ASM_source))) +C_source := +ASM_source := + +OBJS-$(MODULE) := $(C_source-$(MODULE):.c=.o) +OBJS-$(MODULE) += $(ASM_source-$(MODULE):.asm=.o) + +$(MODULE): $(OBJS-$(MODULE)) + +$(NAME).elf: $(OBJS-$(MODULE)) + +clean: clean-$(MODULE) +clean-$(MODULE): clean-% : + @echo Cleaning $(subst _,/,$*) + $Q$(RM) $(OBJS-$*) $(C_source-$*:.c=.dep) + +.PHONY: clean-$(MODULE) $(MODULE) + +-include $(C_source-$(MODULE):.c=.dep) diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..b4868f3 --- /dev/null +++ b/NOTICE @@ -0,0 +1,23 @@ + + eduOS + Copyright 2010-2013, Stefan Lankes, RWTH Aachen University + +The learning operating system eduOS is derived from following tutorials +and software distributions. + +========================================================================= += bkerndev - Bran's Kernel Development Tutorial = +========================================================================= +The first steps to realize eduOS based on Bran's Kernel Development +Tutorial (http://www.osdever.net/bkerndev/index.php). In particular, the +initialization of GDT, IDT and the interrupt handlers are derived from +this tutorial. + +========================================================================= += kprintf, umoddu3, udivdi3, qdivrem, divdi3, lshrdi3, moddi3, strtol, = += strtoul, ucmpdi2 = +========================================================================= +This software contains code 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. diff --git a/README b/README new file mode 100644 index 0000000..ce7f29d --- /dev/null +++ b/README @@ -0,0 +1,28 @@ +Requirements of eduOS +===================== + +1.) Currently, eduOS supports only x86-based architectures. +2.) Following command line tools have to be installed: + make, gcc, binutil, git, qemu, nams, gdb +3.) The test PC has to use grub as bootloader. + +Building eduOS +============== + +1.) Copy Makefile.example to Makefile and edit this Makefile to meet your individual convenience. +2.) Copy include/eduos/config.h.example to include/eduos/config.h and edit this config file to + meet your individual convenience. +3.) Create the dependencies of eduOS with "make depend". +4.) Build kernel with "make" +5.) Copy eduos.bin into the /boot directory. +6.) Create a boot entry in the grub menu. This depends on the version of grub, which is used by + the installed Linux system. For instance, we added following lines to /boot/grub/grub.cfg: + + ### BEGIN /etc/grub.d/40_custom ### + # This file provides an easy way to add custom menu entries. Simply type the + # menu entries you want to add after this comment. Be careful not to change + # the 'exec tail' line above. + menuentry "Boot eduOS!" { + multiboot /boot/eduos.bin + boot + } diff --git a/README.md b/README.md deleted file mode 100644 index ee8dcd0..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -eduOS -===== - -A learning operating system to get a deeper knowledge into system software diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h new file mode 100644 index 0000000..46cac3c --- /dev/null +++ b/arch/x86/include/asm/io.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __ARCH_IO_H__ +#define __ARCH_IO_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +inline static unsigned char inportb(unsigned short _port) { + unsigned char rv; + asm volatile("inb %1, %0":"=a"(rv):"dN"(_port)); + return rv; +} + +inline static unsigned short inportw(unsigned short _port) { + unsigned short rv; + asm volatile("inw %1, %0":"=a"(rv):"dN"(_port)); + return rv; +} + +inline static unsigned int inportl(unsigned short _port) { + unsigned int rv; + asm volatile("inl %1, %0":"=a"(rv):"dN"(_port)); + return rv; +} + +inline static void outportb(unsigned short _port, unsigned char _data) { + asm volatile("outb %1, %0"::"dN"(_port), "a"(_data)); +} + +inline static void outportw(unsigned short _port, unsigned short _data) { + asm volatile("outw %1, %0"::"dN"(_port), "a"(_data)); +} + +inline static void outportl(unsigned short _port, unsigned int _data) +{ + asm volatile("outl %1, %0"::"dN"(_port), "a"(_data)); +} + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/include/asm/limits.h b/arch/x86/include/asm/limits.h new file mode 100644 index 0000000..e8ad07d --- /dev/null +++ b/arch/x86/include/asm/limits.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +/** + * author Stefan Lankes + * @file arch/x86/include/asm/limits.h + * @brief Define constants related to numerical value-ranges of variable types + * + * This file contains define constants for the numerical + * ranges of the most typical variable types. + */ + +#ifndef __ARCH_LIMITS_H__ +#define __ARCH_LIMITS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Number of bits in a char */ +#define CHAR_BIT 8 + +/** Maximum value for a signed char */ +#define SCHAR_MAX 0x7f +/** Minimum value for a signed char */ +#define SCHAR_MIN (-0x7f - 1) + +/** Maximum value for an unsigned char */ +#define UCHAR_MAX 0xff + +/** Maximum value for an unsigned short */ +#define USHRT_MAX 0xffff +/** Maximum value for a short */ +#define SHRT_MAX 0x7fff +/** Minimum value for a short */ +#define SHRT_MIN (-0x7fff - 1) + +/** Maximum value for an unsigned int */ +#define UINT_MAX 0xffffffffU +/** Maximum value for an int */ +#define INT_MAX 0x7fffffff +/** Minimum value for an int */ +#define INT_MIN (-0x7fffffff - 1) + +/** Maximum value for an unsigned long */ +#define ULONG_MAX 0xffffffffUL +/** Maximum value for a long */ +#define LONG_MAX 0x7fffffffL +/** Minimum value for a long */ +#define LONG_MIN (-0x7fffffffL - 1) + +/** Maximum value for an unsigned long long */ +#define ULLONG_MAX 0xffffffffffffffffULL +/** Maximum value for a long long */ +#define LLONG_MAX 0x7fffffffffffffffLL +/** Minimum value for a long long */ +#define LLONG_MIN (-0x7fffffffffffffffLL - 1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/include/asm/multiboot.h b/arch/x86/include/asm/multiboot.h new file mode 100644 index 0000000..0f74111 --- /dev/null +++ b/arch/x86/include/asm/multiboot.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __ARCH_MULTIBOOT_H__ +#define __ARCH_MULTIBOOT_H__ + +#include + +/* + * eduOS is able to use Multiboot (http://www.gnu.org/software/grub/manual/multiboot/), + * which specifies an interface between a boot loader and a operating system + */ + +typedef uint16_t multiboot_uint16_t; +typedef uint32_t multiboot_uint32_t; +typedef uint64_t multiboot_uint64_t; + +/* 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_uint64_t addr; + multiboot_uint64_t len; +#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; + +extern multiboot_info_t* mb_info; + +#endif diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h new file mode 100644 index 0000000..f6ddfcc --- /dev/null +++ b/arch/x86/include/asm/processor.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __ARCH_PROCESSOR_H__ +#define __ARCH_PROCESSOR_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +inline static uint64_t rdtsc(void) +{ + uint64_t x; + asm volatile ("rdtsc" : "=A" (x)); + return x; +} + +inline static void flush_cache(void) { + asm volatile ("wbinvd" : : : "memory"); +} + +inline static void invalid_cache(void) { + asm volatile ("invd"); +} + +inline static int get_return_value(void) { + int ret; + + asm volatile ("movl %%eax, %0" : "=r"(ret)); + + return ret; +} + +/* Force strict CPU ordering */ +#ifdef CONFIG_ROCKCREEK +inline static void mb(void) { asm volatile ("lock; addl $0,0(%%esp)" ::: "memory", "cc"); } +inline static void rmb(void) { asm volatile ("lock; addl $0,0(%%esp)" ::: "memory", "cc"); } +inline static void wmb(void) { asm volatile ("lock; addl $0,0(%%esp)" ::: "memory", "cc"); } +#else +inline static void mb(void) { asm volatile("mfence" ::: "memory"); } +inline static void rmb(void) { asm volatile("lfence" ::: "memory"); } +inline static void wmb(void) { asm volatile("sfence" ::: "memory"); } +#endif + +#define NOP1 asm volatile ("nop") +#define NOP2 asm volatile ("nop;nop") +#define NOP4 asm volatile ("nop;nop;nop;nop") +#define NOP8 asm volatile ("nop;nop;nop;nop;nop;nop;nop;nop") + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/include/asm/stddef.h b/arch/x86/include/asm/stddef.h new file mode 100644 index 0000000..1a78d7d --- /dev/null +++ b/arch/x86/include/asm/stddef.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __ARCH_STDDEF_H__ +#define __ARCH_STDDEF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned long size_t; +typedef long ptrdiff_t; +#ifdef __KERNEL__ +typedef long ssize_t; +typedef long off_t; +#endif + +typedef unsigned long long uint64_t; +typedef long long int64_t; +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef unsigned char uint8_t; +typedef char int8_t; +typedef unsigned short wchar_t; + +#ifndef _WINT_T +#define _WINT_T +typedef unsigned int wint_t; +#endif + +/* This defines what the stack looks like after an ISR was running */ +struct state { + /* + * We switched from software- to hardwaree-based multitasking + * Therefore, we do not longer save the registers by hand. + */ + /*unsigned int gs, fs, es, ds; */ /* pushed the segs last */ + unsigned int edi, esi, ebp, esp, ebx, edx, ecx, eax; /* pushed by 'pusha' */ + unsigned int int_no, err_code; /* our 'push byte #' and ecodes do this */ + /*unsigned int eip, cs, eflags, useresp, ss;*/ /* pushed by the processor automatically */ +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h new file mode 100644 index 0000000..d5c2e4e --- /dev/null +++ b/arch/x86/include/asm/string.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __ARCH_STRING_H__ +#define __ARCH_STRING_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * TODO: add architecture optimized versions of standard functions like memcpy + * + * Perhapy you could use your experiences from GI4! + */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/include/asm/vga.h b/arch/x86/include/asm/vga.h new file mode 100644 index 0000000..01f697a --- /dev/null +++ b/arch/x86/include/asm/vga.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __ARCH_VGA_H__ +#define __ARCH_VGA_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void vga_init(void); +int vga_puts(const char *text); +int vga_putchar(unsigned char c); +void vga_cls(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile new file mode 100644 index 0000000..57d96ec --- /dev/null +++ b/arch/x86/kernel/Makefile @@ -0,0 +1,5 @@ +C_source := multiboot.c vga.c +ASM_source := entry.asm +MODULE := arch_x86_kernel + +include $(TOPDIR)/Makefile.inc diff --git a/arch/x86/kernel/entry.asm b/arch/x86/kernel/entry.asm new file mode 100644 index 0000000..f58877e --- /dev/null +++ b/arch/x86/kernel/entry.asm @@ -0,0 +1,102 @@ +; +; Copyright (c) 2010, Stefan Lankes, RWTH Aachen University +; All rights reserved. +; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions are met: +; * Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; * 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. +; * 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 COPYRIGHT HOLDERS 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. + +[BITS 32] +; We use a special name to map this section at the begin of our kernel +; => Multiboot needs its magic number at the begin of the kernel +SECTION .mboot +global start +start: + jmp stublet + +; This part MUST be 4byte aligned, so we solve that issue using 'ALIGN 4' +ALIGN 4 +mboot: + ; Multiboot macros to make a few lines more readable later + MULTIBOOT_PAGE_ALIGN equ 1<<0 + MULTIBOOT_MEMORY_INFO equ 1<<1 + ; MULTIBOOT_AOUT_KLUDGE equ 1<<16 + MULTIBOOT_HEADER_MAGIC equ 0x1BADB002 + MULTIBOOT_HEADER_FLAGS equ MULTIBOOT_PAGE_ALIGN | MULTIBOOT_MEMORY_INFO ; | MULTIBOOT_AOUT_KLUDGE + MULTIBOOT_CHECKSUM equ -(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS) + EXTERN code, bss, end + + ; This is the GRUB Multiboot header. A boot signature + dd MULTIBOOT_HEADER_MAGIC + dd MULTIBOOT_HEADER_FLAGS + dd MULTIBOOT_CHECKSUM + + ; AOUT kludge - must be physical addresses. Make a note of these: + ; The linker script fills in the data for these ones! + ; dd mboot + ; dd code + ; dd bss + ; dd end + ; dd start + +SECTION .text +ALIGN 4 +stublet: +; initialize stack pointer. + mov esp, default_stack_pointer +; initialize cpu features + call cpu_init +; interpret multiboot information + extern multiboot_init + push ebx + call multiboot_init + add esp, 4 + +; jump to the boot processors's C code + extern main + call main + jmp $ + +global cpu_init +cpu_init: + mov eax, cr0 +; enable caching, disable paging and fpu emulation + and eax, 0x1ffffffb +; ...and turn on FPU exceptions + or eax, 0x22 + mov cr0, eax +; clears the current pgd entry + xor eax, eax + mov cr3, eax +; at this stage, we disable the SSE support + mov eax, cr4 + and eax, 0xfffbf9ff + mov cr4, eax + ret + +; Here is the definition of our stack. Remember that a stack actually grows +; downwards, so we declare the size of the data before declaring +; the identifier 'default_stack_pointer' +SECTION .data + resb 8192 ; This reserves 8KBytes of memory here +default_stack_pointer: + +SECTION .note.GNU-stack noalloc noexec nowrite progbits diff --git a/arch/x86/kernel/multiboot.c b/arch/x86/kernel/multiboot.c new file mode 100644 index 0000000..f6bd932 --- /dev/null +++ b/arch/x86/kernel/multiboot.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#include +#include + +/* + * eduOS is able to use Multiboot (http://www.gnu.org/software/grub/manual/multiboot/), + * which specifies an interface between a boot loader and a operating system + */ + +multiboot_info_t* mb_info __attribute__ ((section (".data"))) = NULL; + +void multiboot_init(void* mb) +{ + mb_info = (multiboot_info_t*) mb; +} diff --git a/arch/x86/kernel/vga.c b/arch/x86/kernel/vga.c new file mode 100644 index 0000000..1107aee --- /dev/null +++ b/arch/x86/kernel/vga.c @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#include +#include +#include + +/* + * These define our textpointer, our background and foreground + * colors (attributes), and x and y cursor coordinates + */ +static unsigned short *textmemptr; +static int attrib = 0x0F; +static int csr_x = 0, csr_y = 0; + +inline static unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t count) +{ + size_t i; + + if (BUILTIN_EXPECT(!dest, 0)) + return dest; + + for (i = 0; i < count; i++) + dest[i] = val; + + return dest; +} + +/* Scrolls the screen */ +static void scroll(void) +{ + unsigned blank, temp; + + /* + * A blank is defined as a space... we need to give it + * backcolor too + */ + blank = 0x20 | (attrib << 8); + + /* Row 25 is the end, this means we need to scroll up */ + if (csr_y >= 25) { + + /* + * Move the current text chunk that makes up the screen + * + * back in the buffer by one line + */ + temp = csr_y - 25 + 1; + memcpy(textmemptr, textmemptr + temp * 80, + (25 - temp) * 80 * 2); + + /* + * Finally, we set the chunk of memory that occupies + * the last line of text to our 'blank' character + */ + memsetw(textmemptr + (25 - temp) * 80, blank, 80); + csr_y = 25 - 1; + } +} + +/* + * Updates the hardware cursor: the little blinking line + * on the screen under the last character pressed! + */ +static void move_csr(void) +{ + unsigned temp; + + /* + * The equation for finding the index in a linear + * chunk of memory can be represented by: + * Index = [(y * width) + x] */ + temp = csr_y * 80 + csr_x; + + /* + * This sends a command to indicies 14 and 15 in the + * CRT Control Register of the VGA controller. These + * are the high and low bytes of the index that show + * where the hardware cursor is to be 'blinking'. To + * learn more, you should look up some VGA specific + * programming documents. A great start to graphics: + * http://www.brackeen.com/home/vga + */ + outportb(0x3D4, 14); + outportb(0x3D5, temp >> 8); + outportb(0x3D4, 15); + outportb(0x3D5, temp); +} + +/* Clears the screen */ +void vga_clear(void) +{ + unsigned blank; + int i; + + /* + * Again, we need the 'short' that will be used to + * represent a space with color + */ + blank = 0x20 | (attrib << 8); + + /* + * Fills the entire screen with spaces in our current + * color + **/ + for (i = 0; i < 25; i++) + memsetw(textmemptr + i * 80, blank, 80); + + /* + * Update out virtual cursor, and then move the + * hardware cursor + */ + csr_x = 0; + csr_y = 0; + move_csr(); +} + +/* Puts a single character on the screen */ +int vga_putchar(unsigned char c) +{ + unsigned short *where; + unsigned att = attrib << 8; + + /* Handle a backspace by moving the cursor back one space */ + if (c == 0x08) { + if (csr_x != 0) + csr_x--; + } + + /* + * Handles a tab by incrementing the cursor's x, but only + * to a point that will make it divisible by 8 + */ + else if (c == 0x09) { + csr_x = (csr_x + 8) & ~(8 - 1); + } + + /* + * Handles a 'Carriage Return', which simply brings the + * cursor back to the margin + */ + else if (c == '\r') { + csr_x = 0; + } + + /* + * We handle our newlines the way DOS and BIOS do: we + * treat it as if a 'CR' was there also, so we bring the + * cursor to the margin and increment the 'y' value + */ + else if (c == '\n') { + csr_x = 0; + csr_y++; + } + + /* + * Any character greater than and including the space is a + * printable character. The equation for finding the index + * in a linear chunk of memory can be represented by: + * Index = [(y * width) + x] + */ + else if (c >= ' ') { + where = textmemptr + (csr_y * 80 + csr_x); + *where = c | att; /* Character AND attributes: color */ + csr_x++; + } + + /* + * If the cursor has reached the edge of the screen's width, we + * insert a new line in there + */ + if (csr_x >= 80) { + csr_x = 0; + csr_y++; + } + + /* Scroll the screen if needed, and finally move the cursor */ + scroll(); + move_csr(); + + return (int) c; +} + +/* Uses the routine above to output a string... */ +int vga_puts(const char *text) +{ + size_t i; + + for (i = 0; i < strlen(text); i++) + vga_putchar(text[i]); + + return i-1; +} + +/* Sets the forecolor and backcolor we will use */ +//void settextcolor(unsigned char forecolor, unsigned char backcolor) +//{ + + /* + * Top 4 bytes are the background, bottom 4 bytes + * are the foreground color + */ +// attrib = (backcolor << 4) | (forecolor & 0x0F); +//} + +/* Sets our text-mode VGA pointer, then clears the screen for us */ +void vga_init(void) +{ + textmemptr = (unsigned short *)VIDEO_MEM_ADDR; + vga_clear(); +} diff --git a/include/eduos/config.h.example b/include/eduos/config.h.example new file mode 100644 index 0000000..ad796f3 --- /dev/null +++ b/include/eduos/config.h.example @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define EDUOS_VERSION "0.1" +#define VIDEO_MEM_ADDR 0xB8000 // the video memora address + +#define BYTE_ORDER LITTLE_ENDIAN + +#define BUILTIN_EXPECT(exp, b) __builtin_expect((exp), (b)) +//#define BUILTIN_EXPECT(exp, b) (exp) +#define NORETURN __attribute__((noreturn)) +#define STDCALL __attribute__((stdcall)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/eduos/processor.h b/include/eduos/processor.h new file mode 100644 index 0000000..9028c73 --- /dev/null +++ b/include/eduos/processor.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __PROCESSOR_H__ +#define __PROCESSOR_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/eduos/stdarg.h b/include/eduos/stdarg.h new file mode 100644 index 0000000..9b8d02d --- /dev/null +++ b/include/eduos/stdarg.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __STDARG_H__ +#define __STDARG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef __builtin_va_list va_list; + +#define va_start __builtin_va_start +#define va_arg __builtin_va_arg +#define va_end __builtin_va_end +#define va_copy __builtin_va_copy + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/eduos/stddef.h b/include/eduos/stddef.h new file mode 100644 index 0000000..888e372 --- /dev/null +++ b/include/eduos/stddef.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __STDDEF_H__ +#define __STDDEF_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define NULL ((void*) 0) + +#define per_core(name) name +#define CORE_ID 0 + +/** @brief String to long + * + * @return Long value of the parsed numerical string + */ +long strtol(const char* str, char** endptr, int base); + +/** @brief String to unsigned long + * + * @return Unsigned long value of the parsed numerical string + */ +unsigned long strtoul(const char* nptr, char** endptr, int base); + +/** @brief ASCII to integer + * + * Convenience function using strtol(). + * + * @return Integer value of the parsed numerical string + */ +static inline int atoi(const char *str) +{ + return (int)strtol(str, (char **)NULL, 10); +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/eduos/stdio.h b/include/eduos/stdio.h new file mode 100644 index 0000000..360e4f1 --- /dev/null +++ b/include/eduos/stdio.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __STDIO_H__ +#define __STDIO_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Works like the ANSI C function puts + */ +int kputs(const char *); + +/* + * Works like the ANSI c function putchar + */ +int kputchar(int); + +/* + * Works like the ANSI C function printf + */ +int kprintf(const char*, ...); + +/* + * Initialize the I/O functions + */ +int koutput_init(void); + +/* + * Scaled down version of printf(3) + */ +int kvprintf(char const *fmt, void (*func) (int, void *), void *arg, int radix, va_list ap); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/eduos/stdlib.h b/include/eduos/stdlib.h new file mode 100644 index 0000000..7c32bcf --- /dev/null +++ b/include/eduos/stdlib.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __STDLIB_H__ +#define __STDLIB_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void NORETURN abort(void); +void* kmalloc(size_t); +void kfree(void*, size_t); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/eduos/string.h b/include/eduos/string.h new file mode 100644 index 0000000..e27410e --- /dev/null +++ b/include/eduos/string.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#ifndef __STRING_H__ +#define __STRING_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HAVE_ARCH_MEMCPY +void *memcpy(void *dest, const void *src, size_t count); +#endif + +#ifndef HAVE_ARCH_MEMSET +void *memset(void *dest, int val, size_t count); +#endif + +#ifndef HAVE_ARCH_STRLEN +size_t strlen(const char *str); +#endif + +#ifndef HAVE_ARCH_STRNCPY +char* strncpy(char *dest, const char *src, size_t n); +#endif + +#ifndef HAVE_ARCH_STRCPY +char* strcpy(char *dest, const char *src); +#endif + +#ifndef HAVE_ARCH_STRCMP +int strcmp(const char *s1, const char *s2); +#endif + +#ifndef HAVE_ARCH_STRNCMP +int strncmp(const char *s1, const char *s2, size_t n); +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kernel/Makefile b/kernel/Makefile new file mode 100644 index 0000000..06612ba --- /dev/null +++ b/kernel/Makefile @@ -0,0 +1,4 @@ +C_source := main.c +MODULE := kernel + +include $(TOPDIR)/Makefile.inc diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000..aec08a6 --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#include +#include +#include +#include + +/* + * Note that linker symbols are not variables, they have no memory allocated for + * maintaining a value, rather their address is their value. + */ +extern const void kernel_start; +extern const void kernel_end; +extern const void bss_start; +extern const void bss_end; +extern char __BUILD_DATE; +extern char __BUILD_TIME; + +static int eduos_init(void) +{ + // initialize .bss section + memset((void*)&bss_start, 0x00, ((size_t) &bss_end - (size_t) &bss_start)); + + koutput_init(); + + return 0; +} + +int main(void) +{ + eduos_init(); + + kprintf("This is eduOS %s Build %u, %u\n", EDUOS_VERSION, &__BUILD_DATE, &__BUILD_TIME); + kprintf("Kernel starts at %p and ends at %p\n", &kernel_start, &kernel_end); + kprintf("\nHello World!\n"); + + while(1) { + NOP8; + } + + return 0; +} diff --git a/libkern/Makefile b/libkern/Makefile new file mode 100644 index 0000000..72e16b9 --- /dev/null +++ b/libkern/Makefile @@ -0,0 +1,4 @@ +C_source := string.c stdio.c printf.c moddi3.c umoddi3.c divdi3.c udivdi3.c qdivrem.c +MODULE := libkern + +include $(TOPDIR)/Makefile.inc diff --git a/libkern/divdi3.c b/libkern/divdi3.c new file mode 100644 index 0000000..b6cfe21 --- /dev/null +++ b/libkern/divdi3.c @@ -0,0 +1,63 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 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. + */ + +/* + * The code has been taken from FreeBSD (sys/libkern/divdi3.c) and is therefore + * BSD-licensed. Unnecessary functions have been removed and all typedefs required + * have been added in quad.h. + */ + +#include "quad.h" + +/* + * Divide two signed quads. + * ??? if -1/2 should produce -1 on this machine, this code is wrong + */ +quad_t +__divdi3(a, b) + quad_t a, b; +{ + u_quad_t ua, ub, uq; + int neg; + + if (a < 0) + ua = -(u_quad_t)a, neg = 1; + else + ua = a, neg = 0; + if (b < 0) + ub = -(u_quad_t)b, neg ^= 1; + else + ub = b; + uq = __qdivrem(ua, ub, (u_quad_t *)0); + return (neg ? -uq : uq); +} diff --git a/libkern/moddi3.c b/libkern/moddi3.c new file mode 100644 index 0000000..5f8ad89 --- /dev/null +++ b/libkern/moddi3.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 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. + */ + +/* + * The code has been taken from FreeBSD (sys/libkern/moddi3.c) and is therefore + * BSD-licensed. Unnecessary functions have been removed and all typedefs required + * have been added quad.h. + */ + +#include "quad.h" + +/* + * Return remainder after dividing two signed quads. + * + * XXX + * If -1/2 should produce -1 on this machine, this code is wrong. + */ +quad_t +__moddi3(a, b) + quad_t a, b; +{ + u_quad_t ua, ub, ur; + int neg; + + if (a < 0) + ua = -(u_quad_t)a, neg = 1; + else + ua = a, neg = 0; + if (b < 0) + ub = -(u_quad_t)b; + else + ub = b; + (void)__qdivrem(ua, ub, &ur); + return (neg ? -ur : ur); +} diff --git a/libkern/printf.c b/libkern/printf.c new file mode 100644 index 0000000..097e5c3 --- /dev/null +++ b/libkern/printf.c @@ -0,0 +1,485 @@ +/*- + * Copyright (c) 1986, 1988, 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. + * 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. + * + * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 + */ + + +/* + * eduOS's printf implementation is based on a implementation which was + * published at http://www.pagetable.com/?p=298. + * The authors built a full-featured standalone version of printf(). The + * base code has been taken from FreeBSD (sys/kern/subr_prf.c) and is + * therefore BSD-licensed. Unnecessary functions have been removed and + * all typedefs required have been added. + */ + +#include + +#define __64BIT__ + +#ifdef __64BIT__ +typedef unsigned long long uintmax_t; +typedef long long intmax_t; +#else +typedef unsigned int uintmax_t; +typedef int intmax_t; +#endif +typedef unsigned char u_char; +typedef unsigned int u_int; +typedef unsigned long u_long; +typedef unsigned short u_short; +typedef unsigned long long u_quad_t; +typedef long long quad_t; +typedef unsigned long uintptr_t; +#define NBBY 8 /* number of bits in a byte */ +char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; +#define hex2ascii(hex) (hex2ascii_data[hex]) +#define va_list __builtin_va_list +#define va_start __builtin_va_start +#define va_arg __builtin_va_arg +#define va_end __builtin_va_end +#define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z'))) + +/* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ +#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) + +/* + * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse + * order; return an optional length and a pointer to the last character + * written in the buffer (i.e., the first character of the string). + * The buffer pointed to by `nbuf' must have length >= MAXNBUF. + */ +static char *ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) +{ + char *p, c; + + p = nbuf; + *p = '\0'; + do { + c = hex2ascii(num % base); + *++p = upper ? toupper(c) : c; + } while (num /= base); + if (lenp) + *lenp = p - nbuf; + return (p); +} + +/* + * Scaled down version of printf(3). + * + * Two additional formats: + * + * The format %b is supported to decode error registers. + * Its usage is: + * + * printf("reg=%b\n", regval, "*"); + * + * where the output base is expressed as a control character, e.g. + * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, + * the first of which gives the bit number to be inspected (origin 1), and + * the next characters (up to a control character, i.e. a character <= 32), + * give the name of the register. Thus: + * + * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); + * + * would produce output: + * + * reg=3 + * + * XXX: %D -- Hexdump, takes pointer and separator string: + * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX + * ("%*D", len, ptr, " " -> XX XX XX XX ... + */ +int kvprintf(char const *fmt, void (*func) (int, void *), void *arg, int radix, + va_list ap) +{ +#define PCHAR(c) {int cc=(c); if (func) (*func)(cc,arg); else *d++ = cc; retval++; } + char nbuf[MAXNBUF]; + char *d; + const char *p, *percent, *q; + u_char *up; + int ch, n; + uintmax_t num; + int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; + int cflag, hflag, jflag, tflag, zflag; + int dwidth, upper; + char padc; + int stop = 0, retval = 0; + + num = 0; + if (!func) + d = (char *)arg; + else + d = NULL; + + if (fmt == NULL) + fmt = "(fmt null)\n"; + + if (radix < 2 || radix > 36) + radix = 10; + + for (;;) { + padc = ' '; + width = 0; + while ((ch = (u_char) * fmt++) != '%' || stop) { + if (ch == '\0') + return (retval); + PCHAR(ch); + } + percent = fmt - 1; + qflag = 0; + lflag = 0; + ladjust = 0; + sharpflag = 0; + neg = 0; + sign = 0; + dot = 0; + dwidth = 0; + upper = 0; + cflag = 0; + hflag = 0; + jflag = 0; + tflag = 0; + zflag = 0; + reswitch: switch (ch = (u_char) * fmt++) { + case '.': + dot = 1; + goto reswitch; + case '#': + sharpflag = 1; + goto reswitch; + case '+': + sign = 1; + goto reswitch; + case '-': + ladjust = 1; + goto reswitch; + case '%': + PCHAR(ch); + break; + case '*': + if (!dot) { + width = va_arg(ap, int); + if (width < 0) { + ladjust = !ladjust; + width = -width; + } + } else { + dwidth = va_arg(ap, int); + } + goto reswitch; + case '0': + if (!dot) { + padc = '0'; + goto reswitch; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + for (n = 0;; ++fmt) { + n = n * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + if (dot) + dwidth = n; + else + width = n; + goto reswitch; + case 'b': + num = (u_int) va_arg(ap, int); + p = va_arg(ap, char *); + for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) + PCHAR(*q--); + + if (num == 0) + break; + + for (tmp = 0; *p;) { + n = *p++; + if (num & (1 << (n - 1))) { + PCHAR(tmp ? ',' : '<'); + for (; (n = *p) > ' '; ++p) + PCHAR(n); + tmp = 1; + } else + for (; *p > ' '; ++p) + continue; + } + if (tmp) + PCHAR('>'); + break; + case 'c': + PCHAR(va_arg(ap, int)); + break; + case 'D': + up = va_arg(ap, u_char *); + p = va_arg(ap, char *); + if (!width) + width = 16; + while (width--) { + PCHAR(hex2ascii(*up >> 4)); + PCHAR(hex2ascii(*up & 0x0f)); + up++; + if (width) + for (q = p; *q; q++) + PCHAR(*q); + } + break; + case 'd': + case 'i': + base = 10; + sign = 1; + goto handle_sign; + case 'h': + if (hflag) { + hflag = 0; + cflag = 1; + } else + hflag = 1; + goto reswitch; + case 'j': + jflag = 1; + goto reswitch; + case 'l': + if (lflag) { + lflag = 0; + qflag = 1; + } else + lflag = 1; + goto reswitch; + case 'n': + if (jflag) + *(va_arg(ap, intmax_t *)) = retval; + else if (qflag) + *(va_arg(ap, quad_t *)) = retval; + else if (lflag) + *(va_arg(ap, long *)) = retval; + else if (zflag) + *(va_arg(ap, size_t *)) = retval; + else if (hflag) + *(va_arg(ap, short *)) = retval; + else if (cflag) + *(va_arg(ap, char *)) = retval; + else + *(va_arg(ap, int *)) = retval; + break; + case 'o': + base = 8; + goto handle_nosign; + case 'p': + base = 16; + sharpflag = (width == 0); + sign = 0; + num = (uintptr_t) va_arg(ap, void *); + goto number; + case 'q': + qflag = 1; + goto reswitch; + case 'r': + base = radix; + if (sign) + goto handle_sign; + goto handle_nosign; + case 's': + p = va_arg(ap, char *); + if (p == NULL) + p = "(null)"; + if (!dot) + n = strlen(p); + else + for (n = 0; n < dwidth && p[n]; n++) + continue; + + width -= n; + + if (!ladjust && width > 0) + while (width--) + PCHAR(padc); + while (n--) + PCHAR(*p++); + if (ladjust && width > 0) + while (width--) + PCHAR(padc); + break; + case 't': + tflag = 1; + goto reswitch; + case 'u': + base = 10; + goto handle_nosign; + case 'X': + upper = 1; + case 'x': + base = 16; + goto handle_nosign; + case 'y': + base = 16; + sign = 1; + goto handle_sign; + case 'z': + zflag = 1; + goto reswitch; + handle_nosign: + sign = 0; + if (jflag) + num = va_arg(ap, uintmax_t); + else if (qflag) + num = va_arg(ap, u_quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, u_long); + else if (zflag) + num = va_arg(ap, size_t); + else if (hflag) + num = (u_short) va_arg(ap, int); + else if (cflag) + num = (u_char) va_arg(ap, int); + else + num = va_arg(ap, u_int); + goto number; + handle_sign: + if (jflag) + num = va_arg(ap, intmax_t); + else if (qflag) + num = va_arg(ap, quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, long); + else if (zflag) + num = va_arg(ap, ssize_t); + else if (hflag) + num = (short)va_arg(ap, int); + else if (cflag) + num = (char)va_arg(ap, int); + else + num = va_arg(ap, int); + number: + if (sign && (intmax_t) num < 0) { + neg = 1; + num = -(intmax_t) num; + } + p = ksprintn(nbuf, num, base, &tmp, upper); + if (sharpflag && num != 0) { + if (base == 8) + tmp++; + else if (base == 16) + tmp += 2; + } + if (neg) + tmp++; + + if (!ladjust && padc != '0' && width + && (width -= tmp) > 0) + while (width--) + PCHAR(padc); + if (neg) + PCHAR('-'); + if (sharpflag && num != 0) { + if (base == 8) { + PCHAR('0'); + } else if (base == 16) { + PCHAR('0'); + PCHAR('x'); + } + } + if (!ladjust && width && (width -= tmp) > 0) + while (width--) + PCHAR(padc); + + while (*p) + PCHAR(*p--); + + if (ladjust && width && (width -= tmp) > 0) + while (width--) + PCHAR(padc); + + break; + default: + while (percent < fmt) + PCHAR(*percent++); + /* + * Since we ignore a formatting argument it is no + * longer safe to obey the remaining formatting + * arguments as the arguments will no longer match + * the format specs. + */ + stop = 1; + break; + } + } +#undef PCHAR +} + +/* + * Print directly a character on the screen + */ +extern int kputchar(int); + +/* + * A wrapper function for kputchar because + * kvprintf needs an output function, which possesses two arguments. + * The first arguments defines the output character, the second could be used to pass + * additional arguments. In the case of kputchar is no additional argument needed. + */ +static void _putchar(int c, void *arg) +{ + kputchar(c); +} + +int kprintf(const char *fmt, ...) +{ + int ret; + + /* http://www.pagetable.com/?p=298 */ + va_list ap; + + va_start(ap, fmt); + ret = kvprintf(fmt, + _putchar, /* output function */ + NULL, /* additional argument for the output function */ + 10, ap); + va_end(ap); + + return ret; +} diff --git a/libkern/qdivrem.c b/libkern/qdivrem.c new file mode 100644 index 0000000..98865ee --- /dev/null +++ b/libkern/qdivrem.c @@ -0,0 +1,329 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 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. + */ + +/* + * The code has been taken from FreeBSD (sys/libkern/qdivrem.c) and is therefore + * BSD-licensed. Unnecessary functions have been removed and all typedefs required + * have been added. + */ + +/* + * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed), + * section 4.3.1, pp. 257--259. + */ + +/* eduOS prelude */ +#include + +typedef uint64_t u_quad_t; +typedef int64_t quad_t; +typedef uint32_t u_long; + +/* + * Depending on the desired operation, we view a `long long' (aka quad_t) in + * one or more of the following formats. + */ +union uu { + quad_t q; /* as a (signed) quad */ + quad_t uq; /* as an unsigned quad */ + int32_t sl[2]; /* as two signed longs */ + uint32_t ul[2]; /* as two unsigned longs */ +}; + +#define CHAR_BIT 8 + +#if BYTE_ORDER == LITTLE_ENDIAN +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 +#else +#define _QUAD_HIGHWORD 0 +#define _QUAD_LOWWORD 1 +#endif + +/* + * Define high and low longwords. + */ +#define H _QUAD_HIGHWORD +#define L _QUAD_LOWWORD + +/* + * Total number of bits in a quad_t and in the pieces that make it up. + * These are used for shifting, and also below for halfword extraction + * and assembly. + */ +#define QUAD_BITS (sizeof(quad_t) * CHAR_BIT) +#define LONG_BITS (sizeof(long) * CHAR_BIT) +#define HALF_BITS (sizeof(long) * CHAR_BIT / 2) + +/* + * Extract high and low shortwords from longword, and move low shortword of + * longword to upper half of long, i.e., produce the upper longword of + * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.) + * + * These are used in the multiply code, to split a longword into upper + * and lower halves, and to reassemble a product as a quad_t, shifted left + * (sizeof(long)*CHAR_BIT/2). + */ +#define HHALF(x) ((x) >> HALF_BITS) +#define LHALF(x) ((x) & ((1 << HALF_BITS) - 1)) +#define LHUP(x) ((x) << HALF_BITS) + +#define B (1 << HALF_BITS) /* digit base */ + +/* Combine two `digits' to make a single two-digit number. */ +#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) + +/* select a type for digits in base B: use unsigned short if they fit */ +#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff +typedef unsigned short digit; +#else +typedef u_long digit; +#endif + +/* + * Shift p[0]..p[len] left `sh' bits, ignoring any bits that + * `fall out' the left (there never will be any such anyway). + * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS. + */ +static void __shl(register digit * p, register int len, register int sh) +{ + register int i; + + for (i = 0; i < len; i++) + p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh)); + p[i] = LHALF(p[i] << sh); +} + +/* + * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v. + * + * We do this in base 2-sup-HALF_BITS, so that all intermediate products + * fit within u_long. As a consequence, the maximum length dividend and + * divisor are 4 `digits' in this base (they are shorter if they have + * leading zeros). + */ +u_quad_t __qdivrem(uq, vq, arq) +u_quad_t uq, vq, *arq; +{ + union uu tmp; + digit *u, *v, *q; + register digit v1, v2; + u_long qhat, rhat, t; + int m, n, d, j, i; + digit uspace[5], vspace[5], qspace[5]; + + /* + * Take care of special cases: divide by zero, and u < v. + */ + if (vq == 0) { + /* divide by zero. */ + static volatile const unsigned int zero = 0; + + tmp.ul[H] = tmp.ul[L] = 1 / zero; + if (arq) + *arq = uq; + return (tmp.q); + } + if (uq < vq) { + if (arq) + *arq = uq; + return (0); + } + u = &uspace[0]; + v = &vspace[0]; + q = &qspace[0]; + + /* + * Break dividend and divisor into digits in base B, then + * count leading zeros to determine m and n. When done, we + * will have: + * u = (u[1]u[2]...u[m+n]) sub B + * v = (v[1]v[2]...v[n]) sub B + * v[1] != 0 + * 1 < n <= 4 (if n = 1, we use a different division algorithm) + * m >= 0 (otherwise u < v, which we already checked) + * m + n = 4 + * and thus + * m = 4 - n <= 2 + */ + tmp.uq = uq; + u[0] = 0; + u[1] = HHALF(tmp.ul[H]); + u[2] = LHALF(tmp.ul[H]); + u[3] = HHALF(tmp.ul[L]); + u[4] = LHALF(tmp.ul[L]); + tmp.uq = vq; + v[1] = HHALF(tmp.ul[H]); + v[2] = LHALF(tmp.ul[H]); + v[3] = HHALF(tmp.ul[L]); + v[4] = LHALF(tmp.ul[L]); + for (n = 4; v[1] == 0; v++) { + if (--n == 1) { + u_long rbj; /* r*B+u[j] (not root boy jim) */ + digit q1, q2, q3, q4; + + /* + * Change of plan, per exercise 16. + * r = 0; + * for j = 1..4: + * q[j] = floor((r*B + u[j]) / v), + * r = (r*B + u[j]) % v; + * We unroll this completely here. + */ + t = v[2]; /* nonzero, by definition */ + q1 = u[1] / t; + rbj = COMBINE(u[1] % t, u[2]); + q2 = rbj / t; + rbj = COMBINE(rbj % t, u[3]); + q3 = rbj / t; + rbj = COMBINE(rbj % t, u[4]); + q4 = rbj / t; + if (arq) + *arq = rbj % t; + tmp.ul[H] = COMBINE(q1, q2); + tmp.ul[L] = COMBINE(q3, q4); + return (tmp.q); + } + } + + /* + * By adjusting q once we determine m, we can guarantee that + * there is a complete four-digit quotient at &qspace[1] when + * we finally stop. + */ + for (m = 4 - n; u[1] == 0; u++) + m--; + for (i = 4 - m; --i >= 0;) + q[i] = 0; + q += 4 - m; + + /* + * Here we run Program D, translated from MIX to C and acquiring + * a few minor changes. + * + * D1: choose multiplier 1 << d to ensure v[1] >= B/2. + */ + d = 0; + for (t = v[1]; t < B / 2; t <<= 1) + d++; + if (d > 0) { + __shl(&u[0], m + n, d); /* u <<= d */ + __shl(&v[1], n - 1, d); /* v <<= d */ + } + /* + * D2: j = 0. + */ + j = 0; + v1 = v[1]; /* for D3 -- note that v[1..n] are constant */ + v2 = v[2]; /* for D3 */ + do { + register digit uj0, uj1, uj2; + + /* + * D3: Calculate qhat (\^q, in TeX notation). + * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and + * let rhat = (u[j]*B + u[j+1]) mod v[1]. + * While rhat < B and v[2]*qhat > rhat*B+u[j+2], + * decrement qhat and increase rhat correspondingly. + * Note that if rhat >= B, v[2]*qhat < rhat*B. + */ + uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */ + uj1 = u[j + 1]; /* for D3 only */ + uj2 = u[j + 2]; /* for D3 only */ + if (uj0 == v1) { + qhat = B; + rhat = uj1; + goto qhat_too_big; + } else { + u_long nn = COMBINE(uj0, uj1); + qhat = nn / v1; + rhat = nn % v1; + } + while (v2 * qhat > COMBINE(rhat, uj2)) { + qhat_too_big: + qhat--; + if ((rhat += v1) >= B) + break; + } + /* + * D4: Multiply and subtract. + * The variable `t' holds any borrows across the loop. + * We split this up so that we do not require v[0] = 0, + * and to eliminate a final special case. + */ + for (t = 0, i = n; i > 0; i--) { + t = u[i + j] - v[i] * qhat - t; + u[i + j] = LHALF(t); + t = (B - HHALF(t)) & (B - 1); + } + t = u[j] - t; + u[j] = LHALF(t); + /* + * D5: test remainder. + * There is a borrow if and only if HHALF(t) is nonzero; + * in that (rare) case, qhat was too large (by exactly 1). + * Fix it by adding v[1..n] to u[j..j+n]. + */ + if (HHALF(t)) { + qhat--; + for (t = 0, i = n; i > 0; i--) { /* D6: add back. */ + t += u[i + j] + v[i]; + u[i + j] = LHALF(t); + t = HHALF(t); + } + u[j] = LHALF(u[j] + t); + } + q[j] = qhat; + } while (++j <= m); /* D7: loop on j. */ + + /* + * If caller wants the remainder, we have to calculate it as + * u[m..m+n] >> d (this is at most n digits and thus fits in + * u[m+1..m+n], but we may need more source digits). + */ + if (arq) { + if (d) { + for (i = m + n; i > m; --i) + u[i] = (u[i] >> d) | + LHALF(u[i - 1] << (HALF_BITS - d)); + u[i] = 0; + } + tmp.ul[H] = COMBINE(uspace[1], uspace[2]); + tmp.ul[L] = COMBINE(uspace[3], uspace[4]); + *arq = tmp.q; + } + + tmp.ul[H] = COMBINE(qspace[1], qspace[2]); + tmp.ul[L] = COMBINE(qspace[3], qspace[4]); + return (tmp.q); +} diff --git a/libkern/quad.h b/libkern/quad.h new file mode 100644 index 0000000..489e8e8 --- /dev/null +++ b/libkern/quad.h @@ -0,0 +1,51 @@ +#ifndef __QUAD_H__ +#define __QUAD_H__ + +/* eduOS prelude */ +#include +#include + +typedef uint64_t u_quad_t; +typedef int64_t quad_t; +typedef uint32_t u_long; +typedef uint32_t qshift_t; + +/* + * Depending on the desired operation, we view a `long long' (aka quad_t) in + * one or more of the following formats. + */ +union uu { + quad_t q; /* as a (signed) quad */ + quad_t uq; /* as an unsigned quad */ + int32_t sl[2]; /* as two signed longs */ + uint32_t ul[2]; /* as two unsigned longs */ +}; + +#define CHAR_BIT 8 + +#if BYTE_ORDER == LITTLE_ENDIAN +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 +#else +#define _QUAD_HIGHWORD 0 +#define _QUAD_LOWWORD 1 +#endif + +/* + * Define high and low longwords. + */ +#define H _QUAD_HIGHWORD +#define L _QUAD_LOWWORD + +/* + * Total number of bits in a quad_t and in the pieces that make it up. + * These are used for shifting, and also below for halfword extraction + * and assembly. + */ +#define QUAD_BITS (sizeof(quad_t) * CHAR_BIT) +#define LONG_BITS (sizeof(long) * CHAR_BIT) +#define HALF_BITS (sizeof(long) * CHAR_BIT / 2) + +u_quad_t __qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t* arq); + +#endif diff --git a/libkern/stdio.c b/libkern/stdio.c new file mode 100644 index 0000000..d9f3a61 --- /dev/null +++ b/libkern/stdio.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010, Stefan Lankes, RWTH Aachen University + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * 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 COPYRIGHT HOLDERS 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. + */ + +#include +#include +#include +#include + +int koutput_init(void) +{ + vga_init(); + + return 0; +} + +int kputchar(int c) +{ + vga_putchar(c); + + return 1; +} + +int kputs(const char *str) +{ + int i; + + for(i=0; str[i] != '\0'; i++) + vga_putchar((int) str[i]); + + return i; +} diff --git a/libkern/string.c b/libkern/string.c new file mode 100644 index 0000000..972afc2 --- /dev/null +++ b/libkern/string.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2010, Stefan Lankes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of the 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 COPYRIGHT HOLDERS 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 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. + */ + +#include + +#ifndef HAVE_ARCH_MEMCPY +void *memcpy(void *dest, const void *src, size_t count) +{ + size_t i; + + if (BUILTIN_EXPECT(!dest || !src, 0)) + return dest; + + for (i = 0; i < count; i++) + ((char*)dest)[i] = ((char*)src)[i]; + + return dest; +} +#endif + +#ifndef HAVE_ARCH_MEMSET +void *memset(void *dest, int val, size_t count) +{ + size_t i; + + if (BUILTIN_EXPECT(!dest, 0)) + return dest; + + for (i = 0; i < count; i++) + ((char*) dest)[i] = (char) val; + + return dest; +} +#endif + +#ifndef HAVE_ARCH_STRLEN +size_t strlen(const char *str) +{ + size_t len = 0; + + if (BUILTIN_EXPECT(!str, 0)) + return len; + + while (str[len] != '\0') + len++; + + return len; +} +#endif + +#ifndef HAVE_ARCH_STRNCPY +char* strncpy(char *dest, const char *src, size_t n) +{ + size_t i; + + if (BUILTIN_EXPECT(!dest || !src, 0)) + return dest; + + for (i = 0 ; i < n && src[i] != '\0' ; i++) + dest[i] = src[i]; + if (i < n) + dest[i] = '\0'; + else + dest[n-1] = '\0'; + + return dest; +} +#endif + +#ifndef HAVE_ARCH_STRCPY +char* strcpy(char *dest, const char *src) +{ + size_t i; + + if (BUILTIN_EXPECT(!dest || !src, 0)) + return dest; + + for (i = 0 ; src[i] != '\0' ; i++) + dest[i] = src[i]; + dest[i] = '\0'; + + return dest; +} +#endif + +#ifndef HAVE_ARCH_STRCMP +int strcmp(const char *s1, const char *s2) +{ + while (*s1 != '\0' && *s1 == *s2) { + s1++; + s2++; + } + + return (*(unsigned char *) s1) - (*(unsigned char *) s2); +} +#endif + +#ifndef HAVE_ARCH_STRNCMP +int strncmp(const char *s1, const char *s2, size_t n) +{ + if (BUILTIN_EXPECT(n == 0, 0)) + return 0; + + while (n-- != 0 && *s1 == *s2) { + if (n == 0 || *s1 == '\0') + break; + s1++; + s2++; + } + + return (*(unsigned char *) s1) - (*(unsigned char *) s2); +} +#endif diff --git a/libkern/udivdi3.c b/libkern/udivdi3.c new file mode 100644 index 0000000..1efa7ab --- /dev/null +++ b/libkern/udivdi3.c @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 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. + */ + +/* + * The code has been taken from FreeBSD (sys/libkern/udivdi3.c) and is therefore + * BSD-licensed. Unnecessary functions have been removed and all typedefs required + * have been added. + */ + +#include + +typedef uint64_t u_quad_t; +u_quad_t __qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t* arq); + +/* + * Divide two unsigned quads. + */ +u_quad_t __udivdi3(a, b) +u_quad_t a, b; +{ + + return (__qdivrem(a, b, (u_quad_t *) 0)); +} diff --git a/libkern/umoddi3.c b/libkern/umoddi3.c new file mode 100644 index 0000000..7879d0c --- /dev/null +++ b/libkern/umoddi3.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * 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. + * 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. + */ + +/* + * The code has been taken from FreeBSD (sys/libkern/umoddi3.c) and is therefore + * BSD-licensed. Unnecessary functions have been removed and all typedefs required + * have been added. + */ + +#include + +typedef uint64_t u_quad_t; +u_quad_t __qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t* arq); + + +/* + * Return remainder after dividing two unsigned quads. + */ +u_quad_t __umoddi3(a, b) +u_quad_t a, b; +{ + u_quad_t r; + + (void)__qdivrem(a, b, &r); + return (r); +} diff --git a/link.ld b/link.ld new file mode 100644 index 0000000..ad03b8f --- /dev/null +++ b/link.ld @@ -0,0 +1,29 @@ +OUTPUT_FORMAT("elf32-i386") +OUTPUT_ARCH("i386") +ENTRY(start) +phys = 0x00100000; + +SECTIONS +{ + kernel_start = phys; + .mboot phys : AT(ADDR(.mboot)) { + *(.mboot) + *(.kmsg) + } + .text ALIGN(4096) : AT(ADDR(.text)) { + *(.text) + } + .rodata ALIGN(4096) : AT(ADDR(.rodata)) { + *(.rodata) + *(.rodata.*) + } + .data ALIGN(4096) : AT(ADDR(.data)) { + *(.data) + } + bss_start = .; + .bss ALIGN(4096) : AT(ADDR(.bss)) { + *(.bss) + } + bss_end = .; + kernel_end = .; +}