added syscalls & fixed bug in mem manager
This commit is contained in:
parent
8b58e8663f
commit
7830b92f87
Binary file not shown.
28
gdt.c
Normal file
28
gdt.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include <gdt.h>
|
||||
|
||||
void write_tss(struct tss_entry *tss, struct gdt_entry *gdt, int num, uint16_t ss0, uint32_t esp0) {
|
||||
uint32_t base = (uint32_t)tss;
|
||||
uint32_t limit = base + sizeof(struct tss_entry);
|
||||
|
||||
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(struct tss_entry));
|
||||
tss->ss0 = ss0;
|
||||
tss->esp0 = esp0;
|
||||
tss->cs = 0x0b;
|
||||
tss->ss = tss->ds = tss->es = tss->fs = tss->gs = 0x13;
|
||||
}
|
||||
|
||||
void tss_flush(uint16_t tss_selector) {
|
||||
asm volatile (
|
||||
"ltr %0"
|
||||
: // no output
|
||||
: "r" (tss_selector)
|
||||
);
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
#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
|
|
@ -2,10 +2,17 @@
|
|||
#define RK_GDT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <mem.h>
|
||||
|
||||
#define GDT_NULL 0
|
||||
#define GDT_KERNEL_CODE 1
|
||||
#define GDT_KERNEL_DATA 2
|
||||
#define GDT_USER_CODE 3
|
||||
#define GDT_USER_DATA 4
|
||||
|
||||
#define RING0 0
|
||||
#define RING3 3
|
||||
|
||||
#define GDT_SEGMENT_SELECTOR(i, p) ((i << 3) | p)
|
||||
|
||||
struct gdt_entry {
|
||||
|
@ -47,4 +54,7 @@ struct tss_entry {
|
|||
uint16_t iomap_base;
|
||||
} __attribute__((packed));
|
||||
|
||||
void write_tss(struct tss_entry *tss, struct gdt_entry *gdt, int num, uint16_t ss0, uint32_t esp0);
|
||||
void tss_flush(uint16_t tss_selector);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -15,6 +15,12 @@ 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);
|
||||
void memset(void *s, int c, uint32_t len);
|
||||
void memcpy(void *dest, void *src, int n);
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
void *next;
|
||||
} linked_mem_t;
|
||||
|
||||
#endif
|
||||
|
|
171
kmain.c
171
kmain.c
|
@ -11,35 +11,51 @@
|
|||
#include <ps2.h>
|
||||
#include <ide.h>
|
||||
#include <mem.h>
|
||||
#include <fat12.h>
|
||||
|
||||
struct kernel_context ctx = {0};
|
||||
|
||||
struct idt_entry g_idt[256] = {0};
|
||||
struct idtr g_idtr = {0};
|
||||
|
||||
extern uint32_t isr_stub_table[32];
|
||||
extern void ps2_isr();
|
||||
|
||||
#define MAGIC_BREAKPOINT __asm__ volatile("xchgw %bx, %bx");
|
||||
#define FD_STDOUT 0
|
||||
#define FD_STDIN 1
|
||||
|
||||
#define USER_DS 0x23 // User data segment selector
|
||||
#define USER_CS 0x1B // User code segment selector
|
||||
|
||||
struct kernel_context ctx = {0};
|
||||
struct idt_entry g_idt[256] = {0};
|
||||
struct idtr g_idtr = {0};
|
||||
extern uint32_t isr_stub_table[32];
|
||||
extern void ps2_isr();
|
||||
extern struct gdt_entry gdt[6];
|
||||
extern void syscall_isr();
|
||||
extern void syscall();
|
||||
extern void test();
|
||||
|
||||
linked_mem_t stdout = {0};
|
||||
linked_mem_t stdin = {0};
|
||||
|
||||
struct tss_entry tss;
|
||||
|
||||
void tss_flush(uint16_t tss_selector) {
|
||||
asm volatile (
|
||||
"ltr %0"
|
||||
: // no output
|
||||
: "r" (tss_selector)
|
||||
);
|
||||
struct stack_frame {
|
||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
||||
};
|
||||
|
||||
void syscall_read(struct stack_frame regs) {
|
||||
uint32_t fd = regs.edi;
|
||||
char *buf = (char *)regs.esi;
|
||||
uint32_t count = regs.edx;
|
||||
|
||||
if (fd == FD_STDOUT) {
|
||||
int pages = count / BLOCK_SIZE;
|
||||
if (pages == 0) {
|
||||
memcpy(buf, stdout.data, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test() {
|
||||
printf("\n\nHello from user mode!\n");
|
||||
for (;;) {}
|
||||
void syscall_write(struct stack_frame regs) {
|
||||
uint32_t fd = regs.edi;
|
||||
char *buf = (char *)regs.esi;
|
||||
//uint32_t count = regs.edx;
|
||||
|
||||
if (fd == FD_STDOUT) {
|
||||
printf("%s", buf);
|
||||
}
|
||||
}
|
||||
|
||||
void switch_to_user_mode(void *user_stack, void *user_entry) {
|
||||
|
@ -67,25 +83,6 @@ void switch_to_user_mode(void *user_stack, void *user_entry) {
|
|||
);
|
||||
}
|
||||
|
||||
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) {
|
||||
clear_screen();
|
||||
set_color(VGA_COLOR_CYAN);
|
||||
|
@ -95,22 +92,13 @@ void kmain(struct multiboot_info *info) {
|
|||
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);
|
||||
printf("[KERNEL] Detected %d bytes of memory\n", ctx.available_bytes);
|
||||
|
||||
// Create and load an IDT
|
||||
for (int i = 0; i < 32; i++) {
|
||||
|
@ -156,7 +144,7 @@ void kmain(struct multiboot_info *info) {
|
|||
goto halt;
|
||||
}
|
||||
|
||||
printf("Using ACPI v1.0\n");
|
||||
printf("[KERNEL] Using ACPI v1.0\n");
|
||||
|
||||
struct fadt *fadt = acpi_locate_sdt(ctx.rsdt, "FACP");
|
||||
if (!fadt) {
|
||||
|
@ -164,9 +152,9 @@ void kmain(struct multiboot_info *info) {
|
|||
printf("Failed to find FADT\n");
|
||||
goto halt;
|
||||
}
|
||||
printf("Found FADT at 0x%x\n", fadt);
|
||||
printf("[KERNEL] Found FADT at 0x%x\n", fadt);
|
||||
if (fadt->Flags & 1)
|
||||
printf("Legacy devices are supported\n");
|
||||
printf("[KERNEL] Legacy devices are supported\n");
|
||||
else {
|
||||
/*
|
||||
set_color(VGA_COLOR_RED);
|
||||
|
@ -176,10 +164,18 @@ void kmain(struct multiboot_info *info) {
|
|||
}
|
||||
pic_remap(PIC_1_START, PIC_2_START);
|
||||
// ACPI version 1.0 is so old that we assume that our PC supports the 8042 ps/2 controller
|
||||
initialize_8042ps2();
|
||||
encode_idt_entry(g_idt, 0x21, (uint32_t)&ps2_isr, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, 0x00), INT_GATE_32 | INT_RING0 | INT_PRESENT);
|
||||
asm volatile ("sti" ::);
|
||||
|
||||
// Allocate 4KiB for stdout
|
||||
stdout.data = mmap_find_first_free_block(&ctx);
|
||||
stdout.next = NULL;
|
||||
// Allocate 4KiB for stdin
|
||||
stdin.data = mmap_find_first_free_block(&ctx);
|
||||
stdin.next = NULL;
|
||||
|
||||
initialize_8042ps2();
|
||||
encode_idt_entry(g_idt, 0x21, (uint32_t)&ps2_isr, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), INT_GATE_32 | INT_RING0 | INT_PRESENT);
|
||||
asm volatile ("sti" ::);
|
||||
/*
|
||||
struct mcfg *mcfg = acpi_locate_sdt(ctx.rsdt, "MCFG");
|
||||
if (!mcfg) {
|
||||
set_color(VGA_COLOR_RED);
|
||||
|
@ -196,19 +192,62 @@ void kmain(struct multiboot_info *info) {
|
|||
ide_identify(ATA_PRIMARY, ATA_MASTER, ide_buf);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
set_color(VGA_COLOR_WHITE);
|
||||
|
||||
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);
|
||||
write_tss(&tss, gdt, 5, 0x10, 0x0);
|
||||
tss_flush(0x2B);
|
||||
encode_idt_entry(g_idt, 0x80, (uint32_t)&syscall_isr, GDT_SEGMENT_SELECTOR(GDT_USER_CODE, RING3), INT_GATE_32 | INT_RING3 | INT_PRESENT);
|
||||
|
||||
uint16_t cs_selector = 0x10; // Example code segment selector
|
||||
uint32_t eip = (uint32_t)&syscall; // Example entry point address
|
||||
uint32_t esp;
|
||||
|
||||
// Get the current value of ESP
|
||||
__asm__ volatile ("mov %%esp, %0" : "=r"(esp));
|
||||
|
||||
// Write to MSR_SYSENTER_CS (0x174)
|
||||
__asm__ volatile (
|
||||
"movl $0x174, %%ecx \n\t" // MSR address
|
||||
"movl %0, %%eax \n\t" // Lower 32 bits (cs_selector)
|
||||
"xor %%edx, %%edx \n\t" // Upper 32 bits (zero for 32-bit value)
|
||||
"wrmsr"
|
||||
:
|
||||
: "r"((uint32_t)cs_selector)
|
||||
: "eax", "ecx", "edx"
|
||||
);
|
||||
|
||||
// Write to MSR_SYSENTER_ESP (0x175)
|
||||
__asm__ volatile (
|
||||
"movl $0x175, %%ecx \n\t" // MSR address
|
||||
"movl %0, %%eax \n\t" // Lower 32 bits (esp)
|
||||
"xor %%edx, %%edx \n\t" // Upper 32 bits (zero for 32-bit value)
|
||||
"wrmsr"
|
||||
:
|
||||
: "r"(esp)
|
||||
: "eax", "ecx", "edx"
|
||||
);
|
||||
|
||||
// Write to MSR_SYSENTER_EIP (0x176)
|
||||
__asm__ volatile (
|
||||
"movl $0x176, %%ecx \n\t" // MSR address
|
||||
"movl %0, %%eax \n\t" // Lower 32 bits (eip)
|
||||
"xor %%edx, %%edx \n\t" // Upper 32 bits (zero for 32-bit value)
|
||||
"wrmsr"
|
||||
:
|
||||
: "r"(eip)
|
||||
: "eax", "ecx", "edx"
|
||||
);
|
||||
|
||||
void *page = mmap_find_first_free_block(&ctx);
|
||||
ata_read_sector(ATA_PRIMARY, ATA_MASTER, 0, page);
|
||||
printf("[KERNEL] Init program loaded to 0x%08X\n", page);
|
||||
printf("[KERNEL] Transferring control... goodbye\n");
|
||||
set_color(VGA_COLOR_WHITE);
|
||||
// 4 KiB for stack
|
||||
void *stack_bottom = mmap_find_first_free_block(&ctx);
|
||||
void *stack_top = stack_bottom + 4096;
|
||||
switch_to_user_mode(stack_top, buf);
|
||||
void *stack_top = stack_bottom + 0x1000;
|
||||
MAGIC_BREAKPOINT
|
||||
switch_to_user_mode(stack_top, page);
|
||||
halt:
|
||||
for (;;) {}
|
||||
}
|
||||
|
|
10
mem.c
10
mem.c
|
@ -19,14 +19,18 @@ void *mmap_block_to_physical(struct kernel_context *ctx, int block) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, uint32_t len) {
|
||||
void memset(void *s, int c, uint32_t len) {
|
||||
unsigned char *dst = s;
|
||||
while (len > 0) {
|
||||
*dst = (unsigned char) c;
|
||||
dst++;
|
||||
len--;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void memcpy(void *dest, void *src, int n) {
|
||||
for (int i=0; i<n; i++)
|
||||
((char *)dest)[i] = ((char *)src)[i];
|
||||
}
|
||||
|
||||
|
||||
|
@ -41,7 +45,6 @@ uint8_t mmap_init(struct kernel_context *ctx) {
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -113,6 +116,7 @@ void *mmap_find_first_free_block(struct kernel_context *ctx) {
|
|||
|
||||
uint32_t dword = ctx->mmap[index];
|
||||
if (!(dword & mask)) {
|
||||
mmap_set_block(ctx, i);
|
||||
return mmap_block_to_physical(ctx, i);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,15 +116,45 @@ isr_stub_table:
|
|||
|
||||
global ps2_isr
|
||||
ps2_isr:
|
||||
cli
|
||||
extern ps2_handler
|
||||
pushad
|
||||
cld
|
||||
and esp, 0xFFFFFFF0
|
||||
call ps2_handler
|
||||
popad
|
||||
iret
|
||||
|
||||
global test
|
||||
test:
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
|
||||
mov eax, 1
|
||||
mov edi, 0
|
||||
mov esi, buf
|
||||
int 0x80
|
||||
jmp $
|
||||
buf: db "Hello from stdout!", 0
|
||||
|
||||
global syscall_isr
|
||||
syscall_isr:
|
||||
xchg bx, bx
|
||||
pushad
|
||||
mov ecx, esp
|
||||
sysenter
|
||||
after_syscall:
|
||||
popad
|
||||
iret
|
||||
|
||||
global syscall
|
||||
syscall:
|
||||
imul eax, eax, 4
|
||||
add eax, syscall_table
|
||||
pushad
|
||||
call [eax]
|
||||
popad
|
||||
mov edx, after_syscall
|
||||
sysexit
|
||||
|
||||
; GDT for a flat memory layout
|
||||
; We get access to all memory and can utilize paging
|
||||
global gdt
|
||||
|
@ -167,6 +197,13 @@ gdtp:
|
|||
dw gdt_end - gdt - 1
|
||||
dd gdt
|
||||
|
||||
global syscall_table
|
||||
syscall_table:
|
||||
extern syscall_read
|
||||
dd syscall_read
|
||||
|
||||
extern syscall_write
|
||||
dd syscall_write
|
||||
|
||||
; Reserve 16KiB of kernel stack space
|
||||
section .bss
|
||||
|
|
3
ps2.c
3
ps2.c
|
@ -5,6 +5,7 @@
|
|||
#include <printf.h>
|
||||
#include <strcmp.h>
|
||||
#include <ide.h>
|
||||
#include <mem.h>
|
||||
|
||||
#define cpu_relax asm volatile ("pause" ::);
|
||||
|
||||
|
@ -54,6 +55,8 @@ void initialize_8042ps2() {
|
|||
outportb(PS2_8042_DATA, config);
|
||||
}
|
||||
|
||||
extern linked_mem_t stdin;
|
||||
|
||||
void ps2_handler() {
|
||||
uint8_t scancode = inportb(0x60);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user