diff options
| author | Franklin Wei <frankhwei536@gmail.com> | 2015-02-01 11:33:16 -0500 |
|---|---|---|
| committer | Franklin Wei <frankhwei536@gmail.com> | 2015-02-01 11:33:16 -0500 |
| commit | 439d724ce5939cab7a5c858d1829f212e01e0402 (patch) | |
| tree | 154afa843a96e4cebd4d4f4f480f36415668d620 | |
| parent | 1d7843c2b6d746376f87c2634c92cd93d8cdb728 (diff) | |
| download | kappa-439d724ce5939cab7a5c858d1829f212e01e0402.zip kappa-439d724ce5939cab7a5c858d1829f212e01e0402.tar.gz kappa-439d724ce5939cab7a5c858d1829f212e01e0402.tar.bz2 kappa-439d724ce5939cab7a5c858d1829f212e01e0402.tar.xz | |
first real commit
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | Makefile | 34 | ||||
| -rw-r--r-- | boot/head.S | 30 | ||||
| -rw-r--r-- | drivers/tty.c | 86 | ||||
| -rw-r--r-- | drivers/tty.h | 9 | ||||
| -rw-r--r-- | drivers/vga.h | 26 | ||||
| -rw-r--r-- | kernel/gdt-as.S | 16 | ||||
| -rw-r--r-- | kernel/gdt.c | 33 | ||||
| -rw-r--r-- | kernel/include/gdt.h | 23 | ||||
| -rw-r--r-- | kernel/include/io.h | 4 | ||||
| -rw-r--r-- | kernel/io.c | 19 | ||||
| -rw-r--r-- | kernel/linker.ld | 44 | ||||
| -rw-r--r-- | kernel/main.c | 14 | ||||
| -rw-r--r-- | kernel/panic.c | 2 | ||||
| -rw-r--r-- | kernel/ssp.c | 19 | ||||
| -rw-r--r-- | libc/string.c | 19 | ||||
| -rw-r--r-- | libc/string.h | 3 |
17 files changed, 385 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2cc6980 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*~ +*.o +kappa.iso +kappa.bin diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2776f75 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ +OBJ = drivers/tty.o kernel/main.o boot/head.o kernel/io.o kernel/gdt-as.o kernel/gdt.o +CC = gcc +LD = ld +INCLUDES = -Idrivers -Ikernel/include +CFLAGS = -std=gnu99 -ffreestanding -fno-stack-protector -nostdlib -Wall -Wextra -m32 $(INCLUDES) + +AS = as +ASFLAGS=-march=i686 --32 + +all: kappa.bin + +test: iso + qemu-system-i386 kappa.iso + +iso: kappa.bin + mkdir -p isodir + mkdir -p isodir/boot + cp kappa.bin isodir/efi.img + cp kappa.bin isodir/boot/kappa.bin + mkdir -p isodir/boot/grub + cp cdrom/grub.cfg isodir/boot/grub + grub-mkrescue -o kappa.iso isodir + +kappa.bin: $(OBJ) $(SOURCES) Makefile + $(LD) -T kernel/linker.ld -o kappa.bin -melf_i386 $(OBJ) + +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +%.o: %.S + $(AS) $(ASFLAGS) -c $< -o $@ + +clean: + rm -f $(OBJ) kappa.iso kappa.bin diff --git a/boot/head.S b/boot/head.S new file mode 100644 index 0000000..864ebeb --- /dev/null +++ b/boot/head.S @@ -0,0 +1,30 @@ + .set ALIGN, 1<<0 + .set MEMINFO, 1<<1 + .set FLAGS, ALIGN | MEMINFO + .set MAGIC, 0x1BADB002 # multiboot magic + .set CHECKSUM, -(MAGIC + FLAGS) + +.section .multiboot + .align 4 +multiboot_header: + .long MAGIC + .long FLAGS + .long CHECKSUM + +.section .stack +stack_bottom: # Stack grows up in addresses, so bottom is + # lower than the top + .skip 16384 # 32KB stack +stack_top: + +.section .text + .global _start + .type _start, @function +_start: + movl $stack_top, %esp + call main + cli + hlt +.Lhang: # Idle + jmp .Lhang + .size _start, . - _start diff --git a/drivers/tty.c b/drivers/tty.c new file mode 100644 index 0000000..e938abd --- /dev/null +++ b/drivers/tty.c @@ -0,0 +1,86 @@ +#include <stdint.h> +#include "io.h" +#include "tty.h" +#include "vga.h" + +static int term_x, term_y; +static uint8_t term_col; +/* VGA buffer starts at 0xB8000 */ +static uint16_t *term_buf; + +void tty_init(void) +{ + term_buf = (uint16_t*)0xB8000; + term_col = VGA_MAKE_COLOR(VGA_WHITE, VGA_BLACK); + tty_clear(); +} + +static void move_cursor(uint16_t cursor_idx) +{ + outb(0x3D4, 14); + outb(0x3D5, cursor_idx >> 8); // high byte + outb(0x3D4, 15); + outb(0x3D5, cursor_idx); // low byte +} + +static void update_cursor(void) +{ + move_cursor(term_y * VGA_WIDTH + term_x); +} + +void tty_clear(void) +{ + term_x = 0; + term_y = 0; + for(int y = 0; y < VGA_HEIGHT; ++y) + { + for(int x = 0; x < VGA_WIDTH; ++x) + { + term_buf[y * VGA_WIDTH + x] = VGA_MAKE_ENTRY(' ', term_col); + } + } +} + +void tty_set_color(uint8_t color) +{ + term_col = color; +} + +uint8_t tty_get_color(void) +{ + return term_col; +} + +void tty_putchar_at(char ch, uint8_t col, int x, int y) +{ + term_buf[y * VGA_WIDTH + x] = VGA_MAKE_ENTRY(ch, col); +} + +void tty_putchar(char ch) +{ + if(ch != '\n') + { + tty_putchar_at(ch, term_col, term_x, term_y); + if(++term_x == VGA_WIDTH) + { + term_x = 0; + if(++term_y == VGA_HEIGHT) + term_y = 0; + } + } + else + { + term_x = 0; + if(++term_y == VGA_HEIGHT) + term_y = 0; + } + update_cursor(); +} + +void tty_puts(const char *str) +{ + while(*str) + { + tty_putchar(*str++); + } +} diff --git a/drivers/tty.h b/drivers/tty.h new file mode 100644 index 0000000..0e142c6 --- /dev/null +++ b/drivers/tty.h @@ -0,0 +1,9 @@ +#include <stdint.h> + +void tty_init(void); +void tty_clear(void); +void tty_set_color(uint8_t); +uint8_t tty_get_color(void); +void tty_putchar_at(char ch, uint8_t color, int x, int y); +void tty_putchar(char ch); +void tty_puts(const char*); diff --git a/drivers/vga.h b/drivers/vga.h new file mode 100644 index 0000000..bf13cba --- /dev/null +++ b/drivers/vga.h @@ -0,0 +1,26 @@ +#include <stdint.h> + +enum vga_color_t { + VGA_BLACK = 0, + VGA_BLUE = 1, + VGA_GREEN = 2, + VGA_CYAN = 3, + VGA_RED = 4, + VGA_MAGENTA = 5, + VGA_BROWN = 6, + VGA_LIGHT_GRAY = 7, + VGA_DARK_GRAY = 8, + VGA_LIGHT_BLUE = 9, + VGA_LIGHT_GREEN = 10, + VGA_LIGHT_CYAN = 11, + VGA_LIGHT_RED = 12, + VGA_LIGHT_MAGENTA = 13, + VGA_LIGHT_BROWN = 14, + VGA_WHITE = 15 +}; + +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 + +#define VGA_MAKE_COLOR(fg, bg) (fg | bg << 4) +#define VGA_MAKE_ENTRY(ch, col) (((uint16_t)ch)|((uint16_t)col<<8)) diff --git a/kernel/gdt-as.S b/kernel/gdt-as.S new file mode 100644 index 0000000..7283dc8 --- /dev/null +++ b/kernel/gdt-as.S @@ -0,0 +1,16 @@ + .global gdt_flush + .type gdt_flush, @function +gdt_flush: # prototype: void gdt_flush(uint32_t addr) + cli + movl 4(%esp), %eax # load the address off the stack (first param) + lgdt (%eax) + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + mov %ax, %ss + sti + jmp .flush +.flush: + ret diff --git a/kernel/gdt.c b/kernel/gdt.c new file mode 100644 index 0000000..f9b2d86 --- /dev/null +++ b/kernel/gdt.c @@ -0,0 +1,33 @@ +#include "gdt.h" + +static void gdt_set_gate(int idx, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) +{ + /* Setup the descriptor base address */ + gdt[idx].base_low = (base & 0xFFFF); + gdt[idx].base_middle = (base >> 16) & 0xFF; + gdt[idx].base_high = (base >> 24) & 0xFF; + + /* Setup the descriptor limits */ + gdt[idx].limit_low = (limit & 0xFFFF); + gdt[idx].granularity = ((limit >> 16) & 0x0F); + + /* Finally, set up the granularity and access flags */ + gdt[idx].granularity |= (gran & 0xF0); + gdt[idx].access = access; +} + +void gdt_init(void) +{ + gp.limit = (sizeof(struct gdt_entry) * sizeof(gdt)/sizeof(gdt[0])) - 1; + gp.base = (uint32_t)&gdt; + + gdt_set_gate(0, 0, 0, 0, 0); + + /* code segment */ + gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xCF); + + /* data segment */ + gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); + + gdt_flush((uint32_t)&gp); +} diff --git a/kernel/include/gdt.h b/kernel/include/gdt.h new file mode 100644 index 0000000..e93c92a --- /dev/null +++ b/kernel/include/gdt.h @@ -0,0 +1,23 @@ +#include <stdint.h> + +struct gdt_entry { + uint16_t limit_low; + uint16_t base_low; + uint8_t base_middle; + uint8_t access; + uint8_t granularity; + uint8_t base_high; +} __attribute__((packed)); + +struct gdt_ptr { + uint8_t limit; + uint32_t base; +} __attribute__((packed)); + +struct gdt_entry gdt[3]; +struct gdt_ptr gp; + +/* assembly */ +extern void gdt_flush(struct gdt_ptr*); + +void gdt_init(void); diff --git a/kernel/include/io.h b/kernel/include/io.h new file mode 100644 index 0000000..c3c735b --- /dev/null +++ b/kernel/include/io.h @@ -0,0 +1,4 @@ +#include <stdint.h> +void outb(uint16_t port, uint8_t val); +uint8_t inb(uint16_t port); +uint16_t inw(uint16_t port); diff --git a/kernel/io.c b/kernel/io.c new file mode 100644 index 0000000..9b56b5d --- /dev/null +++ b/kernel/io.c @@ -0,0 +1,19 @@ +#include <stdint.h> +#include "io.h" + +void outb(uint16_t port, uint8_t val) +{ + asm volatile ("outb %1, %0": :"dN" (port), "a" (val)); +} +uint8_t inb(uint16_t port) +{ + uint8_t ret; + asm volatile ("inb %1, %0" : "=a" (ret) : "dN" (port)); + return ret; +} +uint16_t inw(uint16_t port) +{ + uint16_t ret; + asm volatile ("inw %1, %0" : "=a" (ret) : "dN" (port)); + return ret; +} diff --git a/kernel/linker.ld b/kernel/linker.ld new file mode 100644 index 0000000..9b47325 --- /dev/null +++ b/kernel/linker.ld @@ -0,0 +1,44 @@ +/* The bootloader will look at this image and start execution at the symbol + designated as the entry point. */ +ENTRY(_start) + +/* Tell where the various sections of the object files will be put in the final + kernel image. */ +SECTIONS +{ + /* Begin putting sections at 1 MiB, a conventional place for kernels to be + loaded at by the bootloader. */ + . = 1M; + + /* First put the multiboot header, as it is required to be put very early + early in the image or the bootloader won't recognize the file format. + Next we'll put the .text section. */ + .text BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.text) + } + + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + /* Read-write data (uninitialized) and stack */ + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + *(.bootstrap_stack) + } + + /* The compiler may produce other sections, by default it will put them in + a segment with the same name. Simply add stuff here as needed. */ +} diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000..219e3ee --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,14 @@ +#include "string.h" +#include "tty.h" +#include "vga.h" + +void main(void) +{ + tty_init(); + gdt_init(); + tty_puts("GDT initialized\n"); + tty_set_color(VGA_MAKE_COLOR(VGA_LIGHT_GRAY, VGA_BLACK)); + tty_puts("Hello, world!\n"); + while(1) + ; +} diff --git a/kernel/panic.c b/kernel/panic.c new file mode 100644 index 0000000..106141b --- /dev/null +++ b/kernel/panic.c @@ -0,0 +1,2 @@ +#include "panic.h" +#include " diff --git a/kernel/ssp.c b/kernel/ssp.c new file mode 100644 index 0000000..ad47bb4 --- /dev/null +++ b/kernel/ssp.c @@ -0,0 +1,19 @@ +#include <stdint.h> +#include "panic.h" + +#if UINT32_MAX == UINTPTR_MAX +#define STACK_CHK_GUARD 0xdeadbeef +#else +#define STACK_CHK_GUARD 0x0ddc0ffeebadf00d +#endif + +uintptr_t __stack_chk_guard = STACK_CHK_GUARD; + +__attribute__((noreturn)) void __stack_chk_fail(void) +{ +#if __STDC_HOSTED__ + abort(); +#else + panic("Stack smashing detected"); +#endif +} diff --git a/libc/string.c b/libc/string.c new file mode 100644 index 0000000..33ccad9 --- /dev/null +++ b/libc/string.c @@ -0,0 +1,19 @@ +#include <stdint.h> +#include "string.h" + +int strlen(const char *str) +{ + int len = 0; + while(s++) + len++; + return len; +} + +void* memset(void *buf, int val, size_t sz) +{ + for(size_t i = 0; i < sz; ++i) + { + buf[i] = (uint8_t) val; + } + return buf; +} diff --git a/libc/string.h b/libc/string.h new file mode 100644 index 0000000..8606fab --- /dev/null +++ b/libc/string.h @@ -0,0 +1,3 @@ +#include <stdint.h> +int strlen(const char*); +void* memset(void*, int, size_t); |