diff options
| author | Alexey Gavrilov <rebovas@yahoo.com> | 2023-11-04 10:09:44 +0700 |
|---|---|---|
| committer | Alexey Gavrilov <rebovas@yahoo.com> | 2023-11-04 10:09:44 +0700 |
| commit | c18781e37e6bfe153e7c0f2bc8b04df0aecf151d (patch) | |
| tree | 42bb0e00e58ccf85aa3b93c20347d4939464066e | |
| parent | a93807ad337dd982c49f898cd5205d2b028f365d (diff) | |
Support for GDT has been written + add makefile debug mode
| -rw-r--r-- | README.md | 14 | ||||
| -rwxr-xr-x | arch/x86/gdt/Gdt.cpp | 100 | ||||
| -rwxr-xr-x | arch/x86/gdt/Gdt.h | 82 | ||||
| -rw-r--r-- | arch/x86/gdt/GlobalObj.cpp | 14 | ||||
| -rw-r--r-- | arch/x86/gdt/GlobalObj.h | 10 | ||||
| -rw-r--r-- | arch/x86/gdt/GoToGdtMemSeg.s | 13 | ||||
| -rw-r--r-- | arch/x86/inc/types.h | 2 | ||||
| -rwxr-xr-x | kernel/GlobalConstruct.cpp | 14 | ||||
| -rwxr-xr-x | kernel/GlobalConstruct.h | 14 | ||||
| -rw-r--r-- | kernel/kernel.c | 17 | ||||
| -rw-r--r-- | kernel/linker.ld | 1 | ||||
| -rw-r--r-- | makefile | 13 |
12 files changed, 276 insertions, 18 deletions
@@ -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) @@ -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 |
