summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct15
-rw-r--r--floppy/SConscript24
-rw-r--r--floppy/empty.imgbin0 -> 1474560 bytes
-rw-r--r--floppy/grub.conf9
-rw-r--r--kernel/SConscript30
-rw-r--r--kernel/entry.c92
-rw-r--r--kernel/kernel.ld57
-rw-r--r--kernel/main.c26
-rw-r--r--kernel/types.h11
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
new file mode 100644
index 0000000..d7156a1
--- /dev/null
+++ b/floppy/empty.img
Binary files differ
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