From d3ba3c1d2aedecceceb6c4f3e4a72fd1679bbb93 Mon Sep 17 00:00:00 2001 From: Nathan Date: Wed, 1 Jul 2020 15:47:56 -0500 Subject: [PATCH] Wrote proper Makefile --- .gitignore | 9 +- Makefile | 26 ++++ README.md | 0 src/Makefile | 16 --- src/addressspace.cpp | 27 ++++ src/addressspace.h | 36 ++++++ src/bitmap.h | 0 src/buddyallocator.cpp | 221 ++++++++++++++++++++++++++++++++ src/buddyallocator.h | 94 ++++++++++++++ src/cstring.cpp | 0 src/cstring.h | 0 src/entry.S | 26 +++- src/error.cpp | 0 src/error.h | 0 src/errortype.h | 0 src/linker.ld | 36 ++++++ src/math.cpp | 0 src/math.h | 0 src/memoryallocator.h | 58 +++++++++ src/multiboot2header.S | 0 src/pagetableentry.cpp | 0 src/pagetableentry.h | 0 src/physicalmemoryallocator.cpp | 202 ----------------------------- src/physicalmemoryallocator.h | 90 ------------- src/quarkkernel.cpp | 19 ++- src/tty.cpp | 125 ++++++++++++++++++ src/tty.h | 35 +++++ 27 files changed, 701 insertions(+), 319 deletions(-) mode change 100644 => 100755 .gitignore create mode 100644 Makefile mode change 100644 => 100755 README.md delete mode 100644 src/Makefile create mode 100644 src/addressspace.cpp create mode 100755 src/addressspace.h mode change 100644 => 100755 src/bitmap.h create mode 100755 src/buddyallocator.cpp create mode 100755 src/buddyallocator.h mode change 100644 => 100755 src/cstring.cpp mode change 100644 => 100755 src/cstring.h mode change 100644 => 100755 src/entry.S mode change 100644 => 100755 src/error.cpp mode change 100644 => 100755 src/error.h mode change 100644 => 100755 src/errortype.h create mode 100755 src/linker.ld mode change 100644 => 100755 src/math.cpp mode change 100644 => 100755 src/math.h create mode 100755 src/memoryallocator.h mode change 100644 => 100755 src/multiboot2header.S mode change 100644 => 100755 src/pagetableentry.cpp mode change 100644 => 100755 src/pagetableentry.h delete mode 100644 src/physicalmemoryallocator.cpp delete mode 100644 src/physicalmemoryallocator.h mode change 100644 => 100755 src/quarkkernel.cpp create mode 100644 src/tty.cpp create mode 100644 src/tty.h diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 index 50372c5..d0b6b8e --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ -bin/qkernel -bin/*.o -bin/*~ \ No newline at end of file +bin/* +src/*.o +quark.iso +src/*~ +*~ +rootfs \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..77f81a1 --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +objs = src/addressspace.o src/tty.o src/buddyallocator.o src/math.o \ + src/cstring.o src/error.o src/pagetableentry.o src/multiboot2header.o\ + src/entry.o src/quarkkernel.o +link_script = src/linker.ld +quark_bin = qkernel +quark_img = quark.iso + +CXX = i686-elf-g++ +CC = i686-elf-gcc + +CPPFLAGS = -ffreestanding -O2 -Wall -fno-exceptions -fno-rtti -ggdb + +.PHONY: all +all: $(quark_img) + +$(quark_img): bin/$(quark_bin) + cp bin/$(quark_bin) rootfs/apps + grub-mkrescue -o $@ rootfs + +bin/$(quark_bin): $(objs) + mkdir -p bin/ + $(CXX) -o $@ -T $(link_script) -ffreestanding -nostdlib -O0 $^ -lgcc + +.PHONY: clean +clean: + rm -f $(objs) bin/$(quark_bin) $(quark_img) diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/src/Makefile b/src/Makefile deleted file mode 100644 index 82cf391..0000000 --- a/src/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -objs = math.o cstring.o error.o pagetableentry.o physicalmemoryallocator.o multiboot2header.o entry.o quarkkernel.o -link_script = linker.ld -quark_bin = qkernel - -CXX = i686-elf-g++ -CC = i686-elf-gcc - -CPPFLAGS += -ffreestanding -O2 -Wall -Wextra -fno-exceptions -fno-rtti - -all: $(objs) - echo $(PATH) - i686-elf-g++ -o $(quark_bin) -T $(link_script) -ffreestanding -nostdlib -O2 $(objs) -lgcc - -clean: - rm *.o - rm -f $(quark_bin) diff --git a/src/addressspace.cpp b/src/addressspace.cpp new file mode 100644 index 0000000..a62b903 --- /dev/null +++ b/src/addressspace.cpp @@ -0,0 +1,27 @@ +#include "addressspace.h" + +qkernel::AddressSpace::AddressSpace(MemoryAllocator& malloc) + : malloc(malloc) +{ + this->pageTables = (PageTableEntry*) 0xFFC00000; +} + +void* qkernel::AddressSpace::mmap(void* start, size_t length) +{ + +} + +void qkernel::AddressSpace::munmap(void* start, size_t length) +{ + +} + +void* qkernel::AddressSpace::getPhysicalAddress(void* virtualAddress) const +{ + size_t index = (size_t) virtualAddress / 4096; + PageTableEntry pte = pageTables[index]; + if(pte.getPresent()) + return (void*) pte.getPhysicalAddress(); + else + return (void*) 0; +} diff --git a/src/addressspace.h b/src/addressspace.h new file mode 100755 index 0000000..276a6c7 --- /dev/null +++ b/src/addressspace.h @@ -0,0 +1,36 @@ +#ifndef SRC_ADDRESSSPACE_H_ +#define SRC_ADDRESSSPACE_H_ + +#include + +#include "memoryallocator.h" +#include "pagetableentry.h" + +namespace qkernel { + +class AddressSpace { +public: + + AddressSpace(MemoryAllocator& malloc); + + void* mmap(void* start, size_t length); + + void munmap(void* start, size_t length); + + void* getPhysicalAddress(void* virtualAddress) const; + +private: + + MemoryAllocator& malloc; + + /** + * Array of 1024 page tables, each containing 1024 entries. + * The last table represents the page directory. + */ + PageTableEntry* pageTables; + +}; + +} /* namespace qkernel */ + +#endif diff --git a/src/bitmap.h b/src/bitmap.h old mode 100644 new mode 100755 diff --git a/src/buddyallocator.cpp b/src/buddyallocator.cpp new file mode 100755 index 0000000..a2462b0 --- /dev/null +++ b/src/buddyallocator.cpp @@ -0,0 +1,221 @@ +#include "buddyallocator.h" +#include "math.h" + +#define roundUp(n, m) ((n % m == 0) ? n : (n + m - (n % m))) + +qkernel::BuddyAllocator::BuddyAllocator() +{ + +} + +qkernel::BuddyAllocator::BuddyAllocator(void* heapLocation, char* bitmap, size_t blockSize, size_t blockCount, size_t treeHeight) +{ + this->heapLocation = heapLocation; + this->bitmap = bitmap; + this->blockSize = blockSize; + this->blockCount = blockCount; + this->treeHeight = treeHeight; + for(size_t i = 0; i <= treeHeight; i++) + { + for(size_t j = 0; j < (blockCount >> i); j++) + { + if(i < treeHeight) + reserveNode(i, j); + else + freeNode(i, j); + } + } +} + +void* qkernel::BuddyAllocator::allocate(size_t size) +{ + size_t height = ilog2(roundUp(size, blockSize) / blockSize, true); + if(height > treeHeight) // Requested block size is greater than maximum + { + return NULL; + } + else + { + size_t index = findFreeBlock(height); + if(index == INVALID) // Failed to find a big enough free block; out of memory + { + return NULL; + } + else + { + reserveNode(height, index); + return nodeToAddress(height, index); + } + } +} + +void qkernel::BuddyAllocator::free(void* location, size_t size) +{ + size_t height = ilog2(roundUp(size, blockSize) / blockSize, true); + if(height <= treeHeight) + { + size_t index = addressToNode(height, location); + freeNode(height, index); + if(isFree(height, getBuddy(index))) + { + merge(height, index); + } + } +} + +size_t qkernel::BuddyAllocator::freeBlocks() const +{ + size_t count = 0; + for(int j = 0; j < blockCount; j++) + { + if(isFree(0, j)) + { + count++; + } + } + return count; +} + +size_t qkernel::BuddyAllocator::maxAllocationSize() const +{ + for(int i = treeHeight; i >= 0; i--) + { + for(int j = 0; j < (blockCount >> i); j++) + { + if(isFree(i, j)) + { + return 1 << i; + } + } + } + return 0; +} + +size_t qkernel::BuddyAllocator::getBlockSize() const +{ + return blockSize; +} + +size_t qkernel::BuddyAllocator::getHeapSize() const +{ + return blockCount; +} + +void* qkernel::BuddyAllocator::getHeapLocation() const +{ + return heapLocation; +} + +size_t qkernel::BuddyAllocator::findFreeBlock(size_t height) +{ + for(int i = 0; i < (blockCount >> height); i++) + { + if(isFree(height, i)) + { + return i; + } + } + if(height < treeHeight) + { + size_t parentIndex = findFreeBlock(height + 1); + if(parentIndex != INVALID) + { + return split(height + 1, parentIndex); + } + } + return INVALID; +} + +size_t qkernel::BuddyAllocator::split(size_t height, size_t index) +{ + if(height > 0 && isFree(height, index)) + { + reserveNode(height, index); + freeNode(height - 1, getChild(index)); + freeNode(height - 1, getBuddy(getChild(index))); + return getChild(index); + } + else + { + return INVALID; + } +} + +size_t qkernel::BuddyAllocator::merge(size_t height, size_t index) +{ + if(isFree(height, index) && isFree(height, getBuddy(index)) && height < treeHeight) + { + reserveNode(height, index); + reserveNode(height, getBuddy(index)); + freeNode(height + 1, getParent(index)); + if((height + 1) < treeHeight) + { + if(isFree(height + 1, getBuddy(getParent(index)))) + { + return merge(height + 1, getParent(index)); + + } + } + return getParent(index); + } + else + { + return INVALID; + } +} + +size_t qkernel::BuddyAllocator::getBuddy(size_t index) +{ + return index ^ 1; +} + +size_t qkernel::BuddyAllocator::getParent(size_t index) +{ + return index / 2; +} + +size_t qkernel::BuddyAllocator::getChild(size_t index) +{ + return index * 2; +} + +void* qkernel::BuddyAllocator::nodeToAddress(size_t height, size_t index) const +{ + char* base = (char*) heapLocation; + return reinterpret_cast(base + index * (blockSize << height)); +} + +size_t qkernel::BuddyAllocator::addressToNode(size_t height, void* location) const +{ + size_t offset = (char*) location - (char*) heapLocation; + return offset / (blockSize << height); +} + +void qkernel::BuddyAllocator::reserveNode(size_t height, size_t index) +{ + size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); + bit += index; + bitmap[bit / 8] |= 1 << (bit % 8); +} + +void qkernel::BuddyAllocator::freeNode(size_t height, size_t index) +{ + size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); + bit += index; + bitmap[bit / 8] &= ~(1 << (bit % 8)); +} + +bool qkernel::BuddyAllocator::isFree(size_t height, size_t index) const +{ + size_t bit = (height == 0) ? 0 : ((blockCount * 2) - (blockCount >> (height - 1))); + bit += index; + char data = bitmap[bit / 8] & (1 << (bit % 8)); + if(data == 0) + { + return true; + } + else + { + return false; + } +} diff --git a/src/buddyallocator.h b/src/buddyallocator.h new file mode 100755 index 0000000..f14b7a8 --- /dev/null +++ b/src/buddyallocator.h @@ -0,0 +1,94 @@ +#ifndef BUDDYALLOCATOR_H_ +#define BUDDYALLOCATOR_H_ + +#include "memoryallocator.h" + +namespace qkernel +{ + +class BuddyAllocator : public MemoryAllocator +{ +public: + + BuddyAllocator(); + + BuddyAllocator(void* heapLocation, char* bitmap, size_t blockSize, size_t blockCount, size_t treeHeight); + + /** + * Allocate a block of memory containing at least 'size' bytes. Rounds up to the nearest + * power of 2 times the size of a block. + */ + virtual void* allocate(size_t size); + + /** + * Free the region of memory starting at 'location' and containing 'size' bytes. + */ + virtual void free(void* location, size_t size); + + /** + * @returns the total number of free blocks of memory. + */ + virtual size_t freeBlocks() const; + + /** + * @returns the size in blocks of the largest possible allocation that will not + * fail due to lack of memory. + */ + virtual size_t maxAllocationSize() const; + + /** + * @returns the size in bytes of a single block. + */ + virtual size_t getBlockSize() const; + + /** + * @returns the total number of blocks managed by this memory allocator. + */ + virtual size_t getHeapSize() const; + + /** + * @returns a pointer to the beginning of the heap managed by this memory allocator. + */ + virtual void* getHeapLocation() const; + +private: + + static const size_t INVALID = (size_t) -1; + + void* heapLocation; + + char* bitmap; + + size_t blockSize; + + size_t blockCount; + + size_t treeHeight; + + size_t findFreeBlock(size_t height); + + size_t split(size_t height, size_t index); + + size_t merge(size_t height, size_t index); + + size_t getBuddy(size_t index); + + size_t getParent(size_t index); + + size_t getChild(size_t index); + + void* nodeToAddress(size_t height, size_t index) const; + + size_t addressToNode(size_t height, void* location) const; + + void reserveNode(size_t height, size_t index); + + void freeNode(size_t height, size_t index); + + bool isFree(size_t height, size_t index) const; + +}; + +} + +#endif diff --git a/src/cstring.cpp b/src/cstring.cpp old mode 100644 new mode 100755 diff --git a/src/cstring.h b/src/cstring.h old mode 100644 new mode 100755 diff --git a/src/entry.S b/src/entry.S old mode 100644 new mode 100755 index 195d3d3..5e8ccf8 --- a/src/entry.S +++ b/src/entry.S @@ -1,5 +1,5 @@ .section .multiboot -.include "multiboot2header.S" +.include "src/multiboot2header.S" .section .bss @@ -14,7 +14,7 @@ _tempPgDir: _tempIdentityMap: .skip 4096 _tempPgTable: -.skip 4096 +.skip 8192 .section .text .global _start @@ -73,9 +73,25 @@ _start: # Save the PDE to the entry corresponding to 0xC0000000 mov %eax, 3072(%edi) - # Load the physical address of the page directory into CR3 - mov %edi, %cr3 + # Add another PDE for extra mappings the kernel needs + add $4096, %eax + mov %eax, 3076(%edi) + + # Set the last entry in the page directory to point to the page directory itself + or $3, %edi + mov %edi, 4092(%edi) + # Map VGA memory into the address space + mov $_tempPgTable, %edi + sub $BASE_DIFF, %edi + mov $0xB8003, %eax + mov %eax, 4096(%edi) + + # Load the physical address of the page directory into CR3 + mov $_tempPgDir, %edi + sub $BASE_DIFF, %edi + mov %edi, %cr3 + # Enable paging mov %cr0, %eax or $0x80010000, %eax @@ -95,6 +111,8 @@ _start: # Initialize stack mov $stackTop, %esp + push %ebx + # Call main function call main diff --git a/src/error.cpp b/src/error.cpp old mode 100644 new mode 100755 diff --git a/src/error.h b/src/error.h old mode 100644 new mode 100755 diff --git a/src/errortype.h b/src/errortype.h old mode 100644 new mode 100755 diff --git a/src/linker.ld b/src/linker.ld new file mode 100755 index 0000000..713d4d7 --- /dev/null +++ b/src/linker.ld @@ -0,0 +1,36 @@ +ENTRY(_start) + +SECTIONS +{ + . = 0xC0000000; + VIRTUAL_BASE = .; + PHYSICAL_BASE = 0x100000; + BASE_DIFF = VIRTUAL_BASE - PHYSICAL_BASE; + + .text BLOCK(4K) : ALIGN(4K) + { + *(.multiboot) + *(.text) + } + + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } + + LOAD_START = ADDR(.text) - (VIRTUAL_BASE - PHYSICAL_BASE); + LOAD_END = ADDR(.data) + SIZEOF(.data) - (VIRTUAL_BASE - PHYSICAL_BASE); + BSS_END = ADDR(.bss) + SIZEOF(.bss) - (VIRTUAL_BASE - PHYSICAL_BASE); + IMAGE_SIZE = ((BSS_END - LOAD_START) + (4096 - ((BSS_END - LOAD_START) % 4096))) / 4096; +} diff --git a/src/math.cpp b/src/math.cpp old mode 100644 new mode 100755 diff --git a/src/math.h b/src/math.h old mode 100644 new mode 100755 diff --git a/src/memoryallocator.h b/src/memoryallocator.h new file mode 100755 index 0000000..d420849 --- /dev/null +++ b/src/memoryallocator.h @@ -0,0 +1,58 @@ +#ifndef __MEMORYALLOCATOR_H_ +#define __MEMORYALLOCATOR_H_ + +#include + +namespace qkernel +{ + +/** + * Interface for a dymanic memory allocator. + */ +class MemoryAllocator +{ +public: + + /** + * Allocate a block of memory containing 'size' bytes. May round up + * depending on the implementation. + */ + virtual void* allocate(size_t size) = 0; + + /** + * Free the region of memory starting at 'location' and containing 'size' bytes. + */ + virtual void free(void* location, size_t size) = 0; + + /** + * @returns the total number of free blocks of memory. + */ + virtual size_t freeBlocks() const = 0; + + /** + * @returns the size in blocks of the largest possible allocation that will not + * fail due to lack of memory. + */ + virtual size_t maxAllocationSize() const = 0; + + /** + * @returns the size in bytes of a single block. + */ + virtual size_t getBlockSize() const = 0; + + /** + * @returns the total number of blocks managed by this memory allocator. + */ + virtual size_t getHeapSize() const = 0; + + /** + * @returns a pointer to the beginning of the heap managed by this memory allocator. + */ + virtual void* getHeapLocation() const = 0; + + +}; + +} + +#endif diff --git a/src/multiboot2header.S b/src/multiboot2header.S old mode 100644 new mode 100755 diff --git a/src/pagetableentry.cpp b/src/pagetableentry.cpp old mode 100644 new mode 100755 diff --git a/src/pagetableentry.h b/src/pagetableentry.h old mode 100644 new mode 100755 diff --git a/src/physicalmemoryallocator.cpp b/src/physicalmemoryallocator.cpp deleted file mode 100644 index 911a2f4..0000000 --- a/src/physicalmemoryallocator.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/* - * PhysicalMemoryAllocator.cpp - * - * Created on: May 23, 2019 - * Author: nathan - */ - -#include "physicalmemoryallocator.h" -#include "math.h" -#include "error.h" - -namespace qkernel { - -void* const PhysicalMemoryAllocator::nullPtr = (void*) -1; - -PhysicalMemoryAllocator::PhysicalMemoryAllocator() -{ - for(size_t i = 0; i <= treeHeight; i++) - { - memoryMaps[i] = Bitmap(!available); - } - memoryMaps[treeHeight][0] = available; -} - -PhysicalMemoryAllocator::~PhysicalMemoryAllocator() -{ - // TODO Auto-generated destructor stub -} - -void* PhysicalMemoryAllocator::allocate(uint32_t pages) -{ - uint32_t height = ilog2(pages, true); - if(height >= treeHeight) // We can't allocate the whole address space at once! - { - return (void*) nullPtr; - } - - uint32_t index = findFreeBlock(height); - if(index != nullIndex) - { - memoryMaps[height][index] = !available; - return nodeToAddress(height, index); - } - else - { - return nullPtr; - } -} - -void PhysicalMemoryAllocator::free(void* location, uint32_t pages) -{ - uint32_t height = ilog2(pages, true); - if(height >= treeHeight || reinterpret_cast(location) % (4096 * pages) != 0) // We can't free the whole address space at once! - { - return; - } - - uint32_t index = addressToNode(height, location); - memoryMaps[height][index] = available; - - if(memoryMaps[height][getBuddy(index)] == available) - { - merge(height, index); - } -} - -uint32_t PhysicalMemoryAllocator::totalFreePages() -{ - uint32_t count = 0; - for(size_t i = 0; i <= treeHeight; i++) - { - count += (1 << i) * memoryMaps[i].count(); - } - return count; -} - -uint32_t PhysicalMemoryAllocator::largestFreeBlock() -{ - for(size_t i = treeHeight; i >= 0; i--) - { - if(memoryMaps[i].any()) - { - return 1 << i; - } - } -} - -uint32_t PhysicalMemoryAllocator::findFreeBlock(uint32_t height) -{ - if(memoryMaps[height].none()) - { - if(height == treeHeight) - { - lastError = Error(ErrorType::outOfMemory, "Out of memory"); - return nullIndex; - } - else - { - uint32_t parentIndex = findFreeBlock(height + 1); - if(parentIndex == (uint32_t) -1) - { - lastError = Error(ErrorType::outOfMemory, "Out of memory"); - return nullIndex; - } - split(height + 1, parentIndex); - } - - } - for(size_t index = 0; index < nodesAtHeight(height); index++) - { - if(memoryMaps[height][index] == available) - { - return index; - } - } - lastError = Error(ErrorType::illegalState, "There were still no free blocks after splitting larger ones!"); - return nullIndex; -} - -uint32_t PhysicalMemoryAllocator::merge(uint32_t height, uint32_t index) -{ - if(height == treeHeight) - { - lastError = Error(ErrorType::outOfBounds, "Attempted to merge root node"); - return nullIndex; - } - - if(memoryMaps[height][index] == 0 && memoryMaps[height][getBuddy(index)] == 0) - { - memoryMaps[height][index] = !available; - memoryMaps[height][getBuddy(index)] = !available; - memoryMaps[height + 1][getParent(index)] = available; - if(height + 1 < 20) - { - if(memoryMaps[height + 1][getBuddy(getParent(index))] == available) - { - return merge(height + 1, getParent(index)); - } - } - return getParent(index); - } - else - { - lastError = Error(ErrorType::invalidArgument, "Attempted to merge a node that is in use"); - return nullIndex; - } -} - -uint32_t PhysicalMemoryAllocator::split(uint32_t height, uint32_t index) -{ - if(height == 0) - { - lastError = Error(ErrorType::outOfBounds, "Attempted to split leaf node"); - return nullIndex; - } - - if(memoryMaps[height][index] == available) - { - memoryMaps[height][index] = !available; - memoryMaps[height - 1][getChild(index)] = available; - memoryMaps[height - 1][getBuddy(getChild(index))] = available; - return getChild(index); - } - else - { - lastError = Error(ErrorType::invalidArgument, "Attempted to split node currently in use"); - return nullIndex; - } -} - -uint32_t PhysicalMemoryAllocator::getBuddy(uint32_t index) -{ - return index ^ 1; -} - -uint32_t PhysicalMemoryAllocator::getParent(uint32_t index) -{ - return (index - index % 2) / 2; -} - -uint32_t PhysicalMemoryAllocator::getChild(uint32_t index) -{ - return index * 2; -} - -void* PhysicalMemoryAllocator::nodeToAddress(uint32_t height, uint32_t index) -{ - return reinterpret_cast(index * 4096 * (1 << height)); -} - -uint32_t PhysicalMemoryAllocator::nodesAtHeight(uint32_t height) -{ - return treeLeaves / (1 << height); -} - -uint32_t PhysicalMemoryAllocator::addressToNode(uint32_t height, - void* address) -{ - return reinterpret_cast(address) / (4096 * (1 << height)); -} - -} /* namespace qkernel */ diff --git a/src/physicalmemoryallocator.h b/src/physicalmemoryallocator.h deleted file mode 100644 index 11b0dc0..0000000 --- a/src/physicalmemoryallocator.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * PhysicalMemoryAllocator.h - * - * Created on: May 23, 2019 - * Author: nathan - */ - -#ifndef PHYSICALMEMORYALLOCATOR_H_ -#define PHYSICALMEMORYALLOCATOR_H_ - -#include -#include -#include "bitmap.h" - -namespace qkernel { - -class PhysicalMemoryAllocator { -public: - - static void* const nullPtr; - - PhysicalMemoryAllocator(); - - ~PhysicalMemoryAllocator(); - - void* allocate(uint32_t pages); - - void free(void* location, uint32_t pages); - - uint32_t totalFreePages(); - - uint32_t largestFreeBlock(); - -private: - - static const uint32_t nullIndex = (uint32_t) -1; - - static const bool available = true; - - static const size_t treeHeight = 20; - - static const size_t treeLeaves = 1024 * 1024; - - Bitmap memoryMaps[treeHeight + 1]; - - /** - * Searches nodes of the given height for an available block. If none is - * present, recursively splits higher nodes until one is. - * - * @param height The height of the desired node. - * @returns the index of the located node - */ - uint32_t findFreeBlock(uint32_t height); - - /** - * Merges a pair of buddies that have both become available. Recurses if - * the buddy of the new block is available. - * - * @param height The height of the blocks to merge. - * @param index The index of one of the buddies to be merged. - */ - uint32_t merge(uint32_t height, uint32_t index); - - /** - * Splits a block into a pair of buddies, making the original unavailable. - * - * @param height The height of the block to split. - * @param index The index of the block to split. - * - * @returns the index of the first of the pair of new blocks. - */ - uint32_t split(uint32_t height, uint32_t index); - - uint32_t getBuddy(uint32_t index); - - uint32_t getParent(uint32_t index); - - uint32_t getChild(uint32_t index); - - uint32_t nodesAtHeight(uint32_t height); - - void* nodeToAddress(uint32_t height, uint32_t index); - - uint32_t addressToNode(uint32_t height, void* address); - -}; - -} /* namespace qkernel */ - -#endif /* PHYSICALMEMORYALLOCATOR_H_ */ diff --git a/src/quarkkernel.cpp b/src/quarkkernel.cpp old mode 100644 new mode 100755 index 17aa0fd..9f9cdbc --- a/src/quarkkernel.cpp +++ b/src/quarkkernel.cpp @@ -1,13 +1,24 @@ #include #include +#include "tty.h" + #if __STDC_HOSTED__ == 1 || __i686__ != 1 #error "ERROR: This program must be compiled for a freestanding environment, and currently only supports the i686 target." #endif -void main() +#include "buddyallocator.h" + +using namespace qkernel; + +void main(void* bootInfo) { - int x = 2; - x -= 1; - return; + char* vga = (char*) 0xC0400000; + TTY tty(vga); + tty << "--Quark Kernel--\n"; + tty << "Successfully enabled paging. Kernel image mapped to 0xC0000000.\n"; + tty << "Nothing left to do. Hanging.\n"; + tty << 18542; + char c = 'b'; + return; } diff --git a/src/tty.cpp b/src/tty.cpp new file mode 100644 index 0000000..191304d --- /dev/null +++ b/src/tty.cpp @@ -0,0 +1,125 @@ +#include +#include "tty.h" + +qkernel::TTY::TTY(char* vga) +{ + this->vga = vga; + this->cursor = 0; +} + +qkernel::TTY& qkernel::TTY::operator<<(const char* str) +{ + while(*str) + { + switch(*str) + { + case '\n': + cursor = (cursor + 80) - (cursor % 80); + break; + case '\t': + cursor = (cursor + 4) - (cursor % 4); + break; + case '\r': + cursor -= cursor % 160; + break; + default: + vga[cursor * 2] = *str; + cursor++; + } + str++; + } + return *this; +} + +qkernel::TTY& qkernel::TTY::operator<<(int n) +{ + if(n == 0) + { + operator<<('0'); + return *this; + } + + int sign = n > 0 ? 1 : -1; + if(sign == -1) operator<<('-'); + + int quotient; + bool showZeros = false; + for(int divisor = 1000000000; divisor > 0; divisor /= 10) + { + quotient = n / divisor; + char digit = (char) (sign * (quotient % 10) + '0'); + if(digit != '0' || showZeros) + { + operator<<(digit); + showZeros = true; + } + } + return *this; +} + +qkernel::TTY& qkernel::TTY::operator<<(char c) +{ + switch(c) + { + case '\n': + cursor = (cursor + 160) - (cursor % 160); + break; + case '\t': + cursor = (cursor + 8) - (cursor % 8); + break; + case '\r': + cursor -= cursor % 160; + break; + default: + vga[cursor * 2] = c; + } + cursor++; + return *this; +} + +void qkernel::TTY::clear() +{ + for(int i = 0; i < 80*25; i++) + { + vga[i * 2] = ' '; + } + cursor = 0; +} + +qkernel::TTY& qkernel::TTY::printNumber(unsigned int n, int base = 10, bool sign = true, bool leadingZeros = false) +{ + if(n == 0) + { + operator<<('0'); + return *this; + } + + if(sign) + { + int nSig = (int) n; + int sign = nSig > 0 ? 1 : -1; + if(sign == -1) + { + n = (unsigned int) (nSig * sign); + operator<<('-'); + } + } + + int initDivisor = (base == 10) ? 1000000000 : + ((base == 16) ? 0x10000000 : + ((base == 8) ? 0x40000000 : 0)); + + int quotient; + bool showZeros = leadingZeros; + for(int divisor = 1000000000; divisor > 0; divisor /= base) + { + quotient = n / divisor; + char digit = (char) (sign * (quotient % base) + '0'); + if(digit != '0' || showZeros) + { + operator<<(digit); + showZeros = true; + } + } + return *this; +} diff --git a/src/tty.h b/src/tty.h new file mode 100644 index 0000000..43dddbf --- /dev/null +++ b/src/tty.h @@ -0,0 +1,35 @@ +#ifndef TTY_H_ +#define TTY_H_ + +namespace qkernel +{ + +class TTY +{ +public: + + + TTY(char* vga); + + TTY& operator<<(const char* str); + + TTY& operator<<(int n); + + TTY& operator<<(char c); + + void clear(); + +private: + + TTY& printNumber(unsigned int n, int base, bool sign, + bool leadingZeros); + + char* vga; + + int cursor; + +}; + +} + +#endif