Yay first commit.
commit
2f3ab42667
|
@ -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
|
|
@ -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.
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
TIMEOUT 4
|
||||
default mboot.c32 kernel.bin
|
||||
|
Binary file not shown.
|
@ -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
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
#include "Types.h"
|
||||
#include "kstdio.h"
|
||||
#include "kstdlib.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#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);
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,24 @@
|
|||
ENTRY (_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x00100000;
|
||||
|
||||
.text : {
|
||||
*(.text)
|
||||
}
|
||||
|
||||
.rodata ALIGN (0x1000) : {
|
||||
*(.rodata)
|
||||
}
|
||||
|
||||
.data ALIGN (0x1000) : {
|
||||
*(.data)
|
||||
}
|
||||
|
||||
.bss : {
|
||||
sbss = .;
|
||||
*(COMMON)
|
||||
*(.bss)
|
||||
ebss = .;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue