add memory detection

This commit is contained in:
Tyler McGurrin 2025-02-27 17:58:10 -05:00
parent a40ab1c13a
commit e38974d290
14 changed files with 476 additions and 273 deletions

View File

@ -7,6 +7,8 @@ SOURCES_C=$(wildcard *.c)
SOURCES_ASM=$(wildcard *.asm)
OBJECTS_C=$(patsubst %.c, $(BUILD_DIR)/stage2/c/%.obj, $(SOURCES_C))
OBJECTS_ASM=$(patsubst %.asm, $(BUILD_DIR)/stage2/asm/%.obj, $(SOURCES_ASM))
HEADERS_C= $(wildcard ../../libs/*.h) \
$(wildcard ../../libs/*/*.h)
.PHONY: all stage2 clean always
@ -17,7 +19,7 @@ stage2: $(BUILD_DIR)/stage2.bin
$(BUILD_DIR)/stage2.bin: $(OBJECTS_ASM) $(OBJECTS_C)
$(TARGET_LD) $(TARGET_LINKFLAGS) -Wl,-Map=$(BUILD_DIR)/stage2.map -o $@ $^ $(TARGET_LIBS)
$(BUILD_DIR)/stage2/c/%.obj: %.c always
$(BUILD_DIR)/stage2/c/%.obj: %.c always $(HEADERS_C)
$(TARGET_CC) $(TARGET_CFLAGS) -c -o $@ $<
$(BUILD_DIR)/stage2/asm/%.obj: %.asm always

View File

@ -10,13 +10,18 @@
#include "fat.h"
#include "memdefs.h"
#include "memory.h"
#include "../../version.h"
#include "memdetect.h"
#include "../../libs/version.h"
#include "../../libs/boot/bootparams.h"
uint8_t* KernelLoadBuffer = (uint8_t*)MEMORY_LOAD_KERNEL;
uint8_t* Kernel = (uint8_t*)MEMORY_KERNEL_ADDR;
BootParams g_BootParams;
typedef void (*KernelStart)();
typedef void (*KernelStart)(BootParams* bootParams);
void* g_data = (void*)0x20000;
@ -82,6 +87,12 @@ void* g_data = (void*)0x20000;
}
FAT_Close(ft);
printf("Detecting Memory...\n");
// prep boot params
g_BootParams.BootDevice = bootDrive;
Memory_Detect(&g_BootParams.Memory);
// load kernel from disk
printf("Loading Kernel...");
FAT_File* fd = FAT_Open(&disk, "/kernel.bin"); // move to /boot later????? (TM)
@ -96,7 +107,7 @@ void* g_data = (void*)0x20000;
// execute kernel
KernelStart kernelStart = (KernelStart)Kernel;
kernelStart();
kernelStart(&g_BootParams);

View File

@ -0,0 +1,40 @@
/*----------------*\
|Nanite OS |
|Copyright (C) 2024|
|Tyler McGurrin |
\*----------------*/
#include "x86.h"
#include "stdio.h"
#include "../../libs/boot/bootparams.h"
#define MAX_REGIONS 256
MemoryRegion g_MemRegions[MAX_REGIONS];
int g_MemRegionCount;
void Memory_Detect(MemoryInfo* memoryInfo)
{
E820MemoryBlock block;
uint32_t continuation = 0;
int ret;
g_MemRegionCount = 0;
ret = x86_E820GetNextBlock(&block, &continuation);
while (ret > 0 && continuation != 0)
{
g_MemRegions[g_MemRegionCount].Begin = block.Base;
g_MemRegions[g_MemRegionCount].Length = block.Length;
g_MemRegions[g_MemRegionCount].Type = block.Type;
g_MemRegions[g_MemRegionCount].ACPI = block.ACPI;
++g_MemRegionCount;
printf("E820: base=0x%llx length=0x%llx type=0x%x\n", block.Base, block.Length, block.Type);
ret = x86_E820GetNextBlock(&block, &continuation);
}
// fill meminfo structure
memoryInfo->RegionCount = g_MemRegionCount;
memoryInfo->Regions = g_MemRegions;
}

View File

@ -0,0 +1,10 @@
/*----------------*\
|Nanite OS |
|Copyright (C) 2024|
|Tyler McGurrin |
\*----------------*/
#pragma once
#include "../../libs/boot/bootparams.h"
void Memory_Detect(MemoryInfo* memoryInfo);

View File

