├── servers ├── video │ ├── video.h │ ├── SConscript │ └── video.c ├── test │ ├── SConscript │ └── main.c ├── keyboard │ ├── SConscript │ ├── keyboard.c │ └── keyboard.h └── SConscript ├── kernel ├── include │ ├── syscall.h │ ├── timer.h │ ├── gcc.h │ ├── pmem.h │ ├── drivers.h │ ├── gdt.h │ ├── idt.h │ ├── ipc.h │ ├── scheduler.h │ ├── process.h │ ├── vmem.h │ ├── string.h │ ├── term.h │ ├── layout.h │ ├── interrupt.h │ ├── thread.h │ ├── elf.h │ ├── isr.h │ ├── x86.h │ ├── list.h │ └── multiboot.h ├── SConscript ├── boot.asm ├── devices │ └── timer.c ├── link.ld ├── system │ ├── syscall.c │ ├── drivers.c │ └── ipc.c ├── cpu │ ├── idt.c │ ├── isr.asm │ ├── gdt.c │ └── interrupt.c ├── task │ ├── elf.c │ ├── process.c │ ├── thread.c │ └── scheduler.c ├── memory │ ├── pmem.c │ └── vmem.c ├── main.c ├── x86.asm ├── lib │ └── string.c └── video │ └── term.c ├── .gitignore ├── toolchain ├── newlib-utopia │ ├── getpid.c │ ├── close.c │ ├── isatty.c │ ├── environ.c │ ├── open.c │ ├── _exit.c │ ├── times.c │ ├── lseek.c │ ├── read.c │ ├── fstat.c │ ├── stat.c │ ├── fork.c │ ├── kill.c │ ├── unlink.c │ ├── link.c │ ├── wait.c │ ├── execve.c │ ├── sbrk.c │ ├── configure.in │ ├── crt0.S │ ├── memory_map.c │ ├── write.c │ ├── Makefile.am │ └── include │ │ ├── utopia.h │ │ └── _syscall.h ├── patches │ ├── newlib-2.1.0.patch │ ├── gcc-4.9.0.patch │ └── binutils-2.24.patch └── build.sh ├── .gdbinit ├── README.md ├── qemu.sh ├── SConstruct └── LICENSE /servers/video/video.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /kernel/include/syscall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | void syscall_init(void); 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.elf 2 | *.o 3 | *.a 4 | .sconsign.dblite 5 | toolchain/packages 6 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/getpid.c: -------------------------------------------------------------------------------- 1 | int getpid(void) 2 | { 3 | return 1; 4 | } 5 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/close.c: -------------------------------------------------------------------------------- 1 | int close(int fd) 2 | { 3 | return -1; 4 | } 5 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/isatty.c: -------------------------------------------------------------------------------- 1 | int isatty(int fd) 2 | { 3 | return 1; 4 | } 5 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/environ.c: -------------------------------------------------------------------------------- 1 | char* __env[1] = { 0 }; 2 | char** environ = __env; 3 | -------------------------------------------------------------------------------- /.gdbinit: -------------------------------------------------------------------------------- 1 | file kernel/kernel.elf 2 | target remote localhost:1234 3 | 4 | break main 5 | continue 6 | -------------------------------------------------------------------------------- /kernel/include/timer.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | void timer_init(uint32_t hz); 5 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/open.c: -------------------------------------------------------------------------------- 1 | int open(const char* file, int flags, ...) 2 | { 3 | return -1; 4 | } 5 | -------------------------------------------------------------------------------- /servers/test/SConscript: -------------------------------------------------------------------------------- 1 | Import('senv') 2 | 3 | test = senv.Program('test.elf', Glob('*.c')) 4 | Return('test') 5 | -------------------------------------------------------------------------------- /servers/video/SConscript: -------------------------------------------------------------------------------- 1 | Import('senv') 2 | 3 | video = senv.Program('video.elf', Glob('*.c')) 4 | Return('video') 5 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/_exit.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void _exit(int rc) 4 | { 5 | process_exit(); 6 | } 7 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/times.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | clock_t times(struct tms* buf) 4 | { 5 | return -1; 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Utopia 2 | ====== 3 | 4 | Utopia is an UNIX-like operating system built around a microkernel, with a focus on code clarity. 5 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/lseek.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | off_t lseek(int fd, off_t pos, int whence) 4 | { 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/read.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | size_t read(int fd, void* buf, size_t cnt) 4 | { 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /kernel/include/gcc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define alwaysinline inline __attribute__((always_inline)) 4 | #define unused __attribute__((unused)) 5 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/fstat.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fstat(int fd, struct stat* pstat) 4 | { 5 | pstat->st_mode = S_IFCHR; 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/stat.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int stat(const char* file, struct stat* pstat) 4 | { 5 | pstat->st_mode = S_IFCHR; 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /kernel/include/pmem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "multiboot.h" 3 | 4 | void pmem_init(multiboot_info_t* info); 5 | void* frame_alloc(void); 6 | void frame_free(void* address); 7 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/fork.c: -------------------------------------------------------------------------------- 1 | #include 2 | #undef errno 3 | extern int errno; 4 | 5 | int fork(void) 6 | { 7 | errno = EAGAIN; 8 | return -1; 9 | } 10 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/kill.c: -------------------------------------------------------------------------------- 1 | #include 2 | #undef errno 3 | extern int errno; 4 | 5 | int kill(int pid, int sig) 6 | { 7 | errno = EINVAL; 8 | return -1; 9 | } 10 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/unlink.c: -------------------------------------------------------------------------------- 1 | #include 2 | #undef errno 3 | extern int errno; 4 | 5 | int unlink(const char* file) 6 | { 7 | errno = ENOENT; 8 | return -1; 9 | } 10 | -------------------------------------------------------------------------------- /servers/keyboard/SConscript: -------------------------------------------------------------------------------- 1 | Import('senv') 2 | 3 | env = senv.Clone() 4 | env.Append(CPPFLAGS = ['-Wno-multichar']) 5 | 6 | keyboard = env.Program('keyboard.elf', Glob('*.c')) 7 | Return('keyboard') 8 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/link.c: -------------------------------------------------------------------------------- 1 | #include 2 | #undef errno 3 | extern int errno; 4 | 5 | int link(const char* old, const char* new) 6 | { 7 | errno = EMLINK; 8 | return -1; 9 | } 10 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/wait.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #undef errno 4 | extern int errno; 5 | 6 | pid_t wait(int* status) 7 | { 8 | errno = ECHILD; 9 | return -1; 10 | } 11 | -------------------------------------------------------------------------------- /servers/SConscript: -------------------------------------------------------------------------------- 1 | Import('env') 2 | 3 | senv = env.Clone() 4 | Export('senv') 5 | 6 | servers = [] 7 | for server in Glob('*/SConscript'): 8 | servers += SConscript(server) 9 | 10 | Return('servers') 11 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/execve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #undef errno 3 | extern int errno; 4 | 5 | int execve(const char* name, char* const argv[], char* const env[]) 6 | { 7 | errno = ENOMEM; 8 | return -1; 9 | } 10 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/sbrk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #undef errno 6 | extern int errno; 7 | 8 | void* sbrk(ptrdiff_t incr) 9 | { 10 | return _sbrk(incr); 11 | } 12 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/configure.in: -------------------------------------------------------------------------------- 1 | AC_PREREQ(2.59) 2 | AC_INIT([newlib], [NEWLIB_VERSION]) 3 | AC_CONFIG_SRCDIR([crt0.S]) 4 | AC_CONFIG_AUX_DIR(../../../..) 5 | NEWLIB_CONFIGURE(../../..) 6 | AC_CONFIG_FILES([Makefile]) 7 | AC_OUTPUT 8 | -------------------------------------------------------------------------------- /kernel/include/drivers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | void irq_subscribe(uint8_t irq); 7 | void irq_wait(uint8_t irq); 8 | void memory_map(void* vAddr, void* pAddr, size_t size, bool writable); 9 | -------------------------------------------------------------------------------- /kernel/include/gdt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define USER_RPL 0b11 4 | #define KERNEL_CODE 0x08 5 | #define KERNEL_DATA 0x10 6 | #define USER_CODE 0x18 7 | #define USER_DATA 0x20 8 | 9 | void gdt_init(void); 10 | void set_kernel_stack(void* esp0); 11 | -------------------------------------------------------------------------------- /kernel/include/idt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define INTERRUPT_GATE 0x8E 5 | #define SYSCALL_GATE 0xEE 6 | 7 | typedef void (*IsrStub)(void); 8 | 9 | void idt_init(void); 10 | void idt_set_gate(uint8_t i, uint8_t flags, IsrStub offset); 11 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/crt0.S: -------------------------------------------------------------------------------- 1 | .extern main 2 | .extern exit 3 | 4 | .global _start 5 | _start: 6 | call main 7 | call exit 8 | .wait: 9 | hlt 10 | jmp .wait 11 | 12 | 13 | .section .data 14 | .global _TLSPtr 15 | _TLSPtr: 16 | .long 0x600000 17 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/memory_map.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void* memory_map(void* pAddr, size_t size, bool writable) 5 | { 6 | void* vAddr = memalign(4096, size); 7 | 8 | _memory_map(vAddr, pAddr, size, writable); 9 | 10 | return vAddr; 11 | } 12 | -------------------------------------------------------------------------------- /servers/test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void thread(void) 5 | { 6 | printf(">>> "); 7 | fflush(stdout); 8 | 9 | return; 10 | } 11 | 12 | int main(void) 13 | { 14 | thread_create(thread); 15 | 16 | while(1); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /kernel/include/ipc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | typedef struct 5 | { 6 | struct 7 | { 8 | uint16_t pid; 9 | uint16_t tid; 10 | uint32_t n; 11 | } tag; 12 | uint32_t reg[64]; 13 | } __attribute__((packed)) MsgBox; 14 | 15 | void send_receive(uint16_t to, uint16_t from); 16 | -------------------------------------------------------------------------------- /kernel/include/scheduler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "thread.h" 3 | 4 | void scheduler_init(void); 5 | void scheduler_add(Thread* thread); 6 | void scheduler_remove(Thread* thread); 7 | Thread* scheduler_current(void); 8 | void scheduler_wait(uint16_t waitFor, State reason); 9 | void scheduler_unblock(Thread* thread); 10 | void schedule(void); 11 | -------------------------------------------------------------------------------- /kernel/include/process.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "elf.h" 3 | #include "list.h" 4 | 5 | typedef struct 6 | { 7 | uint16_t pid; 8 | void* PD; 9 | size_t heapSize; 10 | 11 | uint16_t nextLocalTid; 12 | List threads; 13 | } Process; 14 | 15 | void process_create(ElfHeader* elf); 16 | void process_exit(void); 17 | void* sbrk(size_t incr); 18 | -------------------------------------------------------------------------------- /servers/video/video.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "video.h" 4 | 5 | int main(void) 6 | { 7 | int i = 0; 8 | uint16_t* video = memory_map((void*)0xB8000, 0x8000, true); 9 | 10 | while(1) 11 | { 12 | MBOX->tag.n = 0; 13 | send_receive(1, 1); 14 | video[i++] = ((char) MBOX->reg[0]) | 0xF000; 15 | } 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #undef errno 6 | extern int errno; 7 | 8 | size_t write(int fd, const void* buf, size_t cnt) 9 | { 10 | int i; 11 | 12 | if (fd == 1) 13 | { 14 | for (i = 0; i < cnt; i++) 15 | put(((char*)buf)[i]); 16 | return cnt; 17 | } 18 | 19 | errno = ENOSYS; 20 | return -1; 21 | } 22 | -------------------------------------------------------------------------------- /kernel/SConscript: -------------------------------------------------------------------------------- 1 | Import('env') 2 | 3 | kenv = env.Clone() 4 | kenv.Append(CPPPATH = ['include'], 5 | CCFLAGS = ['-ffreestanding'], 6 | LINKFLAGS = ['-nostdlib', '-Tkernel/link.ld'], 7 | LIBS = ['gcc']) 8 | 9 | kernel = kenv.Program('kernel.elf', Glob('*.c') + Glob('*.asm') + 10 | Glob('*/*.c') + Glob('*/*.asm')) 11 | 12 | Depends(kernel, 'link.ld') 13 | Return('kernel') 14 | -------------------------------------------------------------------------------- /kernel/boot.asm: -------------------------------------------------------------------------------- 1 | extern main 2 | 3 | MODALIGN equ (1 << 0) 4 | MEMINFO equ (1 << 1) 5 | FLAGS equ (MODALIGN | MEMINFO) 6 | MAGIC equ 0x1BADB002 7 | CHECKSUM equ -(MAGIC + FLAGS) 8 | 9 | section .multiboot 10 | align 4 11 | dd MAGIC 12 | dd FLAGS 13 | dd CHECKSUM 14 | 15 | section .text 16 | global start 17 | start: 18 | cli 19 | mov esp, 0x7C00 20 | 21 | push ebx 22 | call main 23 | 24 | cli 25 | hlt 26 | -------------------------------------------------------------------------------- /qemu.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | SERVERS="servers/keyboard/keyboard.elf,servers/video/video.elf,servers/test/test.elf" 4 | 5 | if [ "$1" = "-g" ]; then 6 | qemu-system-i386 -s -S -kernel kernel/kernel.elf -initrd $SERVERS & 7 | sleep 0.5 8 | i686-elf-gdb 9 | elif [ "$1" = "-w" ]; then 10 | qemu-system-i386 -s -S -kernel kernel/kernel.elf -initrd $SERVERS & 11 | else 12 | qemu-system-i386 -kernel kernel/kernel.elf -initrd $SERVERS 13 | fi 14 | -------------------------------------------------------------------------------- /kernel/devices/timer.c: -------------------------------------------------------------------------------- 1 | #include "x86.h" 2 | #include "timer.h" 3 | 4 | #define PIT_CMD 0x43 5 | #define PIT_CH_0 0x40 6 | 7 | #define SQUARE_WAVE_GEN (0b011 << 1) 8 | #define LSB_THEN_MSB (0b11 << 4) 9 | 10 | void timer_init(uint32_t hz) 11 | { 12 | uint32_t divisor = 1193182 / hz; 13 | 14 | outb(PIT_CMD, SQUARE_WAVE_GEN | LSB_THEN_MSB); 15 | outb(PIT_CH_0, divisor & 0xFF); 16 | outb(PIT_CH_0, (divisor >> 8) & 0xFF); 17 | } 18 | -------------------------------------------------------------------------------- /kernel/include/vmem.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define PAGE_PRESENT (1 << 0) 5 | #define PAGE_WRITE (1 << 1) 6 | #define PAGE_USER (1 << 2) 7 | #define PAGE_4MB (1 << 7) 8 | #define PAGE_GLOBAL (1 << 8) 9 | 10 | void vmem_init(void); 11 | void* vmem_to_phys(const void* vAddr); 12 | void map(void* vAddr, void* pAddr, uint16_t flags); 13 | void unmap(void* vAddr); 14 | void* new_address_space(void); 15 | void destroy_address_space(void); 16 | -------------------------------------------------------------------------------- /kernel/include/string.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | int memcmp (const void* s1, const void* s2, size_t n); 6 | void* memcpy (void* dest, const void* src, size_t n); 7 | void* memmove(void* dest, const void* src, size_t n); 8 | void* memset (void* s, int c, size_t n); 9 | int strcmp (const char* s1, const char* s2); 10 | char* strcpy (char* dest, const char* src); 11 | size_t strlen (const char* s); 12 | char* itoa (uint32_t val, char* buf, int base); 13 | -------------------------------------------------------------------------------- /kernel/link.ld: -------------------------------------------------------------------------------- 1 | ENTRY(start) 2 | 3 | SECTIONS 4 | { 5 | . = 0x100000; 6 | 7 | .text BLOCK(4K): 8 | { 9 | *(.multiboot) 10 | *(.text*) 11 | } 12 | 13 | .rodata BLOCK(4K): 14 | { 15 | *(.rodata*) 16 | } 17 | 18 | .data BLOCK(4K): 19 | { 20 | *(.data) 21 | } 22 | 23 | .bss BLOCK(4K): 24 | { 25 | *(COMMON) 26 | *(.bss) 27 | } 28 | 29 | /DISCARD/ : 30 | { 31 | *(.comment) 32 | *(.eh_frame) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /kernel/include/term.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "x86.h" 3 | 4 | #define ALERT(message...) \ 5 | printf("\n\e0415" message) 6 | 7 | #define ERROR(message...) \ 8 | ({ \ 9 | ALERT(message); \ 10 | hlt(); \ 11 | }) 12 | 13 | #define STEP(function, message...) \ 14 | ({ \ 15 | printf("\eF09 >> \eF15" message); \ 16 | function; \ 17 | printf("\eF10 OK!\n"); \ 18 | }) 19 | 20 | void put(char c); 21 | void printf(const char* format, ...); 22 | void clear_screen(void); 23 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = cygnus 2 | 3 | INCLUDES = -I$(srcdir)/include $(NEWLIB_CFLAGS) $(CROSS_CFLAGS) $(TARGET_CFLAGS) 4 | 5 | AM_CCASFLAGS = $(INCLUDES) 6 | 7 | noinst_LIBRARIES = lib.a 8 | 9 | lib_a_SOURCES = close.c environ.c execve.c _exit.c fork.c fstat.c \ 10 | getpid.c isatty.c kill.c link.c lseek.c open.c read.c sbrk.c \ 11 | stat.c times.c unlink.c wait.c write.c \ 12 | crt0.S memory_map.c 13 | lib_a_CCASFLAGS = $(AM_CCASFLAGS) 14 | lib_a_CFLAGS = $(AM_CFLAGS) 15 | 16 | all-local: crt0.o 17 | 18 | ACLOCAL_AMFLAGS = -I ../../.. -I ../../../.. 19 | CONFIG_STATUS_DEPENDENCIES = $(newlib_basedir)/configure.host 20 | -------------------------------------------------------------------------------- /kernel/include/layout.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define KERNEL_SPACE 0x00000000 4 | #define FRAME_STACK 0x00200000 5 | #define FRAME_STACK_END 0x00400000 6 | #define TMP_MAP 0x00500000 7 | #define TLS_PTR 0x00600000 8 | #define PCB_START 0x00700000 9 | #define TCB_START 0x10000000 10 | #define KERNEL_TLS 0x20000000 11 | #define KERNEL_SPACE_END 0x30000000 12 | 13 | #define USER_SPACE 0x30000000 14 | #define USER_STACKS 0x30000000 15 | #define USER_TLS 0x34000000 16 | #define USER_HEAP 0x38000000 17 | #define USER_TEXT 0x40000000 18 | #define USER_SPACE_END 0xFFC00000 19 | 20 | #define PAGING_STRUCTS 0xFFC00000 21 | -------------------------------------------------------------------------------- /kernel/system/syscall.c: -------------------------------------------------------------------------------- 1 | #include "drivers.h" 2 | #include "idt.h" 3 | #include "ipc.h" 4 | #include "isr.h" 5 | #include "process.h" 6 | #include "scheduler.h" 7 | #include "term.h" 8 | #include "vmem.h" 9 | #include "x86.h" 10 | #include "syscall.h" 11 | 12 | void _thread_create(void* entry) 13 | { 14 | thread_create(entry, scheduler_current()->process); 15 | } 16 | 17 | void* syscallHandlers[] = 18 | { 19 | [0] = put, 20 | [1] = send_receive, 21 | [2] = sbrk, 22 | [3] = irq_subscribe, 23 | [4] = irq_wait, 24 | [5] = inb, 25 | [6] = _thread_create, 26 | [7] = process_exit, 27 | [8] = memory_map 28 | }; 29 | 30 | void syscall_init(void) 31 | { 32 | idt_set_gate(0x80, SYSCALL_GATE, isr128); 33 | } 34 | -------------------------------------------------------------------------------- /kernel/cpu/idt.c: -------------------------------------------------------------------------------- 1 | #include "gdt.h" 2 | #include "interrupt.h" 3 | #include "x86.h" 4 | #include "idt.h" 5 | 6 | typedef struct 7 | { 8 | uint16_t offsetLow; 9 | uint16_t selector; 10 | uint8_t zero; 11 | uint8_t flags; 12 | uint16_t offsetHigh; 13 | } __attribute__((packed)) IdtEntry; 14 | 15 | static IdtEntry idt[256]; 16 | 17 | void idt_set_gate(uint8_t i, uint8_t flags, IsrStub offset) 18 | { 19 | idt[i].offsetLow = (uintptr_t)offset & 0xFFFF; 20 | idt[i].offsetHigh = (uintptr_t)offset >> 16; 21 | idt[i].selector = KERNEL_CODE; 22 | idt[i].zero = 0; 23 | idt[i].flags = flags; 24 | } 25 | 26 | void idt_init(void) 27 | { 28 | interrupt_init(); 29 | 30 | idt_load(idt, sizeof(idt)); 31 | } 32 | -------------------------------------------------------------------------------- /kernel/include/interrupt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #define IRQ(interrupt) (interrupt - 32) 5 | 6 | typedef struct 7 | { 8 | union 9 | { 10 | uint32_t regs[8]; 11 | struct { uint32_t edi, esi, ebp, _esp, ebx, edx, ecx, eax; }; 12 | }; 13 | uint32_t num, error; 14 | uint32_t eip, cs, eflags, esp, ss; 15 | } __attribute__((packed)) Context; 16 | 17 | typedef void (*InterruptHandler)(void); 18 | 19 | void interrupt_init(void); 20 | void interrupt_register(uint8_t n, InterruptHandler handler); 21 | 22 | void irq_register(uint8_t n, InterruptHandler handler); 23 | void irq_mask (uint8_t irq); 24 | void irq_unmask(uint8_t irq); 25 | 26 | void set_context(Context* newContext); 27 | Context* get_context(void); 28 | -------------------------------------------------------------------------------- /SConstruct: -------------------------------------------------------------------------------- 1 | from os import environ 2 | 3 | DEBUG = int(ARGUMENTS.get('debug', 1)) 4 | CCFLAGS = ['-fdiagnostics-color=always'] + (['-gdwarf-2'] if DEBUG else ['-flto', '-fno-use-linker-plugin', '-O2']), 5 | 6 | env = Environment(ENV = {'PATH': environ['PATH']}, 7 | 8 | AS = 'nasm', 9 | ASFLAGS = ['-felf'] + (['-Fdwarf', '-g'] if DEBUG else []), 10 | 11 | CC = 'i686-pc-utopia-gcc', 12 | CFLAGS = ['-std=gnu11'], 13 | CCFLAGS = CCFLAGS, 14 | CPPFLAGS = ['-Wall', '-Wextra'], 15 | LINKFLAGS = CCFLAGS, 16 | 17 | ASCOMSTR = 'AS\t$SOURCES -> $TARGETS', 18 | CCCOMSTR = 'CC\t$SOURCES -> $TARGETS', 19 | LINKCOMSTR = 'LD\t$SOURCES -> $TARGETS') 20 | Export('env') 21 | 22 | kernel = SConscript('kernel/SConscript') 23 | servers = SConscript('servers/SConscript') 24 | -------------------------------------------------------------------------------- /kernel/task/elf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "string.h" 3 | #include "vmem.h" 4 | #include "x86.h" 5 | #include "elf.h" 6 | 7 | void* elf_load(const ElfHeader* elf) 8 | { 9 | ElfProgHeader* phTbl = (void*)elf + elf->e_phoff; 10 | 11 | for (int i = 0; i < elf->e_phnum; i++) 12 | { 13 | if (phTbl[i].p_type == PT_LOAD) 14 | { 15 | uint32_t flags = PAGE_USER; 16 | if (phTbl[i].p_flags & PF_W) 17 | flags |= PAGE_WRITE; 18 | 19 | void* base = (void*)phTbl[i].p_vaddr; 20 | size_t memsz = phTbl[i].p_memsz; 21 | size_t filesz = phTbl[i].p_filesz; 22 | 23 | for (void* i = base; i < base + memsz; i += PAGE_SIZE) 24 | map(i, NULL, flags); 25 | 26 | memcpy(base, (void*)elf + phTbl[i].p_offset, filesz); 27 | memset(base + filesz, 0, memsz - filesz); 28 | } 29 | } 30 | 31 | return (void*)elf->e_entry; 32 | } 33 | -------------------------------------------------------------------------------- /kernel/include/thread.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "interrupt.h" 3 | #include "ipc.h" 4 | #include "process.h" 5 | #include "x86.h" 6 | 7 | #define THREAD_MAGIC 0xDEADC0DE 8 | 9 | typedef struct 10 | { 11 | MsgBox box; 12 | uint8_t mem[PAGE_SIZE - sizeof(MsgBox)]; 13 | } TLS; 14 | 15 | typedef enum { READY, DYING, WAIT_SENDING, WAIT_RECEIVING, WAIT_SEND_RECV } State; 16 | 17 | typedef union 18 | { 19 | struct 20 | { 21 | uint16_t tid; 22 | uint16_t localTid; 23 | Link queueLink; 24 | 25 | State state; 26 | uint16_t waitingFor; 27 | uint8_t waitingIrq; 28 | List waitingList; 29 | 30 | Process* process; 31 | Link processLink; 32 | }; 33 | struct 34 | { 35 | uint8_t kernelStack[PAGE_SIZE - sizeof(Context)]; 36 | Context context; 37 | }; 38 | } Thread; 39 | 40 | void thread_create(const void* entry, Process* process); 41 | void thread_exit(Thread* thread); 42 | Thread* thread_get(uint16_t tid); 43 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/include/utopia.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include "_syscall.h" 6 | 7 | #define TLS (*_TLSPtr) 8 | #define MBOX (&(TLS->box)) 9 | 10 | typedef struct 11 | { 12 | struct 13 | { 14 | uint16_t pid; 15 | uint16_t tid; 16 | uint32_t n; 17 | } tag; 18 | uint32_t reg[64]; 19 | } __attribute__((packed)) _MsgBox; 20 | 21 | typedef struct 22 | { 23 | _MsgBox box; 24 | uint8_t mem[0x1000 - sizeof(_MsgBox)]; 25 | } _TLS; 26 | 27 | extern _TLS* volatile* const _TLSPtr; 28 | 29 | _SYSCALL_1(0, put, char); 30 | _SYSCALL_2(1, send_receive, uint16_t, uint16_t); 31 | _SYSCALL_1(2, _sbrk, size_t); 32 | _SYSCALL_1(3, irq_subscribe, uint8_t); 33 | _SYSCALL_1(4, irq_wait, uint8_t); 34 | _SYSCALL_1(5, inb, uint16_t); 35 | _SYSCALL_1(6, thread_create, void*); 36 | _SYSCALL_0(7, process_exit); 37 | _SYSCALL_4(8, _memory_map, void*, void*, size_t, bool); 38 | 39 | void* memory_map(void* pAddr, size_t size, bool writable); 40 | -------------------------------------------------------------------------------- /kernel/memory/pmem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "layout.h" 3 | #include "x86.h" 4 | #include "pmem.h" 5 | 6 | static uint16_t* stack = (uint16_t*)FRAME_STACK; 7 | 8 | alwaysinline void* frame_alloc(void) 9 | { 10 | return (void*) (*(--stack) * PAGE_SIZE); 11 | } 12 | 13 | alwaysinline void frame_free(void* address) 14 | { 15 | *(stack++) = (uintptr_t)address / PAGE_SIZE; 16 | } 17 | 18 | void pmem_init(multiboot_info_t* info) 19 | { 20 | uintptr_t map = info->mmap_addr; 21 | while (map < info->mmap_addr + info->mmap_length) 22 | { 23 | multiboot_memory_map_t* entry = (void*)map; 24 | 25 | uintptr_t start = entry->addr; 26 | uintptr_t end = start + (size_t)entry->len; 27 | start = (start >= FRAME_STACK_END) ? start : FRAME_STACK_END; 28 | 29 | if (entry->type == MULTIBOOT_MEMORY_AVAILABLE) 30 | for (uintptr_t i = start; i < end; i += PAGE_SIZE) 31 | frame_free((void*)i); 32 | 33 | map += entry->size + sizeof(entry->size); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /kernel/main.c: -------------------------------------------------------------------------------- 1 | #include "gdt.h" 2 | #include "idt.h" 3 | #include "pmem.h" 4 | #include "process.h" 5 | #include "scheduler.h" 6 | #include "syscall.h" 7 | #include "term.h" 8 | #include "timer.h" 9 | #include "vmem.h" 10 | 11 | void main(multiboot_info_t* info) 12 | { 13 | clear_screen(); 14 | 15 | printf("\t\t\t\t\t\t\t\t \eF12[ Utopia ]\n"); 16 | printf("\n\eF09Initializing the microkernel:\n"); 17 | 18 | STEP(gdt_init(), "Initializing the GDT..."); 19 | STEP(idt_init(), "Initializing the IDT..."); 20 | STEP(pmem_init(info), "Initializing Physical Memory..."); 21 | STEP(vmem_init(), "Initializing Virtual Memory..."); 22 | STEP(timer_init(50), "Initializing the timer..."); 23 | STEP(scheduler_init(), "Initializing the scheduler..."); 24 | STEP(syscall_init(), "Initializing the syscalls..."); 25 | 26 | multiboot_module_t* mods = (void*)info->mods_addr; 27 | for (unsigned i = 0; i < info->mods_count; i++) 28 | process_create((ElfHeader*)mods[i].mod_start); 29 | 30 | sti(); 31 | while (true); 32 | } 33 | -------------------------------------------------------------------------------- /kernel/x86.asm: -------------------------------------------------------------------------------- 1 | section .bss 2 | gdtr: 3 | .limit: resw 1 4 | .base: resd 1 5 | 6 | idtr: 7 | .limit: resw 1 8 | .base: resd 1 9 | 10 | section .text 11 | global gdt_load 12 | gdt_load: 13 | mov eax, [esp + 4] 14 | mov [gdtr.base], eax 15 | mov ax, [esp + 8] 16 | mov [gdtr.limit], ax 17 | lgdt [gdtr] 18 | 19 | mov ax, 0x10 20 | mov ds, ax 21 | mov es, ax 22 | mov fs, ax 23 | mov gs, ax 24 | mov ss, ax 25 | jmp 0x08:.reloadCS 26 | .reloadCS: 27 | ret 28 | 29 | global tss_load 30 | tss_load: 31 | mov ax, [esp + 4] 32 | ltr ax 33 | ret 34 | 35 | global idt_load 36 | idt_load: 37 | mov eax, [esp + 4] 38 | mov [idtr.base], eax 39 | mov ax, [esp + 8] 40 | mov [idtr.limit], ax 41 | 42 | lidt [idtr] 43 | ret 44 | 45 | global enable_paging 46 | enable_paging: 47 | mov eax, [esp + 4] 48 | mov cr3, eax 49 | 50 | mov eax, cr4 51 | or eax, 0b10010000 52 | mov cr4, eax 53 | 54 | mov eax, cr0 55 | or eax, 0x80000000 56 | mov cr0, eax 57 | 58 | ret 59 | -------------------------------------------------------------------------------- /kernel/include/elf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | typedef struct 5 | { 6 | uint8_t e_ident[16]; 7 | uint16_t e_type; 8 | uint16_t e_machine; 9 | uint32_t e_version; 10 | uint32_t e_entry; 11 | uint32_t e_phoff; 12 | uint32_t e_shoff; 13 | uint32_t e_flags; 14 | uint16_t e_ehsize; 15 | uint16_t e_phentsize; 16 | uint16_t e_phnum; 17 | uint16_t e_shentsize; 18 | uint16_t e_shnum; 19 | uint16_t e_shstrndx; 20 | } __attribute__((packed)) ElfHeader; 21 | 22 | #define PT_NULL 0 23 | #define PT_LOAD 1 24 | #define PT_DYNAMIC 2 25 | #define PT_INTERP 3 26 | #define PT_NOTE 4 27 | #define PT_SHLIB 5 28 | #define PT_PHDR 6 29 | #define PT_TLS 7 30 | 31 | #define PF_X 0x1 32 | #define PF_W 0x2 33 | #define PF_R 0x4 34 | 35 | typedef struct 36 | { 37 | uint32_t p_type; 38 | uint32_t p_offset; 39 | uint32_t p_vaddr; 40 | uint32_t p_paddr; 41 | uint32_t p_filesz; 42 | uint32_t p_memsz; 43 | uint32_t p_flags; 44 | uint32_t p_align; 45 | } __attribute__((packed)) ElfProgHeader; 46 | 47 | void* elf_load(const ElfHeader* elf); 48 | -------------------------------------------------------------------------------- /kernel/task/process.c: -------------------------------------------------------------------------------- 1 | #include "layout.h" 2 | #include "scheduler.h" 3 | #include "vmem.h" 4 | #include "process.h" 5 | 6 | static Process* const PCBs = (Process*)PCB_START; 7 | static uint16_t next_pid = 1; 8 | 9 | void* sbrk(size_t incr) 10 | { 11 | Process* current = scheduler_current()->process; 12 | 13 | void* ret = (void*)USER_HEAP + current->heapSize; 14 | current->heapSize += incr; 15 | 16 | return ret; 17 | } 18 | 19 | void process_create(ElfHeader* elf) 20 | { 21 | Process* process = &PCBs[next_pid]; 22 | map(process, NULL, PAGE_WRITE | PAGE_GLOBAL); 23 | 24 | process->pid = next_pid++; 25 | process->PD = new_address_space(); 26 | process->heapSize = 0; 27 | process->nextLocalTid = 1; 28 | list_init(&process->threads); 29 | 30 | write_cr3(process->PD); 31 | thread_create(elf_load(elf), process); 32 | } 33 | 34 | void process_exit(void) 35 | { 36 | Process* process = scheduler_current()->process; 37 | 38 | while (!list_empty(&process->threads)) 39 | thread_exit(list_item(list_pop(&process->threads), Thread, processLink)); 40 | 41 | unmap(process); 42 | } 43 | -------------------------------------------------------------------------------- /kernel/cpu/isr.asm: -------------------------------------------------------------------------------- 1 | extern interruptHandlers 2 | extern syscallHandlers 3 | extern context 4 | 5 | %define EXCEPTION(x) (x < 32) 6 | %define NO_ERROR(x) (x != 8 && !(x >= 10 && x <= 14) && x != 17) 7 | %define IRQ(x) (x >= 32 && x < 32 + 16) 8 | %define IRQ_SLAVE(x) (x - 32 >= 8) 9 | %define SYSCALL(x) (x == 128) 10 | 11 | section .text 12 | %macro isr 1 13 | global isr%1 14 | isr%1: 15 | %if NO_ERROR(%1) 16 | push 0 17 | %endif 18 | push %1 19 | pusha 20 | 21 | mov bp, 0x10 22 | mov ds, bp 23 | mov es, bp 24 | 25 | %if EXCEPTION(%1) 26 | mov [context], esp 27 | %endif 28 | %if SYSCALL(%1) 29 | push ebx 30 | push edx 31 | push ecx 32 | call [syscallHandlers + (eax * 4)] 33 | mov [esp + 40], eax 34 | %else 35 | call [interruptHandlers + (%1 * 4)] 36 | %endif 37 | mov esp, [context] 38 | 39 | %if IRQ(%1) 40 | mov al, 0x20 41 | %if IRQ_SLAVE(%1) 42 | out 0xA0, al 43 | %endif 44 | out 0x20, al 45 | %endif 46 | 47 | mov bp, 0x23 48 | mov ds, bp 49 | mov es, bp 50 | 51 | popa 52 | add esp, 8 53 | iret 54 | %endmacro 55 | 56 | %assign i 0 57 | %rep (32 + 16) 58 | align 4 59 | isr i 60 | %assign i i+1 61 | %endrep 62 | 63 | isr 128 64 | -------------------------------------------------------------------------------- /kernel/include/isr.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | extern void isr0 (void); 4 | extern void isr1 (void); 5 | extern void isr2 (void); 6 | extern void isr3 (void); 7 | extern void isr4 (void); 8 | extern void isr5 (void); 9 | extern void isr6 (void); 10 | extern void isr7 (void); 11 | extern void isr8 (void); 12 | extern void isr9 (void); 13 | extern void isr10(void); 14 | extern void isr11(void); 15 | extern void isr12(void); 16 | extern void isr13(void); 17 | extern void isr14(void); 18 | extern void isr15(void); 19 | extern void isr16(void); 20 | extern void isr17(void); 21 | extern void isr18(void); 22 | extern void isr19(void); 23 | extern void isr20(void); 24 | extern void isr21(void); 25 | extern void isr22(void); 26 | extern void isr23(void); 27 | extern void isr24(void); 28 | extern void isr25(void); 29 | extern void isr26(void); 30 | extern void isr27(void); 31 | extern void isr28(void); 32 | extern void isr29(void); 33 | extern void isr30(void); 34 | extern void isr31(void); 35 | 36 | extern void isr32(void); 37 | extern void isr33(void); 38 | extern void isr34(void); 39 | extern void isr35(void); 40 | extern void isr36(void); 41 | extern void isr37(void); 42 | extern void isr38(void); 43 | extern void isr39(void); 44 | extern void isr40(void); 45 | extern void isr41(void); 46 | extern void isr42(void); 47 | extern void isr43(void); 48 | extern void isr44(void); 49 | extern void isr45(void); 50 | extern void isr46(void); 51 | extern void isr47(void); 52 | 53 | extern void isr128(void); 54 | -------------------------------------------------------------------------------- /kernel/system/drivers.c: -------------------------------------------------------------------------------- 1 | #include "interrupt.h" 2 | #include "scheduler.h" 3 | #include "vmem.h" 4 | #include "drivers.h" 5 | 6 | static bool irqPending[32] = { [0 ... 31] = false }; 7 | static uint16_t irqThread[32] = { [0 ... 31] = 0 }; 8 | 9 | static void irq_notify(void) 10 | { 11 | Context* context = get_context(); 12 | 13 | uint8_t irq = IRQ(context->num); 14 | if (!irqThread[irq]) return; 15 | 16 | Thread* receiver = thread_get(irqThread[irq]); 17 | if (receiver->state == WAIT_RECEIVING && receiver->waitingFor == 0 18 | && receiver->waitingIrq == irq) 19 | { 20 | irqPending[irq] = false; 21 | scheduler_unblock(receiver); 22 | } 23 | else 24 | irqPending[irq] = true; 25 | } 26 | 27 | void irq_subscribe(uint8_t irq) 28 | { 29 | if (irq == 0) return; 30 | Thread* current = scheduler_current(); 31 | 32 | if (!irqThread[irq]) 33 | { 34 | irq_register(irq, irq_notify); 35 | irqThread[irq] = current->tid; 36 | } 37 | } 38 | 39 | void irq_wait(uint8_t irq) 40 | { 41 | Thread* current = scheduler_current(); 42 | if (irqThread[irq] != current->tid) return; 43 | 44 | if (irqPending[current->waitingIrq]) 45 | irqPending[current->waitingIrq] = false; 46 | else 47 | { 48 | current->waitingIrq = irq; 49 | scheduler_wait(0, WAIT_RECEIVING); 50 | } 51 | } 52 | 53 | void memory_map(void* vAddr, void* pAddr, size_t size, bool writable) 54 | { 55 | for (size_t i = 0; i < size; i += PAGE_SIZE) 56 | map(vAddr + i, pAddr + i, PAGE_USER | (writable ? PAGE_WRITE : 0)); 57 | } 58 | -------------------------------------------------------------------------------- /kernel/system/ipc.c: -------------------------------------------------------------------------------- 1 | #include "layout.h" 2 | #include "scheduler.h" 3 | #include "string.h" 4 | #include "ipc.h" 5 | 6 | static TLS* const kernelTLSs = (TLS*)KERNEL_TLS; 7 | 8 | static inline void deliver(Thread* sender, Thread* receiver) 9 | { 10 | MsgBox* senderBox = &kernelTLSs[ sender->tid].box; 11 | MsgBox* receiverBox = &kernelTLSs[receiver->tid].box; 12 | 13 | receiverBox->tag.pid = sender->process->pid; 14 | receiverBox->tag.tid = sender->tid; 15 | receiverBox->tag.n = senderBox->tag.n; 16 | 17 | memcpy(receiverBox->reg, senderBox->reg, senderBox->tag.n * sizeof(uint32_t)); 18 | } 19 | 20 | void send_receive(uint16_t to, uint16_t from) 21 | { 22 | Thread *sender, *receiver, *current = scheduler_current(); 23 | 24 | if (to) 25 | { 26 | receiver = thread_get(to); 27 | 28 | if (receiver->state != WAIT_RECEIVING || 29 | !(receiver->waitingFor == (uint16_t)-1 || 30 | receiver->waitingFor == current->tid)) 31 | { 32 | if (from) 33 | return scheduler_wait(to, WAIT_SEND_RECV); 34 | else 35 | return scheduler_wait(to, WAIT_SENDING); 36 | } 37 | 38 | deliver(current, receiver); 39 | scheduler_unblock(receiver); 40 | } 41 | 42 | if (from) 43 | { 44 | if (!list_empty(¤t->waitingList)) 45 | { 46 | sender = list_item(list_pop(¤t->waitingList), Thread, queueLink); 47 | deliver(sender, current); 48 | 49 | if (sender->state == WAIT_SENDING) 50 | scheduler_unblock(sender); 51 | else 52 | sender->state = WAIT_RECEIVING; 53 | } 54 | else 55 | scheduler_wait(from, WAIT_RECEIVING); 56 | } 57 | 58 | return; 59 | } 60 | -------------------------------------------------------------------------------- /toolchain/patches/newlib-2.1.0.patch: -------------------------------------------------------------------------------- 1 | diff -rupN original/config.sub new/config.sub 2 | --- original/config.sub 2013-04-29 17:13:53.000000000 +0200 3 | +++ new/config.sub 2013-12-27 03:18:31.924865126 +0100 4 | @@ -1354,7 +1354,7 @@ case $os in 5 | | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ 6 | | -sym* | -kopensolaris* | -plan9* \ 7 | | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ 8 | - | -aos* | -aros* \ 9 | + | -aos* | -aros* | -utopia* \ 10 | | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ 11 | | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ 12 | | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ 13 | diff -rupN original/newlib/configure.host new/newlib/configure.host 14 | --- original/newlib/configure.host 2013-12-20 11:27:49.000000000 +0100 15 | +++ new/newlib/configure.host 2013-12-27 03:19:45.017802212 +0100 16 | @@ -435,6 +435,10 @@ case "${host}" in 17 | h8500-*-elf*) 18 | sys_dir=h8500hms 19 | ;; 20 | + i[34567]86-*-utopia*) 21 | + sys_dir=utopia 22 | + newlib_cflags="${newlib_cflags} -DMISSING_SYSCALL_NAMES" 23 | + ;; 24 | i[34567]86-*-rdos*) 25 | sys_dir=rdos 26 | newlib_cflags="${newlib_cflags} -DMISSING_SYSCALL_NAMES" 27 | diff -rupN original/newlib/libc/sys/configure.in new/newlib/libc/sys/configure.in 28 | --- original/newlib/libc/sys/configure.in 2012-02-21 23:34:31.000000000 +0100 29 | +++ new/newlib/libc/sys/configure.in 2013-12-27 03:18:31.928198441 +0100 30 | @@ -45,6 +45,7 @@ if test -n "${sys_dir}"; then 31 | sysvi386) AC_CONFIG_SUBDIRS(sysvi386) ;; 32 | sysvnecv70) AC_CONFIG_SUBDIRS(sysvnecv70) ;; 33 | tic80) AC_CONFIG_SUBDIRS(tic80) ;; 34 | + utopia) AC_CONFIG_SUBDIRS(utopia) ;; 35 | w65) AC_CONFIG_SUBDIRS(w65) ;; 36 | z8ksim) AC_CONFIG_SUBDIRS(z8ksim) ;; 37 | esac; 38 | -------------------------------------------------------------------------------- /kernel/include/x86.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "gcc.h" 4 | 5 | #define PAGE_SIZE 0x1000 6 | #define PAGE_BASE(x) ((void*) ((uintptr_t)(x) & -PAGE_SIZE)) 7 | #define PAGE_ALIGN(x) ((void*)(((uintptr_t)(x) + PAGE_SIZE - 1) & -PAGE_SIZE)) 8 | 9 | extern void gdt_load(void* base, uint16_t limit); 10 | extern void idt_load(void* base, uint16_t limit); 11 | extern void tss_load(uint8_t segment); 12 | extern void enable_paging(void* pd); 13 | 14 | static alwaysinline void hlt(void) 15 | { 16 | asm volatile ("hlt"); 17 | } 18 | 19 | static alwaysinline void cli(void) 20 | { 21 | asm volatile ("cli"); 22 | } 23 | 24 | static alwaysinline void sti(void) 25 | { 26 | asm volatile ("sti"); 27 | } 28 | 29 | static alwaysinline uint8_t inb(uint16_t port) 30 | { 31 | uint8_t ret; 32 | asm volatile ("inb %1, %0" : "=a" (ret) : "Nd" (port) ); 33 | return ret; 34 | } 35 | 36 | static alwaysinline uint16_t inw(uint16_t port) 37 | { 38 | uint16_t ret; 39 | asm volatile ("inw %1, %0" : "=a" (ret) : "Nd" (port) ); 40 | return ret; 41 | } 42 | 43 | static alwaysinline void outb(uint16_t port, uint8_t val) 44 | { 45 | asm volatile ("outb %0, %1" : : "a" (val), "Nd" (port)); 46 | } 47 | 48 | static alwaysinline void outw(uint16_t port, uint16_t val) 49 | { 50 | asm volatile ("outw %0, %1" : : "a" (val), "Nd" (port)); 51 | } 52 | 53 | static alwaysinline void invlpg(void* vAddr) 54 | { 55 | asm volatile ("invlpg (%0)" : : "r" (vAddr) : "memory"); 56 | } 57 | 58 | static alwaysinline void* read_cr2(void) 59 | { 60 | void* ret; 61 | asm volatile ("mov %%cr2, %0" : "=r" (ret)); 62 | return ret; 63 | } 64 | 65 | static alwaysinline void* read_cr3(void) 66 | { 67 | void* ret; 68 | asm volatile ("mov %%cr3, %0" : "=r" (ret)); 69 | return ret; 70 | } 71 | 72 | static alwaysinline void write_cr3(void* cr3) 73 | { 74 | asm volatile ("mov %0, %%cr3" : : "r" (cr3)); 75 | } 76 | -------------------------------------------------------------------------------- /kernel/include/list.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "gcc.h" 5 | 6 | typedef struct Link 7 | { 8 | struct Link* next; 9 | struct Link* prev; 10 | } Link; 11 | typedef Link List; 12 | 13 | #define LINK(name) { &name, &name } 14 | 15 | #define LIST(name) \ 16 | List name = LINK(name); 17 | 18 | #define list_item(link, type, member) \ 19 | ((type*) ((void*)(link) - (void*)&(((type*)NULL)->member))) 20 | 21 | #define list_foreach(list, it) \ 22 | for (Link* it = (list)->next; it != (list); it = it->next) 23 | 24 | static alwaysinline void list_init(List* list) 25 | { 26 | list->next = list->prev = list; 27 | } 28 | 29 | static alwaysinline Link* list_first(const List* list) 30 | { 31 | return list->next; 32 | } 33 | 34 | static alwaysinline Link* list_last(const List* list) 35 | { 36 | return list->prev; 37 | } 38 | 39 | static alwaysinline bool list_empty(const List* list) 40 | { 41 | return list->next == list; 42 | } 43 | 44 | static inline void _list_insert(Link* prev, Link* next, Link* new) 45 | { 46 | next->prev = new; 47 | new->next = next; 48 | new->prev = prev; 49 | prev->next = new; 50 | } 51 | 52 | static alwaysinline void list_insert(Link* entry, Link* new) 53 | { 54 | _list_insert(entry, entry->next, new); 55 | } 56 | 57 | static alwaysinline void list_insert_before(Link* entry, Link* new) 58 | { 59 | _list_insert(entry->prev, entry, new); 60 | } 61 | 62 | static alwaysinline void list_append(List* list, Link* new) 63 | { 64 | list_insert_before(list, new); 65 | } 66 | 67 | static alwaysinline void list_prepend(List* list, Link* new) 68 | { 69 | list_insert(list, new); 70 | } 71 | 72 | static inline void list_remove(Link* entry) 73 | { 74 | entry->next->prev = entry->prev; 75 | entry->prev->next = entry->next; 76 | } 77 | 78 | static inline Link* list_pop(List* list) 79 | { 80 | Link* first = list_first(list); 81 | list_remove(first); 82 | 83 | return first; 84 | } 85 | -------------------------------------------------------------------------------- /kernel/cpu/gdt.c: -------------------------------------------------------------------------------- 1 | #include "x86.h" 2 | #include "gdt.h" 3 | 4 | #define KERNEL 0x90 5 | #define USER 0xF0 6 | #define CODE 0x0A 7 | #define DATA 0x02 8 | 9 | #define TSS 0x89 10 | #define TSS_DESC 0x28 11 | 12 | #define PROTECTED (1 << 2) 13 | #define BLOCKS_4K (1 << 3) 14 | 15 | typedef struct 16 | { 17 | uint32_t unused1; 18 | uint32_t esp0; 19 | uint32_t ss0; 20 | uint32_t unused2[22]; 21 | uint16_t unused3; 22 | uint16_t iomapBase; 23 | } __attribute__ ((packed)) Tss; 24 | 25 | typedef struct 26 | { 27 | unsigned limitLow : 16; 28 | unsigned baseLow : 16; 29 | unsigned baseMid : 8; 30 | unsigned access : 8; 31 | unsigned limitHigh : 4; 32 | unsigned flags : 4; 33 | unsigned baseHigh : 8; 34 | } __attribute__((packed)) GdtEntry; 35 | 36 | static GdtEntry gdt[] = 37 | { 38 | { 0, 0, 0, 0, 0, 0, 0 }, 39 | { 0xFFFF, 0, 0, KERNEL | CODE, 0xF, PROTECTED | BLOCKS_4K, 0 }, 40 | { 0xFFFF, 0, 0, KERNEL | DATA, 0xF, PROTECTED | BLOCKS_4K, 0 }, 41 | { 0xFFFF, 0, 0, USER | CODE, 0xF, PROTECTED | BLOCKS_4K, 0 }, 42 | { 0xFFFF, 0, 0, USER | DATA, 0xF, PROTECTED | BLOCKS_4K, 0 }, 43 | { 0, 0, 0, TSS, 0, PROTECTED , 0 } 44 | }; 45 | 46 | static Tss tss; 47 | 48 | static void tss_init(void) 49 | { 50 | uintptr_t base = (uintptr_t)&tss; 51 | uint32_t limit = sizeof(tss) - 1; 52 | uint16_t desc = TSS_DESC >> 3; 53 | 54 | gdt[desc].baseLow = base & 0xFFFF; 55 | gdt[desc].baseMid = (base >> 16) & 0xFF; 56 | gdt[desc].baseHigh = (base >> 24) & 0xFF; 57 | 58 | gdt[desc].limitLow = limit & 0xFFFF; 59 | gdt[desc].limitHigh = (limit >> 16) & 0xF; 60 | 61 | tss.ss0 = KERNEL_DATA; 62 | tss.iomapBase = sizeof(tss); 63 | } 64 | 65 | alwaysinline void set_kernel_stack(void* esp0) 66 | { 67 | tss.esp0 = (uint32_t)esp0; 68 | } 69 | 70 | void gdt_init(void) 71 | { 72 | tss_init(); 73 | 74 | gdt_load(gdt, sizeof(gdt)); 75 | tss_load(TSS_DESC); 76 | } 77 | -------------------------------------------------------------------------------- /kernel/task/thread.c: -------------------------------------------------------------------------------- 1 | #include "gdt.h" 2 | #include "layout.h" 3 | #include "scheduler.h" 4 | #include "string.h" 5 | #include "pmem.h" 6 | #include "vmem.h" 7 | #include "thread.h" 8 | 9 | static Thread* const TCBs = (Thread*)TCB_START; 10 | static uint16_t next_tid = 1; 11 | 12 | static TLS* const kernelTLSs = (TLS*)KERNEL_TLS; 13 | static TLS* const userTLSs = (TLS*)USER_TLS; 14 | 15 | alwaysinline Thread* thread_get(uint16_t tid) 16 | { 17 | return &TCBs[tid]; 18 | } 19 | 20 | void thread_create(const void* entry, Process* process) 21 | { 22 | Thread* thread = &TCBs[next_tid]; 23 | map(thread, NULL, PAGE_WRITE | PAGE_GLOBAL); 24 | 25 | thread->tid = next_tid++; 26 | thread->state = READY; 27 | thread->waitingIrq = 0; 28 | thread->waitingFor = 0; 29 | list_init(&thread->waitingList); 30 | 31 | thread->process = process; 32 | thread->localTid = process->nextLocalTid++; 33 | list_append(&process->threads, &thread->processLink); 34 | 35 | void* stack = (void*)USER_STACKS + (thread->localTid * PAGE_SIZE) - 4; 36 | map(stack, NULL, PAGE_WRITE | PAGE_USER); 37 | *(void**)stack = (void*)THREAD_MAGIC; 38 | 39 | void* TLS = frame_alloc(); 40 | map(&kernelTLSs[thread->tid], TLS, PAGE_WRITE | PAGE_GLOBAL); 41 | map(&userTLSs[thread->localTid], TLS, PAGE_WRITE | PAGE_USER); 42 | 43 | memset(&thread->context, 0, sizeof(Context)); 44 | thread->context.cs = USER_CODE | USER_RPL; 45 | thread->context.ss = USER_DATA | USER_RPL; 46 | thread->context.eip = (uint32_t)entry; 47 | thread->context.esp = (uint32_t)stack; 48 | thread->context.eflags = 0x202; 49 | 50 | scheduler_add(thread); 51 | } 52 | 53 | void thread_exit(Thread* thread) 54 | { 55 | list_remove(&thread->processLink); 56 | unmap((void*)USER_STACKS + ((thread->localTid - 1) * PAGE_SIZE)); 57 | 58 | frame_free(vmem_to_phys(&kernelTLSs[thread->tid])); 59 | unmap(&kernelTLSs[thread->tid]); 60 | unmap(&userTLSs[thread->localTid]); 61 | 62 | thread->state = DYING; 63 | if (scheduler_current() == thread) 64 | schedule(); 65 | } 66 | -------------------------------------------------------------------------------- /kernel/task/scheduler.c: -------------------------------------------------------------------------------- 1 | #include "gdt.h" 2 | #include "ipc.h" 3 | #include "layout.h" 4 | #include "scheduler.h" 5 | #include "term.h" 6 | #include "vmem.h" 7 | 8 | static LIST(readyQueue); 9 | static TLS* volatile* const TLSPtr = (TLS**)TLS_PTR; 10 | 11 | static inline void switch_to(Thread* thread) 12 | { 13 | if (thread->process->PD != read_cr3()) 14 | write_cr3(thread->process->PD); 15 | 16 | *TLSPtr = (TLS*)USER_TLS + thread->localTid; 17 | set_kernel_stack(&thread->context + 1); 18 | set_context(&thread->context); 19 | } 20 | 21 | void schedule(void) 22 | { 23 | retry: 24 | if (list_empty(&readyQueue)) 25 | ERROR("No more threads to schedule."); 26 | 27 | Thread* new = list_item(list_pop(&readyQueue), Thread, queueLink); 28 | if (new->state == DYING) 29 | { 30 | unmap(new); 31 | goto retry; 32 | } 33 | 34 | list_append(&readyQueue, &new->queueLink); 35 | switch_to(scheduler_current()); 36 | } 37 | 38 | alwaysinline void scheduler_add(Thread* thread) 39 | { 40 | list_prepend(&readyQueue, &thread->queueLink); 41 | } 42 | 43 | inline void scheduler_remove(Thread* thread) 44 | { 45 | bool current = (list_last(&readyQueue) == &thread->queueLink); 46 | 47 | list_remove(&thread->queueLink); 48 | if (current) 49 | schedule(); 50 | } 51 | 52 | alwaysinline Thread* scheduler_current(void) 53 | { 54 | return list_item(list_last(&readyQueue), Thread, queueLink); 55 | } 56 | 57 | void scheduler_wait(uint16_t waitFor, State reason) 58 | { 59 | Thread* thread = scheduler_current(); 60 | scheduler_remove(thread); 61 | 62 | thread->state = reason; 63 | 64 | if (reason == WAIT_SENDING) 65 | list_append(&thread_get(waitFor)->waitingList, &thread->queueLink); 66 | 67 | else if (reason == WAIT_RECEIVING) 68 | thread->waitingFor = waitFor; 69 | 70 | else 71 | { 72 | thread->waitingFor = waitFor; 73 | list_append(&thread_get(waitFor)->waitingList, &thread->queueLink); 74 | } 75 | } 76 | 77 | inline void scheduler_unblock(Thread* thread) 78 | { 79 | thread->state = READY; 80 | scheduler_add(thread); 81 | } 82 | 83 | void scheduler_init(void) 84 | { 85 | map((void*)TLSPtr, NULL, PAGE_WRITE | PAGE_USER | PAGE_GLOBAL); 86 | 87 | irq_register(0, schedule); 88 | } 89 | -------------------------------------------------------------------------------- /kernel/lib/string.c: -------------------------------------------------------------------------------- 1 | #include "string.h" 2 | 3 | int memcmp(const void* s1, const void* s2, size_t n) 4 | { 5 | const uint8_t* p1 = (const uint8_t*)s1; 6 | const uint8_t* p2 = (const uint8_t*)s2; 7 | 8 | for (; n--; p1++, p2++) 9 | { 10 | uint8_t u1 = *p1, u2 = *p2; 11 | 12 | if (u1 != u2) 13 | return (u1 - u2); 14 | } 15 | 16 | return 0; 17 | } 18 | 19 | void* memcpy(void* dest, const void* src, size_t n) 20 | { 21 | const char* s = src; 22 | char* d = dest; 23 | 24 | while (n--) 25 | *d++ = *s++; 26 | 27 | return dest; 28 | } 29 | 30 | void* memmove(void* dest, const void* src, size_t n) 31 | { 32 | const uint8_t* s = src; 33 | uint8_t* d = dest; 34 | 35 | if (s < d) 36 | for (d += n, s += n; n--;) 37 | *--d = *--s; 38 | else 39 | while (n--) 40 | *d++ = *s++; 41 | 42 | return dest; 43 | } 44 | 45 | void* memset(void* s, int c, size_t n) 46 | { 47 | uint8_t* p = s; 48 | 49 | while (n--) 50 | *p++ = (uint8_t)c; 51 | 52 | return s; 53 | } 54 | 55 | int strcmp(const char* s1, const char* s2) 56 | { 57 | while (*s1 && (*s1 == *s2)) 58 | s1++, s2++; 59 | 60 | return *(const unsigned char*)s1 - *(const unsigned char*)s2; 61 | } 62 | 63 | char* strcpy(char* dest, const char* src) 64 | { 65 | char* ret = dest; 66 | 67 | while ((*dest++ = *src++)); 68 | 69 | return ret; 70 | } 71 | 72 | size_t strlen(const char* s) 73 | { 74 | const char* p = s; 75 | 76 | while (*s) ++s; 77 | 78 | return s - p; 79 | } 80 | 81 | char* itoa(uint32_t val, char* buf, int base) 82 | { 83 | if ((base < 2 || base > 36) && base != -10) 84 | { 85 | *buf = '\0'; 86 | return buf; 87 | } 88 | 89 | char *ptr = buf; 90 | switch (base) 91 | { 92 | case 2: strcpy(ptr, "0b"); ptr += 2; break; 93 | case 8: strcpy(ptr, "0"); ptr += 1; break; 94 | case 16: strcpy(ptr, "0x"); ptr += 2; break; 95 | case -10: base = -base; if ((int32_t)val < 0) { val = -val; *ptr++ = '-'; } break; 96 | } 97 | char* low = ptr; 98 | 99 | if (val != 0) 100 | do 101 | { 102 | *ptr++ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[val % base]; 103 | val /= base; 104 | } 105 | while (val); 106 | else 107 | *ptr++ = '0'; 108 | 109 | *ptr-- = '\0'; 110 | while (low < ptr) 111 | { 112 | char c = *low; 113 | *low++ = *ptr; 114 | *ptr-- = c; 115 | } 116 | 117 | return buf; 118 | } 119 | -------------------------------------------------------------------------------- /toolchain/newlib-utopia/include/_syscall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define alwaysinline inline __attribute__((always_inline)) 4 | 5 | #define _SYSCALL_0(n, fun) \ 6 | static alwaysinline int fun(void) \ 7 | { \ 8 | int ret; \ 9 | asm volatile ("int $0x80" : "=a" (ret) : "0" (n)); \ 10 | return ret; \ 11 | } 12 | 13 | #define _SYSCALL_1(n, fun, T1) \ 14 | static alwaysinline int fun(T1 p1) \ 15 | { \ 16 | int ret; \ 17 | asm volatile ("int $0x80" : "=a" (ret) : "0" (n), "c" (p1)); \ 18 | return ret; \ 19 | } 20 | 21 | #define _SYSCALL_2(n, fun, T1, T2) \ 22 | static alwaysinline int fun(T1 p1, T2 p2) \ 23 | { \ 24 | int ret; \ 25 | asm volatile ("int $0x80" : "=a" (ret) : "0" (n), "c" (p1), "d" (p2)); \ 26 | return ret; \ 27 | } 28 | 29 | #define _SYSCALL_3(n, fun, T1, T2, T3) \ 30 | static alwaysinline int fun(T1 p1, T2 p2, T3 p3) \ 31 | { \ 32 | int ret; \ 33 | asm volatile ("int $0x80" : "=a" (ret) : "0" (n), "c" (p1), "d" (p2), "b" (p3)); \ 34 | return ret; \ 35 | } 36 | 37 | #define _SYSCALL_4(n, fun, T1, T2, T3, T4) \ 38 | static alwaysinline int fun(T1 p1, T2 p2, T3 p3, T4 p4) \ 39 | { \ 40 | int ret; \ 41 | asm volatile ("int $0x80" : "=a" (ret) : "0" (n), "c" (p1), "d" (p2), "b" (p3), "D" (p4)); \ 42 | return ret; \ 43 | } 44 | 45 | #define _SYSCALL_5(n, fun, T1, T2, T3, T4, T5) \ 46 | static alwaysinline int fun(T1 p1, T2 p2, T3 p3, T4 p4, T5 p5) \ 47 | { \ 48 | int ret; \ 49 | asm volatile ("int $0x80" : "=a" (ret) : "0" (n), "c" (p1), "d" (p2), "b" (p3), "D" (p4), "S" (p5)); \ 50 | return ret; \ 51 | } 52 | -------------------------------------------------------------------------------- /toolchain/patches/gcc-4.9.0.patch: -------------------------------------------------------------------------------- 1 | diff -rupN original/config.sub new/config.sub 2 | --- original/config.sub 2013-01-11 14:02:58.000000000 +0100 3 | +++ new/config.sub 2014-01-22 11:39:31.000000000 +0100 4 | @@ -1358,7 +1358,7 @@ case $os in 5 | | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ 6 | | -sym* | -kopensolaris* | -plan9* \ 7 | | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ 8 | - | -aos* | -aros* \ 9 | + | -aos* | -aros* | -utopia* \ 10 | | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ 11 | | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ 12 | | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ 13 | diff -rupN original/gcc/config/utopia.h new/gcc/config/utopia.h 14 | --- original/gcc/config/utopia.h 1970-01-01 01:00:00.000000000 +0100 15 | +++ new/gcc/config/utopia.h 2014-01-22 11:39:31.000000000 +0100 16 | @@ -0,0 +1,8 @@ 17 | +#undef TARGET_OS_CPP_BUILTINS 18 | +#define TARGET_OS_CPP_BUILTINS() \ 19 | + do { \ 20 | + builtin_define_std ("utopia"); \ 21 | + builtin_define_std ("unix"); \ 22 | + builtin_assert ("system=utopia"); \ 23 | + builtin_assert ("system=unix"); \ 24 | + } while(0); 25 | diff -rupN original/gcc/config.gcc new/gcc/config.gcc 26 | --- original/gcc/config.gcc 2013-10-03 02:47:24.000000000 +0200 27 | +++ new/gcc/config.gcc 2014-01-22 11:39:31.000000000 +0100 28 | @@ -746,6 +746,12 @@ case ${target} in 29 | *-*-rdos*) 30 | use_gcc_stdint=wrap 31 | ;; 32 | +*-*-utopia*) 33 | + extra_parts="crtbegin.o crtend.o" 34 | + gas=yes 35 | + gnu_ld=yes 36 | + default_use_cxa_atexit=yes 37 | + ;; 38 | *-*-solaris2*) 39 | # i?86-*-solaris2* needs to insert headers between cpu default and 40 | # Solaris 2 specific ones. 41 | @@ -1215,6 +1221,11 @@ i[34567]86-*-elf*) 42 | x86_64-*-elf*) 43 | tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/x86-64.h" 44 | ;; 45 | +i[34567]86-*-utopia*) 46 | + tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h i386/i386elf.h utopia.h" 47 | + tmake_file="i386/t-i386elf t-svr4" 48 | + use_fixproto=yes 49 | + ;; 50 | i[34567]86-*-rdos*) 51 | tm_file="${tm_file} i386/unix.h i386/att.h dbxelf.h elfos.h newlib-stdint.h i386/i386elf.h i386/rdos.h" 52 | ;; 53 | diff -rupN original/libgcc/config.host new/libgcc/config.host 54 | --- original/libgcc/config.host 2013-07-09 23:35:57.000000000 +0200 55 | +++ new/libgcc/config.host 2014-01-22 11:39:31.000000000 +0100 56 | @@ -501,6 +501,10 @@ i[34567]86-*-elf*) 57 | x86_64-*-elf*) 58 | tmake_file="$tmake_file i386/t-crtstuff t-crtstuff-pic t-libgcc-pic" 59 | ;; 60 | +i[34567]86-*-utopia*) 61 | + extra_parts="crtbegin.o crtend.o" 62 | + tmake_file="$tmake_file i386/t-crtstuff" 63 | + ;; 64 | i[34567]86-*-freebsd*) 65 | tmake_file="${tmake_file} i386/t-freebsd i386/t-crtstuff" 66 | ;; 67 | diff -rupN original/libstdc++-v3/crossconfig.m4 new/libstdc++-v3/crossconfig.m4 68 | --- original/libstdc++-v3/crossconfig.m4 2012-05-02 21:34:31.000000000 +0200 69 | +++ new/libstdc++-v3/crossconfig.m4 2014-01-22 11:42:40.000000000 +0100 70 | @@ -150,6 +150,12 @@ case "${host}" in 71 | GCC_CHECK_TLS 72 | AM_ICONV 73 | ;; 74 | + *-utopia*) 75 | + AC_CHECK_HEADERS([sys/types.h locale.h float.h]) 76 | + GLIBCXX_CHECK_BUILTIN_MATH_SUPPORT 77 | + GLIBCXX_CHECK_COMPLEX_MATH_SUPPORT 78 | + GLIBCXX_CHECK_STDLIB_SUPPORT 79 | + ;; 80 | *-mingw32*) 81 | GLIBCXX_CHECK_LINKER_FEATURES 82 | GLIBCXX_CHECK_MATH_SUPPORT 83 | -------------------------------------------------------------------------------- /servers/keyboard/keyboard.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "keyboard.h" 3 | 4 | static int scancodeTable[] = 5 | { 6 | KEY_UNKNOWN, // 0x00 7 | KEY_ESCAPE, // 0x01 8 | KEY_1, // 0x02 9 | KEY_2, // 0x03 10 | KEY_3, // 0x04 11 | KEY_4, // 0x05 12 | KEY_5, // 0x06 13 | KEY_6, // 0x07 14 | KEY_7, // 0x08 15 | KEY_8, // 0x09 16 | KEY_9, // 0x0A 17 | KEY_0, // 0x0B 18 | KEY_MINUS, // 0x0C 19 | KEY_EQUAL, // 0x0D 20 | KEY_BACKSPACE, // 0x0E 21 | KEY_TAB, // 0x0F 22 | KEY_Q, // 0x10 23 | KEY_W, // 0x11 24 | KEY_E, // 0x12 25 | KEY_R, // 0x13 26 | KEY_T, // 0x14 27 | KEY_Y, // 0x15 28 | KEY_U, // 0x16 29 | KEY_I, // 0x17 30 | KEY_O, // 0x18 31 | KEY_P, // 0x19 32 | KEY_LEFTBRACKET, // 0x1A 33 | KEY_RIGHTBRACKET, // 0x1B 34 | KEY_RETURN, // 0x1C 35 | KEY_LCTRL, // 0x1D 36 | KEY_A, // 0x1E 37 | KEY_S, // 0x1F 38 | KEY_D, // 0x20 39 | KEY_F, // 0x21 40 | KEY_G, // 0x22 41 | KEY_H, // 0x23 42 | KEY_J, // 0x24 43 | KEY_K, // 0x25 44 | KEY_L, // 0x26 45 | KEY_SEMICOLON, // 0x27 46 | KEY_QUOTE, // 0x28 47 | KEY_GRAVE, // 0x29 48 | KEY_LSHIFT, // 0x2A 49 | KEY_BACKSLASH, // 0x2B 50 | KEY_Z, // 0x2C 51 | KEY_X, // 0x2D 52 | KEY_C, // 0x2E 53 | KEY_V, // 0x2F 54 | KEY_B, // 0x30 55 | KEY_N, // 0x31 56 | KEY_M, // 0x32 57 | KEY_COMMA, // 0x33 58 | KEY_DOT, // 0x34 59 | KEY_SLASH, // 0x35 60 | KEY_RSHIFT, // 0x36 61 | KEY_KP_ASTERISK, // 0x37 62 | KEY_RALT, // 0x38 63 | KEY_SPACE, // 0x39 64 | KEY_CAPSLOCK, // 0x3A 65 | KEY_F1, // 0x3B 66 | KEY_F2, // 0x3C 67 | KEY_F3, // 0x3D 68 | KEY_F4, // 0x3E 69 | KEY_F5, // 0x3F 70 | KEY_F6, // 0x40 71 | KEY_F7, // 0x41 72 | KEY_F8, // 0x42 73 | KEY_F9, // 0x43 74 | KEY_F10, // 0x44 75 | KEY_KP_NUMLOCK, // 0x45 76 | KEY_SCROLLLOCK, // 0x46 77 | KEY_HOME, // 0x47 78 | KEY_KP_8, // 0x48 79 | KEY_PAGEUP, // 0x49 80 | KEY_KP_2, // 0x50 81 | KEY_KP_3, // 0x51 82 | KEY_KP_0, // 0x52 83 | KEY_KP_DECIMAL, // 0x53 84 | KEY_UNKNOWN, // 0x54 85 | KEY_UNKNOWN, // 0x55 86 | KEY_UNKNOWN, // 0x56 87 | KEY_F11, // 0x57 88 | KEY_F12 // 0x58 89 | }; 90 | 91 | int main(void) 92 | { 93 | irq_subscribe(1); 94 | 95 | while(1) 96 | { 97 | irq_wait(1); 98 | 99 | if (inb(0x64) & 1) 100 | { 101 | int code = inb(0x60); 102 | if (code & 0x80) 103 | continue; 104 | int key = scancodeTable[code]; 105 | 106 | send_receive(0, -1); 107 | MBOX->tag.n = 1; 108 | MBOX->reg[0] = (char)key; 109 | send_receive(MBOX->tag.tid, 0); 110 | } 111 | } 112 | 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /toolchain/patches/binutils-2.24.patch: -------------------------------------------------------------------------------- 1 | diff -rupN original/bfd/config.bfd new/bfd/config.bfd 2 | --- original/bfd/config.bfd 2013-11-04 16:33:37.000000000 +0100 3 | +++ new/bfd/config.bfd 2013-12-25 19:51:28.656619916 +0100 4 | @@ -538,6 +538,9 @@ case "${targ}" in 5 | i[3-7]86-*-aros*) 6 | targ_defvec=bfd_elf32_i386_vec 7 | ;; 8 | + i[3-7]86-*-utopia*) 9 | + targ_defvec=bfd_elf32_i386_vec 10 | + ;; 11 | i[3-7]86-*-chorus*) 12 | targ_defvec=bfd_elf32_i386_vec 13 | ;; 14 | diff -rupN original/config.sub new/config.sub 15 | --- original/config.sub 2013-11-26 12:37:33.000000000 +0100 16 | +++ new/config.sub 2013-12-25 19:50:10.037045835 +0100 17 | @@ -1356,7 +1356,7 @@ case $os in 18 | | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ 19 | | -sym* | -kopensolaris* | -plan9* \ 20 | | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ 21 | - | -aos* | -aros* \ 22 | + | -aos* | -aros* | -utopia* \ 23 | | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ 24 | | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ 25 | | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ 26 | diff -rupN original/gas/configure.tgt new/gas/configure.tgt 27 | --- original/gas/configure.tgt 2013-11-04 16:33:37.000000000 +0100 28 | +++ new/gas/configure.tgt 2013-12-25 19:57:02.168146462 +0100 29 | @@ -206,6 +206,7 @@ case ${generic_target} in 30 | i386-*-beos*) fmt=elf ;; 31 | i386-*-coff) fmt=coff ;; 32 | i386-*-elf) fmt=elf ;; 33 | + i386-*-utopia*) fmt=elf ;; 34 | i386-*-kaos*) fmt=elf ;; 35 | i386-*-bsd*) fmt=aout em=386bsd ;; 36 | i386-*-nacl*) fmt=elf em=nacl 37 | diff -rupN original/ld/configure.tgt new/ld/configure.tgt 38 | --- original/ld/configure.tgt 2013-11-26 12:37:33.000000000 +0100 39 | +++ new/ld/configure.tgt 2013-12-25 19:53:26.489314895 +0100 40 | @@ -218,6 +218,7 @@ i[3-7]86-*-lynxos*) targ_emul=i386lynx ; 41 | i[3-7]86-*-coff) targ_emul=i386coff ;; 42 | i[3-7]86-*-rtems*) targ_emul=elf_i386 ;; 43 | i[3-7]86-*-aros*) targ_emul=elf_i386 ;; 44 | +i[3-7]86-*-utopia*) targ_emul=utopia_i386 ;; 45 | i[3-7]86-*-rdos*) targ_emul=elf_i386 ;; 46 | x86_64-*-rdos*) targ_emul=elf64rdos ;; 47 | i[3-7]86-*-bsd) targ_emul=i386bsd ;; 48 | diff -rupN original/ld/emulparams/utopia_i386.sh new/ld/emulparams/utopia_i386.sh 49 | --- original/ld/emulparams/utopia_i386.sh 1970-01-01 01:00:00.000000000 +0100 50 | +++ new/ld/emulparams/utopia_i386.sh 2013-12-25 19:54:38.118926844 +0100 51 | @@ -0,0 +1,15 @@ 52 | +SCRIPT_NAME=elf 53 | +OUTPUT_FORMAT="elf32-i386" 54 | +NO_RELA_RELOCS=yes 55 | +TEXT_START_ADDR=0x40000000 56 | +MAXPAGESIZE="CONSTANT (MAXPAGESIZE)" 57 | +COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)" 58 | +ARCH=i386 59 | +MACHINE= 60 | +NOP=0x90909090 61 | +TEMPLATE_NAME=elf32 62 | +GENERATE_SHLIB_SCRIPT=yes 63 | +GENERATE_PIE_SCRIPT=yes 64 | +NO_SMALL_DATA=yes 65 | +SEPARATE_GOTPLT=12 66 | +IREL_IN_PLT= 67 | diff -rupN original/ld/Makefile.in new/ld/Makefile.in 68 | --- original/ld/Makefile.in 2013-11-26 12:37:33.000000000 +0100 69 | +++ new/ld/Makefile.in 2013-12-25 19:55:37.035274333 +0100 70 | @@ -2752,6 +2752,9 @@ eelf32xtensa.c: $(srcdir)/emulparams/elf 71 | eelf_i386.c: $(srcdir)/emulparams/elf_i386.sh \ 72 | $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} 73 | ${GENSCRIPTS} elf_i386 "$(tdir_elf_i386)" 74 | +eutopia_i386.c: $(srcdir)/emulparams/utopia_i386.sh \ 75 | + $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} 76 | + ${GENSCRIPTS} utopia_i386 "$(tdir_utopia_i386)" 77 | eelf_i386_be.c: $(srcdir)/emulparams/elf_i386_be.sh \ 78 | $(ELF_DEPS) $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} 79 | ${GENSCRIPTS} elf_i386_be "$(tdir_elf_i386_be)" 80 | -------------------------------------------------------------------------------- /kernel/video/term.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "string.h" 3 | #include "term.h" 4 | 5 | #define SIZE_X 80 6 | #define SIZE_Y 25 7 | #define DEFAULT_BG 0 8 | #define DEFAULT_FG 7 9 | 10 | static uint16_t* const VRAM = (uint16_t*)0xB8000; 11 | static int cursor = 0; 12 | 13 | static uint8_t bg = DEFAULT_BG; 14 | static uint8_t fg = DEFAULT_FG; 15 | 16 | static void update_cursor(void) 17 | { 18 | uint16_t h = (cursor & 0xFF00) | 0x0E; 19 | uint16_t l = ((cursor & 0x00FF) << 8) | 0x0F; 20 | 21 | outw(0x3D4, h); 22 | outw(0x3D4, l); 23 | } 24 | 25 | inline void put(char c) 26 | { 27 | if (cursor == SIZE_X * SIZE_Y) 28 | { 29 | cursor -= SIZE_X; 30 | 31 | for (int i = 0; i < cursor; i++) 32 | VRAM[i] = VRAM[i + SIZE_X]; 33 | 34 | for (int i = 0; i < SIZE_X; i++) 35 | VRAM[i + cursor] = (bg << 12) | ' '; 36 | } 37 | 38 | VRAM[cursor++] = ((bg << 4 | (fg & 0x0F)) << 8) | c; 39 | } 40 | 41 | static void write(const char* s) 42 | { 43 | for (int i = 0; s[i] != '\0'; i++) 44 | put(s[i]); 45 | } 46 | 47 | void clear_screen(void) 48 | { 49 | for (int i = 0; i < SIZE_X * SIZE_Y; i++) 50 | VRAM[i] = (bg << 12) | ' '; 51 | 52 | cursor = 0; 53 | update_cursor(); 54 | } 55 | 56 | void printf(const char* format, ...) 57 | { 58 | static char buf[35]; 59 | 60 | va_list args; 61 | va_start(args, format); 62 | 63 | uint8_t saved_bg = bg, saved_fg = fg; 64 | 65 | for (int i = 0; format[i] != '\0'; i++) 66 | switch (format[i]) 67 | { 68 | case '\n': 69 | do 70 | put(' '); 71 | while (cursor % SIZE_X); 72 | break; 73 | 74 | case '\t': 75 | do 76 | put(' '); 77 | while (cursor % 4); 78 | break; 79 | 80 | case '\e': 81 | switch (format[i+1]) 82 | { 83 | case 'B': 84 | bg = format[i+2] == '1' ? format[i+3] + 0xA : format[i+3]; 85 | i += 3; 86 | break; 87 | 88 | case 'F': 89 | fg = format[i+2] == '1' ? format[i+3] + 0xA : format[i+3]; 90 | i += 3; 91 | break; 92 | 93 | default: 94 | bg = format[i+1] == '1' ? format[i+2] + 0xA : format[i+2]; 95 | fg = format[i+3] == '1' ? format[i+4] + 0xA : format[i+4]; 96 | i += 4; 97 | break; 98 | } 99 | break; 100 | 101 | case '%': 102 | switch (format[++i]) 103 | { 104 | case 'x': write(itoa(va_arg(args, uint32_t), buf, 16)); break; 105 | case 'u': write(itoa(va_arg(args, uint32_t), buf, 10)); break; 106 | case 'd': 107 | case 'i': write(itoa(va_arg(args, uint32_t), buf, -10)); break; 108 | case 'o': write(itoa(va_arg(args, uint32_t), buf, 8)); break; 109 | case 'b': write(itoa(va_arg(args, uint32_t), buf, 2)); break; 110 | case 'c': put (va_arg(args, uint32_t)); break; 111 | case 's': write(va_arg(args, char*)); break; 112 | case '%': put ('%'); break; 113 | } 114 | break; 115 | 116 | default: 117 | put(format[i]); 118 | break; 119 | } 120 | 121 | bg = saved_bg; fg = saved_fg; 122 | update_cursor(); 123 | 124 | va_end(args); 125 | } 126 | -------------------------------------------------------------------------------- /toolchain/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$(uname)" == "Darwin" ]; then 4 | export CC=/usr/local/bin/gcc-4.9 5 | export CXX=/usr/local/bin/g++-4.9 6 | export CPP=/usr/local/bin/cpp-4.9 7 | export LD=/usr/local/bin/gcc-4.9 8 | 9 | BINUTILS_CFLAGS="-Wno-error=deprecated-declarations -Wno-error=unused-value" 10 | AUTOCONF_264="autoconf264" 11 | NEWLIB_AUTOMAKE="automake112" 12 | NEWLIB_ACLOCAL="aclocal112" 13 | else 14 | AUTOCONF_264="autoconf-2.64" 15 | NEWLIB_AUTOMAKE="automake-1.12" 16 | NEWLIB_ACLOCAL="aclocal-1.12" 17 | fi 18 | 19 | BINUTILS_VER=2.24 20 | GMP_VER=5.1.3 21 | MPFR_VER=3.1.2 22 | MPC_VER=1.0.2 23 | ICONV_VER=1.14 24 | GCC_VER=4.9.0 25 | GDB_VER=7.7.1 26 | NEWLIB_VER=2.1.0 27 | 28 | BINUTILS_URL=http://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VER.tar.bz2 29 | GMP_URL=https://gmplib.org/download/gmp/gmp-$GMP_VER.tar.bz2 30 | MPFR_URL=http://www.mpfr.org/mpfr-current/mpfr-$MPFR_VER.tar.bz2 31 | MPC_URL=http://multiprecision.org/mpc/download/mpc-$MPC_VER.tar.gz 32 | ICONV_URL=http://ftp.gnu.org/gnu/libiconv/libiconv-$ICONV_VER.tar.gz 33 | GCC_URL=http://ftp.gnu.org/gnu/gcc/gcc-$GCC_VER/gcc-$GCC_VER.tar.bz2 34 | GDB_URL=http://ftp.gnu.org/gnu/gdb/gdb-$GDB_VER.tar.bz2 35 | NEWLIB_URL=ftp://sourceware.org/pub/newlib/newlib-$NEWLIB_VER.tar.gz 36 | 37 | export TARGET=i686-pc-utopia 38 | export PREFIX=/usr/local/utopia 39 | export PATH="$PREFIX/bin:$PATH" 40 | 41 | mkdir packages 42 | cd packages 43 | 44 | 45 | if [ "$1" != "-n" ]; then 46 | wget -c $BINUTILS_URL 47 | tar xjf binutils-$BINUTILS_VER.tar.bz2 48 | 49 | pushd binutils-$BINUTILS_VER 50 | patch -p1 < ../../patches/binutils-$BINUTILS_VER.patch || exit 1 51 | popd 52 | 53 | mkdir build-binutils 54 | pushd build-binutils 55 | CFLAGS="$BINUTILS_CFLAGS" ../binutils-$BINUTILS_VER/configure --target=$TARGET --prefix="$PREFIX" --disable-nls || exit 1 56 | make -j4 || exit 1 57 | sudo make install || exit 1 58 | popd 59 | 60 | 61 | 62 | wget -c $GMP_URL 63 | wget -c $MPFR_URL 64 | wget -c $MPC_URL 65 | wget -c $ICONV_URL 66 | wget -c $GCC_URL 67 | 68 | tar xjf gmp-$GMP_VER.tar.bz2 69 | tar xjf mpfr-$MPFR_VER.tar.bz2 70 | tar xzf mpc-$MPC_VER.tar.gz 71 | tar xzf libiconv-$ICONV_VER.tar.gz 72 | tar xjf gcc-$GCC_VER.tar.bz2 73 | 74 | pushd gcc-$GCC_VER 75 | mv ../gmp-$GMP_VER gmp 76 | mv ../mpfr-$MPFR_VER mpfr 77 | mv ../mpc-$MPC_VER mpc 78 | mv ../libiconv-$ICONV_VER libiconv 79 | patch -p1 < ../../patches/gcc-$GCC_VER.patch || exit 1 80 | pushd libstdc++-v3 81 | $AUTOCONF_264 || exit 1 82 | popd 83 | popd 84 | 85 | mkdir build-gcc 86 | pushd build-gcc 87 | ../gcc-$GCC_VER/configure --target=$TARGET --prefix="$PREFIX" --disable-nls \ 88 | --enable-languages=c,c++ --disable-libssp --with-newlib || exit 1 89 | make all-gcc -j4 || exit 1 90 | make all-target-libgcc -j4 || exit 1 91 | sudo make install-gcc || exit 1 92 | sudo make install-target-libgcc || exit 1 93 | popd 94 | 95 | 96 | 97 | wget -c $GDB_URL 98 | tar xjf gdb-$GDB_VER.tar.bz2 99 | 100 | mkdir build-gdb 101 | pushd build-gdb 102 | ../gdb-$GDB_VER/configure --target=i686-elf --prefix="$PREFIX" --disable-nls || exit 1 103 | make -j4 || exit 1 104 | sudo make install || exit 1 105 | popd 106 | fi 107 | 108 | 109 | 110 | wget -c $NEWLIB_URL 111 | tar xzf newlib-$NEWLIB_VER.tar.gz 112 | 113 | pushd newlib-$NEWLIB_VER 114 | patch -p1 < ../../patches/newlib-$NEWLIB_VER.patch || exit 1 115 | cp -a ../../newlib-utopia newlib/libc/sys/utopia 116 | pushd newlib/libc/sys 117 | autoconf || exit 1 118 | pushd utopia 119 | AUTOMAKE="$NEWLIB_AUTOMAKE" ACLOCAL="$NEWLIB_ACLOCAL" autoreconf || exit 1 120 | popd 121 | popd 122 | popd 123 | 124 | mkdir build-newlib 125 | pushd build-newlib 126 | ../newlib-$NEWLIB_VER/configure --target=$TARGET --prefix="$PREFIX" || exit 1 127 | make -j4 || exit 1 128 | sudo make install || exit 1 129 | popd 130 | 131 | if [ "$1" != "-n" ]; then 132 | pushd build-gcc 133 | make || exit 1 134 | sudo make install || exit 1 135 | popd 136 | fi 137 | -------------------------------------------------------------------------------- /kernel/memory/vmem.c: -------------------------------------------------------------------------------- 1 | #include "interrupt.h" 2 | #include "layout.h" 3 | #include "pmem.h" 4 | #include "scheduler.h" 5 | #include "string.h" 6 | #include "term.h" 7 | #include "vmem.h" 8 | 9 | typedef uintptr_t PEntry; 10 | 11 | static PEntry* const PD = (PEntry*)0xFFFFF000; 12 | static PEntry* const PTs = (PEntry*)0xFFC00000; 13 | 14 | #define PAGE_ALLOCATED (1 << 9) 15 | 16 | #define PD_INDEX(x) ((uintptr_t)(x) >> 22) 17 | #define PT_INDEX(x) ((uintptr_t)(x) >> 12 & 0x3FF) 18 | 19 | #define PD_ENTRY(x) (PD + PD_INDEX(x)) 20 | #define PT_ENTRY(x) (PTs + (PD_INDEX(x) * 0x400) + PT_INDEX(x)) 21 | 22 | void* vmem_to_phys(const void* vAddr) 23 | { 24 | PEntry* pdEntry = PD_ENTRY(vAddr); 25 | if (! *pdEntry) 26 | return NULL; 27 | 28 | PEntry* ptEntry = PT_ENTRY(vAddr); 29 | if (! *ptEntry) 30 | return NULL; 31 | 32 | return (void*) ((*ptEntry & ~0xFFF) | ((uintptr_t)vAddr & 0xFFF)); 33 | } 34 | 35 | void map(void* vAddr, void* pAddr, uint16_t flags) 36 | { 37 | PEntry* pdEntry = PD_ENTRY(vAddr); 38 | PEntry* ptEntry = PT_ENTRY(vAddr); 39 | 40 | if (! *pdEntry) 41 | { 42 | *pdEntry = (PEntry)frame_alloc() | flags | PAGE_PRESENT | PAGE_WRITE | PAGE_USER; 43 | invlpg(ptEntry); 44 | 45 | memset(PAGE_BASE(ptEntry), 0, PAGE_SIZE); 46 | } 47 | 48 | if (pAddr == NULL) 49 | { 50 | if (*ptEntry & PAGE_ALLOCATED) 51 | *ptEntry = (*ptEntry & ~0xFFF) | flags | PAGE_PRESENT | PAGE_ALLOCATED; 52 | else 53 | *ptEntry = (PEntry)frame_alloc() | flags | PAGE_PRESENT | PAGE_ALLOCATED; 54 | } 55 | else 56 | { 57 | if (*ptEntry & PAGE_ALLOCATED) 58 | frame_free((void*) *ptEntry); 59 | 60 | *ptEntry = (PEntry)PAGE_BASE(pAddr) | flags | PAGE_PRESENT; 61 | } 62 | 63 | invlpg(vAddr); 64 | } 65 | 66 | void unmap(void* vAddr) 67 | { 68 | PEntry* pdEntry = PD_ENTRY(vAddr); 69 | if (! *pdEntry) 70 | return; 71 | PEntry* ptEntry = PT_ENTRY(vAddr); 72 | 73 | if (*ptEntry & PAGE_ALLOCATED) 74 | frame_free((void*) *ptEntry); 75 | 76 | *ptEntry = 0; 77 | invlpg(vAddr); 78 | } 79 | 80 | static void page_fault(void) 81 | { 82 | void* cr2 = read_cr2(); 83 | if (cr2 == (void*)THREAD_MAGIC) 84 | return thread_exit(scheduler_current()); 85 | 86 | Context* context = get_context(); 87 | if ((context->error & (PAGE_USER | ~PAGE_PRESENT)) && 88 | cr2 >= (void*)USER_HEAP && 89 | cr2 < (void*)USER_HEAP + scheduler_current()->process->heapSize) 90 | { 91 | return map(cr2, NULL, PAGE_WRITE | PAGE_USER); 92 | } 93 | 94 | ALERT("Page fault at address %x.", cr2); 95 | if (context->error & PAGE_USER) 96 | ALERT(" DPL: userspace "); 97 | else 98 | ALERT(" DPL: kernel "); 99 | 100 | if (context->error & PAGE_WRITE) 101 | ALERT(" OP: write "); 102 | else 103 | ALERT(" OP: read "); 104 | 105 | if (context->error & PAGE_PRESENT) 106 | ALERT(" ERR: protection "); 107 | else 108 | ALERT(" ERR: non-present"); 109 | 110 | hlt(); 111 | } 112 | 113 | void* new_address_space(void) 114 | { 115 | PEntry* extPD = (PEntry*)TMP_MAP; 116 | PEntry* newPD = frame_alloc(); 117 | 118 | map(extPD, newPD, PAGE_WRITE | PAGE_GLOBAL); 119 | memset(extPD, 0, PAGE_SIZE); 120 | 121 | unsigned kSpace = PD_INDEX(KERNEL_SPACE_END); 122 | memcpy(extPD, PD, kSpace * sizeof(PEntry)); 123 | 124 | extPD[1023] = (PEntry)newPD | PAGE_PRESENT | PAGE_WRITE; 125 | 126 | return newPD; 127 | } 128 | 129 | void destroy_address_space(void) 130 | { 131 | PEntry* physPD = read_cr3(); 132 | frame_free(physPD); 133 | 134 | for (uint32_t i = PD_INDEX(USER_SPACE); 135 | i < PD_INDEX(USER_SPACE_END); 136 | i++) 137 | { 138 | if (PD[i]) 139 | { 140 | frame_free((void*) (PD[i] & ~0xFFF)); 141 | 142 | for (PEntry* ptEntry = PT_ENTRY(0x400000*i); 143 | ptEntry < (PT_ENTRY(0x400000*i) + 0x400); 144 | ptEntry++) 145 | { 146 | if (*ptEntry & PAGE_ALLOCATED) 147 | frame_free((void*) *ptEntry); 148 | *ptEntry = 0; 149 | } 150 | } 151 | } 152 | } 153 | 154 | void vmem_init(void) 155 | { 156 | PEntry* physPD = frame_alloc(); 157 | memset(physPD, 0, PAGE_SIZE); 158 | 159 | physPD[0] = (PEntry)0x000000 | PAGE_PRESENT | PAGE_WRITE | PAGE_4MB | PAGE_GLOBAL; 160 | physPD[1023] = (PEntry)physPD | PAGE_PRESENT | PAGE_WRITE; 161 | 162 | interrupt_register(14, page_fault); 163 | enable_paging(physPD); 164 | } 165 | -------------------------------------------------------------------------------- /servers/keyboard/keyboard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef enum 4 | { 5 | // Alphanumeric: 6 | KEY_SPACE = ' ', 7 | KEY_0 = '0', 8 | KEY_1 = '1', 9 | KEY_2 = '2', 10 | KEY_3 = '3', 11 | KEY_4 = '4', 12 | KEY_5 = '5', 13 | KEY_6 = '6', 14 | KEY_7 = '7', 15 | KEY_8 = '8', 16 | KEY_9 = '9', 17 | KEY_A = 'a', 18 | KEY_B = 'b', 19 | KEY_C = 'c', 20 | KEY_D = 'd', 21 | KEY_E = 'e', 22 | KEY_F = 'f', 23 | KEY_G = 'g', 24 | KEY_H = 'h', 25 | KEY_I = 'i', 26 | KEY_J = 'j', 27 | KEY_K = 'k', 28 | KEY_L = 'l', 29 | KEY_M = 'm', 30 | KEY_N = 'n', 31 | KEY_O = 'o', 32 | KEY_P = 'p', 33 | KEY_Q = 'q', 34 | KEY_R = 'r', 35 | KEY_S = 's', 36 | KEY_T = 't', 37 | KEY_U = 'u', 38 | KEY_V = 'v', 39 | KEY_W = 'w', 40 | KEY_X = 'x', 41 | KEY_Y = 'y', 42 | KEY_Z = 'z', 43 | KEY_RETURN = '\r', 44 | KEY_ESCAPE = 0x1001, 45 | KEY_BACKSPACE = '\b', 46 | 47 | // Arrows: 48 | KEY_UP = 0x1100, 49 | KEY_DOWN = 0x1101, 50 | KEY_LEFT = 0x1102, 51 | KEY_RIGHT = 0x1103, 52 | 53 | // Functions: 54 | KEY_F1 = 0x1201, 55 | KEY_F2 = 0x1202, 56 | KEY_F3 = 0x1203, 57 | KEY_F4 = 0x1204, 58 | KEY_F5 = 0x1205, 59 | KEY_F6 = 0x1206, 60 | KEY_F7 = 0x1207, 61 | KEY_F8 = 0x1208, 62 | KEY_F9 = 0x1209, 63 | KEY_F10 = 0x120a, 64 | KEY_F11 = 0x120b, 65 | KEY_F12 = 0x120b, 66 | KEY_F13 = 0x120c, 67 | KEY_F14 = 0x120d, 68 | KEY_F15 = 0x120e, 69 | 70 | // Symbols: 71 | KEY_DOT = '.', 72 | KEY_COMMA = ',', 73 | KEY_COLON = ':', 74 | KEY_SEMICOLON = ';', 75 | KEY_SLASH = '/', 76 | KEY_BACKSLASH = '\\', 77 | KEY_PLUS = '+', 78 | KEY_MINUS = '-', 79 | KEY_ASTERISK = '*', 80 | KEY_EXCLAMATION = '!', 81 | KEY_QUESTION = '?', 82 | KEY_QUOTEDOUBLE = '\"', 83 | KEY_QUOTE = '\'', 84 | KEY_EQUAL = '=', 85 | KEY_HASH = '#', 86 | KEY_PERCENT = '%', 87 | KEY_AMPERSAND = '&', 88 | KEY_UNDERSCORE = '_', 89 | KEY_LEFTPARENTHESIS = '(', 90 | KEY_RIGHTPARENTHESIS = ')', 91 | KEY_LEFTBRACKET = '[', 92 | KEY_RIGHTBRACKET = ']', 93 | KEY_LEFTCURL = '{', 94 | KEY_RIGHTCURL = '}', 95 | KEY_DOLLAR = '$', 96 | KEY_POUND = '£', 97 | KEY_EURO = '$', 98 | KEY_LESS = '<', 99 | KEY_GREATER = '>', 100 | KEY_BAR = '|', 101 | KEY_GRAVE = '`', 102 | KEY_TILDE = '~', 103 | KEY_AT = '@', 104 | KEY_CARRET = '^', 105 | 106 | // Numeric keypad: 107 | KEY_KP_0 = '0', 108 | KEY_KP_1 = '1', 109 | KEY_KP_2 = '2', 110 | KEY_KP_3 = '3', 111 | KEY_KP_4 = '4', 112 | KEY_KP_5 = '5', 113 | KEY_KP_6 = '6', 114 | KEY_KP_7 = '7', 115 | KEY_KP_8 = '8', 116 | KEY_KP_9 = '9', 117 | KEY_KP_PLUS = '+', 118 | KEY_KP_MINUS = '-', 119 | KEY_KP_DECIMAL = '.', 120 | KEY_KP_DIVIDE = '/', 121 | KEY_KP_ASTERISK = '*', 122 | KEY_KP_NUMLOCK = 0x300f, 123 | KEY_KP_ENTER = 0x3010, 124 | 125 | KEY_TAB = 0x4000, 126 | KEY_CAPSLOCK = 0x4001, 127 | 128 | // Modifiers: 129 | KEY_LSHIFT = 0x4002, 130 | KEY_LCTRL = 0x4003, 131 | KEY_LALT = 0x4004, 132 | KEY_LWIN = 0x4005, 133 | KEY_RSHIFT = 0x4006, 134 | KEY_RCTRL = 0x4007, 135 | KEY_RALT = 0x4008, 136 | KEY_RWIN = 0x4009, 137 | 138 | // Actions: 139 | KEY_INSERT = 0x400a, 140 | KEY_DELETE = 0x400b, 141 | KEY_HOME = 0x400c, 142 | KEY_END = 0x400d, 143 | KEY_PAGEUP = 0x400e, 144 | KEY_PAGEDOWN = 0x400f, 145 | KEY_SCROLLLOCK = 0x4010, 146 | KEY_PAUSE = 0x4011, 147 | 148 | KEY_UNKNOWN, 149 | KEY_NUMKEYCODES 150 | } KeyCode; 151 | -------------------------------------------------------------------------------- /kernel/cpu/interrupt.c: -------------------------------------------------------------------------------- 1 | #include "idt.h" 2 | #include "isr.h" 3 | #include "term.h" 4 | #include "interrupt.h" 5 | 6 | #define PIC1_CMD 0x20 7 | #define PIC2_CMD 0xA0 8 | #define PIC1_DATA 0x21 9 | #define PIC2_DATA 0xA1 10 | 11 | Context* volatile context; 12 | 13 | static const char* const interruptNames[] = 14 | { 15 | "Division By Zero", 16 | "Debug", 17 | "Non Maskable Interrupt", 18 | "Breakpoint", 19 | "Overflow", 20 | "Bound Range Exceeded", 21 | "Invalid Opcode", 22 | "Device Not Available", 23 | "Double Fault", 24 | "Coprocessor Segment Overrun", 25 | "Invalid TSS", 26 | "Segment Not Present", 27 | "Stack Segment Fault", 28 | "General Protection Fault", 29 | "Page Fault", 30 | "Reserved", 31 | "x87 Floating Point Exception", 32 | "Alignment Check", 33 | "Machine Check", 34 | "SIMD Floating Point Exception", 35 | "Virtualization Exception", 36 | "Reserved", "Reserved", "Reserved", 37 | "Reserved", "Reserved", "Reserved", 38 | "Reserved", "Reserved", "Reserved", 39 | "Security Exception", 40 | "Reserved", 41 | 42 | "Programmable Interrupt Timer", 43 | "Keyboard", 44 | "Cascade", 45 | "COM2", 46 | "COM1", 47 | "LPT2", 48 | "Floppy Disk", 49 | "LPT1", 50 | "CMOS RTC", 51 | "Legacy SCSI / NIC / ?", 52 | "SCSI / NIC / ?", 53 | "SCSI / NIC / ?", 54 | "PS2 Mouse", 55 | "FPU", 56 | "Primary ATA Hard Disk", 57 | "Secondary ATA Hard Disk" 58 | }; 59 | 60 | static void interrupt_unhandled(void) 61 | { 62 | Context* context = get_context(); 63 | 64 | if (context->num < 32) 65 | ERROR("Exception: %s.", interruptNames[context->num]); 66 | else if (context->num < 32 + 16) 67 | ERROR("IRQ: %s", interruptNames[context->num]); 68 | } 69 | 70 | InterruptHandler interruptHandlers[32 + 16] = { [0 ... 47] = interrupt_unhandled }; 71 | 72 | void interrupt_register(uint8_t n, InterruptHandler handler) 73 | { 74 | interruptHandlers[n] = handler; 75 | } 76 | 77 | void irq_register(uint8_t n, InterruptHandler handler) 78 | { 79 | interruptHandlers[32 + n] = handler; 80 | irq_unmask(n); 81 | } 82 | 83 | void irq_mask(uint8_t irq) 84 | { 85 | uint16_t port = (irq < 8) ? PIC1_DATA : PIC2_DATA; 86 | outb(port, inb(port) | (1 << irq % 8)); 87 | } 88 | 89 | void irq_unmask(uint8_t irq) 90 | { 91 | uint16_t port = (irq < 8) ? PIC1_DATA : PIC2_DATA; 92 | outb(port, inb(port) & ~(1 << irq % 8)); 93 | } 94 | 95 | static void pic_remap(void) 96 | { 97 | outb(PIC1_CMD, 0x11); outb(PIC2_CMD, 0x11); 98 | outb(PIC1_DATA, 32); outb(PIC2_DATA, 40); 99 | outb(PIC1_DATA, 0b100); outb(PIC2_DATA, 0b10); 100 | outb(PIC1_DATA, 0x01); outb(PIC2_DATA, 0x01); 101 | outb(PIC1_DATA, 0xFF); outb(PIC2_DATA, 0xFF); 102 | } 103 | 104 | alwaysinline Context* get_context(void) 105 | { 106 | return context; 107 | } 108 | 109 | alwaysinline void set_context(Context* newContext) 110 | { 111 | context = newContext; 112 | } 113 | 114 | void interrupt_init(void) 115 | { 116 | pic_remap(); 117 | 118 | idt_set_gate(0, INTERRUPT_GATE, isr0); 119 | idt_set_gate(1, INTERRUPT_GATE, isr1); 120 | idt_set_gate(2, INTERRUPT_GATE, isr2); 121 | idt_set_gate(3, INTERRUPT_GATE, isr3); 122 | idt_set_gate(4, INTERRUPT_GATE, isr4); 123 | idt_set_gate(5, INTERRUPT_GATE, isr5); 124 | idt_set_gate(6, INTERRUPT_GATE, isr6); 125 | idt_set_gate(7, INTERRUPT_GATE, isr7); 126 | idt_set_gate(8, INTERRUPT_GATE, isr8); 127 | idt_set_gate(9, INTERRUPT_GATE, isr9); 128 | idt_set_gate(10, INTERRUPT_GATE, isr10); 129 | idt_set_gate(11, INTERRUPT_GATE, isr11); 130 | idt_set_gate(12, INTERRUPT_GATE, isr12); 131 | idt_set_gate(13, INTERRUPT_GATE, isr13); 132 | idt_set_gate(14, INTERRUPT_GATE, isr14); 133 | idt_set_gate(15, INTERRUPT_GATE, isr15); 134 | idt_set_gate(16, INTERRUPT_GATE, isr16); 135 | idt_set_gate(17, INTERRUPT_GATE, isr17); 136 | idt_set_gate(18, INTERRUPT_GATE, isr18); 137 | idt_set_gate(19, INTERRUPT_GATE, isr19); 138 | idt_set_gate(20, INTERRUPT_GATE, isr20); 139 | idt_set_gate(21, INTERRUPT_GATE, isr21); 140 | idt_set_gate(22, INTERRUPT_GATE, isr22); 141 | idt_set_gate(23, INTERRUPT_GATE, isr23); 142 | idt_set_gate(24, INTERRUPT_GATE, isr24); 143 | idt_set_gate(25, INTERRUPT_GATE, isr25); 144 | idt_set_gate(26, INTERRUPT_GATE, isr26); 145 | idt_set_gate(27, INTERRUPT_GATE, isr27); 146 | idt_set_gate(28, INTERRUPT_GATE, isr28); 147 | idt_set_gate(29, INTERRUPT_GATE, isr29); 148 | idt_set_gate(30, INTERRUPT_GATE, isr30); 149 | idt_set_gate(31, INTERRUPT_GATE, isr31); 150 | 151 | idt_set_gate(32, INTERRUPT_GATE, isr32); 152 | idt_set_gate(33, INTERRUPT_GATE, isr33); 153 | idt_set_gate(34, INTERRUPT_GATE, isr34); 154 | idt_set_gate(35, INTERRUPT_GATE, isr35); 155 | idt_set_gate(36, INTERRUPT_GATE, isr36); 156 | idt_set_gate(37, INTERRUPT_GATE, isr37); 157 | idt_set_gate(38, INTERRUPT_GATE, isr38); 158 | idt_set_gate(39, INTERRUPT_GATE, isr39); 159 | idt_set_gate(40, INTERRUPT_GATE, isr40); 160 | idt_set_gate(41, INTERRUPT_GATE, isr41); 161 | idt_set_gate(42, INTERRUPT_GATE, isr42); 162 | idt_set_gate(43, INTERRUPT_GATE, isr43); 163 | idt_set_gate(44, INTERRUPT_GATE, isr44); 164 | idt_set_gate(45, INTERRUPT_GATE, isr45); 165 | idt_set_gate(46, INTERRUPT_GATE, isr46); 166 | idt_set_gate(47, INTERRUPT_GATE, isr47); 167 | } 168 | -------------------------------------------------------------------------------- /kernel/include/multiboot.h: -------------------------------------------------------------------------------- 1 | /* multiboot.h - Multiboot header file. */ 2 | /* Copyright (C) 1999,2003,2007,2008,2009 Free Software Foundation, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a copy 5 | * of this software and associated documentation files (the "Software"), to 6 | * deal in the Software without restriction, including without limitation the 7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 | * sell copies of the Software, and to permit persons to whom the Software is 9 | * furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY 17 | * DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 19 | * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | */ 21 | 22 | #ifndef MULTIBOOT_HEADER 23 | #define MULTIBOOT_HEADER 1 24 | 25 | /* How many bytes from the start of the file we search for the header. */ 26 | #define MULTIBOOT_SEARCH 8192 27 | 28 | /* The magic field should contain this. */ 29 | #define MULTIBOOT_HEADER_MAGIC 0x1BADB002 30 | 31 | /* This should be in %eax. */ 32 | #define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002 33 | 34 | /* The bits in the required part of flags field we don't support. */ 35 | #define MULTIBOOT_UNSUPPORTED 0x0000fffc 36 | 37 | /* Alignment of multiboot modules. */ 38 | #define MULTIBOOT_MOD_ALIGN 0x00001000 39 | 40 | /* Alignment of the multiboot info structure. */ 41 | #define MULTIBOOT_INFO_ALIGN 0x00000004 42 | 43 | /* Flags set in the 'flags' member of the multiboot header. */ 44 | 45 | /* Align all boot modules on i386 page (4KB) boundaries. */ 46 | #define MULTIBOOT_PAGE_ALIGN 0x00000001 47 | 48 | /* Must pass memory information to OS. */ 49 | #define MULTIBOOT_MEMORY_INFO 0x00000002 50 | 51 | /* Must pass video information to OS. */ 52 | #define MULTIBOOT_VIDEO_MODE 0x00000004 53 | 54 | /* This flag indicates the use of the address fields in the header. */ 55 | #define MULTIBOOT_AOUT_KLUDGE 0x00010000 56 | 57 | /* Flags to be set in the 'flags' member of the multiboot info structure. */ 58 | 59 | /* is there basic lower/upper memory information? */ 60 | #define MULTIBOOT_INFO_MEMORY 0x00000001 61 | /* is there a boot device set? */ 62 | #define MULTIBOOT_INFO_BOOTDEV 0x00000002 63 | /* is the command-line defined? */ 64 | #define MULTIBOOT_INFO_CMDLINE 0x00000004 65 | /* are there modules to do something with? */ 66 | #define MULTIBOOT_INFO_MODS 0x00000008 67 | 68 | /* These next two are mutually exclusive */ 69 | 70 | /* is there a symbol table loaded? */ 71 | #define MULTIBOOT_INFO_AOUT_SYMS 0x00000010 72 | /* is there an ELF section header table? */ 73 | #define MULTIBOOT_INFO_ELF_SHDR 0X00000020 74 | 75 | /* is there a full memory map? */ 76 | #define MULTIBOOT_INFO_MEM_MAP 0x00000040 77 | 78 | /* Is there drive info? */ 79 | #define MULTIBOOT_INFO_DRIVE_INFO 0x00000080 80 | 81 | /* Is there a config table? */ 82 | #define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100 83 | 84 | /* Is there a boot loader name? */ 85 | #define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200 86 | 87 | /* Is there a APM table? */ 88 | #define MULTIBOOT_INFO_APM_TABLE 0x00000400 89 | 90 | /* Is there video information? */ 91 | #define MULTIBOOT_INFO_VIDEO_INFO 0x00000800 92 | 93 | #ifndef ASM_FILE 94 | 95 | typedef unsigned short multiboot_uint16_t; 96 | typedef unsigned int multiboot_uint32_t; 97 | typedef unsigned long long multiboot_uint64_t; 98 | 99 | struct multiboot_header 100 | { 101 | /* Must be MULTIBOOT_MAGIC - see above. */ 102 | multiboot_uint32_t magic; 103 | 104 | /* Feature flags. */ 105 | multiboot_uint32_t flags; 106 | 107 | /* The above fields plus this one must equal 0 mod 2^32. */ 108 | multiboot_uint32_t checksum; 109 | 110 | /* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */ 111 | multiboot_uint32_t header_addr; 112 | multiboot_uint32_t load_addr; 113 | multiboot_uint32_t load_end_addr; 114 | multiboot_uint32_t bss_end_addr; 115 | multiboot_uint32_t entry_addr; 116 | 117 | /* These are only valid if MULTIBOOT_VIDEO_MODE is set. */ 118 | multiboot_uint32_t mode_type; 119 | multiboot_uint32_t width; 120 | multiboot_uint32_t height; 121 | multiboot_uint32_t depth; 122 | }; 123 | 124 | /* The symbol table for a.out. */ 125 | struct multiboot_aout_symbol_table 126 | { 127 | multiboot_uint32_t tabsize; 128 | multiboot_uint32_t strsize; 129 | multiboot_uint32_t addr; 130 | multiboot_uint32_t reserved; 131 | }; 132 | typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t; 133 | 134 | /* The section header table for ELF. */ 135 | struct multiboot_elf_section_header_table 136 | { 137 | multiboot_uint32_t num; 138 | multiboot_uint32_t size; 139 | multiboot_uint32_t addr; 140 | multiboot_uint32_t shndx; 141 | }; 142 | typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t; 143 | 144 | struct multiboot_info 145 | { 146 | /* Multiboot info version number */ 147 | multiboot_uint32_t flags; 148 | 149 | /* Available memory from BIOS */ 150 | multiboot_uint32_t mem_lower; 151 | multiboot_uint32_t mem_upper; 152 | 153 | /* "root" partition */ 154 | multiboot_uint32_t boot_device; 155 | 156 | /* Kernel command line */ 157 | multiboot_uint32_t cmdline; 158 | 159 | /* Boot-Module list */ 160 | multiboot_uint32_t mods_count; 161 | multiboot_uint32_t mods_addr; 162 | 163 | union 164 | { 165 | multiboot_aout_symbol_table_t aout_sym; 166 | multiboot_elf_section_header_table_t elf_sec; 167 | } u; 168 | 169 | /* Memory Mapping buffer */ 170 | multiboot_uint32_t mmap_length; 171 | multiboot_uint32_t mmap_addr; 172 | 173 | /* Drive Info buffer */ 174 | multiboot_uint32_t drives_length; 175 | multiboot_uint32_t drives_addr; 176 | 177 | /* ROM configuration table */ 178 | multiboot_uint32_t config_table; 179 | 180 | /* Boot Loader Name */ 181 | multiboot_uint32_t boot_loader_name; 182 | 183 | /* APM table */ 184 | multiboot_uint32_t apm_table; 185 | 186 | /* Video */ 187 | multiboot_uint32_t vbe_control_info; 188 | multiboot_uint32_t vbe_mode_info; 189 | multiboot_uint16_t vbe_mode; 190 | multiboot_uint16_t vbe_interface_seg; 191 | multiboot_uint16_t vbe_interface_off; 192 | multiboot_uint16_t vbe_interface_len; 193 | }; 194 | typedef struct multiboot_info multiboot_info_t; 195 | 196 | struct multiboot_mmap_entry 197 | { 198 | multiboot_uint32_t size; 199 | multiboot_uint64_t addr; 200 | multiboot_uint64_t len; 201 | #define MULTIBOOT_MEMORY_AVAILABLE 1 202 | #define MULTIBOOT_MEMORY_RESERVED 2 203 | multiboot_uint32_t type; 204 | } __attribute__((packed)); 205 | typedef struct multiboot_mmap_entry multiboot_memory_map_t; 206 | 207 | struct multiboot_mod_list 208 | { 209 | /* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */ 210 | multiboot_uint32_t mod_start; 211 | multiboot_uint32_t mod_end; 212 | 213 | /* Module command line */ 214 | multiboot_uint32_t cmdline; 215 | 216 | /* padding to take it to 16 bytes (must be zero) */ 217 | multiboot_uint32_t pad; 218 | }; 219 | typedef struct multiboot_mod_list multiboot_module_t; 220 | 221 | #endif /* ! ASM_FILE */ 222 | 223 | #endif /* ! MULTIBOOT_HEADER */ 224 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------