From 2f3ab42667d0feb446725f1fc7ab610f1d7a1471 Mon Sep 17 00:00:00 2001 From: Sergiusz Bazanski Date: Sun, 20 Feb 2011 23:38:15 +0100 Subject: [PATCH] Yay first commit. --- Makefile | 70 ++++++++++++++ README | 7 ++ dst/syslinux.cfg | 4 + src/Tier0/.gdt.h.swp | Bin 0 -> 12288 bytes src/Tier0/Types.h | 14 +++ src/Tier0/_start.asm | 52 +++++++++++ src/Tier0/kmain.c | 17 ++++ src/Tier0/kstdio.c | 218 +++++++++++++++++++++++++++++++++++++++++++ src/Tier0/kstdio.h | 18 ++++ src/Tier0/kstdlib.c | 30 ++++++ src/Tier0/kstdlib.h | 10 ++ src/kernel.ld | 24 +++++ 12 files changed, 464 insertions(+) create mode 100644 Makefile create mode 100644 README create mode 100644 dst/syslinux.cfg create mode 100644 src/Tier0/.gdt.h.swp create mode 100644 src/Tier0/Types.h create mode 100644 src/Tier0/_start.asm create mode 100644 src/Tier0/kmain.c create mode 100644 src/Tier0/kstdio.c create mode 100644 src/Tier0/kstdio.h create mode 100644 src/Tier0/kstdlib.c create mode 100644 src/Tier0/kstdlib.h create mode 100644 src/kernel.ld diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6fbfb42 --- /dev/null +++ b/Makefile @@ -0,0 +1,70 @@ +# I hate GNU Make +# +# Seriously. +# +# Fuck M4. I do this because it's probably the most portable way, and I don't +# wan't to write Yet Another Compile System because fuck that shit. I could +# use cmake but I don't know whether it is flexible enough. It probably is +# but whatever. I wrote this piece of shit below, let's just keep it that +# way. There are better way to do the hthings I do below, but who gives a +# shit. + +default: emulate + +SHELL:=/bin/bash +ENV:=/usr/xdev/bin +TARGET:=i586-elf +CC:=$(ENV)/$(TARGET)-gcc +CX:=$(ENV)/$(TARGET)-g++ +AS:=nasm +LD:=$(ENV)/$(TARGET)-ld + +CFLAGS:=-Wall -Wextra -Werror -nostdlib -nostartfiles -nodefaultlibs -std=c99 +LFLAGS:=-nostdlib -nostartfiles -nodefaultlibs + +.PHONY: all clean kernel.bin emulate hdd.img + +obj/src/%.nao : src/%.asm + @echo "[i] Assembling $*.asm..." + @$(AS) -f elf -o obj/src/$*.nao src/$*.asm + +obj/src/%.o : src/%.c + @echo "[i] Compining $*.c ..." + @mkdir -p obj/src/$*.o + @rmdir obj/src/$*.o + @$(CC) $(CFLAGS) -c src/$*.c -o obj/src/$*.o + +TIER0SRC := $(shell find src/Tier0 -mindepth 1 -maxdepth 3 -name "*.c") +TIER0SRC += $(shell find src/Tier0 -mindepth 1 -maxdepth 3 -name "*.asm") + +TIER0OBJ := $(patsubst %.c,%.o,$(TIER0SRC)) +TIER0OBJ := $(patsubst %.asm,%.nao,$(TIER0OBJ)) + +TIER0 := $(foreach i, $(TIER0OBJ), obj/$(i)) + +Tier0: $(TIER0) + +kernel.bin: Tier0 + @echo "[i] Linking kernel.bin..." + @$(LD) -T src/kernel.ld -o kernel.bin $(TIER0) + +hdd.img: kernel.bin + @echo "[i] Creating HDD image..." + @if [ -e hdd_temp.img ] ; then rm hdd_temp.img ; fi + @dd if=/dev/zero of=hdd_temp.img bs=4k count=4096 2> /dev/null + @mkfs.vfat hdd_temp.img > /dev/null + @syslinux hdd_temp.img + @mcopy -i hdd_temp.img /usr/lib/syslinux/mboot.c32 ::mboot.c32 + @mcopy -i hdd_temp.img kernel.bin ::kernel.bin + @mcopy -i hdd_temp.img dst/syslinux.cfg ::syslinux.cfg + @mv hdd_temp.img hdd.img + +emulate: hdd.img + @echo "[i] Starting QEmu..." + @qemu -hda hdd.img + +clean: + @rm -Rf obj + @if [ -e kernel.bin ] ; then rm kernel.bin ; fi + @if [ -e hdd_temp.img ] ; then rm hdd_temp.img ; fi + @if [ -e hdd.img ] ; then rm hdd.img; fi diff --git a/README b/README new file mode 100644 index 0000000..2c77bfb --- /dev/null +++ b/README @@ -0,0 +1,7 @@ +This is Cucumber. + +It doesn't do much yet. If you're browsing this right now, you should +probably leave as there is nothing remotely interesting here to be seen - I +just needed a repo to protect against data loss. + +But yeah. x86. Microkernel. Paged. 32-bit (for now). Pre-emptive multitasking. POSIX-compliant. diff --git a/dst/syslinux.cfg b/dst/syslinux.cfg new file mode 100644 index 0000000..e884477 --- /dev/null +++ b/dst/syslinux.cfg @@ -0,0 +1,4 @@ + +TIMEOUT 4 +default mboot.c32 kernel.bin + diff --git a/src/Tier0/.gdt.h.swp b/src/Tier0/.gdt.h.swp new file mode 100644 index 0000000000000000000000000000000000000000..7b79204886987ff0de79196c351c83e0c469b806 GIT binary patch literal 12288 zcmeI%%}T>S5Ww-N2XCV23q<$cjrQOR2r43YXuZkOB$FDbTiLcA^-X*zZ+<+3&)~+U zAVNL#7WpqshMnvVyT4mVmR_G=}F(6IVYwneJuW{d;!>rGJ*gA literal 0 HcmV?d00001 diff --git a/src/Tier0/Types.h b/src/Tier0/Types.h new file mode 100644 index 0000000..16ffb34 --- /dev/null +++ b/src/Tier0/Types.h @@ -0,0 +1,14 @@ +// Basic data types (because typing unsigned int is annoying) + +#ifndef __TYPES_H__ +#define __TYPES_H__ + +typedef unsigned int u32; +typedef unsigned short u16; +typedef unsigned char u8; + +typedef int s32; +typedef short s16; +typedef char s8; + +#endif diff --git a/src/Tier0/_start.asm b/src/Tier0/_start.asm new file mode 100644 index 0000000..feee3c5 --- /dev/null +++ b/src/Tier0/_start.asm @@ -0,0 +1,52 @@ +global _start +extern kmain + +; Multiboot-related constants +MODULEALIGN equ 1 << 0 +MEMINFO equ 1 << 1 +FLAGS equ MODULEALIGN | MEMINFO +MAGIC equ 0x1BADB002 +CHECKSUM equ -(MAGIC + FLAGS) + +; Other constants +STACKSIZE equ 0x4000 + +; ############################################################################## +; ############################# text segment ################################### +; ############################################################################## + +section .text +align 4 + +; Multiboot header +MultiBootHeader: + dd MAGIC + dd FLAGS + dd CHECKSUM + +; Actual entry point +_start: + mov esp, kstack + STACKSIZE + push eax + push ebx + + call kmain + + cli + +; If we are here, just loop - we're dead anyway +ohshit: + hlt + jmp ohshit + + +; ############################################################################## +; ################################ bss segment ################################# +; ############################################################################## + +section .bss +align 4 + +; here be 16k stack +kstack: + resb STACKSIZE diff --git a/src/Tier0/kmain.c b/src/Tier0/kmain.c new file mode 100644 index 0000000..4514707 --- /dev/null +++ b/src/Tier0/kmain.c @@ -0,0 +1,17 @@ +#include "Types.h" +#include "kstdio.h" + +// Real kernel entry point, called from _start.asm +void kmain(void *mbd, u32 magic) +{ + if (magic != 0x2BADB002) + { + kprintf("[e] Fatal! Boot via incompatible bootloader.\n"); + return; + } + + char *szBootLoaderName = (char *)((u32 *)mbd)[16]; + + kclear(); + kprintf("[i] Booting via %s.\n", szBootLoaderName); +} diff --git a/src/Tier0/kstdio.c b/src/Tier0/kstdio.c new file mode 100644 index 0000000..5c065fe --- /dev/null +++ b/src/Tier0/kstdio.c @@ -0,0 +1,218 @@ +#include "Types.h" +#include "kstdio.h" +#include "kstdlib.h" +#include + +#define va_start(v,l) __builtin_va_start(v,l) +#define va_arg(v,l) __builtin_va_arg(v,l) +#define va_end(v) __builtin_va_end(v) +#define va_copy(d,s) __builtin_va_copy(d,s) +typedef __builtin_va_list va_list; + +u8 g_kstdio_current_line = 0; +u8 g_kstdio_cur_x = 0, g_kstdio_cur_y = 0; + +void koutb(u16 Port, u8 Data) +{ + __asm__ __volatile__ ("outb %1, %0" : : "dN" (Port), "a" (Data)); +} + +void kputi(s32 Number) +{ + s32 Sign, i; + + if ((Sign = Number) < 0) + Number = -Number; + + u8 szString[11]; + + i = 0; + do { + szString[i++] = Number % 10 + '0'; + } while (( Number /= 10) > 0); + + if (Sign < 0) + szString[i] = '-'; + else + i--; + + for (s32 j = i; j >= 0; j--) + { + kputch(szString[j]); + } +} + +void kprintf(s8 *szFormat, ...) +{ + va_list ap; + va_start(ap, szFormat); + + u32 Offset = 0; + while (Offset < kstrlen(szFormat)) + { + if (szFormat[Offset] == '%') + { + switch (szFormat[Offset + 1]) + { + case '%': + kputch('%'); + break; + case 'c': + kputch(va_arg(ap, u32)); + break; + case 's': + kputs(va_arg(ap, s8*)); + break; + case 'i': + kputi(va_arg(ap, s32)); + break; + case 'u': + kputi(va_arg(ap, u32)); + break; + case 'm': //dump + ; u8 *szString = va_arg(ap, u8*); //stupid gcc bug + kdump(szString, kstrlen((s8 *)szString)); + break; + case 'X': + case 'x': + ; u32 bData = va_arg(ap, u32); + kprint_hex(bData); + break; + default: + kprintf("printf: Unknown escape character %c!\n", szFormat[Offset + 1]); + } + Offset += 2; + } + else + { + kputch(szFormat[Offset]); + Offset++; + } + } + + va_end(ap); +} + +void kscroll_up(void) +{ + u16 Blank = 0x20 | (0x0F << 8); + u16 Temp; + + if (g_kstdio_cur_y >= 25) + { + Temp = g_kstdio_cur_y - 25 + 1; + kmemcpy((void*)0xB8000, (void*)(0xB8000 - Temp * 80 * 2), (25 - Temp) * 80 * 2); + + kmemsetw((void*)(0xB8000 + (25 - Temp) * 80), Blank, 80); + g_kstdio_cur_y = 25 - 1; + } +} + +u32 kstrlen(s8 *szString) +{ + const s8 *s; + for (s = szString; *s; ++s) + {} + return s - szString; +} + +void kmove_cursor(u8 X, u8 Y) +{ + g_kstdio_cur_x = X; + g_kstdio_cur_y = Y; + + //wraparound + if (g_kstdio_cur_x >= 80) + { + g_kstdio_cur_y += g_kstdio_cur_y / 80; + g_kstdio_cur_x = 0; + } + + //wrapup + kscroll_up(); + + if (Y > 24) + Y = 24; + + u16 Position = Y * 80 + X; + + koutb(0x3D4, 0x0F); + koutb(0x3D5, (u8)(Position & 0xFF)); + + koutb(0x3D4, 0x0E); + koutb(0x3D5, (u8)(Position >> 8 & 0xFF)); +} + +void kdump_nibble(u8 Nibble) +{ + if (Nibble < 10) + kputch(Nibble + 48); + else + kputch(Nibble + 55); +} + +void kprint_hex(u32 Number) +{ + for (s8 i = 3; i >= 0; i--) + { + u8 Byte = (Number >> (i << 3)) & 0xFF; //switch i bytes to the right and mask as byte + kdump_nibble((Byte >> 4) & 0x0F); //high nibble + kdump_nibble(Byte & 0x0F); //low nibble + } +} + +void kdump(u8 *bData, u32 Length) +{ + for (u32 i = 0; i < Length; i++) + { + u8 Low = bData[i] & 0x0F; + u8 High = (bData[i] >> 4) & 0x0F; + + kdump_nibble(High); + kdump_nibble(Low); + } +} + +void kputch(s8 Character) +{ + volatile u8 *VideoMemory = (u8 *)0xB8000; + u16 Offset = (g_kstdio_cur_y * 80 + g_kstdio_cur_x) << 1; + + if (Character == '\n') + kmove_cursor(0, g_kstdio_cur_y + 1); + else + { + VideoMemory[Offset] = Character; + VideoMemory[Offset+1] = 0x0F; + if (g_kstdio_cur_x + 1 >= 80) + kmove_cursor(0, g_kstdio_cur_y); + else + kmove_cursor(g_kstdio_cur_x + 1, g_kstdio_cur_y); + } +} + +void kputs(s8 *szString) +{ + while (*szString != 0) + { + kputch(*szString); + szString++; + } +} + +void kprint(s8 *szString) +{ + kputs(szString); +} + +void kclear(void) +{ + volatile u8 *VideoMemory = (u8 *)0xB8000; + u32 Size = (80 * 25 ) << 1; + for (u32 i = 0; i < Size; i += 2) + { + VideoMemory[i] = 0; + VideoMemory[i+1] = 0xF; + } + kmove_cursor(0, 0); +} diff --git a/src/Tier0/kstdio.h b/src/Tier0/kstdio.h new file mode 100644 index 0000000..6a013e7 --- /dev/null +++ b/src/Tier0/kstdio.h @@ -0,0 +1,18 @@ +#ifndef __KSTDIO_H__ +#define __KSTDIO_H__ + +#include "Types.h" + +void koutb(u16 Port, u8 Data); +u32 kstrlen(s8 *szString); +void kmove_cursor(u8 X, u8 Y); +void kputs(s8 *szString); +void kputch(s8 Character); +void kclear(void); +void kprint(s8 *szString); +void kputi(s32 Number); +void kprintf(s8 *Format, ...); +void kdump(u8 *bData, u32 Length); +void kprint_hex(u32 Number); + +#endif diff --git a/src/Tier0/kstdlib.c b/src/Tier0/kstdlib.c new file mode 100644 index 0000000..7747eb3 --- /dev/null +++ b/src/Tier0/kstdlib.c @@ -0,0 +1,30 @@ +#include "Types.h" +#include "kstdlib.h" + +void *kmemcpy(void* Destination, const void *Source, u32 Count) +{ + u8* Destination8 = (u8*)Destination; + u8* Source8 = (u8*)Source; + + while (Count--) + { + *Destination8++ = *Source8++; + } + return Destination; +} + +void *kmemset(void *Destination, u8 Value, u32 Count) +{ + u8 *us = (u8 *)Destination; + while (Count-- != 0) + *us++ = Value; + return Destination; +} + +void *kmemsetw(void *Destination, u16 Value, u32 Count) +{ + u16 *us = (u16 *)Destination; + while (Count-- != 0) + *us++ = Value; + return Destination; +} diff --git a/src/Tier0/kstdlib.h b/src/Tier0/kstdlib.h new file mode 100644 index 0000000..5655caf --- /dev/null +++ b/src/Tier0/kstdlib.h @@ -0,0 +1,10 @@ +#ifndef __KSTDLIB_H__ +#define __KSTDLIB_H__ + +#include "Types.h" + +void *kmemcpy(void* Destination, const void *Source, u32 Count); +void *kmemset(void *Destination, u8 Value, u32 Count); +void *kmemsetw(void *Destination, u16 Value, u32 Count); + +#endif diff --git a/src/kernel.ld b/src/kernel.ld new file mode 100644 index 0000000..362e620 --- /dev/null +++ b/src/kernel.ld @@ -0,0 +1,24 @@ +ENTRY (_start) + +SECTIONS { + . = 0x00100000; + + .text : { + *(.text) + } + + .rodata ALIGN (0x1000) : { + *(.rodata) + } + + .data ALIGN (0x1000) : { + *(.data) + } + + .bss : { + sbss = .; + *(COMMON) + *(.bss) + ebss = .; + } +}