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