physical memory management and started usermode
This commit is contained in:
parent
e1b6525a7e
commit
8b58e8663f
Binary file not shown.
1
Makefile
1
Makefile
|
@ -15,6 +15,7 @@ KERNELIMG := $(BUILDDIR)/kernel.bin
|
||||||
|
|
||||||
QEMUFLAGS = -d int -s \
|
QEMUFLAGS = -d int -s \
|
||||||
-kernel $(KERNELIMG) \
|
-kernel $(KERNELIMG) \
|
||||||
|
-m 512M \
|
||||||
-device piix3-ide,id=ide -drive id=disk,file=image.img,format=raw,if=none -device ide-hd,drive=disk,bus=ide.0 \
|
-device piix3-ide,id=ide -drive id=disk,file=image.img,format=raw,if=none -device ide-hd,drive=disk,bus=ide.0 \
|
||||||
|
|
||||||
.PHONY: all kernel qemu clean docs
|
.PHONY: all kernel qemu clean docs
|
||||||
|
|
12
idt.c
12
idt.c
|
@ -1,4 +1,6 @@
|
||||||
#include <idt.h>
|
#include <idt.h>
|
||||||
|
#include <vga.h>
|
||||||
|
#include <printf.h>
|
||||||
|
|
||||||
void encode_idt_entry(struct idt_entry idt[], int i, uint32_t offset, uint16_t segment_selector, uint8_t attributes) {
|
void encode_idt_entry(struct idt_entry idt[], int i, uint32_t offset, uint16_t segment_selector, uint8_t attributes) {
|
||||||
idt[i].offset_lo = (uint16_t)(offset & 0xFFFF);
|
idt[i].offset_lo = (uint16_t)(offset & 0xFFFF);
|
||||||
|
@ -7,3 +9,13 @@ void encode_idt_entry(struct idt_entry idt[], int i, uint32_t offset, uint16_t s
|
||||||
idt[i].attributes = attributes;
|
idt[i].attributes = attributes;
|
||||||
idt[i].offset_hi = (uint16_t)(offset >> 16);
|
idt[i].offset_hi = (uint16_t)(offset >> 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exception_handler(struct registers regs) {
|
||||||
|
clear_screen();
|
||||||
|
|
||||||
|
printf("Exception 0x%X (0x%X) has occurred\nEAX: 0x%08X\nECX: 0x%08X\nEDX: 0x%08X\nEBX: 0x%08X\nESI: 0x%08X\nEDI: 0x%08X\nEBP: 0x%08X\nESP: 0x%08X\n",
|
||||||
|
regs.int_no, regs.err_code, regs.eax, regs.ecx, regs.edx, regs.ebx, regs.esi, regs.edi, regs.ebp, regs.esp+24);
|
||||||
|
|
||||||
|
printf("\nEIP: 0x%08X\nCS: 0x%08X\nEFLAGS: 0x%08X",
|
||||||
|
regs.eip, regs.cs, regs.eflags);
|
||||||
|
}
|
||||||
|
|
34
include/fat12.h
Normal file
34
include/fat12.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef RK_FAT12_H_
|
||||||
|
#define RK_FAT12_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct fat12_boot_sector {
|
||||||
|
uint8_t jump_boot[3]; // Jump instruction to boot code
|
||||||
|
uint8_t oem_name[8]; // OEM name and version
|
||||||
|
uint16_t bytes_per_sector; // Bytes per sector
|
||||||
|
uint8_t sectors_per_cluster; // Sectors per cluster
|
||||||
|
uint16_t reserved_sectors; // Reserved sectors
|
||||||
|
uint8_t num_fats; // Number of FATs
|
||||||
|
uint16_t root_entry_count; // Number of root directory entries
|
||||||
|
uint16_t total_sectors_16; // Total sectors (16-bit)
|
||||||
|
uint8_t media; // Media descriptor
|
||||||
|
uint16_t fat_size_16; // Sectors per FAT (16-bit)
|
||||||
|
uint16_t sectors_per_track; // Sectors per track (for BIOS)
|
||||||
|
uint16_t num_heads; // Number of heads (for BIOS)
|
||||||
|
uint32_t hidden_sectors; // Hidden sectors
|
||||||
|
uint32_t total_sectors_32; // Total sectors (32-bit)
|
||||||
|
|
||||||
|
// Extended Boot Record (EBR) fields
|
||||||
|
uint8_t drive_number; // Drive number
|
||||||
|
uint8_t reserved1; // Reserved
|
||||||
|
uint8_t boot_signature; // Extended boot signature
|
||||||
|
uint32_t volume_id; // Volume ID (serial number)
|
||||||
|
uint8_t volume_label[11]; // Volume label
|
||||||
|
uint8_t file_system_type[8]; // File system type (e.g., "FAT12 ")
|
||||||
|
|
||||||
|
uint8_t boot_code[448]; // Boot code
|
||||||
|
uint16_t boot_sector_signature; // Boot sector signature (0xAA55)
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,9 +1,50 @@
|
||||||
#ifndef RK_GDT_H_
|
#ifndef RK_GDT_H_
|
||||||
#define RK_GDT_H_
|
#define RK_GDT_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define GDT_NULL 0
|
#define GDT_NULL 0
|
||||||
#define GDT_KERNEL_CODE 1
|
#define GDT_KERNEL_CODE 1
|
||||||
#define GDT_KERNEL_DATA 2
|
#define GDT_KERNEL_DATA 2
|
||||||
#define GDT_SEGMENT_SELECTOR(i, p) ((i << 3) | p)
|
#define GDT_SEGMENT_SELECTOR(i, p) ((i << 3) | p)
|
||||||
|
|
||||||
|
struct gdt_entry {
|
||||||
|
uint16_t limit_low;
|
||||||
|
uint16_t base_low;
|
||||||
|
uint8_t base_middle;
|
||||||
|
uint8_t access;
|
||||||
|
uint8_t granularity;
|
||||||
|
uint8_t base_high;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct tss_entry {
|
||||||
|
uint32_t prev_tss; // The previous TSS - with hardware task switching this is used
|
||||||
|
uint32_t esp0; // The stack pointer to load when we change to kernel mode
|
||||||
|
uint32_t ss0; // The stack segment to load when we change to kernel mode
|
||||||
|
uint32_t esp1; // Unused...
|
||||||
|
uint32_t ss1;
|
||||||
|
uint32_t esp2;
|
||||||
|
uint32_t ss2;
|
||||||
|
uint32_t cr3;
|
||||||
|
uint32_t eip;
|
||||||
|
uint32_t eflags;
|
||||||
|
uint32_t eax;
|
||||||
|
uint32_t ecx;
|
||||||
|
uint32_t edx;
|
||||||
|
uint32_t ebx;
|
||||||
|
uint32_t esp;
|
||||||
|
uint32_t ebp;
|
||||||
|
uint32_t esi;
|
||||||
|
uint32_t edi;
|
||||||
|
uint32_t es; // The value to load into ES when we change to kernel mode
|
||||||
|
uint32_t cs; // The value to load into CS when we change to kernel mode
|
||||||
|
uint32_t ss; // The value to load into SS when we change to kernel mode
|
||||||
|
uint32_t ds; // The value to load into DS when we change to kernel mode
|
||||||
|
uint32_t fs; // The value to load into FS when we change to kernel mode
|
||||||
|
uint32_t gs; // The value to load into GS when we change to kernel mode
|
||||||
|
uint32_t ldt; // Unused...
|
||||||
|
uint16_t trap;
|
||||||
|
uint16_t iomap_base;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -36,7 +36,17 @@ enum IDT_ATTRIBUTES {
|
||||||
INT_PRESENT = 0x80,
|
INT_PRESENT = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct registers {
|
||||||
|
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
|
||||||
|
uint32_t int_no, err_code; /* Interrupt number and error code (if applicable) */
|
||||||
|
|
||||||
|
uint32_t eip;
|
||||||
|
uint32_t cs;
|
||||||
|
uint32_t eflags;
|
||||||
|
};
|
||||||
|
|
||||||
void encode_idt_entry(struct idt_entry idt[], int i, uint32_t offset, uint16_t segment_selector, uint8_t attributes);
|
void encode_idt_entry(struct idt_entry idt[], int i, uint32_t offset, uint16_t segment_selector, uint8_t attributes);
|
||||||
void flush_idt(uint32_t idt_pointer);
|
void flush_idt(uint32_t idt_pointer);
|
||||||
|
void exception_handler(struct registers regs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
22
include/kernel.h
Normal file
22
include/kernel.h
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef RK_KERNEL_H_
|
||||||
|
#define RK_KERNEL_H_
|
||||||
|
|
||||||
|
#include <multiboot.h>
|
||||||
|
#include <acpi.h>
|
||||||
|
|
||||||
|
struct kernel_context {
|
||||||
|
struct rsdp *rsdp;
|
||||||
|
struct xsdp *xsdp;
|
||||||
|
|
||||||
|
struct rsdt *rsdt;
|
||||||
|
struct mcfg *mcfg;
|
||||||
|
|
||||||
|
uint32_t multi_mmap_size;
|
||||||
|
struct multiboot_mmap_entry *multi_mmap;
|
||||||
|
|
||||||
|
uint32_t available_bytes;
|
||||||
|
uint32_t mmap_size;
|
||||||
|
uint32_t *mmap;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
20
include/mem.h
Normal file
20
include/mem.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef RK_MEM_H_
|
||||||
|
#define RK_MEM_H_
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define KERNEL_START 0x1000000 // 1 MiB
|
||||||
|
#define KERNEL_SIZE 0xC800 // 50 KiB
|
||||||
|
#define BLOCK_SIZE 4096
|
||||||
|
#define BITS 32
|
||||||
|
|
||||||
|
uint8_t mmap_init(struct kernel_context *ctx);
|
||||||
|
void mmap_set_block(struct kernel_context *ctx, int block);
|
||||||
|
void mmap_free_block(struct kernel_context *ctx, int block);
|
||||||
|
void *mmap_find_first_free_block(struct kernel_context *ctx);
|
||||||
|
void *mmap_block_to_physical(struct kernel_context *ctx, int block);
|
||||||
|
|
||||||
|
void *memset(void *s, int c, uint32_t len);
|
||||||
|
|
||||||
|
#endif
|
|
@ -28,4 +28,19 @@ struct multiboot_info {
|
||||||
uint32_t vbeInterfaceLength;
|
uint32_t vbeInterfaceLength;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct multiboot_mmap_entry
|
||||||
|
{
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t addr_low;
|
||||||
|
uint32_t addr_high;
|
||||||
|
uint32_t len_low;
|
||||||
|
uint32_t len_high;
|
||||||
|
#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
|
||||||
|
uint32_t type;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
111
kmain.c
111
kmain.c
|
@ -1,4 +1,4 @@
|
||||||
#include "ide.h"
|
#include <kernel.h>
|
||||||
#include <multiboot.h>
|
#include <multiboot.h>
|
||||||
#include <acpi.h>
|
#include <acpi.h>
|
||||||
#include <vga.h>
|
#include <vga.h>
|
||||||
|
@ -9,33 +9,112 @@
|
||||||
#include <idt.h>
|
#include <idt.h>
|
||||||
#include <pic8259.h>
|
#include <pic8259.h>
|
||||||
#include <ps2.h>
|
#include <ps2.h>
|
||||||
|
#include <ide.h>
|
||||||
struct kernel_context {
|
#include <mem.h>
|
||||||
struct rsdp *rsdp;
|
#include <fat12.h>
|
||||||
struct xsdp *xsdp;
|
|
||||||
|
|
||||||
struct rsdt *rsdt;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct kernel_context ctx = {0};
|
struct kernel_context ctx = {0};
|
||||||
|
|
||||||
struct idt_entry g_idt[256] = {0};
|
struct idt_entry g_idt[256] = {0};
|
||||||
struct idtr g_idtr = {0};
|
struct idtr g_idtr = {0};
|
||||||
|
|
||||||
extern void exception_handler();
|
extern uint32_t isr_stub_table[32];
|
||||||
extern void ps2_isr();
|
extern void ps2_isr();
|
||||||
|
|
||||||
#define MAGIC_BREAKPOINT __asm__ volatile("xchgw %bx, %bx");
|
#define MAGIC_BREAKPOINT __asm__ volatile("xchgw %bx, %bx");
|
||||||
|
|
||||||
|
#define USER_DS 0x23 // User data segment selector
|
||||||
|
#define USER_CS 0x1B // User code segment selector
|
||||||
|
|
||||||
|
extern struct gdt_entry gdt[6];
|
||||||
|
struct tss_entry tss;
|
||||||
|
|
||||||
|
void tss_flush(uint16_t tss_selector) {
|
||||||
|
asm volatile (
|
||||||
|
"ltr %0"
|
||||||
|
: // no output
|
||||||
|
: "r" (tss_selector)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
printf("\n\nHello from user mode!\n");
|
||||||
|
for (;;) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
void switch_to_user_mode(void *user_stack, void *user_entry) {
|
||||||
|
asm volatile (
|
||||||
|
"movl $0x23, %%eax \n" // User data segment selector
|
||||||
|
"mov %%ax, %%ds \n"
|
||||||
|
"mov %%ax, %%es \n"
|
||||||
|
"mov %%ax, %%fs \n"
|
||||||
|
"mov %%ax, %%gs \n"
|
||||||
|
|
||||||
|
"pushl $0x23 \n" // User stack segment
|
||||||
|
"pushl %0 \n" // User stack pointer
|
||||||
|
"pushfl \n" // Push EFLAGS
|
||||||
|
"popl %%eax \n"
|
||||||
|
"orl $0x200, %%eax \n" // Enable interrupts (set IF)
|
||||||
|
"pushl %%eax \n"
|
||||||
|
|
||||||
|
"pushl $0x1B \n" // User code segment
|
||||||
|
"pushl %1 \n" // User entry point
|
||||||
|
|
||||||
|
"iret \n" // Interrupt return (switches to user mode)
|
||||||
|
:
|
||||||
|
: "r"(user_stack), "r"(user_entry)
|
||||||
|
: "eax"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_tss(int num, uint16_t ss0, uint32_t esp0) {
|
||||||
|
uint32_t base = (uint32_t)&tss;
|
||||||
|
uint32_t limit = base + sizeof(tss);
|
||||||
|
|
||||||
|
gdt[num].base_low = base & 0xFFFF;
|
||||||
|
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||||
|
gdt[num].base_high = (base >> 24) & 0xFF;
|
||||||
|
gdt[num].limit_low = limit & 0xFFFF;
|
||||||
|
gdt[num].granularity = (limit >> 16) & 0x0F;
|
||||||
|
gdt[num].granularity |= 0x40;
|
||||||
|
gdt[num].access = 0x89;
|
||||||
|
|
||||||
|
memset(&tss, 0, sizeof(tss));
|
||||||
|
tss.ss0 = ss0;
|
||||||
|
tss.esp0 = esp0;
|
||||||
|
tss.cs = 0x0b;
|
||||||
|
tss.ss = tss.ds = tss.es = tss.fs = tss.gs = 0x13;
|
||||||
|
}
|
||||||
|
|
||||||
void kmain(struct multiboot_info *info) {
|
void kmain(struct multiboot_info *info) {
|
||||||
clear_screen();
|
clear_screen();
|
||||||
set_color(VGA_COLOR_CYAN);
|
set_color(VGA_COLOR_CYAN);
|
||||||
// Check if the bootloader gave us the upper and lower memory
|
// Check if the bootloader gave us the upper and lower memory
|
||||||
if (!(info->flags & 0x1)) goto halt;
|
if (!(info->flags & 0x1)) goto halt;
|
||||||
|
|
||||||
|
ctx.multi_mmap = (struct multiboot_mmap_entry *)info->memMapAddress;
|
||||||
|
ctx.multi_mmap_size = info->memMapLength / sizeof(struct multiboot_mmap_entry);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < ctx.multi_mmap_size; i++) {
|
||||||
|
struct multiboot_mmap_entry entry = ctx.multi_mmap[i];
|
||||||
|
if (entry.type != MULTIBOOT_MEMORY_AVAILABLE) continue;
|
||||||
|
|
||||||
|
uint32_t len = (uint32_t)(entry.len_low | entry.len_high);
|
||||||
|
uint32_t addr = (uint32_t)(entry.addr_low | entry.addr_high);
|
||||||
|
printf("Region #%d: 0x%08X-0x%08X\n", i, addr, addr+len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mmap_init(&ctx)) {
|
||||||
|
set_color(VGA_COLOR_RED);
|
||||||
|
printf("Failed to create memory map\n");
|
||||||
|
goto halt;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Detected %d bytes of memory\n", ctx.available_bytes);
|
||||||
|
|
||||||
// Create and load an IDT
|
// Create and load an IDT
|
||||||
for (int i = 0; i < 32; i++) {
|
for (int i = 0; i < 32; i++) {
|
||||||
encode_idt_entry(g_idt, i, (uint32_t)&exception_handler, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, 0x00), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
|
encode_idt_entry(g_idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, 0x00), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_idtr.size = (sizeof(struct idt_entry) * 256) - 1;
|
g_idtr.size = (sizeof(struct idt_entry) * 256) - 1;
|
||||||
|
@ -119,7 +198,17 @@ void kmain(struct multiboot_info *info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
set_color(VGA_COLOR_WHITE);
|
set_color(VGA_COLOR_WHITE);
|
||||||
printf("\nYou are now being dropped into a kernel shell\n$ ");
|
|
||||||
|
void *buf = mmap_find_first_free_block(&ctx);
|
||||||
|
ata_read_sector(ATA_PRIMARY, ATA_MASTER, 0, (uint8_t *)buf);
|
||||||
|
// struct fat12_boot_sector *boot_sect = (struct fat12_boot_sector *)buf;
|
||||||
|
// int fat_size = boot_sect->total_sectors_16 * boot_sect->bytes_per_sector;
|
||||||
|
|
||||||
|
write_tss(5, 0x10, 0x0);
|
||||||
|
tss_flush(0x2B);
|
||||||
|
void *stack_bottom = mmap_find_first_free_block(&ctx);
|
||||||
|
void *stack_top = stack_bottom + 4096;
|
||||||
|
switch_to_user_mode(stack_top, buf);
|
||||||
halt:
|
halt:
|
||||||
for (;;) {}
|
for (;;) {}
|
||||||
}
|
}
|
||||||
|
|
121
mem.c
Normal file
121
mem.c
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
#include <mem.h>
|
||||||
|
#include <printf.h>
|
||||||
|
|
||||||
|
// TODO: Fix this, it wastes memory when switching regions because the previous offset isnt being subtracted
|
||||||
|
// Should work fine for now?
|
||||||
|
void *mmap_block_to_physical(struct kernel_context *ctx, int block) {
|
||||||
|
uint32_t offset = block * BLOCK_SIZE;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < ctx->multi_mmap_size; i++) {
|
||||||
|
struct multiboot_mmap_entry entry = ctx->multi_mmap[i];
|
||||||
|
if (entry.type != MULTIBOOT_MEMORY_AVAILABLE) continue;
|
||||||
|
|
||||||
|
uint32_t len = (uint32_t)(entry.len_low | entry.len_high);
|
||||||
|
uint32_t addr = (uint32_t)(entry.addr_low | entry.addr_high);
|
||||||
|
if (len > offset)
|
||||||
|
return (void *)(addr + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memset(void *s, int c, uint32_t len) {
|
||||||
|
unsigned char *dst = s;
|
||||||
|
while (len > 0) {
|
||||||
|
*dst = (unsigned char) c;
|
||||||
|
dst++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t mmap_init(struct kernel_context *ctx) {
|
||||||
|
// Calculate the number of bytes available to us
|
||||||
|
for (uint32_t i = 0; i < ctx->multi_mmap_size; i++) {
|
||||||
|
struct multiboot_mmap_entry entry = ctx->multi_mmap[i];
|
||||||
|
if (entry.type != MULTIBOOT_MEMORY_AVAILABLE) continue;
|
||||||
|
|
||||||
|
uint32_t len = (uint32_t)(entry.len_low | entry.len_high);
|
||||||
|
ctx->available_bytes += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->mmap_size = ctx->available_bytes / BLOCK_SIZE / 8;
|
||||||
|
printf("Memory map size: %d bytes\n", ctx->mmap_size);
|
||||||
|
|
||||||
|
// Loop again to find the first region with enough space to hold the memory map
|
||||||
|
int index = -1;
|
||||||
|
for (uint32_t i = 0; i < ctx->multi_mmap_size; i++) {
|
||||||
|
struct multiboot_mmap_entry entry = ctx->multi_mmap[i];
|
||||||
|
if (entry.type != MULTIBOOT_MEMORY_AVAILABLE) continue;
|
||||||
|
|
||||||
|
uint32_t len = (uint32_t)(entry.len_low | entry.len_high);
|
||||||
|
if (len > ctx->mmap_size) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1) return 0; // Failed
|
||||||
|
|
||||||
|
// Create map
|
||||||
|
struct multiboot_mmap_entry entry = ctx->multi_mmap[index];
|
||||||
|
uint32_t addr = (uint32_t)(entry.addr_low | entry.addr_high);
|
||||||
|
ctx->mmap = (uint32_t *)addr;
|
||||||
|
// Zero the map
|
||||||
|
memset(ctx->mmap, 0, ctx->mmap_size);
|
||||||
|
// Reserve the blocks that hold the memory map + 1
|
||||||
|
uint32_t blocks_to_set = ctx->mmap_size / BLOCK_SIZE + 1;
|
||||||
|
for (uint32_t i = 0; i < blocks_to_set; i++)
|
||||||
|
mmap_set_block(ctx, i);
|
||||||
|
// Reserve the kernel space
|
||||||
|
int bits = ctx->mmap_size * 8;
|
||||||
|
for (int i = 0; i < bits; i++) {
|
||||||
|
uint32_t phys = (uint32_t)mmap_block_to_physical(ctx, i);
|
||||||
|
if (phys > KERNEL_START && phys < KERNEL_START + KERNEL_SIZE)
|
||||||
|
mmap_set_block(ctx, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmap_set_block(struct kernel_context *ctx, int block) {
|
||||||
|
int index = block / BITS;
|
||||||
|
int bit = block;
|
||||||
|
if (block >= BITS)
|
||||||
|
bit -= BITS;
|
||||||
|
|
||||||
|
uint32_t mask = 1 << bit;
|
||||||
|
if (!(ctx->mmap[index] & mask))
|
||||||
|
ctx->mmap[index] |= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mmap_free_block(struct kernel_context *ctx, int block) {
|
||||||
|
int index = block / BITS;
|
||||||
|
int bit = block;
|
||||||
|
if (block >= BITS)
|
||||||
|
bit -= BITS;
|
||||||
|
|
||||||
|
uint32_t mask = 1 << bit;
|
||||||
|
if (ctx->mmap[index] & mask)
|
||||||
|
ctx->mmap[index] ^= mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *mmap_find_first_free_block(struct kernel_context *ctx) {
|
||||||
|
int bits = ctx->mmap_size * 8;
|
||||||
|
for (int i = 0; i < bits; i++) {
|
||||||
|
int index = i / BITS;
|
||||||
|
int bit = i;
|
||||||
|
if (i >= BITS)
|
||||||
|
bit -= BITS;
|
||||||
|
|
||||||
|
uint32_t mask = 1 << bit;
|
||||||
|
|
||||||
|
uint32_t dword = ctx->mmap[index];
|
||||||
|
if (!(dword & mask)) {
|
||||||
|
return mmap_block_to_physical(ctx, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
%define MAGIC 0x1BADB002
|
%define MAGIC 0x1BADB002
|
||||||
%define FLAGS 0b100
|
%define FLAGS 0b110
|
||||||
|
|
||||||
; Multiboot v1 Specification
|
; Multiboot v1 Specification
|
||||||
; https://www.gnu.org/software/grub/manual/multiboot/multiboot.html
|
; https://www.gnu.org/software/grub/manual/multiboot/multiboot.html
|
||||||
|
@ -49,13 +49,74 @@ _start:
|
||||||
halt:
|
halt:
|
||||||
hlt
|
hlt
|
||||||
jmp halt
|
jmp halt
|
||||||
global exception_handler
|
|
||||||
exception_handler:
|
extern exception_handler
|
||||||
add esp, 4
|
%macro isr_err_stub 1
|
||||||
mov byte [0xb8000], 'X'
|
isr_stub_%+%1:
|
||||||
iret
|
cli
|
||||||
|
push %1
|
||||||
|
pusha
|
||||||
|
call exception_handler
|
||||||
|
popa
|
||||||
|
add esp, 8
|
||||||
|
iret
|
||||||
|
%endmacro
|
||||||
|
%macro isr_no_err_stub 1
|
||||||
|
isr_stub_%+%1:
|
||||||
|
cli
|
||||||
|
push 0
|
||||||
|
push %1
|
||||||
|
pusha
|
||||||
|
call exception_handler
|
||||||
|
popa
|
||||||
|
add esp, 12
|
||||||
|
iret
|
||||||
|
%endmacro
|
||||||
|
|
||||||
|
isr_no_err_stub 0
|
||||||
|
isr_no_err_stub 1
|
||||||
|
isr_no_err_stub 2
|
||||||
|
isr_no_err_stub 3
|
||||||
|
isr_no_err_stub 4
|
||||||
|
isr_no_err_stub 5
|
||||||
|
isr_no_err_stub 6
|
||||||
|
isr_no_err_stub 7
|
||||||
|
isr_err_stub 8
|
||||||
|
isr_no_err_stub 9
|
||||||
|
isr_err_stub 10
|
||||||
|
isr_err_stub 11
|
||||||
|
isr_err_stub 12
|
||||||
|
isr_err_stub 13
|
||||||
|
isr_err_stub 14
|
||||||
|
isr_no_err_stub 15
|
||||||
|
isr_no_err_stub 16
|
||||||
|
isr_err_stub 17
|
||||||
|
isr_no_err_stub 18
|
||||||
|
isr_no_err_stub 19
|
||||||
|
isr_no_err_stub 20
|
||||||
|
isr_no_err_stub 21
|
||||||
|
isr_no_err_stub 22
|
||||||
|
isr_no_err_stub 23
|
||||||
|
isr_no_err_stub 24
|
||||||
|
isr_no_err_stub 25
|
||||||
|
isr_no_err_stub 26
|
||||||
|
isr_no_err_stub 27
|
||||||
|
isr_no_err_stub 28
|
||||||
|
isr_no_err_stub 29
|
||||||
|
isr_err_stub 30
|
||||||
|
isr_no_err_stub 31
|
||||||
|
|
||||||
|
global isr_stub_table
|
||||||
|
isr_stub_table:
|
||||||
|
%assign i 0
|
||||||
|
%rep 32
|
||||||
|
dd isr_stub_%+i
|
||||||
|
%assign i i+1
|
||||||
|
%endrep
|
||||||
|
|
||||||
global ps2_isr
|
global ps2_isr
|
||||||
ps2_isr:
|
ps2_isr:
|
||||||
|
cli
|
||||||
extern ps2_handler
|
extern ps2_handler
|
||||||
pushad
|
pushad
|
||||||
cld
|
cld
|
||||||
|
@ -66,7 +127,8 @@ ps2_isr:
|
||||||
|
|
||||||
; GDT for a flat memory layout
|
; GDT for a flat memory layout
|
||||||
; We get access to all memory and can utilize paging
|
; We get access to all memory and can utilize paging
|
||||||
gdt_start:
|
global gdt
|
||||||
|
gdt:
|
||||||
gdt_null:
|
gdt_null:
|
||||||
dq 0
|
dq 0
|
||||||
gdt_kern_code:
|
gdt_kern_code:
|
||||||
|
@ -83,11 +145,27 @@ gdt_kern_data:
|
||||||
db 0b10010010
|
db 0b10010010
|
||||||
db 0b11001111
|
db 0b11001111
|
||||||
db 0x00
|
db 0x00
|
||||||
|
gdt_user_code:
|
||||||
|
dw 0xffff
|
||||||
|
dw 0x0000
|
||||||
|
db 0x00
|
||||||
|
db 0b11111010
|
||||||
|
db 0b11001111
|
||||||
|
db 0x00
|
||||||
|
gdt_user_data:
|
||||||
|
dw 0xffff
|
||||||
|
dw 0x0000
|
||||||
|
db 0x00
|
||||||
|
db 0b11110010
|
||||||
|
db 0b11001111
|
||||||
|
db 0x00
|
||||||
|
tss:
|
||||||
|
dq 0
|
||||||
gdt_end:
|
gdt_end:
|
||||||
|
|
||||||
gdtp:
|
gdtp:
|
||||||
dw gdt_end - gdt_start - 1
|
dw gdt_end - gdt - 1
|
||||||
dd gdt_start
|
dd gdt
|
||||||
|
|
||||||
|
|
||||||
; Reserve 16KiB of kernel stack space
|
; Reserve 16KiB of kernel stack space
|
||||||
|
|
Loading…
Reference in New Issue
Block a user