x86_64 port

This commit is contained in:
Morten Delenk 2016-06-17 21:39:43 +02:00
parent fddedb4448
commit 75e498aeaf
54 changed files with 2001 additions and 3648 deletions

View file

@ -12,5 +12,6 @@ user:
clean:
make -C kernel clean
rm -rf mtgos
find . -name '*.o' -delete
.PHONY: all mtgos user clean

View file

@ -1,13 +1,15 @@
arch = x86_64
arch = x86
#MODE = debug
MODE = release # enables optimization
export PATH := $(HOME)/opt/bin:$(PATH)
ARCHFLAGS =
ifeq ($(arch),x86)
PREFIX = i686-elf-
else
ifeq ($(arch),x86_64)
PREFIX = x86_64-elf-
ARCHFLAGS =
endif
endif

View file

@ -4,10 +4,8 @@ KERNSRCS = $(shell find kernel -name '*.cpp' -o -name '*.c')
OBJS = $(addsuffix .o,$(basename $(SRCS)))
OBJS += $(addsuffix .o,$(basename $(KERNSRCS)))
LD = $(PREFIX)g++
LDFLAGS = -nostdlib -nodefaultlibs -nostdlib -fno-builtin
ifeq ($(arch),x86)
LDFLAGS += -m32 -T kernel-$(arch).ld
endif
LDFLAGS = -nostdlib -nodefaultlibs -nostdlib -fno-builtin $(ARCHFLAGS) -T kernel-$(arch).ld
all: hal kernel
$(LD) $(LDFLAGS) -o mtgos $(OBJS)
hal:

View file

@ -321,9 +321,31 @@ intr_common_handler:
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov $8, %ecx
mov $fld_hi, %ebx
mov $fld_lo, %edx
.storeloop:
fstpl (%edx)
mov (%edx), %eax
push %eax
mov (%ebx), %eax
push %eax
loop .storeloop
push %esp
call handleINT
mov %eax, %esp
mov $8, %ecx
mov $fld_hi, %ebx
mov $fld_lo, %edx
.loadloop:
pop %eax
mov %eax, (%ebx)
pop %eax
mov %eax, (%edx)
fldl (%ebx)
loop .loadloop
//Load user datasegs
mov $0x23, %ax
mov %ax, %ds
@ -339,3 +361,9 @@ intr_common_handler:
add $8, %esp
// Exit interrupt
iret
.section .data
fld_lo:
.space 4
fld_hi:
.space 4

View file

@ -13,6 +13,7 @@
.extern init
.global _start
_start:
finit
mov $kernel_stack, %esp
push %ebx
push %eax

File diff suppressed because it is too large Load diff

View file

@ -1,2 +0,0 @@
#define MIN(a,b) ((a)>(b))?(b):(a)
#define MAX(a,b) ((a)<(b))?(b):(a)

View file

@ -1,10 +0,0 @@
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef signed long long int int64_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long int uint64_t;
typedef unsigned int uintptr_t;
typedef unsigned long int size_t;

View file

