Added module loading and a fully working module!

This commit is contained in:
Morten Delenk 2016-08-02 21:27:44 +02:00
parent e934e2e555
commit e2a334bb44
No known key found for this signature in database
GPG key ID: 3F818D0F65DCB490
17 changed files with 3836 additions and 25 deletions

1
.gitignore vendored
View file

@ -8,3 +8,4 @@ mtgos.firm
*.elf *.elf
docs/html/ docs/html/
docs/latex/ docs/latex/
*.class

4
1 Normal file
View 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

View file

@ -1,5 +1,5 @@
all: loader.bin firm.bin all: loader.bin firm.bin
$(MAKE) -C modules
loader.bin: loader.bin:
$(MAKE) -C boot $(MAKE) -C boot
mv boot/loader.bin . mv boot/loader.bin .

View file

@ -18,11 +18,15 @@ struct FIRM_sect {
struct FIRM_header { struct FIRM_header {
char magic[4]; //! Magic "FIRM" string (not-null terminated) char magic[4]; //! Magic "FIRM" string (not-null terminated)
int version; //! Version. Currently 1 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]; unsigned int reserved[0xD];
struct FIRM_sect sections[4]; //! The four internal sections struct FIRM_sect sections[4]; //! The four internal sections
unsigned char RSA2048[0x100]; //! Currently unused unsigned char RSA2048[0x100]; //! Currently unused
}__attribute__((packed)); }__attribute__((packed));
/**
* \brief Module table for the kernel (Up to 1024 mods)
*/
void *modtable[1024];
/** /**
* \fn init(int, struct multiboot_info*) * \fn init(int, struct multiboot_info*)
* \brief This routine is called by boot.S * \brief This routine is called by boot.S
@ -31,6 +35,10 @@ struct FIRM_header {
*/ */
void init(int eax, struct multiboot_info* mb_info) { void init(int eax, struct multiboot_info* mb_info) {
multiboot_module_t *mods = (multiboot_module_t *) mb_info->mods_addr; 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++) { for(unsigned int i=0;i<mb_info->mods_count;i++) {
struct FIRM_header *firm=(struct FIRM_header*)(mods[i].mod_start); 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')) 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++; *to++=*from++;
} }
} }
const char hw[] = "Hello World!"; firm->entrypoint(modtable); //Jump to kernel
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();
} }
} }

3563
c_include/elf.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -30,7 +30,7 @@ private:
/** /**
* \brief Output of a character (UTF-32) * \brief Output of a character (UTF-32)
*/ */
virtual auto putChar(int) -> void = 0; virtual auto putChar(int) -> void {}
/** /**
* \brief Output of an ASCII-char * \brief Output of an ASCII-char
*/ */
@ -40,6 +40,7 @@ private:
*/ */
int base=10; int base=10;
public: public:
Output() {}
/** /**
* \brief Outputs an generic null-terminated ASCII string * \brief Outputs an generic null-terminated ASCII string
*/ */
@ -49,6 +50,7 @@ public:
*/ */
template <typename T> auto operator<<(T object) -> Output & { template <typename T> auto operator<<(T object) -> Output & {
puts(object); puts(object);
return *this;
} }
}; };
template <> template <>

20
include/modstubs.h Normal file
View 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
View 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;

View file

@ -7,10 +7,10 @@ CC = $(PREFIX)gcc
LD = $(PREFIX)g++ LD = $(PREFIX)g++
CFLAGS += -m32 -Wall -fno-stack-protector -nostdinc -Ic_include/ -I../c_include -ffreestanding -std=c11 -fno-builtin -Werror -nostdlib -g -fpie 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 LDFLAGS = -nostdlib -nodefaultlibs -nostdlib -fno-builtin $(ARCHFLAGS) -T loader.ld
all: $(OBJS) all: $(OBJS)
$(LD) $(LDFLAGS) -o mtgos.elf $(OBJS) $(LD) $(LDFLAGS) -o mtgos.elf $(OBJS) -lgcc
%.o: %.cpp %.o: %.cpp
$(CPP) $(CPPFLAGS) -c -o $@ $^ $(CPP) $(CPPFLAGS) -c -o $@ $^

View file

@ -1,3 +1,7 @@
#include <stdint.h>
#include <moduleinterface.h>
#include <elf.h>
#include <base/output.hpp>
/** \brief beginning of constructor table */ /** \brief beginning of constructor table */
extern "C" void(*start_ctors)(); extern "C" void(*start_ctors)();
/** \brief end of constructor table */ /** \brief end of constructor table */
@ -6,13 +10,49 @@ extern "C" void(*end_ctors)();
extern "C" void(*start_dtors)(); extern "C" void(*start_dtors)();
/** \brief end of destructor table */ /** \brief end of destructor table */
extern "C" void(*end_dtors)(); 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() * \function _start()
* \brief Initializes the kernel * \brief Initializes the kernel
*/ */
extern "C" void _start() { extern "C" void _start(void ** modtable) {
for(void(**i)()=&start_ctors;i<&end_ctors;i++) //for(void(**i)()=&start_ctors;i<&end_ctors;i++)
(*i)(); //Calling constructors // (*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++) for(void(**i)()=&start_dtors;i<&end_dtors;i++)
(*i)(); //Calling destructors (*i)(); //Calling destructors
for(;;); for(;;);

View file

@ -10,9 +10,19 @@ echo "Building..."
gmake gmake
echo "stripping" echo "stripping"
strip --strip-debug loader.bin 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 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?" echo "How many kilobytes should the image be?"
read length read length
echo "OK. Creating image..." echo "OK. Creating image..."
@ -32,12 +42,13 @@ sudo mount -t msdosfs /dev/${dev}s1 mount
echo "Installing grub... (May take some time)" 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 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..." echo "Copying files..."
sudo mv loader.bin mtgos.firm mount sudo mv loader.bin mtgos.firm.xz *.elf.xz mount
echo "Creating grub.cfg" echo "Creating grub.cfg"
cat > grub.cfg << "EOF" cat > grub.cfg << "EOF"
menuentry "MTGos" { menuentry "MTGos" {
multiboot /loader.bin multiboot /loader.bin
module /mtgos.firm module /mtgos.firm.xz
module /dsp_txt.elf.xz
} }
EOF EOF
sudo mv grub.cfg mount/grub sudo mv grub.cfg mount/grub

6
modules/Makefile Normal file
View 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
View file

@ -0,0 +1,5 @@
SUBDIRS = dsp
all:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir; \
done

5
modules/x86/dsp/Makefile Normal file
View file

@ -0,0 +1,5 @@
SUBDIRS = txt
all:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir; \
done

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
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

View 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
View 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 = .;
}