diff options
-rw-r--r-- | SConstruct | 15 | ||||
-rw-r--r-- | floppy/SConscript | 24 | ||||
-rw-r--r-- | floppy/empty.img | bin | 0 -> 1474560 bytes | |||
-rw-r--r-- | floppy/grub.conf | 9 | ||||
-rw-r--r-- | kernel/SConscript | 30 | ||||
-rw-r--r-- | kernel/entry.c | 92 | ||||
-rw-r--r-- | kernel/kernel.ld | 57 | ||||
-rw-r--r-- | kernel/main.c | 26 | ||||
-rw-r--r-- | kernel/types.h | 11 |
9 files changed, 264 insertions, 0 deletions
diff --git a/SConstruct b/SConstruct new file mode 100644 index 0000000..ce87bb9 --- /dev/null +++ b/SConstruct @@ -0,0 +1,15 @@ +import os + +env = Environment( + ENV = os.environ, +) + +Export('env') + +env.SConscript('kernel/SConscript') + +env.SConscript('floppy/SConscript') + +env.Command('qemu', 'floppy/floppy.img', 'qemu -s -m 32 -fda $SOURCE') + +Default('kernel') diff --git a/floppy/SConscript b/floppy/SConscript new file mode 100644 index 0000000..2021b18 --- /dev/null +++ b/floppy/SConscript @@ -0,0 +1,24 @@ +Import('env') + +env = env.Clone( + BASE_IMAGE = File('empty.img').path, + MOUNTPOINT = Dir('mountpoint').path, + GRUB_CONF = File('grub.conf').path, +) + +floppy = env.Command( + 'floppy.img', + ['#kernel/kernel'], + [ + 'cp $BASE_IMAGE $TARGET', + 'mkdir $MOUNTPOINT', + 'hdiutil attach -quiet -mountpoint $MOUNTPOINT $TARGET', + 'cp $SOURCE $MOUNTPOINT/', + 'cp $GRUB_CONF $MOUNTPOINT/boot/grub/', + 'hdiutil detach -quiet $MOUNTPOINT', + 'rmdir $MOUNTPOINT', + ] +) + +Depends(floppy, 'empty.img') +Depends(floppy, 'grub.conf') diff --git a/floppy/empty.img b/floppy/empty.img Binary files differnew file mode 100644 index 0000000..d7156a1 --- /dev/null +++ b/floppy/empty.img diff --git a/floppy/grub.conf b/floppy/grub.conf new file mode 100644 index 0000000..476404b --- /dev/null +++ b/floppy/grub.conf @@ -0,0 +1,9 @@ +default 0 +timeout 1 +serial +terminal --dumb serial +hiddenmenu + +title=Potetmos + root (fd0) + kernel /kernel diff --git a/kernel/SConscript b/kernel/SConscript new file mode 100644 index 0000000..87fcb1f --- /dev/null +++ b/kernel/SConscript @@ -0,0 +1,30 @@ +Import('env') + +env = env.Clone( + CC = 'i386-elf-gcc', + CCFLAGS = '-Wall -W -nostdinc -fno-builtin -fno-hosted -ggdb -std=gnu99', + LINK = 'i386-elf-ld', + LINKFLAGS = '-nostdinc -nostdlib', +) + +def kernel_bld_generator(source, target, env, for_signature): + link_script = None + for s in source: + if s.suffix == '.ld': + link_script = s + break + if not link_script: + Exit(1) + return '$LINK $LINKFLAGS -o %s -T %s %s ' % (target[0], link_script, ' '.join(str(s) for s in source if s != link_script)) + +kernel_bld = Builder( + generator = kernel_bld_generator, + suffix = '', + src_suffix = '.o', + src_builder = 'Object', + target_scanner = ProgramScanner +) + +env.Append(BUILDERS = {'Kernel' : kernel_bld}) + +kernel = env.Kernel('kernel', ['kernel.ld', 'entry.c', 'main.c']) diff --git a/kernel/entry.c b/kernel/entry.c new file mode 100644 index 0000000..d040cfb --- /dev/null +++ b/kernel/entry.c @@ -0,0 +1,92 @@ +#include "types.h" + +extern void addr_phys; +extern void addr_virt; +extern void addr_virt_end; +extern void addr_load_virt; +extern void addr_load_virt_end; + +extern void entry_stack; + +extern uint32_t entry_pagedir[]; +extern uint32_t entry_pagetable_low[]; +extern uint32_t entry_pagetable_high[]; + +extern void main(); + +asm( + ".globl entry\n" + "entry:\n" + "mov $entry_stack_top,%esp\n" + "push %eax\n" + "call entry_main\n" +); + +void entry_serial_out(char* str); + +void entry_main(uint32_t mb_magic, void* mb_info) { + entry_serial_out("entry_main()\n"); + if(mb_magic != 0x2badb002) { + entry_serial_out("Multiboot magic word is wrong!\n"); + goto stop; + } + entry_serial_out("Multiboot ok\n"); + + // TODO: Copy multiboot information. + + // Create initial page tables. + for(unsigned int i = 0; i < 1024; i++) { + // Clear page directory. + entry_pagedir[i] = 0; + + // Identity mapping of the current code. + entry_pagetable_low[i] = ((uint32_t)&addr_phys & 0xffc00000) | (i << 12) | 0x003; + + // Map kernelspace. + if((i << 12) < ((uint32_t)&addr_virt_end & 0x003ff000 )) { + entry_pagetable_high[i] = ((uint32_t)&addr_load_virt + (i << 12)) | 0x003; + } else { + entry_pagetable_high[i] = 0; + } + } + + entry_pagedir[(uint32_t)&addr_phys >> 22] = (uint32_t)&entry_pagetable_low | 0x003; + entry_pagedir[(uint32_t)&addr_virt >> 22] = (uint32_t)&entry_pagetable_high | 0x003; + + // Mapping stack to top without creating another page directory. + entry_pagetable_high[1023] = (uint32_t)&entry_stack | 0x003; + entry_pagedir[1023] = (uint32_t)&entry_pagetable_high | 0x003; + + // Enable paging. + asm volatile( + "mov %0, %%cr3\n" + "mov %%cr0, %0\n" + "or $0x80000000, %0\n" + "mov %0, %%cr0\n" + : : "r" (&entry_pagedir) : "%0" + ); + + // TODO: Check that segments are loaded and mapped right. + + // Call main() in virtual memory. + main(); + + stop: + entry_serial_out("Halting.\n"); + asm volatile( + "cli\n" + "hlt\n" + ); + while(1); +} + +#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port)); + +void entry_serial_out(char* str) { + while(*str) { + if(*str == '\n') { + outb(0x3f8, '\r'); + } + outb(0x3f8, *str++); + } +} diff --git a/kernel/kernel.ld b/kernel/kernel.ld new file mode 100644 index 0000000..2bcbcbc --- /dev/null +++ b/kernel/kernel.ld @@ -0,0 +1,57 @@ +OUTPUT_FORMAT("elf32-i386") +ENTRY(entry) + +addr_phys = 0x00100000; +addr_virt = 0xc0000000; + +addr_virt_end = ADDR(.bss) + SIZEOF(.bss); + +addr_load_virt = LOADADDR(.text); +addr_load_virt_end = LOADADDR(.bss) + SIZEOF(.bss); + +SECTIONS { + + .text_low addr_phys : { + LONG(0x1badb002); + LONG(0x00000003); + LONG(-0x1badb002 -0x00000003); + + kernel/entry.o(.text) + kernel/entry.o(.rodata*) + . = ALIGN(0x1000); + } + + .data_low : { + kernel/entry.o(.data) + . = ALIGN(0x1000); + } + + .bss_low : { + kernel/entry.o(.bss) + . = ALIGN(0x1000); + entry_pagedir = .; . += 0x1000; + entry_pagetable_low = .; . += 0x1000; + entry_pagetable_high = .; . += 0x1000; + entry_stack = .; . += 0x1000; entry_stack_top = .; + } + + .text addr_virt : AT(LOADADDR(.bss_low) + SIZEOF(.bss_low)) { + magic_text = .; LONG(0x0f00ba02); + *(.text) + *(.rodata*) + . = ALIGN(0x1000); + } + + .data : AT(LOADADDR(.text) + SIZEOF(.text)) { + magic_data = .; LONG(0x0f00ba03); + *(.data) + *(.ctors) + . = ALIGN(0x1000); + } + + .bss : AT(LOADADDR(.data) + SIZEOF(.data)) { + *(.bss) + *(COMMON) + . = ALIGN(0x1000); + } +} diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000..513894b --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,26 @@ + +void kernel_serial_out(char* str); + +void main() { + + kernel_serial_out("main()\n"); + + // TODO: GDT. + + asm volatile( + "cli\n" + "hlt\n" + ); + while(1); +} + +#define outb(port, value) asm volatile("out %b0,%w1" : : "a" (value), "d" (port)); + +void kernel_serial_out(char* str) { + while(*str) { + if(*str == '\n') { + outb(0x3f8, '\r'); + } + outb(0x3f8, *str++); + } +} diff --git a/kernel/types.h b/kernel/types.h new file mode 100644 index 0000000..4fdca6b --- /dev/null +++ b/kernel/types.h @@ -0,0 +1,11 @@ +#ifndef TYPES_H +#define TYPES_H + +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; + +#endif |