summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md14
-rwxr-xr-xarch/x86/gdt/Gdt.cpp100
-rwxr-xr-xarch/x86/gdt/Gdt.h82
-rw-r--r--arch/x86/gdt/GlobalObj.cpp14
-rw-r--r--arch/x86/gdt/GlobalObj.h10
-rw-r--r--arch/x86/gdt/GoToGdtMemSeg.s13
-rw-r--r--arch/x86/inc/types.h2
-rwxr-xr-xkernel/GlobalConstruct.cpp14
-rwxr-xr-xkernel/GlobalConstruct.h14
-rw-r--r--kernel/kernel.c17
-rw-r--r--kernel/linker.ld1
-rw-r--r--makefile13
12 files changed, 276 insertions, 18 deletions
diff --git a/README.md b/README.md
index b7d31cf..9736ee0 100644
--- a/README.md
+++ b/README.md
@@ -11,15 +11,21 @@ sudo apt update -y
sudo apt -y install build-essential binutils nasm xorriso grub-common qemu-system-i386 mtools
```
+Need build GCC cross compiler for i686 architecture to compile project sources.
+Refer to GCC documentation for detailed information - <https://gcc.gnu.org/install/>
+
## Build and run
#### Ubuntu
+Build and run release version
+```sh
+make all
+```
+
+Build and run debug version
```sh
-# Build and create iso image
-make install
-# Run emulator
-make run
+make DEBUG=true all
```
## Docs
diff --git a/arch/x86/gdt/Gdt.cpp b/arch/x86/gdt/Gdt.cpp
new file mode 100755
index 0000000..63c70ef
--- /dev/null
+++ b/arch/x86/gdt/Gdt.cpp
@@ -0,0 +1,100 @@
+#include "Gdt.h"
+
+
+DescSeg32::DescSeg32(uint32 base, uint32 limit, uint8 access, uint8 flags)
+{
+ this->baseLow = base & 0x0000FFFF;
+ this->baseMiddle = (base & 0x00FF0000) >> 16;
+ this->baseHight = (base & 0xFF000000) >> 24;
+
+ this->limitLow = limit & 0x0000FFFF;
+ this->limitMiddle = (limit & 0x000F0000) >> 16;
+
+ this->access = access;
+ this->flags = flags & 0x000E;
+};
+
+uint64 DescSeg32::getDescriptor()
+{
+ uint64 descriptor = 0;
+
+ descriptor |= (uint64)limitLow;
+ descriptor |= (uint64)baseLow << 16;
+ descriptor |= (uint64)baseMiddle << 32;
+ descriptor |= (uint64)access << 40;
+ descriptor |= (uint64)limitMiddle << 48;
+ descriptor |= (uint64)flags << 52;
+ descriptor |= (uint64)baseHight << 56;
+
+ return descriptor;
+};
+
+uint64 DescSeg32::flatCodeKernel()
+{
+ return DescSeg32(0, 0xFFFFF, CODE_ER | PRESENT | NSYSTEMSEG
+ , PAGEGRAN | HIGHSIZE).getDescriptor();
+};
+
+uint64 DescSeg32::flatDataKernel()
+{
+ return DescSeg32(0, 0xFFFFF, DATA_RW | PRESENT | NSYSTEMSEG
+ , PAGEGRAN | HIGHSIZE).getDescriptor();
+}
+
+uint64 DescSeg32::flatCodeUser()
+{
+
+ return DescSeg32(0, 0xFFFFF, CODE_ER | PRESENT | NSYSTEMSEG | USER
+ , PAGEGRAN | HIGHSIZE).getDescriptor();
+};
+
+uint64 DescSeg32::flatDataUser()
+{
+
+ return DescSeg32(0, 0xFFFFF, DATA_RW | PRESENT | NSYSTEMSEG | USER
+ , PAGEGRAN | HIGHSIZE).getDescriptor();
+};
+
+MngGdt::MngGdt()
+{
+ this->gdt[0] = 0;
+ currIdx = 1;
+ isGdtLoaded = 0;
+};
+
+bool MngGdt::addDescriptor(uint64 desc)
+{
+ if(currIdx >= size || currIdx == 0)
+ {
+ return false;
+ }
+
+ this->gdt[currIdx++] = desc;
+ return true;
+};
+
+bool MngGdt::loadGdt()
+{
+ if(isGdtLoaded)
+ {
+ return false;
+ }
+
+ uint64 pointer = 0;
+ uint16 size = sizeof(uint64) * this->size - 1;
+ uint16 offset = (uint32)((void *)(&gdt));
+
+ pointer |= offset;
+ pointer <<= 16;
+ pointer |= size;
+
+ GOTOGDTMEMSEG(pointer);
+
+ isGdtLoaded = 1;
+ return true;
+};
+
+bool MngGdt::getIsGdtLoaded()
+{
+ return isGdtLoaded;
+};
diff --git a/arch/x86/gdt/Gdt.h b/arch/x86/gdt/Gdt.h
new file mode 100755
index 0000000..e3d48a3
--- /dev/null
+++ b/arch/x86/gdt/Gdt.h
@@ -0,0 +1,82 @@
+#ifndef GDT_H
+#define GDT_H
+
+#include "../inc/types.h"
+
+
+// Define access options
+#define PRESENT (1 << 7) // Present bit
+#define USER (3 << 5) // Descriptor privelege level
+#define NSYSTEMSEG (1 << 4) // Descriptor type
+#define EXEC (1 << 3) // Executable bit
+#define GROWDOWN (1 << 2) // Direction bit
+#define WRITABLE (1 << 1) // Readable/Writable bit
+#define ACCESSED 1 // Accessed bit
+
+// Define flags byte
+#define PAGEGRAN (1 << 3) // Granularity flag
+#define HIGHSIZE (1 << 2) // Size flag
+#define LONGMODEON (1 << 1) // Long-mode flag
+
+// Set of segment descriptors assign acesses bits
+#define DATA_RO 0x00 // data seg, grows up, read only, not accessed
+#define DATA_ROA 0x01 // data seg, grows up, read only, accessed
+#define DATA_RW 0x02 // data seg, grows up, read/write, not accessed
+#define DATA_RWA 0x03 // data seg, grows up, read/write, accessed
+#define DATA_ROD 0x04 // data seg, grows down, read only, not accessed
+#define DATA_RODGA 0x05 // data seg, grows down, read only, accessed
+#define DATA_RWD 0x06 // data seg, grows down, read/write, not accessed
+#define DATA_RWDA 0x07 // data seg, grows down, read/write, accessed
+#define CODE_EO 0x08 // code seg, conforming, execute only, not accessed
+#define CODE_EOA 0x09 // code seg, conforming, execute only, accessed
+#define CODE_ER 0x0A // code seg, conforming, execute/read, not accessed
+#define CODE_ERA 0x0B // code seg, conforming, execute/read, accessed
+#define CODE_EONC 0x0C // code seg, not conforming, execute only, not accessed
+#define CODE_EONCA 0x0D // code seg, not conforming, execute only, accessed
+#define CODE_ERNC 0x0E // code seg, not conforming, execute/read, not accessed
+#define CODE_ERNCA 0x0F // code seg, not conforming, execute/read, accessed
+
+class DescSeg32 // Segment descriptor
+{
+ private:
+ uint16 limitLow;
+ uint16 baseLow;
+ uint8 baseMiddle;
+ uint8 access;
+ uint8 limitMiddle; // one word limit value 19:16
+ uint8 flags; // one word located 55:52 bits in descriptor
+ uint8 baseHight;
+ public:
+ DescSeg32(uint32 base, uint32 limit, uint8 access, uint8 flags);
+ void setDescriptor(uint32 base, uint32 limit, uint8 access, uint8 flags);
+ uint64 getDescriptor();
+ static uint64 flatCodeKernel();
+ static uint64 flatDataKernel();
+ static uint64 flatCodeUser();
+ static uint64 flatDataUser();
+} __attribute__((packed));
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern void GOTOGDTMEMSEG(uint64 pointer);
+#ifdef __cplusplus
+};
+#endif
+
+class MngGdt
+{
+ private:
+ const static uint8 size = 10;
+ static uint64 gdt[size];
+ uint8 currIdx;
+ bool isGdtLoaded;
+
+ public:
+ MngGdt();
+ bool addDescriptor(uint64 desc); // 0 - not set descriptor, 1 - set
+ bool loadGdt(); // 0 - if GDT is not loaded, 1 - loaded
+ bool getIsGdtLoaded();
+};
+
+#endif
diff --git a/arch/x86/gdt/GlobalObj.cpp b/arch/x86/gdt/GlobalObj.cpp
new file mode 100644
index 0000000..5832c11
--- /dev/null
+++ b/arch/x86/gdt/GlobalObj.cpp
@@ -0,0 +1,14 @@
+#include "GlobalObj.h"
+
+
+uint64 MngGdt::gdt[MngGdt::size];
+
+MngGdt mngGdt;
+
+void mngGdtInit()
+{
+ if(!mngGdt.getIsGdtLoaded())
+ {
+ mngGdt = MngGdt();
+ }
+};
diff --git a/arch/x86/gdt/GlobalObj.h b/arch/x86/gdt/GlobalObj.h
new file mode 100644
index 0000000..563a2a9
--- /dev/null
+++ b/arch/x86/gdt/GlobalObj.h
@@ -0,0 +1,10 @@
+#ifndef GDTGLOBALOBJ_H
+#define GDTGLOBALOBJ_H
+#include "../inc/types.h"
+#include "Gdt.h"
+
+extern MngGdt mngGdt;
+
+void mngGdtInit();
+
+#endif
diff --git a/arch/x86/gdt/GoToGdtMemSeg.s b/arch/x86/gdt/GoToGdtMemSeg.s
new file mode 100644
index 0000000..2b5dd62
--- /dev/null
+++ b/arch/x86/gdt/GoToGdtMemSeg.s
@@ -0,0 +1,13 @@
+global GOTOGDTMEMSEG
+GOTOGDTMEMSEG:
+ lgdt [esp + 4]
+ jmp 0x08:.reloadCS
+.reloadCS:
+ mov ax, 0x10
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+ ret
+.end:
diff --git a/arch/x86/inc/types.h b/arch/x86/inc/types.h
index d688a35..1ec71f3 100644
--- a/arch/x86/inc/types.h
+++ b/arch/x86/inc/types.h
@@ -1,3 +1,5 @@
+#define NULL 0
+
typedef unsigned char uint8;
typedef unsigned int uint16;
diff --git a/kernel/GlobalConstruct.cpp b/kernel/GlobalConstruct.cpp
new file mode 100755
index 0000000..dc0a83a
--- /dev/null
+++ b/kernel/GlobalConstruct.cpp
@@ -0,0 +1,14 @@
+#include "GlobalConstruct.h"
+
+void GlobalConstruct::terminalInit()
+{
+ display = VGADisplay();
+};
+
+void GlobalConstruct::gdtInit()
+{
+ mngGdtInit();
+ mngGdt.addDescriptor(DescSeg32::flatCodeKernel());
+ mngGdt.addDescriptor(DescSeg32::flatDataKernel());
+ mngGdt.loadGdt();
+};
diff --git a/kernel/GlobalConstruct.h b/kernel/GlobalConstruct.h
new file mode 100755
index 0000000..2b0a675
--- /dev/null
+++ b/kernel/GlobalConstruct.h
@@ -0,0 +1,14 @@
+#ifndef GLOBALCONSTRUCT_H
+#define GLOBALCONSTRUCT_H
+
+#include "../arch/x86/io/GlobalObj.h"
+#include "../arch/x86/gdt/GlobalObj.h"
+
+class GlobalConstruct
+{
+ public:
+ static void terminalInit();
+ static void gdtInit();
+};
+
+#endif
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 9a901b1..59caf0a 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -1,22 +1,13 @@
-#ifdef __cplusplus
-extern "C" {
-#endif
-
+#include "GlobalConstruct.h"
#include "../arch/x86/io/GlobalObj.h"
#include "../arch/x86/inc/TypeConverter.h"
void main()
{
- VGADisplay d;
- IntConverter conv;
+ GlobalConstruct::terminalInit();
+ GlobalConstruct::gdtInit();
- unsigned int i = 124;
+ display << "Hello, World!";
- d << conv.intToChar(i);
- d << "Hello, world!\tHello, world!";
- for(int i = 0; i < 10; i++)d << "\tHello!";
};
-#ifdef __cplusplus
-};
-#endif
diff --git a/kernel/linker.ld b/kernel/linker.ld
index d5ee742..ae4d98d 100644
--- a/kernel/linker.ld
+++ b/kernel/linker.ld
@@ -12,6 +12,7 @@ SECTIONS
{
*(.text)
*(.eh_frame)
+ *(.ctors)
}
.rodata BLOCK(4K) : ALIGN(4k)
diff --git a/makefile b/makefile
index 71a7a6c..ab744ff 100644
--- a/makefile
+++ b/makefile
@@ -5,6 +5,7 @@ ASM = nasm
CFLAGS = -c -m32 -Wall -ffreestanding -nostdinc -nostdlib -lgcc
AFLAGS = -f elf32
LDFLAGS = -m elf_i386
+QEMUFLAGS =
CFILES = $(shell find ./ -type f \( -name \*.cpp -o -name \*.c \))
AFILES = $(shell find ./ -type f \( -iname \*.s -o -name \*.asm \))
@@ -12,12 +13,20 @@ LDFILE = $(shell find ./ -type f -name *.ld)
SOURCE_FILES = $(CFILES) $(AFILES)
OBJ_FILES = $(addprefix $(BDIR)/, $(addsuffix .o, $(basename $(SOURCE_FILES))))
+ifeq ($(DEBUG), true)
+ CFLAGS := -g3 $(CFLAGS)
+ AFLAGS := -g $(AFLAGS)
+ QEMUFLAGS := -s -S $(QEMUFLAGS)
+endif
+
OS_BINARY = $(BDIR)/kernel.bin
BDIR = ./build
.PHONY: install $(SOURCE_FILES)
build: startbuild $(SOURCE_FILES)
+ echo $(AFLAGS)
+ echo $(CFLAGS)
@echo "Link object files..."
$(LD) $(LDFLAGS) -o $(OS_BINARY) -T $(LDFILE) $(OBJ_FILES)
@echo "Project was built"
@@ -45,4 +54,6 @@ clean:
rm -rf ./iso/os/kernel.bin
run:
- qemu-system-i386 -cdrom ./$(BDIR)/kernel.iso
+ qemu-system-i386 $(QEMUFLAGS) -cdrom ./$(BDIR)/kernel.iso
+
+all: clean build install run