@ -1,13 +0,0 @@
#ifndef _STRING_H
#define _STRING_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void memmove(void* dst, void* src, uint32_t size);
uint32_t strlen(const char* str);
int strcmp(const char* str1, const char* str2);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -12,6 +12,7 @@
#define GDT_FLAG_4K_GRAN 0x800
#define GDT_FLAG_32_BIT 0x400
#define GDT_FLAG_64_BIT 0x200
extern "C" void loadGDT(void * gdtpr);
namespace MTGosHAL {
class GDT {

View file

@ -17,6 +17,14 @@ extern "C" {
namespace MTGosHAL {
struct cpu_state {
double st7;
double st6;
double st5;
double st4;
double st3;
double st2;
double st1;
double st0;
uint32_t eax;
uint32_t ebx;
uint32_t ecx;

View file

@ -15,8 +15,9 @@ private:
PMM2 pmm2;
public:
PMM();
PMM(struct multiboot_info* mb_info): PMM() {init(mb_info);}
auto init(struct multiboot_info*) -> void;
auto alloc(uint32_t length) -> void *;
auto alloc(size_t length) -> void *;
auto free(void* ptr) -> bool;
auto markUsed(const void * addr, uint32_t length) -> bool;
auto operator >> (void * &addr) -> PMM &; //alloc

View file

@ -52,6 +52,7 @@ namespace MTGosHAL {
public:
Screen(): fg(FG_color::WHITE), bg(BG_color::BLACK) {
}
Screen(struct multiboot_info* mb_info): Screen() {init(mb_info);}
auto init(struct multiboot_info*) -> void;
template <typename T>
auto operator<< (T output) -> Screen & {

View file

@ -31,6 +31,14 @@ auto Multitasking::initTask(void(* entry)()) -> struct cpu_state*
mm >> tmp1 >> tmp2;
uint8_t *stack=(uint8_t*)tmp1, *user_stack=(uint8_t*)tmp2;
struct cpu_state new_state = {
0.0, //ST0
0.0, //ST1
0.0, //ST2
0.0, //ST3
0.0, //ST4
0.0, //ST5
0.0, //ST6
0.0, //ST7
0, //EAX
0, //EBX
0, //ECX

View file

@ -8,28 +8,27 @@
#include <Multitasking.hpp>
#include <multiboot.h>
#include <blockdev.hpp>
#include <vmm3.hpp>
#include <pmm.hpp>
extern "C" void intr_stub_0(void);
void main(void ** programs);
void** progs;
namespace MTGosHAL {
Serial debug;
GDT gdt;
IDT idt;
PMM mm;
Screen out;
Screen err;
Keyboard in;
IDT idt;
GDT gdt;
Multitasking tasks;
BlockDevice disk;
PMM mm;
void main(int eax, struct multiboot_info* ebx) {
out.init(ebx);
err.init(ebx);
out << BG_color::BLACK << FG_color::WHITE << "Loading MTGos...\n";
err << BG_color::BLACK << FG_color::RED;
if(eax!=0x2BADB002)
err << "System wasn't loaded by a Multiboot-conformant launcher!\n";
//Init debug output
new (&debug) Serial();
debug << "Hello debugger! This is MTGos v00r01\nThese logs are probably very long, so please redirect the output to a file.\n";
debug << "Init GDT\n";
new (&gdt) GDT();
gdt.setEntry(0, 0, 0, 0);
gdt.setEntry(1, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT | GDT_FLAG_CODESEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT);
gdt.setEntry(2, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_32_BIT | GDT_FLAG_DATASEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT);
@ -38,15 +37,37 @@ namespace MTGosHAL {
gdt.setEntry(5, (uint32_t)tasks.tss, sizeof(tasks.tss), GDT_FLAG_RING3 | GDT_FLAG_TSS | GDT_FLAG_PRESENT);
gdt.setEntry(6, 0, 0xfffff, GDT_FLAG_RING3 | GDT_FLAG_TSS | GDT_FLAG_PRESENT);
gdt.apply();
asm volatile("ltr %%ax" : : "a"(5<<3));
debug << "We are now creating the IDT.\n";
debug << "Init IDT\n";
new (&idt) IDT();
for(int i=0;i<256;i++) {
idt.setEntry(i, (void *)((uint32_t)&intr_stub_0+i*16), SEG_KERNEL, IDT_INTERRUPT_GATE | IDT_SEG_32_BIT | IDT_RING_0 | IDT_USED);
}
idt.setEntry(48, (void *)((uint32_t)&intr_stub_0+768), SEG_KERNEL, IDT_TRAP_GATE | IDT_SEG_32_BIT | IDT_RING_3 | IDT_USED);
idt.setEntry(8, (void *)((uint32_t)&intr_stub_0+128), SEG_DBL_FAULT, IDT_TASK_GATE | IDT_SEG_32_BIT | IDT_RING_0 | IDT_USED);
idt.apply();
mm.init(ebx);
asm volatile("ltr %%ax" : : "a"(5<<3));
debug << "Init MM\n";
new (&mm) PMM(ebx);
debug << "Init Screen output\n";
new (&out) Screen(ebx);
new (&err) Screen(ebx);
out << BG_color::BLACK << FG_color::WHITE << "Loading MTGos...\n";
err << BG_color::BLACK << FG_color::RED;
debug << "Init Keyboard\n";
new (&in) Keyboard();
debug << "Init Multitasking\n";
new (&tasks) Multitasking();
debug << "Init Disk\n";
new (&disk) BlockDevice();
debug << "Kernel initialized\n";
if(eax!=0x2BADB002)
err << "System wasn't loaded by a Multiboot-conformant launcher!\n";
multiboot_mod_list *mods = (multiboot_mod_list*) ebx->mods_addr;
progs=(void**)mm.alloc(4096);
for(int i=0;i<1024;i++) {
@ -57,19 +78,18 @@ namespace MTGosHAL {
debug << "Found module!\n";
}
::main(progs);
uint8_t buf[512];
disk.readSector(disk.getDriveNumByName("ATA0m1"),0,buf);
out << (char*)buf;
sti();
for(;;);
}
}
typedef void (*constructor)();
typedef void (*destructor)();
extern "C" constructor start_ctors;
extern "C" constructor end_ctors;
extern "C" destructor start_dtors;
extern "C" destructor end_dtors;
extern "C" void init(int eax, struct multiboot_info* ebx) {
for(constructor* i = &start_ctors; i != &end_ctors; ++i)
(*i)();
MTGosHAL::main(eax, ebx);
for(destructor* i = &start_dtors; i != &end_dtors; i++)
(*i)();

View file

@ -0,0 +1,26 @@
include ../../../kernel.settings
SRCS = $(shell find -name '*.cpp' -o -name '*.[cS]')
OBJS = $(addsuffix .o,$(basename $(SRCS)))
CPP = $(PREFIX)g++
CC = $(PREFIX)gcc
ASFLAGS = -m64
CFLAGS = -m64 -Wall -fno-stack-protector -nostdinc -Ic_include/ -I../../kernel/c_include -ffreestanding -std=c11 -fno-builtin -Werror -nostdlib -g -fpie
CPPFLAGS = -m64 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -I../../kernel/c_include -I../../kernel/include -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fno-pie -Wno-reorder
all: $(OBJS)
%.o: %.cpp
$(CPP) $(CPPFLAGS) -c -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $^
%.o: $.S
$(CC) $(CFLAGS) -c -o $@ $^
clean:
rm -rf $(OBJS)
.PHONY: clean all

View file

@ -0,0 +1,381 @@
.global loadGDT
//void _stdcall loadGDT(struct gdtp* ptr);
loadGDT:
mov 0x8(%rsp), %rax // Load argument
lgdt (%rax)
//GDT is loaded now
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
mov $0x10, %rax
.code32
ljmp $8, $.1 //Hacky hack
.code64
.1:
ret
.global loadIDT
//void _stdcall loadIDT(struct idtp* ptr);
loadIDT:
mov 0x8(%rsp), %rax
lidt (%rax)
ret
.global enterPaging
//void _stdcall enterPaging(uint32** pd);
enterPaging:
mov 0x8(%rsp), %rax
mov %rax, %cr3
mov %cr4, %rax
or $0x10, %rax
mov %rax, %cr4
mov %cr0, %rax
push %rbx
mov $0x80000000,%rbx
or %rbx, %rax
pop %rbx
mov %rax, %cr0
mov (%rsp), %rax
ret
//Handle interrupts
.macro intr_stub nr
.global intr_stub_\nr
.align 32
intr_stub_\nr:
pushq $0
pushq $\nr
jmp intr_common_handler
.endm
.macro intr_stub_error_code nr
.global intr_stub_\nr
.align 32
intr_stub_\nr:
pushq $\nr
jmp intr_common_handler
.endm
intr_stub 0
intr_stub 1
intr_stub 2
intr_stub 3
intr_stub 4
intr_stub 5
intr_stub 6
intr_stub 7
intr_stub_error_code 8
intr_stub 9
intr_stub_error_code 10
intr_stub_error_code 11
intr_stub_error_code 12
intr_stub_error_code 13
intr_stub_error_code 14
intr_stub 15
intr_stub 16
intr_stub_error_code 17
intr_stub 18
intr_stub 19
intr_stub 20
intr_stub 21
intr_stub 22
intr_stub 23
intr_stub 24
intr_stub 25
intr_stub 26
intr_stub 27
intr_stub 28
intr_stub 29
intr_stub 30
intr_stub 31
intr_stub 32
intr_stub 33
intr_stub 34
intr_stub 35
intr_stub 36
intr_stub 37
intr_stub 38
intr_stub 39
intr_stub 40
intr_stub 41
intr_stub 42
intr_stub 43
intr_stub 44
intr_stub 45
intr_stub 46
intr_stub 47
intr_stub 48
intr_stub 49
intr_stub 50
intr_stub 51
intr_stub 52
intr_stub 53
intr_stub 54
intr_stub 55
intr_stub 56
intr_stub 57
intr_stub 58
intr_stub 59
intr_stub 60
intr_stub 61
intr_stub 62
intr_stub 63
intr_stub 64
intr_stub 65
intr_stub 66
intr_stub 67
intr_stub 68
intr_stub 69
intr_stub 70
intr_stub 71
intr_stub 72
intr_stub 73
intr_stub 74
intr_stub 75
intr_stub 76
intr_stub 77
intr_stub 78
intr_stub 79
intr_stub 80
intr_stub 81
intr_stub 82
intr_stub 83
intr_stub 84
intr_stub 85
intr_stub 86
intr_stub 87
intr_stub 88
intr_stub 89
intr_stub 90
intr_stub 91
intr_stub 92
intr_stub 93
intr_stub 94
intr_stub 95
intr_stub 96
intr_stub 97
intr_stub 98
intr_stub 99
intr_stub 100
intr_stub 101
intr_stub 102
intr_stub 103
intr_stub 104
intr_stub 105
intr_stub 106
intr_stub 107
intr_stub 108
intr_stub 109
intr_stub 110
intr_stub 111
intr_stub 112
intr_stub 113
intr_stub 114
intr_stub 115
intr_stub 116
intr_stub 117
intr_stub 118
intr_stub 119
intr_stub 120
intr_stub 121
intr_stub 122
intr_stub 123
intr_stub 124
intr_stub 125
intr_stub 126
intr_stub 127
intr_stub 128
intr_stub 129
intr_stub 130
intr_stub 131
intr_stub 132
intr_stub 133
intr_stub 134
intr_stub 135
intr_stub 136
intr_stub 137
intr_stub 138
intr_stub 139
intr_stub 140
intr_stub 141
intr_stub 142
intr_stub 143
intr_stub 144
intr_stub 145
intr_stub 146
intr_stub 147
intr_stub 148
intr_stub 149
intr_stub 150
intr_stub 151
intr_stub 152
intr_stub 153
intr_stub 154
intr_stub 155
intr_stub 156
intr_stub 157
intr_stub 158
intr_stub 159
intr_stub 160
intr_stub 161
intr_stub 162
intr_stub 163
intr_stub 164
intr_stub 165
intr_stub 166
intr_stub 167
intr_stub 168
intr_stub 169
intr_stub 170
intr_stub 171
intr_stub 172
intr_stub 173
intr_stub 174
intr_stub 175
intr_stub 176
intr_stub 177
intr_stub 178
intr_stub 179
intr_stub 180
intr_stub 181
intr_stub 182
intr_stub 183
intr_stub 184
intr_stub 185
intr_stub 186
intr_stub 187
intr_stub 188
intr_stub 189
intr_stub 190
intr_stub 191
intr_stub 192
intr_stub 193
intr_stub 194
intr_stub 195
intr_stub 196
intr_stub 197
intr_stub 198
intr_stub 199
intr_stub 200
intr_stub 201
intr_stub 202
intr_stub 203
intr_stub 204
intr_stub 205
intr_stub 206
intr_stub 207
intr_stub 208
intr_stub 209
intr_stub 210
intr_stub 211
intr_stub 212
intr_stub 213
intr_stub 214
intr_stub 215
intr_stub 216
intr_stub 217
intr_stub 218
intr_stub 219
intr_stub 220
intr_stub 221
intr_stub 222
intr_stub 223
intr_stub 224
intr_stub 225
intr_stub 226
intr_stub 227
intr_stub 228
intr_stub 229
intr_stub 230
intr_stub 231
intr_stub 232
intr_stub 233
intr_stub 234
intr_stub 235
intr_stub 236
intr_stub 237
intr_stub 238
intr_stub 239
intr_stub 240
intr_stub 241
intr_stub 242
intr_stub 243
intr_stub 244
intr_stub 245
intr_stub 246
intr_stub 247
intr_stub 248
intr_stub 249
intr_stub 250
intr_stub 251
intr_stub 252
intr_stub 253
intr_stub 254
intr_stub 255
//This should cover everything.
.extern handleINT
intr_common_handler:
cli
push %r15
push %r14
push %r13
push %r12
push %r11
push %r10
push %r9
push %r8
push %rbp
push %rdi
push %rsi
push %rdx
push %rcx
push %rbx
push %rax
mov $8, %rcx
mov $fldval, %rbx
.storeloop:
fstpl (%rbx)
mov (%rbx), %rax
push %rax
loop .storeloop
//Load kernel datasegs
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
push %rsp
call handleINT
mov %rax, %rsp
mov $8, %rcx
mov $fldval, %rbx
.loadloop:
pop %rax
mov %rax, (%rbx)
fldl (%rbx)
loop .loadloop
//Load user datasegs
mov $0x23, %ax
mov %ax, %ds
mov %ax, %es
pop %rax
pop %rbx
pop %rcx
pop %rdx
pop %rsi
pop %rdi
pop %rbp
pop %r8
pop %r9
pop %r10
pop %r11
pop %r12
pop %r13
pop %r14
pop %r15
// Take error code and interrupt number from stack
add $16, %rsp
// Exit interrupt
iret
.section .data
fldval:

View file

@ -1,16 +1,20 @@
.code32
.section multiboot
#define MB_MAGIC 0x1BADB002
#define MB_FLAGS 0x0
#define MB_FLAGS 0x7
#define MB_CHECKSUM -(MB_MAGIC + MB_FLAGS)
.align 4
.int MB_MAGIC
.int MB_FLAGS
.int MB_CHECKSUM
.int 0,0,0,0,0
.int 0
.int 1024, 768, 32
.section .text
.extern init
.global _start
_start:
finit
mov $mb_ptr, %edi
stosl
mov %ebx, %eax

View file

@ -0,0 +1,43 @@
#ifndef _IO_H
#define _IO_H
#include <stdint.h>
static inline void outb(uint16_t port, uint8_t val) {
asm volatile("outb %0, %1" : : "a"(val), "Nd"(port));
}
static inline void outw(uint16_t port, uint16_t val) {
asm volatile("outw %0, %1" : : "a"(val), "Nd"(port));
}
static inline void outl(uint16_t port, uint32_t val) {
asm volatile("outl %0, %1" : : "a"(val), "Nd"(port));
}
static inline uint8_t inb(uint16_t port) {
uint8_t ret;
asm volatile("inb %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static inline uint16_t inw(uint16_t port) {
uint16_t ret;
asm volatile("inw %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static inline uint32_t inl(uint16_t port) {
uint32_t ret;
asm volatile("inl %1, %0" : "=a"(ret) : "Nd"(port));
return ret;
}
static inline void io_wait() {
asm volatile("outb %%al, $0x80" : : "a"(0));
}
static inline void cli() {
asm volatile("cli");
}
static inline void sti() {
asm volatile("sti");
}
static inline uint64_t rdtsc()
{
uint64_t ret;
asm volatile ( "rdtsc" : "=A"(ret) );
return ret;
}
#endif

View file

@ -0,0 +1,309 @@
/* multiboot.h - Multiboot header file. */
/* Copyright (C) 1999,2003,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ANY
* DEVELOPER OR DISTRIBUTOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef MULTIBOOT_HEADER
#define MULTIBOOT_HEADER 1
/* How many bytes from the start of the file we search for the header. */
#define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_HEADER_ALIGN 4
/* The magic field should contain this. */
#define MULTIBOOT_HEADER_MAGIC 0x1BADB002
/* This should be in %eax. */
#define MULTIBOOT_BOOTLOADER_MAGIC 0x2BADB002
/* Alignment of multiboot modules. */
#define MULTIBOOT_MOD_ALIGN 0x00001000
/* Alignment of the multiboot info structure. */
#define MULTIBOOT_INFO_ALIGN 0x00000004
/* Flags set in the 'flags' member of the multiboot header. */
/* Align all boot modules on i386 page (4KB) boundaries. */
#define MULTIBOOT_PAGE_ALIGN 0x00000001
/* Must pass memory information to OS. */
#define MULTIBOOT_MEMORY_INFO 0x00000002
/* Must pass video information to OS. */
#define MULTIBOOT_VIDEO_MODE 0x00000004
/* This flag indicates the use of the address fields in the header. */
#define MULTIBOOT_AOUT_KLUDGE 0x00010000
/* Flags to be set in the 'flags' member of the multiboot info structure. */
/* is there basic lower/upper memory information? */
#define MULTIBOOT_INFO_MEMORY 0x00000001
/* is there a boot device set? */
#define MULTIBOOT_INFO_BOOTDEV 0x00000002
/* is the command-line defined? */
#define MULTIBOOT_INFO_CMDLINE 0x00000004
/* are there modules to do something with? */
#define MULTIBOOT_INFO_MODS 0x00000008
/* These next two are mutually exclusive */
/* is there a symbol table loaded? */
#define MULTIBOOT_INFO_AOUT_SYMS 0x00000010
/* is there an ELF section header table? */
#define MULTIBOOT_INFO_ELF_SHDR 0X00000020
/* is there a full memory map? */
#define MULTIBOOT_INFO_MEM_MAP 0x00000040
/* Is there drive info? */
#define MULTIBOOT_INFO_DRIVE_INFO 0x00000080
/* Is there a config table? */
#define MULTIBOOT_INFO_CONFIG_TABLE 0x00000100
/* Is there a boot loader name? */
#define MULTIBOOT_INFO_BOOT_LOADER_NAME 0x00000200
/* Is there a APM table? */
#define MULTIBOOT_INFO_APM_TABLE 0x00000400
/* Is there video information? */
#define MULTIBOOT_INFO_VBE_INFO 0x00000800
#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000
#ifndef ASM_FILE
typedef unsigned char multiboot_uint8_t;
typedef unsigned short multiboot_uint16_t;
typedef unsigned int multiboot_uint32_t;
typedef unsigned long long multiboot_uint64_t;
struct multiboot_header
{
/* Must be MULTIBOOT_MAGIC - see above. */
multiboot_uint32_t magic;
/* Feature flags. */
multiboot_uint32_t flags;
/* The above fields plus this one must equal 0 mod 2^32. */
multiboot_uint32_t checksum;
/* These are only valid if MULTIBOOT_AOUT_KLUDGE is set. */
multiboot_uint32_t header_addr;
multiboot_uint32_t load_addr;
multiboot_uint32_t load_end_addr;
multiboot_uint32_t bss_end_addr;
multiboot_uint32_t entry_addr;
/* These are only valid if MULTIBOOT_VIDEO_MODE is set. */
multiboot_uint32_t mode_type;
multiboot_uint32_t width;
multiboot_uint32_t height;
multiboot_uint32_t depth;
};
/* The symbol table for a.out. */
struct multiboot_aout_symbol_table
{
multiboot_uint32_t tabsize;
multiboot_uint32_t strsize;
multiboot_uint32_t addr;
multiboot_uint32_t reserved;
};
typedef struct multiboot_aout_symbol_table multiboot_aout_symbol_table_t;
/* The section header table for ELF. */
struct multiboot_elf_section_header_table
{
multiboot_uint32_t num;
multiboot_uint32_t size;
multiboot_uint32_t addr;
multiboot_uint32_t shndx;
};
typedef struct multiboot_elf_section_header_table multiboot_elf_section_header_table_t;
struct multiboot_info
{
/* Multiboot info version number */
multiboot_uint32_t flags;
/* Available memory from BIOS */
multiboot_uint32_t mem_lower;
multiboot_uint32_t mem_upper;
/* "root" partition */
multiboot_uint32_t boot_device;
/* Kernel command line */
multiboot_uint32_t cmdline;
/* Boot-Module list */
multiboot_uint32_t mods_count;
multiboot_uint32_t mods_addr;
union
{
multiboot_aout_symbol_table_t aout_sym;
multiboot_elf_section_header_table_t elf_sec;
} u;
/* Memory Mapping buffer */
multiboot_uint32_t mmap_length;
multiboot_uint32_t mmap_addr;
/* Drive Info buffer */
multiboot_uint32_t drives_length;
multiboot_uint32_t drives_addr;
/* ROM configuration table */
multiboot_uint32_t config_table;
/* Boot Loader Name */
multiboot_uint32_t boot_loader_name;
/* APM table */
multiboot_uint32_t apm_table;
/* Video */
multiboot_uint32_t vbe_control_info;
multiboot_uint32_t vbe_mode_info;
multiboot_uint16_t vbe_mode;
multiboot_uint16_t vbe_interface_seg;
multiboot_uint16_t vbe_interface_off;
multiboot_uint16_t vbe_interface_len;
multiboot_uint64_t framebuffer_addr;
multiboot_uint32_t framebuffer_pitch;
multiboot_uint32_t framebuffer_width;
multiboot_uint32_t framebuffer_height;
multiboot_uint8_t framebuffer_bpp;
#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0
#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1
#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2
multiboot_uint8_t framebuffer_type;
union
{
struct
{
multiboot_uint32_t framebuffer_palette_addr;
multiboot_uint16_t framebuffer_palette_num_colors;
};
struct
{
multiboot_uint8_t framebuffer_red_field_position;
multiboot_uint8_t framebuffer_red_mask_size;
multiboot_uint8_t framebuffer_green_field_position;
multiboot_uint8_t framebuffer_green_mask_size;
multiboot_uint8_t framebuffer_blue_field_position;
multiboot_uint8_t framebuffer_blue_mask_size;
};
};
};
typedef struct multiboot_info multiboot_info_t;
struct multiboot_color
{
multiboot_uint8_t red;
multiboot_uint8_t green;
multiboot_uint8_t blue;
};
struct multiboot_mmap_entry
{
multiboot_uint32_t size;
multiboot_uint64_t addr;
multiboot_uint64_t len;
#define MULTIBOOT_MEMORY_AVAILABLE 1
#define MULTIBOOT_MEMORY_RESERVED 2
#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
#define MULTIBOOT_MEMORY_NVS 4
#define MULTIBOOT_MEMORY_BADRAM 5
multiboot_uint32_t type;
} __attribute__((packed));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_mod_list
{
/* the memory used goes from bytes 'mod_start' to 'mod_end-1' inclusive */
multiboot_uint32_t mod_start;
multiboot_uint32_t mod_end;
/* Module command line */
multiboot_uint32_t cmdline;
/* padding to take it to 16 bytes (must be zero) */
multiboot_uint32_t pad;
};
typedef struct multiboot_mod_list multiboot_module_t;
/* APM BIOS info. */
struct multiboot_apm_info
{
multiboot_uint16_t version;
multiboot_uint16_t cseg;
multiboot_uint32_t offset;
multiboot_uint16_t cseg_16;
multiboot_uint16_t dseg;
multiboot_uint16_t flags;
multiboot_uint16_t cseg_len;
multiboot_uint16_t cseg_16_len;
multiboot_uint16_t dseg_len;
};
struct MODE_INFO
{
unsigned short ModeAttributes ;
unsigned char WinAAttributes ;
unsigned char WinBAttributes ;
unsigned short WinGranularity ;
unsigned short WinSize ;
unsigned short WinASegment ;
unsigned short WinBSegment ;
unsigned int WinFuncPtr ;
unsigned short BytesPerScanLine ;
unsigned short XResolution ;
unsigned short YResolution ;
unsigned char XCharSize ;
unsigned char YCharSize ;
unsigned char NumberOfPlanes ;
unsigned char BitsPerPixel ;
unsigned char NumberOfBanks ;
unsigned char MemoryModel ;
unsigned char BankSize ;
unsigned char NumberOfImagePages ;
unsigned char Reserved_page ;
unsigned char RedMaskSize ;
unsigned char RedMaskPos ;
unsigned char GreenMaskSize ;
unsigned char GreenMaskPos ;
unsigned char BlueMaskSize ;
unsigned char BlueMaskPos ;
unsigned char ReservedMaskSize ;
unsigned char ReservedMaskPos ;
unsigned char DirectColorModeInfo ;
unsigned int PhysBasePtr ;
unsigned int OffScreenMemOffset ;
unsigned short OffScreenMemSize ;
unsigned char Reserved[206] ;
}__attribute__ ((packed));
#endif /* ! ASM_FILE */
#endif /* ! MULTIBOOT_HEADER */

View file

@ -0,0 +1,32 @@
#ifndef MULTITASKING_H
#define MULTITASKING_H
namespace MTGosHAL {
class Multitasking
{
public:
Multitasking();
auto schedule(struct cpu_state* cpu) -> struct cpu_state*;
auto initTask(void(*entry)()) -> struct cpu_state*;
uint32_t tss[32];
protected:
private:
Task* first_task;
Task* curr_task;
};
class Task
{
private:
struct cpu_state* cpu_state;
Task* next;
public:
Task(struct cpu_state*);
auto unpause() -> struct cpu_state*;
auto pause(struct cpu_state*) -> Task *;
auto addTask(Task*) -> void;
auto hasNext() -> bool;
};
} // namespace MTGosHAL
#endif // MULTITASKING_H

View file

@ -0,0 +1,32 @@
#ifndef _GDT_HPP
#define _GDT_HPP
#include <stdint.h>
#define GDT_FLAG_DATASEG 0x02
#define GDT_FLAG_CODESEG 0x0a
#define GDT_FLAG_TSS 0x09
#define GDT_FLAG_SEGMENT 0x10
#define GDT_FLAG_RING0 0x00
#define GDT_FLAG_RING3 0x60
#define GDT_FLAG_PRESENT 0x80
#define GDT_FLAG_4K_GRAN 0x800
#define GDT_FLAG_32_BIT 0x400
#define GDT_FLAG_64_BIT 0x200
extern "C" void loadGDT(void * gdtpr);
namespace MTGosHAL {
class GDT {
private:
uint64_t gdt[7];
struct gdtp {
uint16_t limit;
void* pointer;
} __attribute__((packed));
struct gdtp fin;
public:
GDT();
auto setEntry(int i, unsigned int base, unsigned int limit, int flags) -> void;
auto apply() -> void;
};
}
#endif

View file

@ -0,0 +1,70 @@
#ifndef _IDT_HPP
#define _IDT_HPP
#include <stdint.h>
#define IDT_INTERRUPT_GATE 0x06
#define IDT_TRAP_GATE 0x07
#define IDT_TASK_GATE 0x05
#define IDT_SEG_32_BIT 0x08
#define IDT_RING_0 0x00
#define IDT_RING_3 0x60
#define IDT_USED 0x80
#define SEG_KERNEL 0x08
#define SEG_USER 0x18 /*NEVER USE!!*/
#define SEG_DBL_FAULT 0x28 /*Only use for double fault handler!!*/
extern "C" {
void loadIDT(void * ptr);
}
namespace MTGosHAL {
struct cpu_state {
double st7;
double st6;
double st5;
double st4;
double st3;
double st2;
double st1;
double st0;
uint64_t rax;
uint64_t rbx;
uint64_t rcx;
uint64_t rdx;
uint64_t rsi;
uint64_t rdi;
uint64_t rbp;
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t intr;
uint64_t error;
uint64_t rip;
uint64_t cs;
uint64_t rflags;
uint64_t rsp;
uint64_t ss;
};
class IDT {
private:
unsigned __int128 idt[256];
struct cpu_state* (*ivt[256][16])(struct cpu_state *);
struct idtp {
uint16_t limit;
unsigned __int128* pointer;
}__attribute__((packed));
struct idtp idtptr;
public:
IDT();
auto setEntry(int i, void* offset, uint16_t seg, uint8_t flags) -> void;
auto apply() -> void;
auto handle(struct cpu_state* cpu) -> struct cpu_state*;
auto request(uint8_t intr, struct cpu_state* (*handler)(struct cpu_state*)) -> bool;
};
}
#endif

View file

@ -0,0 +1,23 @@
#ifndef _KEYBOARD_HPP
#define _KEYBOARD_HPP
#include <stdint.h>
#include <input.hpp>
#include <io.h>
#include <idt.hpp>
namespace MTGosHAL {
class Keyboard: public Input {
private:
//This kernel has a buffer of 16 chars
char buf[16];
int len;
auto getChar() -> char;
auto sendCommand(uint8_t command) -> void;
bool numlock, capslock, scrolllock, response;
public:
auto handleIRQ1(struct cpu_state* cpu) -> struct cpu_state*;
Keyboard();
};
}
#endif // -Wno-pmf-conversions

View file

@ -0,0 +1,28 @@
#ifndef _PMM_HPP
#define _PMM_HPP
#include <pmm2.hpp>
#include <stdint.h>
#include <multiboot.h>
namespace MTGosHAL {
struct malloc_t {
size_t len;
malloc_t *last;
malloc_t *next;
};
class PMM {
private:
malloc_t *head;
PMM2 pmm2;
public:
PMM();
PMM(struct multiboot_info* mb_info): PMM() {init(mb_info);}
auto init(struct multiboot_info*) -> void;
auto alloc(size_t length) -> void *;
auto free(void* ptr) -> bool;
auto markUsed(const void * addr, uint64_t length) -> bool;
auto operator >> (void * &addr) -> PMM &; //alloc
auto operator << (const void * addr) -> PMM &; //free
auto operator()(int pages) -> void*; //alloc_multipage
};
}
#endif

View file

@ -0,0 +1,20 @@
#ifndef _PMM2_HPP
#define _PMM2_HPP
#include <pmm3.hpp>
#include <stdint.h>
#include <multiboot.h>
namespace MTGosHAL {
class PMM2 {
private:
uint64_t *pageTable;
PMM3 pmm3;
public:
PMM2();
auto markUsed(const void * addr, uint32_t length) -> bool;
auto init(struct multiboot_info*) -> void;
auto operator >> (void * &addr) -> PMM2 &; //alloc
auto operator << (const void * addr) -> PMM2 &; //free
auto operator()(int pages) -> void*; //alloc_multipage
};
}
#endif

View file

@ -0,0 +1,18 @@
#ifndef _PMM3_HPP
#define _PMM3_HPP
#include <stdint.h>
#include <multiboot.h>
namespace MTGosHAL {
class PMM3 {
private:
uint32_t bitmap[0x8000]; //Enough for 512 GB (2MB pages)
protected:
public:
PMM3();
auto markUsed(const void * addr) -> void;
auto init(struct multiboot_info*) -> void;
auto operator >> (void * &addr) -> PMM3 &; //alloc
auto operator << (const void * addr) -> PMM3 &; //free
};
}
#endif

View file

@ -0,0 +1,31 @@
#ifndef _SERIAL_HPP
#define _SERIAL_HPP
#include <output.hpp>
#include <input.hpp>
#include <textDISP.hpp>
#include <io.h>
#define SERIAL_IER 1
#define SERIAL_IIR 2
#define SERIAL_FCR 2
#define SERIAL_LCR 3
#define SERIAL_MCR 4
#define SERIAL_LSR 5
#define SERIAL_MSR 6
namespace MTGosHAL {
class Serial: public Output, public Input {
private:
uint16_t port;
uint64_t waittimes;
uint64_t transmits;
bool works;
auto isTransmitEmpty() -> int;
auto putChar(char chr) -> void;
auto serial_received() -> int;
auto getChar() -> char;
public:
Serial();
auto debug() -> void;
};
}
#endif

View file

@ -0,0 +1,73 @@
#ifndef _TEXTDISP_H
#define _TEXTDISP_H
#include <base.hpp>
#include <stdint.h>
#include <output.hpp>
#include <multiboot.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 96
namespace MTGosHAL {
enum class BG_color : uint32_t {
BLACK=0x000000,
BLUE=0x0000AA,
GREEN=0x00AA00,
CYAN=0x00AAAA,
RED=0xAA0000,
MAGENTA=0xAA00AA,
BROWN=0xAA5500,
LIGHT_GREY=0xAAAAAA,
GREY=0x555555,
LIGHT_BLUE=0x5555FF,
LIGHT_GREEN=0x55FF55,
LIGHT_CYAN=0x55FFFF,
LIGHT_RED=0xFF5555,
LIGHT_MAGENTA=0xFF55FF,
YELLOW=0xFFFF55,
WHITE=0xFFFFFF
};
enum class FG_color : uint32_t {
BLACK=0x000000,
BLUE=0x0000AA,
GREEN=0x00AA00,
CYAN=0x00AAAA,
RED=0xAA0000,
MAGENTA=0xAA00AA,
BROWN=0xAA5500,
LIGHT_GREY=0xAAAAAA,
GREY=0x555555,
LIGHT_BLUE=0x5555FF,
LIGHT_GREEN=0x55FF55,
LIGHT_CYAN=0x55FFFF,
LIGHT_RED=0xFF5555,
LIGHT_MAGENTA=0xFF55FF,
YELLOW=0xFFFF55,
WHITE=0xFFFFFF
};
class Screen: public Output {
private:
FG_color fg;
BG_color bg;
uint32_t* lfb;
auto putChar(char c) -> void;
public:
Screen(): fg(FG_color::WHITE), bg(BG_color::BLACK) {
}
Screen(struct multiboot_info* mb_info): Screen() {init(mb_info);}
auto init(struct multiboot_info*) -> void;
template <typename T>
auto operator<< (T output) -> Screen & {
Output::operator<<<T>(output);
return *this;
}
auto clrscr() -> void;
auto scroll() -> void;
auto setColor(FG_color fg) -> Screen &;
auto setColor(BG_color bg) -> Screen &;
auto setColor(FG_color fg, BG_color bg) -> Screen &;
};
template <>
auto Screen::operator<<<FG_color>(FG_color fg) -> Screen &;
template <>
auto Screen::operator<<<BG_color>(BG_color bg) -> Screen &;
}
#endif

View file

@ -0,0 +1,90 @@
#include <base.hpp>
#include <textDISP.hpp>
#include <Multitasking.hpp>
#include <serial.hpp>
#include <blockdev.hpp>
#include <idt.hpp>
#include <pmm.hpp>
namespace MTGosHAL {
auto schedule(struct cpu_state* cpu) -> struct cpu_state* {
return MTGosHAL::tasks.schedule(cpu);
}
Multitasking::Multitasking(): curr_task(nullptr), first_task(nullptr)
{
for(int i=0;i<32;i++) {
if(i==2)
continue;
tss[i]=0;
}
tss[2]=0x10;
//task_states[0] = initTask(stack_a, user_stack_a, task_a);
//task_states[1] = initTask(stack_b, user_stack_b, task_b);
if(!idt.request(0x20,MTGosHAL::schedule)) {
err << "Could not start multitasking\nFatal error; Kernel halted!\n";
while(true)
asm volatile("cli; hlt");
}
}
auto Multitasking::initTask(void(* entry)()) -> struct cpu_state*
{
void* tmp1, *tmp2;
mm >> tmp1 >> tmp2;
uint8_t *stack=(uint8_t*)tmp1, *user_stack=(uint8_t*)tmp2;
struct cpu_state new_state = {
0.0, //ST0
0.0, //ST1
0.0, //ST2
0.0, //ST3
0.0, //ST4
0.0, //ST5
0.0, //ST6
0.0, //ST7
0, //RAX
0, //RBX
0, //RCX
0, //RDX
0, //RSI
0, //RDI
0, //RBP
0, //R8
0, //R9
0, //r10
0, //r11
0, //r12
0, //r13
0, //r14
0, //r15
0, //INTR
0, //ERROR
(uint64_t) entry, //RIP
0x18 | 0x03, //CS
0x202, // RFLAGS
(uint64_t) user_stack+0x200000, //RSP
0x20 | 0x03 //SS
};
struct cpu_state* state = (struct cpu_state*)(stack+0x200000-sizeof(new_state));
*state = new_state;
//Create new task class
Task* task = new Task(state);
if(first_task)
first_task->addTask(task);
else {
first_task=task;
}
return state;
}
auto Multitasking::schedule(struct cpu_state* cpu) -> struct cpu_state*
{
Task* next=nullptr;
if(curr_task) {
next=curr_task->pause(cpu);
}
if (!next) {
next=first_task;
}
curr_task=next;
struct cpu_state* cpu_state=next->unpause();
MTGosHAL::tasks.tss[1] = (uint32_t) (uint64_t)(cpu_state + 1);
return cpu_state;
}
} // namespace MTGosHAL

View file

@ -0,0 +1,21 @@
#include <base.hpp>
#include <gdt.hpp>
#include <serial.hpp>
namespace MTGosHAL {
GDT::GDT() {
gdt[0]=gdt[1]=gdt[2]=gdt[3]=gdt[4]=gdt[5]=gdt[6]=0x0ull;
}
auto GDT::setEntry(int i, unsigned int base, unsigned int limit, int flags) -> void {
gdt[i] = limit & 0xffffLL;
gdt[i] |= (base & 0xffffffLL) << 16;
gdt[i] |= (flags & 0xffLL) << 40;
gdt[i] |= ((limit >> 16) & 0xfLL) << 48;
gdt[i] |= ((flags >> 8 )& 0xffLL) << 52;
gdt[i] |= ((base >> 24) & 0xffLL) << 56;
}
auto GDT::apply() -> void {
debug << "We are now trying to set our GDT. If the CPU triplefaults, something went wrong in MTGosHAL::GDT::apply() or loadGDT().\n";
fin={(uint16_t)7*8-1, (void*)gdt};
loadGDT((void*)(&fin));
};
}

View file

@ -0,0 +1,91 @@
#include <base.hpp>
#include <io.h>
#include <idt.hpp>
#include <serial.hpp>
#include <textDISP.hpp>
#include <pmm.hpp>
auto syscall(uint32_t syscall_num, void* handle, void* args) -> void*;
extern void** progs;
namespace MTGosHAL {
IDT::IDT() {
//Init PIC
outb(0x20, 0x11); //Init Master-PIC
outb(0x21, 0x20); //Interrupt number for IRQ0
outb(0x21, 0x04); //IRQ is the Slave
outb(0x21, 0x01); //ICW 4
outb(0xA0, 0x11); //Init Master-PIC
outb(0xA1, 0x28); //Interrupt number for IRQ8
outb(0xA1, 0x02); //IRQ is the Slave
outb(0xA1, 0x01); //ICW 4
//Activate IRQ's
outb(0x21, 0x00);
outb(0xA1, 0x00);
}
auto IDT::setEntry(int i, void* offset, uint16_t seg, uint8_t flags) -> void {
idt[i]=(uint16_t)((uint64_t)offset);
idt[i]|=(unsigned __int128)(((uint64_t)offset)>>16)<<48;
idt[i]|=((unsigned __int128)seg)<<16;
idt[i]|=((unsigned __int128)flags)<<40;
}
auto IDT::apply() -> void {
debug << "Now trying to load the IDT.\n";
idtptr.limit=(uint16_t)(256*8-1);
idtptr.pointer=(unsigned __int128*)&idt;
loadIDT((void*)&idtptr);
}
auto IDT::handle(struct cpu_state* cpu) -> struct cpu_state* {
struct cpu_state* new_cpu=cpu;
debug << "Interrupt 0x" << Base::HEXADECIMAL << (int) cpu->intr << " was raised.\n";
if(cpu->intr<=0x1F) {
err << "Exception 0x" << Base::HEXADECIMAL << (int) cpu->intr << "! Kernel halted!\n";
err << "EAX = 0x" << (int)cpu->rax << " - EBX = 0x" << (int)cpu->rbx << "\n";
err << "ECX = 0x" << (int)cpu->rcx << " - EDX = 0x" << (int)cpu->rdx << "\n";
err << "ESI = 0x" << (int)cpu->rsi << " - EDI = 0x" << (int)cpu->rdi << "\n";
err << "SS:ESP = 0x" << (int)cpu->ss << ":0x" << (int)cpu->rsp << " - SS:EBP = 0x" << (int)cpu->ss << ":0x" << (int)cpu->rbp << "\n";
err << "CS:EIP = 0x" << (int)cpu->cs << ":0x" << (int)cpu->rip << " - INTR:ERR = 0x" << (int)cpu->intr << ":0x" << (int)cpu->error << "\n";
err << "------ END OF REGISTER DUMP ------ ------ START OF PROGRAM LOADPOINTS ------\n";
for(int i=0;i<1024;i++) {
if(!progs[i])
break;
err << "0x" << (int)((uint64_t)progs[i]) << "; ";
}
err << "\n";
uint16_t counter = 1193180 / 220; //Make an annoying beep
outb(0x43, 0xB6);
outb(0x42, (uint8_t)counter);
outb(0x42, (uint8_t)(counter>>8));
outb(0x61, inb(0x61) | 3);
while(1) {
asm volatile("cli; hlt");
}
} else if(cpu->intr >= 0x20 && cpu->intr <= 0x2F) {
if(cpu->intr >= 0x28) {
outb(0xA0, 0x20);
}
outb(0x20, 0x20);
debug << "The IRQ " << Base::DECIMAL << (int) cpu->intr-0x20 << " was handled.\n";
if(cpu->intr==0x20) {
debug.debug();
}
}
for(int i=0;i<16;i++) {
if(ivt[cpu->intr][i])
new_cpu=ivt[cpu->intr][i](new_cpu);
}
if(cpu->intr>=48)
new_cpu->rax=(uint64_t)(::syscall(cpu->rax, (void*)(cpu->rbx), (void*)(cpu->rsp)));
return new_cpu;
}
auto IDT::request(uint8_t intr, struct cpu_state* (*handler)(struct cpu_state*)) -> bool {
for(int i=0;i<16;i++) {
if(ivt[intr][i])
continue;
ivt[intr][i]=handler;
return true;
}
return false;
}
}
extern "C" void* handleINT(void* cpu) {
return (void*)MTGosHAL::idt.handle((MTGosHAL::cpu_state*)cpu);
}

View file

@ -0,0 +1,73 @@
#include <base.hpp>
#include <output.hpp>
#include <serial.hpp>
#include <textDISP.hpp>
#include <keyboard.hpp>
#include <Multitasking.hpp>
#include <multiboot.h>
#include <blockdev.hpp>
#include <gdt.hpp>
#include <idt.hpp>
#include <pmm.hpp>
extern "C" void intr_stub_0(void);
void main(void ** programs);
void** progs;
namespace MTGosHAL {
Serial debug;
GDT gdt;
IDT idt;
PMM mm;
Screen out;
Screen err;
Keyboard in;
Multitasking tasks;
void main(long eax, struct multiboot_info* ebx, uint64_t**** pt) {
new (&debug) Serial();
debug << "Hello debugger! This is MTGos v00r01\nThese logs are probably very long, so please redirect the output to a file.\n";
debug << "Init GDT\n";
new (&gdt) GDT();
gdt.setEntry(0, 0, 0, 0);
gdt.setEntry(1, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_64_BIT | GDT_FLAG_CODESEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT);
gdt.setEntry(2, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_64_BIT | GDT_FLAG_DATASEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT);
gdt.setEntry(3, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_64_BIT | GDT_FLAG_CODESEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
gdt.setEntry(4, 0, 0xfffff, GDT_FLAG_SEGMENT | GDT_FLAG_64_BIT | GDT_FLAG_DATASEG | GDT_FLAG_4K_GRAN | GDT_FLAG_PRESENT | GDT_FLAG_RING3);
gdt.setEntry(5, (uint64_t)tasks.tss, sizeof(tasks.tss), GDT_FLAG_RING3 | GDT_FLAG_TSS | GDT_FLAG_PRESENT);
gdt.setEntry(6, 0, 0xfffff, GDT_FLAG_RING3 | GDT_FLAG_TSS | GDT_FLAG_PRESENT);
gdt.apply();
debug << "Init IDT\n";
new (&idt) IDT();
for(int i=0;i<256;i++) {
idt.setEntry(i, (void *)((uint64_t)&intr_stub_0+i*32), SEG_KERNEL, IDT_INTERRUPT_GATE | IDT_SEG_32_BIT | IDT_RING_0 | IDT_USED);
}
idt.setEntry(48, (void *)((uint64_t)&intr_stub_0+768*2), SEG_KERNEL, IDT_TRAP_GATE | IDT_SEG_32_BIT | IDT_RING_3 | IDT_USED);
idt.setEntry(8, (void *)((uint64_t)&intr_stub_0+128*2), SEG_DBL_FAULT, IDT_TASK_GATE | IDT_SEG_32_BIT | IDT_RING_0 | IDT_USED);
idt.apply();
asm volatile("ltr %%ax" : : "a"(5<<3));
debug << "Init MM\n";
new (&mm) PMM(ebx);
debug << "Init Screen output\n";
new (&out) Screen(ebx);
new (&err) Screen(ebx);
out << BG_color::BLACK << FG_color::WHITE << "Loading MTGos...\n";
err << BG_color::BLACK << FG_color::RED;
debug << "Init Keyboard\n";
new (&in) Keyboard();
}
}
typedef void (*constructor)();
typedef void (*destructor)();
extern "C" destructor start_dtors;
extern "C" destructor end_dtors;
extern "C" void init(int eax, struct multiboot_info* ebx, uint64_t**** ecx) {
MTGosHAL::main(eax, ebx,ecx);
for(destructor* i = &start_dtors; i != &end_dtors; i++)
(*i)();
}
extern "C" void __cxa_pure_virtual() {
MTGosHAL::debug << "A pure virtual function just got called.\n";
}

View file

@ -0,0 +1,128 @@
#include <base.hpp>
#include <output.hpp>
#include <serial.hpp>
#include <keyboard.hpp>
#include <keymap_DE.hpp>
namespace MTGosHAL {
auto handleIRQ(struct cpu_state* cpu) -> struct cpu_state* {
return in.handleIRQ1(cpu);
}
auto Keyboard::getChar() -> char {
char chr=buf[0];
for(int i=0;i<15;i++) {
buf[i]=buf[i+1];
}
buf[15]='\0';
if(len)
len--;
return chr;
}
auto Keyboard::sendCommand(uint8_t command) -> void {
while((inb(0x64) & 0x2));
outb(0x60, command);
}
auto Keyboard::handleIRQ1(struct cpu_state* cpu) -> struct cpu_state* {
uint8_t keycode=0,scancode=inb(0x60);
if(scancode==0xFA) {
response=false;
return cpu;
} else if(response && scancode == 0xFE) {
sendCommand(0xED);
outb(0x60, (scrolllock) + (numlock<<1) + (capslock<<2));
return cpu;
}
debug << "Keyboard interrupt received.\nGot: 0x" << Base::HEXADECIMAL << (int)scancode;
bool break_code=false;
static bool e0_code=false;
static int e1_code=0;
static uint16_t e1_prev=0;
uint8_t tableID=0;
if((scancode & 0x80 ) && (e1_code || (scancode != 0xE1)) && (e0_code || (scancode != 0xE0))) {
break_code = true;
scancode &= ~0x80;
}
if(e0_code) {
if((scancode==0x2A) || (scancode = 0x36)) {
e0_code = false;
return cpu;
}
keycode=keyboardKeycodes[1][scancode];
e0_code=false;
} else if (e1_code == 2) {
e1_prev |= ((uint16_t) scancode << 8);
//TODO. translate it, although I might not even use this code
return cpu;
} else if (e1_code) {
e1_prev = scancode;
e1_code++;
return cpu;
} else if (scancode == 0xE0) {
e0_code = true;
return cpu;
} else if (scancode == 0xE1) {
e1_code = true;
return cpu;
} else {
keycode=keyboardKeycodes[0][scancode];
}
//Now put it into the keystate array
if(break_code)
keydowns[keycode]=false;
else
keydowns[keycode]=true;
//0x2A 0x36 = Shift
if(keydowns[0x2A] || keydowns[0x36])
tableID^=1;
//0x1D = Ctrl
if(keydowns[0x1D])
tableID^=2;
//0x38 = Alt
if(keydowns[0x38])
tableID^=4;
//0x45 = Numlock
if(keycode==0x45)
numlock=!numlock;
//0x3A = CAPS
if(keycode==0x3A)
capslock=!capslock;
//0x46 = Scrolllock
if(keycode==0x46)
scrolllock=!scrolllock;
if(capslock)
tableID^=1;
//Correct the LEDs
sendCommand(0xED);
outb(0x60, (scrolllock) + (numlock<<1) + (capslock<<2));
response=true;
//Convert it into a char
if(!break_code)
out << keymap[tableID][keycode];
debug << " -> 0x" << (int)keycode << ".\n";
return cpu;
}
Keyboard::Keyboard(): numlock(true), capslock(false), scrolllock(false), response(false) {
if(!idt.request(0x21, (struct cpu_state*(*)(struct cpu_state*))&handleIRQ)) {
debug << "Could not get an handler for IRQ1 (Keyboard)\n";
return;
}
//Clear keyboard buffer
while(inb(0x64) & 0x1) {
inb(0x60);
}
sendCommand(0xF4); //Activate keyboard
//Check for self-test being passed
sendCommand(0x20);
uint8_t ccb=inb(0x60);
if((ccb&4)) {
ccb &= ~1;
} else {
debug << "Keyboard didn't pass self-test!\nDeactivating IRQ1.\n";
ccb |= 1;
}
sendCommand(0x60);
outb(0x64, ccb);
}
}

View file

@ -0,0 +1,78 @@
#include <base.hpp>
#include <serial.hpp>
namespace MTGosHAL {
auto Serial::isTransmitEmpty() -> int {
return inb(port+SERIAL_LSR)&0x20;
}
auto Serial::putChar(char chr) -> void {
// if(!works)
return;
int tries=65535;
while(!isTransmitEmpty()) {
waittimes++;
tries--;
if(!tries){
works=false;
return;
}
}
outb(port, chr);
transmits++;
}
auto Serial::serial_received() -> int {
return inb(port+SERIAL_LSR)&1;
}
auto Serial::getChar() -> char {
//We try 500 times to get a character
int tries=500;
while(!serial_received()) {
tries--;
waittimes++;
if(!tries) {
return '\0';
}
}
transmits++;
char chr = inb(port);
if(chr!='\r')
*this << chr;
else
*this << '\n';
return chr;
}
Serial::Serial(): works(true) {
uint32_t baud=115200;
port=*((uint16_t*)0x0400);
union {
uint8_t b[2];
uint16_t w;
} divisor;
divisor.w = 115200/baud;
//Turn off interrupts
outb(port+SERIAL_IER, 0x00);
//Set DLAB-bit
outb(port+SERIAL_LCR, 0x80);
//Set baud divisor
outb(port, divisor.b[0]);
outb(port+1, divisor.b[1]);
//Set bit count, parity and reset DLAB
outb(port+SERIAL_LCR, 3);
//Finish init
outb(port+SERIAL_FCR, 0xC7);
outb(port+SERIAL_MCR, 0x0B);
}
auto Serial::debug() -> void {
if(getChar()) {
*this << "The interactive debug shell was started.\n> ";
out << "The debug shell was started.\n";
char buf[256];
*this >> buf;
out << buf << "\nDebug shell closed.\n";
*this << "Unknown command. TODO\n";
}
uint64_t wt = waittimes;
uint64_t tm = transmits;
*this << "Transmit stats: " << (int32_t)wt << " times waited; " << (int32_t)tm << " bytes transferred.\n";
waittimes=transmits=0;
}
}

View file

@ -0,0 +1,21 @@
#include <base.hpp>
#include <textDISP.hpp>
#include <string.h>
#include <stdfnt.h>
namespace MTGosHAL {
auto Screen::init(struct multiboot_info* mb_info) -> void {
lfb=(uint32_t*)((uintptr_t)mb_info->framebuffer_addr);
//clrscr();
//Render '\001' character
for(int tx=0;tx<16;tx++) {
for(int ty=0;ty<16;ty++) {
for(int x=0;x<8;x++) {
for(int y=0;y<8;y++) {
if(font[tx+ty*16][y]&(1<<x))
lfb[(x+tx*8)+(y+ty*8)*1024]=0xFFFFFF;
}
}
}
}
}
}

View file

@ -0,0 +1,24 @@
#include <base.hpp>
#include <pmm.hpp>
extern "C" const int kernel_start;
extern "C" const int kernel_end; //those are voids actually
namespace MTGosHAL {
PMM::PMM(): head(nullptr), pmm2() {}
auto PMM::init(struct multiboot_info* mb_info) -> void {
pmm2.init(mb_info);
}
auto PMM::markUsed(const void * addr, uint64_t length) -> bool {
return pmm2.markUsed(addr, length);
}
auto PMM::operator >> (void * &addr) -> PMM & {
pmm2>>addr;
return *this;
} //alloc
auto PMM::operator << (const void * addr) -> PMM & {
pmm2<<addr;
return *this;
} //free
auto PMM::operator()(int pages) -> void*{
return pmm2(pages);
} //alloc_multipage
}

View file

@ -0,0 +1,83 @@
#include <pmm2.hpp>
#include <base.hpp>
//In this part, please remember that the address is split into 2 parts. Bitmap:
// AAA AAAA AAAA AAAA AAAB BBBB BBBB BBBB BBBB BBBB
#define SPLIT1_FLAG 0x3ffff00000ull
#define SPLIT1_SHIFT(a) ((a)<<20)
#define SPLIT1_UNSHIFT(a) ((a)>>20)
#define SPLIT2_FLAG 0xFFFFFull
#define SPLIT2_SHIFT(a) ((a))
#define SPLIT2_UNSHIFT(a) ((a)&SPLIT2_FLAG)
extern "C" const int kernel_start;
extern "C" const int kernel_end; //those are voids actually
namespace MTGosHAL {
PMM2::PMM2(): pmm3() {
}
auto PMM2::markUsed(const void * addr, uint32_t length) -> bool {
uintptr_t add=(uintptr_t)addr;
uint32_t pagetid = SPLIT1_UNSHIFT(add);
//Check if used
for(uintptr_t curr_addr=add+length;curr_addr>=add;curr_addr-=0x200000) {
if(pageTable[SPLIT1_UNSHIFT(curr_addr)])
return false;
}
//Mark as used
uint64_t counter=1;
for(uintptr_t curr_addr=add+length;curr_addr>=add;curr_addr-=0x200000) {
pageTable[SPLIT1_UNSHIFT(curr_addr)]=counter++;
pmm3.markUsed((void*)curr_addr);
}
return true;
}
auto PMM2::operator >> (void * &addr) -> PMM2 & {
pmm3 >> addr;
markUsed(addr,0x200000);
return *this;
}
auto PMM2::operator << (const void *addr) -> PMM2 & {
uint64_t add=(uint64_t)addr;
for(uint64_t i=0;i<pageTable[SPLIT1_UNSHIFT(add)];i++) {
pageTable[SPLIT1_UNSHIFT(add+i*0x200000)]=0;
pmm3 << (void*)(add+i*0x200000);
}
return *this;
}
auto PMM2::operator()(int pages) -> void* {
//I want to get this working so:
//TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
// NEVER USE A BRUTE-FORCE ALGO TO ALLOC PAGES!
//TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO TODO
for(uint64_t i=0;i<(uint64_t)(-(pages*0x200000));i+=0x200000) {
if(markUsed((void*)i,pages*0x200000))
return (void*)i;
}
return nullptr;
}
auto PMM2::init(struct multiboot_info* mb_info) -> void {
pmm3.init(mb_info);
void *temp;
pmm3 >> temp;
pageTable=(uint64_t*)temp;
for(int i=0;i<0x80000;i++)
pageTable[i]=0;
markUsed(pageTable,0x200000);
markUsed((void*)nullptr,0x200000);
struct multiboot_mmap_entry* mmap = (struct multiboot_mmap_entry*) (uintptr_t)(mb_info->mmap_addr);
struct multiboot_mmap_entry* mmap_end = (struct multiboot_mmap_entry*) ((uintptr_t) mb_info->mmap_addr + mb_info->mmap_length);
while(mmap < mmap_end) {
if(mmap->type != 1) {
markUsed((void*)mmap->addr,mmap->len);
}
mmap++;
}
markUsed(&kernel_start,((uintptr_t)&kernel_end)-((uintptr_t)&kernel_start)); //Protect kernel)
multiboot_mod_list *mods = (multiboot_mod_list*) (uintptr_t)(mb_info->mods_addr);
for(uint32_t i=0;i<mb_info->mods_count;i++) {
markUsed((void*)((uintptr_t)(&mods[i])&(~0xFFF)),4096); //Mark all of the module table as used
markUsed((void*)(uintptr_t)(mods[i].mod_start),mods[i].mod_end-mods[i].mod_start);
}
}
}

View file

@ -0,0 +1,71 @@
#include <stdint.h>
#include <base.hpp>
#include <pmm3.hpp>
#include <multiboot.h>
extern "C" const int kernel_start;
extern "C" const int kernel_end; //those are voids actually
namespace MTGosHAL {
PMM3::PMM3() {}
auto PMM3::init(struct multiboot_info * mb_info) -> void {
for(int i=0;i<0x8000;i++)
bitmap[i]=0;
struct multiboot_mmap_entry* mmap = (struct multiboot_mmap_entry*) (uintptr_t)(mb_info->mmap_addr);
struct multiboot_mmap_entry* mmap_end = (struct multiboot_mmap_entry*) ((uintptr_t) mb_info->mmap_addr + mb_info->mmap_length);
while (mmap < mmap_end) {
if (mmap->type == 1) {
// Memory is free
uintptr_t addr = mmap->addr;
uintptr_t end_addr = addr + mmap->len;
while (addr < end_addr) {
*this << (void*) addr;
addr += 0x200000;
}
}
mmap++;
}
uintptr_t addr = (uintptr_t) &kernel_start;
while(addr < (uintptr_t) &kernel_end) {
markUsed((void*)addr);
addr+=0x200000;
}
markUsed((void*)0);
multiboot_mod_list *mods = (multiboot_mod_list*) (uintptr_t)(mb_info->mods_addr);
for(uint32_t i=0;i<mb_info->mods_count;i++) {
markUsed((void*)((uint64_t)(&mods[i])&(~0x1FFFFF))); //Mark all of the module table as used
for(uint64_t start=(uint64_t)(mods[i].mod_start)&(~0x1FFFFF);start<(uint32_t)(mods[i].mod_end);start+=0x200000) {
markUsed((void*)start); //Protect all multiboot modules
}
}
}
auto PMM3::markUsed(const void * addr) -> void {
uintptr_t address=(uintptr_t)addr;
address>>=21;
int index=address>>5;
int bit=1<<(address&0x1F);
bitmap[index]&=~bit;
}
auto PMM3::operator >> (void * &addr) -> PMM3 & {
for(uintptr_t i=0;i<0x8000;i++) {
if(!bitmap[i])
continue;
for(uintptr_t j=0;j<32;j++) {
if(bitmap[i]&(1<<j)) {
//We found a free page!
bitmap[i]&=~(1<<j);
addr=(void*)(((i<<5)+j)<<21);
return *this;
}
}
}
addr=nullptr;
return *this;
}
auto PMM3::operator << (const void * addr) -> PMM3 & {
uintptr_t address=(uintptr_t)addr;
address>>=21;
int index=address>>5;
int bit=1<<(address&0x1F);
bitmap[index]|=bit;
return *this;
}
}

View file

@ -9,7 +9,7 @@ SECTIONS
*(multiboot)
*(.text)
}
.data ALIGN(4096) : {
.data ALIGN(0x200000) : {
start_ctors = .;
KEEP(*( .init_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
@ -20,12 +20,12 @@ SECTIONS
end_dtors = .;
*(.data)
}
.rodata ALIGN(4096) : {
.rodata ALIGN(0x200000) : {
*(.rodata)
}
.bss ALIGN(4096) : {
.bss ALIGN(0x200000) : {
*(.bss)
}
. = ALIGN(4096);
. = ALIGN(0x200000);
kernel_end = .;
}

View file

@ -3,9 +3,9 @@ SRCS = $(shell find -name '*.cpp' -o -name '*.c')
OBJS = $(addsuffix .o,$(basename $(SRCS)))
CPP = $(PREFIX)g++
CC = $(PREFIX)gcc
ASFLAGS = -m32
CFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -Ic_include/ -ffreestanding -std=c11 -fno-builtin -Werror -nostdlib -g -fpie
CPPFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fpie
ASFLAGS = $(ARCHFLAGS)
CFLAGS = $(ARCHFLAGS) -Wall -fno-stack-protector -nostdinc -Ic_include/ -ffreestanding -std=c11 -fno-builtin -Werror -nostdlib -g -fpie
CPPFLAGS = $(ARCHFLAGS) -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fpie
all: $(OBJS)
%.o: %.cpp

View file

@ -11,7 +11,7 @@ auto load(Elf32_Ehdr* file) -> void* {
return nullptr;
debug << "File is not a valid ELF file!\n";
}
Elf32_Phdr *phdr = (Elf32_Phdr*)((uint32_t)(file->e_phoff)+(uint32_t)file);
Elf32_Phdr *phdr = (Elf32_Phdr*)((uintptr_t)(file->e_phoff)+(uintptr_t)file);
debug << "entry=";
debug << Base::HEXADECIMAL;
debug << (int)file->e_entry;
@ -27,8 +27,8 @@ auto load(Elf32_Ehdr* file) -> void* {
if((start <= file->e_entry) && (file->e_entry < end)) {
debug << "start=";
debug << Base::HEXADECIMAL;
debug << (int)(file->e_entry-start+phdr[i].p_offset+(uint32_t)file);
return (void*) (file->e_entry-start+phdr[i].p_offset+(uint32_t)file); //Calculate _start address
debug << (int)(file->e_entry-start+phdr[i].p_offset+(uintptr_t)file);
return (void*) (file->e_entry-start+phdr[i].p_offset+(uintptr_t)file); //Calculate _start address
}
}
return nullptr;

View file

@ -1,6 +1,10 @@
#ifndef _BASE_HPP
#define _BASE_HPP
#include <stdint.h>
void * operator new (size_t, void * p);
void * operator new[] (size_t, void * p);
void operator delete (void *, void *);
void operator delete[] (void *, void *);
namespace MTGosHAL {
class Output;
class Input;

View file

@ -3,7 +3,7 @@
#include <stdint.h>
namespace MTGosHAL {
struct malloc_t {
uint32_t len;
size_t len;
malloc_t *last;
malloc_t *next;
};
@ -12,7 +12,7 @@ private:
malloc_t *head;
public:
PMM();
auto alloc(uint32_t length) -> void *;
auto alloc(size_t length) -> void *;
auto free(void* ptr) -> bool;
auto markUsed(const void * addr, uint32_t length) -> bool;
auto operator >> (void * &addr) -> PMM &; //alloc

View file

@ -6,6 +6,10 @@
#include <Multitasking.hpp>
#include <blockdev.hpp>
#include <elf.hpp>
void * operator new (size_t, void * p) { return p ; }
void * operator new[] (size_t, void * p) { return p ; }
void operator delete (void *, void *) { }
void operator delete[] (void *, void *) { }
using namespace MTGosHAL;
void pid_null() {
for(;;);

View file

@ -21,7 +21,7 @@ void operator delete[](void* p, size_t size) {
}
namespace MTGosHAL {
auto PMM::alloc(uint32_t length) -> void * {
auto PMM::alloc(size_t length) -> void * {
if(!head) {
//Alloc space for head
if(length+sizeof(malloc_t)<=4096) { //Small optimization. The routine for allocating more than one continuous page is terribly slow.
@ -41,9 +41,9 @@ namespace MTGosHAL {
malloc_t* curr=head;
malloc_t* last=nullptr;
do {
uint32_t loc=(uint32_t)curr+sizeof(malloc_t)+curr->len;
uintptr_t loc=(uintptr_t)curr+sizeof(malloc_t)+curr->len;
if((loc+length+sizeof(malloc_t))<((loc&(~0xFFF))+4096) &&
((!curr->next) || (loc+length+sizeof(malloc_t))<((uint32_t)(curr->next)))) {
((!curr->next) || (loc+length+sizeof(malloc_t))<((uintptr_t)(curr->next)))) {
malloc_t *allocd=(malloc_t *)loc;
allocd->len=length;
allocd->last=curr;
@ -83,9 +83,9 @@ namespace MTGosHAL {
chk--;
do {
if(curr==chk) {
uint32_t start=((uint32_t)chk)&(~0xFFF);
uint32_t end=start+0x1000;
if((((uint32_t)(curr->last)<start)||((uint32_t)(curr->last)>=end))&&(((uint32_t)(curr->next)>=end)||((uint32_t)(curr->next)<start))) {
uintptr_t start=((uintptr_t)chk)&(~0xFFF);
uintptr_t end=start+0x1000;
if((((uintptr_t)(curr->last)<start)||((uintptr_t)(curr->last)>=end))&&(((uintptr_t)(curr->next)>=end)||((uintptr_t)(curr->next)<start))) {
*this << (void*)start;
}
if(curr->last)

View file

@ -15,7 +15,7 @@ void memmove(void* dst, void* src, uint32_t size) {
}
uint32_t strlen(const char* str) {
uint32_t i=0;
char* str2=(char*)((int)str);
char* str2=(char*)((uintptr_t)str);
while(*str2) {
i++;
str2++;

BIN
test.elf

Binary file not shown.

View file

@ -4,9 +4,9 @@ OBJS = $(addsuffix .o,$(basename $(SRCS)))
AS = $(PREFIX)gcc
CPP = $(PREFIX)g++
LD = $(PREFIX)ld
ASFLAGS = -m32
CPPFLAGS = -m32 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fpie
LDFLAGS = -melf_i386 -Ttest.ld
ASFLAGS = $(ARCHFLAGS)
CPPFLAGS = $(ARCHFLAGS) -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fpie
LDFLAGS = -Ttest-$(arch).ld
test.elf: $(OBJS) $(arch)/syscall.o
$(LD) $(LDFLAGS) -o $@ $^

30
user/test-x86_64.ld Normal file
View file

@ -0,0 +1,30 @@
ENTRY(_start)
OUTPUT_FORMAT(elf32-i386)
OUTPUT_ARCH(i386:x86-64)
SECTIONS
{
. = 0x400000;
.text : {
*(.text)
}
.data ALIGN(0x200000) : {
start_ctors = .;
KEEP(*( .init_array ));
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
*(.ctors)
end_ctors = .;
start_dtors = .;
*(.dtors)
end_dtors = .;
*(.data)
*(.got)
}
.rodata ALIGN(0x200000) : {
*(.rodata)
}
.bss ALIGN(0x200000) : {
*(.bss)
}
. = ALIGN(0x200000);
}

View file

@ -13,6 +13,14 @@ void main()
int i;
out.setColor(BGColor::BLUE, FGColor::YELLOW);
for(;;) {
out << arr;
long double a;
long double b=a;
out << a;
a+=0.5;
if(a!=b+0.5)
out << " ";
else
out << "=";
out << a;
}
}

62
user/x86_64/syscall.S Normal file
View file

@ -0,0 +1,62 @@
.global screenout_init
// void * screenout_init(int err);
screenout_init:
mov %rdi, %rax
push %rax
xor %rax, %rax
int $0x30
pop %rcx
ret
.global screenout_out
// void * screenout_out(void* handle, char *str);
screenout_out:
push %rbx
mov %rsi, %rax
mov %rdi, %rbx
push %rax
xor %rax, %rax
inc %rax
int $0x30
pop %rbx
pop %rbx
ret
.global screenout_clear
// void * screenout_clear(void* handle);
screenout_clear:
push %rbx
mov %rdi, %rbx
xor %rax, %rax
inc %rax
inc %rax
int $0x30
pop %rbx
ret
.global screenout_setcolor
// void * screenout_setcolor(void* handle, uint32_t BG, uint32_t FG)
screenout_setcolor:
push %rbx
mov %rdi, %rbx
mov %rsi, %rax
mov %rdx, %rcx
push %rcx
push %rax
mov $3, %rax
int $0x30
pop %rbx
pop %rbx
pop %rbx
ret
.global screenout_destroy
// void * screenout_destroy(void * handle)
screenout_destroy:
push %rbx
mov %rdi, %rbx
xor %rax, %rax
dec %ax
int $0x30
pop %rbx
ret