Added module loading and a fully working module!
This commit is contained in:
parent
e934e2e555
commit
e2a334bb44
17 changed files with 3836 additions and 25 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -8,3 +8,4 @@ mtgos.firm
|
|||
*.elf
|
||||
docs/html/
|
||||
docs/latex/
|
||||
*.class
|
||||
|
|
4
1
Normal file
4
1
Normal file
|
@ -0,0 +1,4 @@
|
|||
WARNING: Image format was not specified for 'mtgos.img' and probing guessed raw.
|
||||
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
|
||||
Specify the 'raw' format explicitly to remove the restrictions.
|
||||
qemu-system-x86_64: -d in_asm: drive with bus=0, unit=0 (index=0) exists
|
2
Makefile
2
Makefile
|
@ -1,5 +1,5 @@
|
|||
all: loader.bin firm.bin
|
||||
|
||||
$(MAKE) -C modules
|
||||
loader.bin:
|
||||
$(MAKE) -C boot
|
||||
mv boot/loader.bin .
|
||||
|
|
|
@ -18,11 +18,15 @@ struct FIRM_sect {
|
|||
struct FIRM_header {
|
||||
char magic[4]; //! Magic "FIRM" string (not-null terminated)
|
||||
int version; //! Version. Currently 1
|
||||
void(*entrypoint)(); //! Address where the processor jumps to after loading
|
||||
void(*entrypoint)(void**); //! Address where the processor jumps to after loading
|
||||
unsigned int reserved[0xD];
|
||||
struct FIRM_sect sections[4]; //! The four internal sections
|
||||
unsigned char RSA2048[0x100]; //! Currently unused
|
||||
}__attribute__((packed));
|
||||
/**
|
||||
* \brief Module table for the kernel (Up to 1024 mods)
|
||||
*/
|
||||
void *modtable[1024];
|
||||
/**
|
||||
* \fn init(int, struct multiboot_info*)
|
||||
* \brief This routine is called by boot.S
|
||||
|
@ -31,6 +35,10 @@ struct FIRM_header {
|
|||
*/
|
||||
void init(int eax, struct multiboot_info* mb_info) {
|
||||
multiboot_module_t *mods = (multiboot_module_t *) mb_info->mods_addr;
|
||||
for(unsigned int i=0;i<mb_info->mods_count;i++) { //Get modules
|
||||
modtable[i]=(void*)mods[i].mod_start;
|
||||
}
|
||||
modtable[mb_info->mods_count]=0;
|
||||
for(unsigned int i=0;i<mb_info->mods_count;i++) {
|
||||
struct FIRM_header *firm=(struct FIRM_header*)(mods[i].mod_start);
|
||||
if((firm->magic[0]!='F')||(firm->magic[1]!='I')||(firm->magic[2]!='R')||(firm->magic[3]!='M'))
|
||||
|
@ -46,18 +54,6 @@ void init(int eax, struct multiboot_info* mb_info) {
|
|||
*to++=*from++;
|
||||
}
|
||||
}
|
||||
const char hw[] = "Hello World!";
|
||||
char* video = (char*) 0xb8000;
|
||||
|
||||
// C-Strings haben ein Nullbyte als Abschluss
|
||||
for (int k = 0; hw[k] != '\0'; k++) {
|
||||
|
||||
// Zeichen i in den Videospeicher kopieren
|
||||
video[k * 2] = hw[k];
|
||||
|
||||
// 0x07 = Hellgrau auf Schwarz
|
||||
video[k * 2 + 1] = 0x07;
|
||||
}
|
||||
firm->entrypoint();
|
||||
firm->entrypoint(modtable); //Jump to kernel
|
||||
}
|
||||
}
|
3563
c_include/elf.h
Normal file
3563
c_include/elf.h
Normal file
File diff suppressed because it is too large
Load diff
|
@ -30,7 +30,7 @@ private:
|
|||
/**
|
||||
* \brief Output of a character (UTF-32)
|
||||
*/
|
||||
virtual auto putChar(int) -> void = 0;
|
||||
virtual auto putChar(int) -> void {}
|
||||
/**
|
||||
* \brief Output of an ASCII-char
|
||||
*/
|
||||
|
@ -40,6 +40,7 @@ private:
|
|||
*/
|
||||
int base=10;
|
||||
public:
|
||||
Output() {}
|
||||
/**
|
||||
* \brief Outputs an generic null-terminated ASCII string
|
||||
*/
|
||||
|
@ -49,6 +50,7 @@ public:
|
|||
*/
|
||||
template <typename T> auto operator<<(T object) -> Output & {
|
||||
puts(object);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
template <>
|
||||
|
|
20
include/modstubs.h
Normal file
20
include/modstubs.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
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 *) { }
|
||||
extern "C" void __cxa_pure_virtual()
|
||||
{
|
||||
// Do nothing or print an error message.
|
||||
}
|
||||
/** \brief beginning of constructor table */
|
||||
extern "C" void(*start_ctors)();
|
||||
/** \brief end of constructor table */
|
||||
extern "C" void(*end_ctors)();
|
||||
/** \brief start of destructor table */
|
||||
extern "C" void(*start_dtors)();
|
||||
/** \brief end of destructor table */
|
||||
extern "C" void(*end_dtors)();
|
||||
void doCtors() {
|
||||
for(void(**i)()=&start_ctors;i<&end_ctors;i++)
|
||||
(*i)(); //Calling constructors
|
||||
}
|
42
include/moduleinterface.h
Normal file
42
include/moduleinterface.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* \brief Contains the possible module types the kernel supports.
|
||||
*/
|
||||
enum class ModType : int {
|
||||
/// Contains nothing
|
||||
none,
|
||||
/// Contains a module for ouputting text
|
||||
output_text,
|
||||
};
|
||||
//Some typedefs to make the code look cleaner.
|
||||
typedef void(**table_type)();
|
||||
typedef ModType(*getType_type)();
|
||||
typedef bool(*spawnAt_type)(void*);
|
||||
typedef size_t(*sizeof_type)();
|
||||
/**
|
||||
* \brief returns the function table (3 entries)
|
||||
*
|
||||
* The function table contains 3 entries in the following order:
|
||||
* ModType getType();
|
||||
* size_t size_of();
|
||||
* bool spawnAt(void*);
|
||||
*/
|
||||
extern "C" table_type getTable();
|
||||
|
||||
/**
|
||||
* \brief returns the type of the module
|
||||
*/
|
||||
auto getType() -> ModType;
|
||||
|
||||
/**
|
||||
* \brief spawns a module at a specified address
|
||||
* returns true if successful
|
||||
*/
|
||||
auto spawnAt(void*) -> bool;
|
||||
|
||||
/**
|
||||
* \brief size of the module object
|
||||
*/
|
||||
auto size_of() -> size_t;
|
|
@ -7,10 +7,10 @@ CC = $(PREFIX)gcc
|
|||
LD = $(PREFIX)g++
|
||||
|
||||
CFLAGS += -m32 -Wall -fno-stack-protector -nostdinc -Ic_include/ -I../c_include -ffreestanding -std=c11 -fno-builtin -Werror -nostdlib -g -fpie
|
||||
CPPFLAGS += -m32 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -I../c_include -I../include -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fno-pie -Wno-reorder
|
||||
CPPFLAGS += -m32 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -I../c_include -I../include -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fno-pie -Wno-reorder -fdump-class-hierarchy
|
||||
LDFLAGS = -nostdlib -nodefaultlibs -nostdlib -fno-builtin $(ARCHFLAGS) -T loader.ld
|
||||
all: $(OBJS)
|
||||
$(LD) $(LDFLAGS) -o mtgos.elf $(OBJS)
|
||||
$(LD) $(LDFLAGS) -o mtgos.elf $(OBJS) -lgcc
|
||||
%.o: %.cpp
|
||||
$(CPP) $(CPPFLAGS) -c -o $@ $^
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#include <stdint.h>
|
||||
#include <moduleinterface.h>
|
||||
#include <elf.h>
|
||||
#include <base/output.hpp>
|
||||
/** \brief beginning of constructor table */
|
||||
extern "C" void(*start_ctors)();
|
||||
/** \brief end of constructor table */
|
||||
|
@ -6,13 +10,49 @@ extern "C" void(*end_ctors)();
|
|||
extern "C" void(*start_dtors)();
|
||||
/** \brief end of destructor table */
|
||||
extern "C" void(*end_dtors)();
|
||||
/**
|
||||
* \function load(Elf32_Ehdr)
|
||||
* \brief returns program entry point
|
||||
*/
|
||||
auto load(Elf32_Ehdr* file) -> void(**(*)(void*))() {
|
||||
if((file->e_ident[0]!=ELFMAG0)||
|
||||
(file->e_ident[1]!=ELFMAG1)||
|
||||
(file->e_ident[2]!=ELFMAG2)||
|
||||
(file->e_ident[3]!=ELFMAG3) ) {
|
||||
return nullptr;
|
||||
}
|
||||
Elf32_Phdr *phdr = (Elf32_Phdr*)((uintptr_t)(file->e_phoff)+(uintptr_t)file);
|
||||
for(int i=0;i<file->e_phnum;i++) {
|
||||
uint32_t start=phdr[i].p_vaddr;
|
||||
uint32_t end=start+phdr[i].p_memsz;
|
||||
if((start <= file->e_entry) && (file->e_entry < end)) {
|
||||
return (void (** (*)(void*))()) (file->e_entry-start+phdr[i].p_offset+(uintptr_t)file); //Calculate _start address
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
MTGos::Base::Output out;
|
||||
/**
|
||||
* \function _start()
|
||||
* \brief Initializes the kernel
|
||||
*/
|
||||
extern "C" void _start() {
|
||||
for(void(**i)()=&start_ctors;i<&end_ctors;i++)
|
||||
(*i)(); //Calling constructors
|
||||
extern "C" void _start(void ** modtable) {
|
||||
//for(void(**i)()=&start_ctors;i<&end_ctors;i++)
|
||||
// (*i)(); //Calling constructors
|
||||
for(int i=0;i<1024;i++) {
|
||||
if(!modtable[i])
|
||||
break;
|
||||
void(**(*fptr)(void*))() = load((Elf32_Ehdr*) modtable[i]);
|
||||
if(!fptr)
|
||||
continue;
|
||||
void(**table)()=fptr(modtable[i]);
|
||||
ModType type=((getType_type)table[0])(); //Get module type
|
||||
if(type!=ModType::output_text)
|
||||
continue;
|
||||
size_t size=((sizeof_type)table[1])(); //Get module size
|
||||
((spawnAt_type)table[2])((void*)&out);
|
||||
out << "HI!\nbye!";
|
||||
}
|
||||
for(void(**i)()=&start_dtors;i<&end_dtors;i++)
|
||||
(*i)(); //Calling destructors
|
||||
for(;;);
|
||||
|
|
19
makeimage.sh
19
makeimage.sh
|
@ -10,9 +10,19 @@ echo "Building..."
|
|||
gmake
|
||||
echo "stripping"
|
||||
strip --strip-debug loader.bin
|
||||
echo "Compressing..."
|
||||
for f in *.elf; do
|
||||
strip --strip-debug $f
|
||||
done
|
||||
echo "Extracting symbols (for bochs)"
|
||||
nm loader.bin | grep " T " | awk '{ print $1" "$3 }' > loader.bin.sym
|
||||
nm mtgos.elf | grep " T " | awk '{ print $1" "$3 }' > mtgos.elf.sym
|
||||
for f in *.elf; do
|
||||
nm $f | grep " T " | awk '{ print $1" "$3 }' > $f.sym
|
||||
done
|
||||
echo "Compressing..."
|
||||
xz -vv9e mtgos.firm
|
||||
for f in *.elf; do
|
||||
xz -vv9e $f
|
||||
done
|
||||
echo "How many kilobytes should the image be?"
|
||||
read length
|
||||
echo "OK. Creating image..."
|
||||
|
@ -32,12 +42,13 @@ sudo mount -t msdosfs /dev/${dev}s1 mount
|
|||
echo "Installing grub... (May take some time)"
|
||||
sudo grub-install --target=i386-pc --boot-directory=mount /dev/$dev --compress=xz --install-modules="normal part_msdos fat multiboot biosdisk xzio" --modules="normal part_msdos fat multiboot biosdisk xzio" --locales="" --force
|
||||
echo "Copying files..."
|
||||
sudo mv loader.bin mtgos.firm mount
|
||||
sudo mv loader.bin mtgos.firm.xz *.elf.xz mount
|
||||
echo "Creating grub.cfg"
|
||||
cat > grub.cfg << "EOF"
|
||||
menuentry "MTGos" {
|
||||
multiboot /loader.bin
|
||||
module /mtgos.firm
|
||||
module /mtgos.firm.xz
|
||||
module /dsp_txt.elf.xz
|
||||
}
|
||||
EOF
|
||||
sudo mv grub.cfg mount/grub
|
||||
|
|
6
modules/Makefile
Normal file
6
modules/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
|||
include ../kernel.settings
|
||||
SUBDIRS = $(arch)
|
||||
all:
|
||||
for dir in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$dir; \
|
||||
done
|
5
modules/x86/Makefile
Normal file
5
modules/x86/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
SUBDIRS = dsp
|
||||
all:
|
||||
for dir in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$dir; \
|
||||
done
|
5
modules/x86/dsp/Makefile
Normal file
5
modules/x86/dsp/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
SUBDIRS = txt
|
||||
all:
|
||||
for dir in $(SUBDIRS); do \
|
||||
$(MAKE) -C $$dir; \
|
||||
done
|
26
modules/x86/dsp/txt/Makefile
Normal file
26
modules/x86/dsp/txt/Makefile
Normal 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
|
||||
LD = $(PREFIX)g++
|
||||
|
||||
CFLAGS += -m32 -Wall -fno-stack-protector -nostdinc -Ic_include/ -I../../../../c_include -ffreestanding -std=c11 -fno-builtin -Werror -nostdlib -g -fpic
|
||||
CPPFLAGS += -m32 -Wall -fno-stack-protector -nostdinc -std=c++14 -Iinclude/ -Ic_include/ -I../../../../c_include -I../../../../include -fno-rtti -fno-exceptions -ffreestanding -fno-builtin -Werror -nostdlib -fno-use-cxa-atexit -Wextra -Wno-unused -g -fpic -Wno-reorder -fdump-class-hierarchy
|
||||
LDFLAGS = -nostdlib -nodefaultlibs -nostdlib -fno-builtin $(ARCHFLAGS) -T ../../link.ld
|
||||
all: $(OBJS)
|
||||
$(LD) $(LDFLAGS) -o ../../../../dsp_txt.elf $(OBJS) -lgcc
|
||||
%.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
|
67
modules/x86/dsp/txt/init.cpp
Normal file
67
modules/x86/dsp/txt/init.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
#include <moduleinterface.h>
|
||||
#include <base/output.hpp>
|
||||
#include <modstubs.h>
|
||||
int x=0,y=0;
|
||||
uint16_t* vmem = (uint16_t*)0xB8000;
|
||||
namespace MTGos {
|
||||
namespace {
|
||||
/**
|
||||
* \class Screen
|
||||
* \brief Text output to the screen
|
||||
*/
|
||||
class Screen: public Base::Output {
|
||||
public:
|
||||
Screen() {}
|
||||
auto scroll() -> void {
|
||||
for(int p=0;p<80*25;p++)
|
||||
vmem[p]=vmem[p+80];
|
||||
for(int p=80*25; p<81*25; p++)
|
||||
vmem[p]=0x0700;
|
||||
y--;
|
||||
}
|
||||
private:
|
||||
virtual auto putChar(int c) -> void{
|
||||
switch(c) {
|
||||
case '\n':
|
||||
x=0; y++;
|
||||
break;
|
||||
case '\r':
|
||||
x=0;
|
||||
break;
|
||||
case '\b':
|
||||
if(x==0)
|
||||
break;
|
||||
x--;
|
||||
putChar(' '),
|
||||
x--;
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
||||
vmem[y*80+(x++)]=((uint16_t)0x0700) | ((uint8_t)c);
|
||||
if(x==80) {
|
||||
x=0; y++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(y>25)
|
||||
scroll();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
void(*tbl[3])()={(void(*)())&getType,(void(*)())&size_of,(void(*)())&spawnAt};
|
||||
table_type getTable() {
|
||||
doCtors();
|
||||
return (void(**)())&tbl;
|
||||
}
|
||||
auto getType() -> ModType {
|
||||
return ModType::output_text;
|
||||
}
|
||||
auto spawnAt(void* pos) -> bool {
|
||||
new(pos) MTGos::Screen;
|
||||
return true;
|
||||
}
|
||||
auto size_of() -> size_t {
|
||||
return sizeof(MTGos::Screen);
|
||||
}
|
23
modules/x86/link.ld
Normal file
23
modules/x86/link.ld
Normal file
|
@ -0,0 +1,23 @@
|
|||
ENTRY(getTable)
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x106000;
|
||||
module_start = .;
|
||||
.text : {
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
start_ctors = .;
|
||||
KEEP(*( .init_array ));
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY( .init_array.* )));
|
||||
*(.ctors)
|
||||
end_ctors = .;
|
||||
start_dtors = .;
|
||||
*(.dtors)
|
||||
end_dtors = .;
|
||||
*(.data)
|
||||
*(.data.*)
|
||||
*(.rodata)
|
||||
*(.bss)
|
||||
}
|
||||
module_end = .;
|
||||
}
|
Loading…
Reference in a new issue