@ -162,145 +162,144 @@ void printf_signed(long long number, int radix)
#define PRINTF_LENGTH_LONG 3
#define PRINTF_LENGTH_LONG_LONG 4
void printf(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
void printf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
int state= PRINTF_STATE_NORMAL;
int length = PRINTF_LENGTH_DEFAULT;
int radix = 10;
bool sign = false;
bool number = false;
int state = PRINTF_STATE_NORMAL;
int length = PRINTF_LENGTH_DEFAULT;
int radix = 10;
bool sign = false;
bool number = false;
while (*fmt)
{
switch (state)
{
case PRINTF_STATE_NORMAL:
switch (*fmt)
{
case '%': state = PRINTF_STATE_LENGTH;
break;
default: putc(*fmt);
break;
}
break;
while (*fmt)
{
switch (state)
{
case PRINTF_STATE_NORMAL:
switch (*fmt)
{
case '%': state = PRINTF_STATE_LENGTH;
break;
default: putc(*fmt);
break;
}
break;
case PRINTF_STATE_LENGTH:
switch (*fmt)
{
case 'h': length = PRINTF_LENGTH_SHORT;
state = PRINTF_STATE_LENGTH_SHORT;
break;
case 'l': length = PRINTF_LENGTH_LONG;
state = PRINTF_STATE_LENGTH_LONG;
break;
default: goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_LENGTH:
switch (*fmt)
{
case 'h': length = PRINTF_LENGTH_SHORT;
state = PRINTF_STATE_LENGTH_SHORT;
break;
case 'l': length = PRINTF_LENGTH_LONG;
state = PRINTF_STATE_LENGTH_LONG;
break;
default: goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_LENGTH_SHORT:
if (*fmt == 'h')
{
length = PRINTF_LENGTH_SHORT_SHORT;
state = PRINTF_STATE_SPEC;
}
else goto PRINTF_STATE_SPEC_;
break;
case PRINTF_STATE_LENGTH_SHORT:
if (*fmt == 'h')
{
length = PRINTF_LENGTH_SHORT_SHORT;
state = PRINTF_STATE_SPEC;
}
else goto PRINTF_STATE_SPEC_;
break;
case PRINTF_STATE_LENGTH_LONG:
if (*fmt == 'h')
{
length = PRINTF_LENGTH_LONG_LONG;
state = PRINTF_STATE_SPEC;
}
else goto PRINTF_STATE_SPEC_;
break;
case PRINTF_STATE_LENGTH_LONG:
if (*fmt == 'l')
{
length = PRINTF_LENGTH_LONG_LONG;
state = PRINTF_STATE_SPEC;
}
else goto PRINTF_STATE_SPEC_;
break;
case PRINTF_STATE_SPEC:
PRINTF_STATE_SPEC_:
switch (*fmt)
{
case 'c': putc((char)va_arg(args, int));
break;
case 's': puts(va_arg(args, const char*));
break;
case PRINTF_STATE_SPEC:
PRINTF_STATE_SPEC_:
switch (*fmt)
{
case 'c': putc((char)va_arg(args, int));
break;
case '%': putc('%');
break;
case 's':
puts(va_arg(args, const char*));
break;
case 'd':
case 'i': radix = 10;
sign = true;
number = true;
break;
case 'u': radix = 10; sign = false; number = true;
break;
case '%': putc('%');
break;
case 'X':
case 'x':
case 'p': radix = 16; sign = false; number = true;
break;
case 'd':
case 'i': radix = 10; sign = true; number = true;
break;
case 'o': radix = 8; sign = false; number = true;
break;
case 'u': radix = 10; sign = false; number = true;
break;
//ignore invalid specifiers (specs)
default: break;
}
if (number)
{
if (sign)
{
switch (length)
{
case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_DEFAULT:
printf_signed(va_arg(args, int), radix);
break;
case PRINTF_LENGTH_LONG:
printf_signed(va_arg(args, long), radix);
break;
case PRINTF_LENGTH_LONG_LONG:
printf_signed(va_arg(args, long long), radix);
break;
}
}
else
{
switch (length)
{
case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_DEFAULT:
printf_unsigned(va_arg(args, unsigned int), radix);
break;
case PRINTF_LENGTH_LONG:
printf_unsigned(va_arg(args, unsigned long), radix);
break;
case PRINTF_LENGTH_LONG_LONG:
printf_unsigned(va_arg(args, unsigned long long), radix);
break;
}
}
}
case 'X':
case 'x':
case 'p': radix = 16; sign = false; number = true;
break;
//reset state
state = PRINTF_STATE_NORMAL;
length = PRINTF_LENGTH_DEFAULT;
radix = 10;
sign = false;
bool number = false;
break;
}
case 'o': radix = 8; sign = false; number = true;
break;
fmt++;
}
// ignore invalid spec
default: break;
}
va_end(args);
if (number)
{
if (sign)
{
switch (length)
{
case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_DEFAULT: printf_signed(va_arg(args, int), radix);
break;
case PRINTF_LENGTH_LONG: printf_signed(va_arg(args, long), radix);
break;
case PRINTF_LENGTH_LONG_LONG: printf_signed(va_arg(args, long long), radix);
break;
}
}
else
{
switch (length)
{
case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_DEFAULT: printf_unsigned(va_arg(args, unsigned int), radix);
break;
case PRINTF_LENGTH_LONG: printf_unsigned(va_arg(args, unsigned long), radix);
break;
case PRINTF_LENGTH_LONG_LONG: printf_unsigned(va_arg(args, unsigned long long), radix);
break;
}
}
}
// reset state
state = PRINTF_STATE_NORMAL;
length = PRINTF_LENGTH_DEFAULT;
radix = 10;
sign = false;
number = false;
break;
}
fmt++;
}
va_end(args);
}

View File

@ -278,3 +278,73 @@ x86_realmode_putc:
mov esp, ebp
pop ebp
ret
;
; int ASMCALL x86_E820GetNextBlock(E820MemoryBlock* block, uint32_t* continuationId);
;
E820Signature equ 0x534D4150
global x86_E820GetNextBlock
x86_E820GetNextBlock:
; make new call frame
push ebp ; save old call frame
mov ebp, esp ; initialize new call frame
x86_EnterRealMode
; save modified regs
push ebx
push ecx
push edx
push esi
push edi
push ds
push es
; setup params
LinearToSegOffset [bp + 8], es, edi, di ; es:di pointer to structure
LinearToSegOffset [bp + 12], ds, esi, si ; ebx - pointer to continuationId
mov ebx, ds:[si]
mov eax, 0xE820 ; eax - function
mov edx, E820Signature ; edx - signature
mov ecx, 24 ; ecx - size of structure
; call interrupt
int 0x15
; test results
cmp eax, E820Signature
jne .Error
.IfSuccedeed:
mov eax, ecx ; return size
mov ds:[si], ebx ; fill continuation parameter
jmp .EndIf
.Error:
mov eax, -1
.EndIf:
; restore regs
pop es
pop ds
pop edi
pop esi
pop edx
pop ecx
pop ebx
push eax
x86_EnterProtectedMode
pop eax
; restore old call frame
mov esp, ebp
pop ebp
ret

View File

@ -7,22 +7,46 @@
#include <stdint.h>
#include <stdbool.h>
void __attribute__((cdecl)) x86_outb(uint16_t port, uint8_t value);
uint8_t __attribute__((cdecl)) x86_inb(uint16_t port);
#define ASMCALL __attribute__((cdecl))
void __attribute__((cdecl)) x86_realmode_putc(char c);
bool __attribute__((cdecl)) x86_Disk_GetDriveParams(uint8_t drive,
uint8_t* driveTypeOut,
uint16_t* cylindersOut,
uint16_t* sectorsOut,
uint16_t* headsOut);
void ASMCALL x86_outb(uint16_t port, uint8_t value);
uint8_t ASMCALL x86_inb(uint16_t port);
bool __attribute__((cdecl)) x86_Disk_Reset(uint8_t drive);
void ASMCALL x86_realmode_putc(char c);
bool __attribute__((cdecl)) x86_Disk_Read(uint8_t drive,
uint16_t cylinder,
uint16_t sector,
uint16_t head,
uint8_t count,
void* lowerDataOut);
bool ASMCALL x86_Disk_GetDriveParams(uint8_t drive,
uint8_t* driveTypeOut,
uint16_t* cylindersOut,
uint16_t* sectorsOut,
uint16_t* headsOut);
bool ASMCALL x86_Disk_Reset(uint8_t drive);
bool ASMCALL x86_Disk_Read(uint8_t drive,
uint16_t cylinder,
uint16_t sector,
uint16_t head,
uint8_t count,
void* lowerDataOut);
typedef struct
{
uint64_t Base;
uint64_t Length;
uint32_t Type;
uint32_t ACPI;
} E820MemoryBlock;
enum E820MemoryBlockType {
E820_USABLE = 1,
E820_RESERVED = 2,
E820_ACPI_RECLAIMABLE = 3,
E820_ACPI_NVS = 4,
E820_BAD_MEMORY = 5,
};
int ASMCALL x86_E820GetNextBlock(E820MemoryBlock* block, uint32_t* continuationId);

View File

@ -6,7 +6,9 @@ TARGET_LINKFLAGS += -T linker.ld -nostdlib
HEADERS_C = $(wildcard *.h) \
$(wildcard */*.h) \
$(wildcard */*/*.h) \
$(wildcard */*/*/*.h)
$(wildcard */*/*/*.h) \
$(wildcard ../libs/*.h) \
$(wildcard ../libs/*/*.h)
SOURCES_C = $(wildcard *.c) \
$(wildcard */*.c) \

View File

@ -0,0 +1,6 @@
/*----------------*\
|Nanite OS |
|Copyright (C) 2024|
|Tyler McGurrin |
\*----------------*/
#include "keyboard.h"

View File

@ -0,0 +1,6 @@
/*----------------*\
|Nanite OS |
|Copyright (C) 2024|
|Tyler McGurrin |
\*----------------*/
#pragma once

View File

@ -10,17 +10,19 @@
#include <arch/i686/io.h>
#include <arch/i686/irq.h>
#include <arch/i686/basicfunc.h>
#include "../version.h"
#include "../libs/version.h"
#include "../libs/boot/bootparams.h"
extern uint8_t __bss_start;
extern uint8_t __end;
void timer(Registers* regs)
{
printf(".");
int uptime;
uptime++;
}
void __attribute__((section(".entry"))) start(uint16_t bootDrive) {
void __attribute__((section(".entry"))) start(BootParams* bootParams) {
// print logo
clrscr();
@ -35,6 +37,13 @@ void __attribute__((section(".entry"))) start(uint16_t bootDrive) {
printf("Done!\n\n\n\n\n");
i686_IRQ_RegisterHandler(0, timer);
printf("Boot Device: %x\n", bootParams->BootDevice);
printf("Memory Region Count: %x\n", bootParams->Memory.RegionCount);
for (int i = 0; i < bootParams->Memory.RegionCount; i++) {
printf("Memory: start=0x%llx length=0x%llx type=0x%x\n",
bootParams->Memory.Regions[i].Begin, bootParams->Memory.Regions[i].Length, bootParams->Memory.Regions[i].Type);
}
end:

View File

@ -174,146 +174,144 @@ void printf_signed(long long number, int radix)
#define PRINTF_LENGTH_LONG 3
#define PRINTF_LENGTH_LONG_LONG 4
void printf(const char* fmt, ...) {
va_list args;
va_start(args, fmt);
void printf(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
int state= PRINTF_STATE_NORMAL;
int length = PRINTF_LENGTH_DEFAULT;
int radix = 10;
bool sign = false;
bool number = false;
int state = PRINTF_STATE_NORMAL;
int length = PRINTF_LENGTH_DEFAULT;
int radix = 10;
bool sign = false;
bool number = false;
while (*fmt)
{
switch (state)
{
case PRINTF_STATE_NORMAL:
switch (*fmt)
{
case '%': state = PRINTF_STATE_LENGTH;
break;
default: putc(*fmt);
break;
}
break;
while (*fmt)
{
switch (state)
{
case PRINTF_STATE_NORMAL:
switch (*fmt)
{
case '%': state = PRINTF_STATE_LENGTH;
break;
default: putc(*fmt);
break;
}
break;
case PRINTF_STATE_LENGTH:
switch (*fmt)
{
case 'h': length = PRINTF_LENGTH_SHORT;
state = PRINTF_STATE_LENGTH_SHORT;
break;
case 'l': length = PRINTF_LENGTH_LONG;
state = PRINTF_STATE_LENGTH_LONG;
break;
default: goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_LENGTH:
switch (*fmt)
{
case 'h': length = PRINTF_LENGTH_SHORT;
state = PRINTF_STATE_LENGTH_SHORT;
break;
case 'l': length = PRINTF_LENGTH_LONG;
state = PRINTF_STATE_LENGTH_LONG;
break;
default: goto PRINTF_STATE_SPEC_;
}
break;
case PRINTF_STATE_LENGTH_SHORT:
if (*fmt == 'h')
{
length = PRINTF_LENGTH_SHORT_SHORT;
state = PRINTF_STATE_SPEC;
}
else goto PRINTF_STATE_SPEC_;
break;
case PRINTF_STATE_LENGTH_SHORT:
if (*fmt == 'h')
{
length = PRINTF_LENGTH_SHORT_SHORT;
state = PRINTF_STATE_SPEC;
}
else goto PRINTF_STATE_SPEC_;
break;
case PRINTF_STATE_LENGTH_LONG:
if (*fmt == 'h')
{
length = PRINTF_LENGTH_LONG_LONG;
state = PRINTF_STATE_SPEC;
}
else goto PRINTF_STATE_SPEC_;
break;
case PRINTF_STATE_LENGTH_LONG:
if (*fmt == 'l')
{
length = PRINTF_LENGTH_LONG_LONG;
state = PRINTF_STATE_SPEC;
}
else goto PRINTF_STATE_SPEC_;
break;
case PRINTF_STATE_SPEC:
PRINTF_STATE_SPEC_:
switch (*fmt)
{
case 'c': putc((char)va_arg(args, int));
break;
case 's': puts(va_arg(args, const char*));
break;
case PRINTF_STATE_SPEC:
PRINTF_STATE_SPEC_:
switch (*fmt)
{
case 'c': putc((char)va_arg(args, int));
break;
case '%': putc('%');
break;
case 's':
puts(va_arg(args, const char*));
break;
case 'd':
case 'i': radix = 10;
sign = true;
number = true;
break;
case 'u': radix = 10; sign = false; number = true;
break;
case '%': putc('%');
break;
case 'X':
case 'x':
case 'p': radix = 16; sign = false; number = true;
break;
case 'd':
case 'i': radix = 10; sign = true; number = true;
break;
case 'o': radix = 8; sign = false; number = true;
break;
case 'u': radix = 10; sign = false; number = true;
break;
//ignore invalid specifiers (specs)
default: break;
}
if (number)
{
if (sign)
{
switch (length)
{
case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_DEFAULT:
printf_signed(va_arg(args, int), radix);
break;
case PRINTF_LENGTH_LONG:
printf_signed(va_arg(args, long), radix);
break;
case PRINTF_LENGTH_LONG_LONG:
printf_signed(va_arg(args, long long), radix);
break;
}
}
else
{
switch (length)
{
case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_DEFAULT:
printf_unsigned(va_arg(args, unsigned int), radix);
break;
case PRINTF_LENGTH_LONG:
printf_unsigned(va_arg(args, unsigned long), radix);
break;
case PRINTF_LENGTH_LONG_LONG:
printf_unsigned(va_arg(args, unsigned long long), radix);
break;
}
}
}
case 'X':
case 'x':
case 'p': radix = 16; sign = false; number = true;
break;
//reset state
state = PRINTF_STATE_NORMAL;
length = PRINTF_LENGTH_DEFAULT;
radix = 10;
sign = false;
bool number = false;
case 'o': radix = 8; sign = false; number = true;
break;
break;
}
// ignore invalid spec
default: break;
}
fmt++;
}
if (number)
{
if (sign)
{
switch (length)
{
case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_DEFAULT: printf_signed(va_arg(args, int), radix);
break;
va_end(args);
case PRINTF_LENGTH_LONG: printf_signed(va_arg(args, long), radix);
break;
case PRINTF_LENGTH_LONG_LONG: printf_signed(va_arg(args, long long), radix);
break;
}
}
else
{
switch (length)
{
case PRINTF_LENGTH_SHORT_SHORT:
case PRINTF_LENGTH_SHORT:
case PRINTF_LENGTH_DEFAULT: printf_unsigned(va_arg(args, unsigned int), radix);
break;
case PRINTF_LENGTH_LONG: printf_unsigned(va_arg(args, unsigned long), radix);
break;
case PRINTF_LENGTH_LONG_LONG: printf_unsigned(va_arg(args, unsigned long long), radix);
break;
}
}
}
// reset state
state = PRINTF_STATE_NORMAL;
length = PRINTF_LENGTH_DEFAULT;
radix = 10;
sign = false;
number = false;
break;
}
fmt++;
}
va_end(args);
}

View File

@ -0,0 +1,26 @@
/*----------------*\
|Nanite OS |
|Copyright (C) 2024|
|Tyler McGurrin |
\*----------------*/
#pragma once
#include <stdint.h>
typedef struct {
uint64_t Begin, Length;
uint32_t Type;
uint32_t ACPI;
} MemoryRegion;
typedef struct
{
int RegionCount;
MemoryRegion* Regions;
} MemoryInfo;
typedef struct {
MemoryInfo Memory;
uint8_t BootDevice;
} BootParams;