diff --git a/Makefile b/Makefile
index a5bfb2f..9ffbd33 100644
--- a/Makefile
+++ b/Makefile
@@ -171,7 +171,7 @@ $(KOBJDIR)/kernel/malloc.o: $(KERNELDIR)/kernel/mm/malloc.c $(KERNELDIR)/include
.PHONY: test
test: all
- @qemu-system-x86_64 -m 5G -hda build/bin/disk.img -d cpu_reset,guest_errors,pcall,int -enable-kvm 2> qemu.log &
+ @qemu-system-x86_64 -m 5G -mem-prealloc -hda build/bin/disk.img -d cpu_reset,guest_errors,pcall,int -enable-kvm 2> qemu.log &
@ndisasm $(BINDIR)/kaleid -o 0x00100000 -b 64 > loader_disasm64.asm
@ndisasm $(BINDIR)/kaleid -o 0x00100000 -b 32 > loader_disasm32.asm
.PHONY: test32
diff --git a/ProjectTree b/ProjectTree
index 74b8d52..03a52e6 100644
--- a/ProjectTree
+++ b/ProjectTree
@@ -56,15 +56,6 @@
│ │ │ └── loader.o
│ │ └── kaleid
│ │ ├── kernel
-│ │ │ ├── init
-│ │ │ │ ├── init.o
-│ │ │ │ └── table.o
-│ │ │ ├── io
-│ │ │ │ ├── cursor.o
-│ │ │ │ ├── term.o
-│ │ │ │ └── vga.o
-│ │ │ ├── ke
-│ │ │ │ └── panic.o
│ │ │ ├── cpuid.o
│ │ │ ├── cursor.o
│ │ │ ├── heap.o
@@ -167,4 +158,4 @@
├── qemu.log
└── Readme.md
-30 directories, 112 files
+27 directories, 106 files
diff --git a/build/kernel.ld b/build/kernel.ld
index ea46357..50a5d81 100644
--- a/build/kernel.ld
+++ b/build/kernel.ld
@@ -61,6 +61,8 @@ SECTIONS {
*(.rodata) /* all rodata sections from all files */
}
+ kernelEnd = .;
+
/DISCARD/ :
{
*(.comment)
diff --git a/kaleid/include/kernel/base.h b/kaleid/include/kernel/base.h
index e6efe12..9719931 100644
--- a/kaleid/include/kernel/base.h
+++ b/kaleid/include/kernel/base.h
@@ -108,6 +108,7 @@ struct BootInfo_t
void *modulesAddr; //mods_addr
char *grubName; //boot_loader_name
void *kernelAddr;
+ void *kernelEndAddr;
} btldr;
// Informations about drives
diff --git a/kaleid/include/kernel/mm.h b/kaleid/include/kernel/mm.h
index 49072e0..928dfd8 100644
--- a/kaleid/include/kernel/mm.h
+++ b/kaleid/include/kernel/mm.h
@@ -22,19 +22,54 @@
// along with OS/K. If not, see . //
//----------------------------------------------------------------------------//
-#include
#include
-#define MINIMUM_RAM_SIZE 16 //Mio, the minimum RAM size.
+#define MINIMUM_RAM_SIZE 16 // Mio, the minimum RAM size.
-//
-// Returns a pointer to the first entry of the memory map
-//
-void *GetMemoryMap(void);
+#define AVAILABLE_ZONE 1 // Fully usable RAM zone
+#define RESERVED_ZONE 2 // Used by the firmware
+#define ACPI_ZONE 3 // Used by ACPI but can be freed
+#define NVS_ZONE 4 // Dunno
+#define BADRAM_ZONE 5 // Invalid zone because material problem...
+#define MAX_ENTRIES 2048 // Max number of memory map entries
+
+// -------------------------------------------------------------------------- //
+
+typedef struct MemoryMap_t MemoryMap_t;
+typedef struct MapEntry_t MapEntry_t;
+
+// -------------------------------------------------------------------------- //
+// The entry structure of the map
+struct MapEntry_t {
+ void *addr;
+ size_t length; // in bytes
+ uint type; // reserved or not
+} __attribute__((packed));
+
+// the map structure
+struct MemoryMap_t {
+ size_t length;
+ size_t freeRamSize;
+ size_t nonfreeRamSize;
+ MapEntry_t entry[MAX_ENTRIES];
+} __attribute__((packed));
+
+
+
+// -------------------------------------------------------------------------- //
//
// Initializes the memory map structure
//
error_t InitMemoryMap(void);
+//
+// Returns the size of the first available memory zone from the start address pointer
+//
+size_t GetAvailZoneSize(void *start);
+
+//
+// Returns the first available memory zone from the start address pointer
+void *GetFirstAvailZone(void *start);
+
// -------------------------------------------------------------------------- //
diff --git a/kaleid/include/kernel/multiboot.h b/kaleid/include/kernel/multiboot.h
index d1f8516..896f23d 100644
--- a/kaleid/include/kernel/multiboot.h
+++ b/kaleid/include/kernel/multiboot.h
@@ -232,15 +232,12 @@ struct multiboot_color
struct multiboot_mmap_entry
{
uint size;
- ullong addr;
- ullong len;
-#define MULTIBOOT_MEMORY_AVAILABLE 1
-#define MULTIBOOT_MEMORY_RESERVED 2
-#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3
-#define MULTIBOOT_MEMORY_NVS 4
-#define MULTIBOOT_MEMORY_BADRAM 5
+ uint addr_low;
+ uint addr_high;
+ uint len_low;
+ uint len_high;
uint type;
-} __attribute__((packed));
+} __attribute__((packed)) __attribute__((aligned (4)));
typedef struct multiboot_mmap_entry multiboot_memory_map_t;
struct multiboot_mod_list
diff --git a/kaleid/kernel/init/init.c b/kaleid/kernel/init/init.c
index 94c8034..23bb762 100644
--- a/kaleid/kernel/init/init.c
+++ b/kaleid/kernel/init/init.c
@@ -22,8 +22,9 @@
// along with OS/K. If not, see . //
//----------------------------------------------------------------------------//
-#include
+#include
#include
+#include
#include
//
@@ -32,7 +33,8 @@
//
void InitBootInfo(multiboot_info_t *mbi)
{
- extern void MB_header(void);
+ extern ullong MB_header;
+ extern ullong kernelEnd;
// We need the multiboot structure
KalAlwaysAssert(mbi);
@@ -43,6 +45,7 @@ void InitBootInfo(multiboot_info_t *mbi)
if (GetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_BOOT_LOADER_NAME) {
GetBootInfo(btldr).grubName = (char*)(ullong)(mbi->boot_loader_name);
GetBootInfo(btldr).kernelAddr = (void*)&MB_header;
+ GetBootInfo(btldr).kernelEndAddr = (void*)&kernelEnd;
GetBootInfo(btldr).valid = 1;
}
if (GetBootInfo(btldr).grubFlags & MULTIBOOT_INFO_MODS) {
@@ -135,6 +138,11 @@ noreturn void StartKern(multiboot_info_t *mbInfo, int mbMagic)
mapBad
);
+ KernLog("[Init] TEST First zone from %p : %p\n", (void*)0xB8010, GetFirstAvailZone((void*)0xB8010));
+ KernLog("[Init] TEST Size of zone : %u Kio\n\n", GetAvailZoneSize(GetFirstAvailZone((void*)0xB8010)) / KB);
+
+
+
// We're out
KernLog("\n[Init] Evil never dies !\n");
CrashSystem(); //yay
diff --git a/kaleid/kernel/mm/heap.c b/kaleid/kernel/mm/heap.c
index 06dbf9c..74048c2 100644
--- a/kaleid/kernel/mm/heap.c
+++ b/kaleid/kernel/mm/heap.c
@@ -23,6 +23,7 @@
//----------------------------------------------------------------------------//
#include
+#include
// Least address out of the heap
static void *_heap_end;
@@ -33,9 +34,6 @@ static size_t _heap_max;
// Lock NOT used internally, but used by KalAllocMemory() & co.
static Lock_t _heap_lock = INITLOCK(KLOCK_SPINLOCK);
-// Debugging stub
-size_t GetAvailZoneSize(void *x) { (void)x; return 8 * MB; }
-
//
// Initializes heap managment
//
diff --git a/kaleid/kernel/mm/map.c b/kaleid/kernel/mm/map.c
index d84f662..7c27017 100644
--- a/kaleid/kernel/mm/map.c
+++ b/kaleid/kernel/mm/map.c
@@ -1,7 +1,7 @@
//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
-// Desc: //
+// Desc: Mapping and checking memory related functions //
// //
// //
// Copyright © 2018-2019 The OS/K Team //
@@ -24,23 +24,139 @@
#include
#include
+#include
+MemoryMap_t memoryMap = { 0 };
+
+
+
+//
+// Initilization of the memory map, and computation of the available ram size
+//
error_t InitMemoryMap(void)
{
+ multiboot_memory_map_t *currentEntry;
+ multiboot_memory_map_t *mapEnd;
+ uint i = 0;
+
+ // sanity checks
if (!GetBootInfo(memory).memValid && GetBootInfo(memory).mapValid)
return ENXIO;
- DebugLog("[InitMemoryMap] Memory map address : %p, length : %d\n",
- GetBootInfo(memory).mapAddr, GetBootInfo(memory).mapLength);
if ((GetBootInfo(memory).upMemory / (MB/KB)) <= MINIMUM_RAM_SIZE)
return ENOMEM;
- DebugLog("[InitMemoryMap] Low memory : %d Kio, Up memory : %d Mio\n",
- GetBootInfo(memory).lowMemory, GetBootInfo(memory).upMemory / (MB/KB));
+
+// Ok then we can work ------------------------------------------------------ //
+
+ // the memory map provided by GRUB via the BIOS
+ currentEntry = (multiboot_memory_map_t*)GetBootInfo(memory).mapAddr;
+ // End address of the map
+ mapEnd = (multiboot_memory_map_t*)
+ ((ullong)currentEntry + (ullong)GetBootInfo(memory).mapLength);
+
+ // fill the map
+ while (currentEntry < mapEnd) {
+ // memory zone address
+ memoryMap.entry[i].addr = (void*)( (ullong)currentEntry->addr_low +
+ (((ullong)currentEntry->addr_high) << 32 ));
+ // memory zone size in bytes
+ memoryMap.entry[i].length = (ullong)currentEntry->len_low +
+ (((ullong)currentEntry->len_high) << 32);
+ // memory availability
+ memoryMap.entry[i].type = (uint)currentEntry->type;
+ // Adding the size to the size (yup)
+ memoryMap.length++;
+ // moving up !
+ currentEntry = (multiboot_memory_map_t*) ((ullong)currentEntry +
+ currentEntry->size + sizeof(currentEntry->size));
+ i++;
+ }
+
+ DebugLog("[InitMemoryMap] %d entries detected in the memory map\n",
+ memoryMap.length);
+
+ // compute the free ram size
+ for (i = 0; i < memoryMap.length; i++) {
+ if (memoryMap.entry[i].type == AVAILABLE_ZONE) {
+ memoryMap.freeRamSize += memoryMap.entry[i].length;
+ } else {
+ memoryMap.nonfreeRamSize += memoryMap.entry[i].length;
+ }
+ }
+
+ // Trully strange if it happens...
+ if (memoryMap.freeRamSize < MINIMUM_RAM_SIZE)
+ return ENOMEM;
+
+ KernLog("[InitMemoryMap] Available Ram Size : %u Mio, Used Ram Size : %u Kio\n",
+ memoryMap.freeRamSize / MB, memoryMap.nonfreeRamSize / KB);
+ KernLog("[InitMemoryMap] Physical Ram Size : %d Mio\n\n",
+ (memoryMap.freeRamSize + memoryMap.nonfreeRamSize) / MB);
return EOK;
}
-void *GetMemoryMap(void)
-{
- return (void*)0;
+size_t GetAvailZoneSize(void *start) {
+ uint i;
+
+ // Because the kernel is the kernel
+ if (start < GetBootInfo(btldr).kernelEndAddr)
+ return 0;
+
+ // Search the zone where the start address is
+ for (i = 0; i < memoryMap.length; i++) {
+ // if the address is in an available zone, we can return the length
+ if (
+ memoryMap.entry[i].type == AVAILABLE_ZONE &&
+ (ullong)start >= (ullong)memoryMap.entry[i].addr &&
+ (ullong)start < ((ullong)memoryMap.entry[i].addr +
+ (ullong)memoryMap.entry[i].length)
+ ) {
+ return (size_t)((ullong)memoryMap.entry[i].length - (ullong)start);
+ }
+ }
+
+ // If there is no zone, we return a 0 size
+ return 0;
+}
+
+void *GetFirstAvailZone(void *start) {
+ uint i;
+ void *current = 0;
+
+ // Because the kernel is the kernel
+ if ((ullong)start < (ullong)GetBootInfo(btldr).kernelEndAddr) {
+ return GetFirstAvailZone(GetBootInfo(btldr).kernelEndAddr);
+ }
+
+ // Search the zone where the start address is
+ for (i = 0; i < memoryMap.length; i++) {
+ // if the address is in an available zone, we can return the start address
+ if (
+ memoryMap.entry[i].type == AVAILABLE_ZONE &&
+ (ullong)start >= (ullong)memoryMap.entry[i].addr &&
+ (ullong)start < ((ullong)memoryMap.entry[i].addr +
+ (ullong)memoryMap.entry[i].length)
+ ) {
+ current = start;
+ break;
+ }
+ }
+
+ if (current)
+ return current;
+
+ // Search the first zone from start
+ for (i = 0; i < memoryMap.length; i++) {
+ // Return the first zone that is after start
+ if (
+ memoryMap.entry[i].type == AVAILABLE_ZONE &&
+ (ullong)start <= (ullong)memoryMap.entry[i].addr
+ ) {
+ current = memoryMap.entry[i].addr;
+ break;
+ }
+ }
+
+ return current;
}