added syscalls & fixed bug in mem manager

This commit is contained in:
rami 2024-05-26 01:24:40 -05:00
parent 8b58e8663f
commit 7830b92f87
11 changed files with 214 additions and 106 deletions

28
gdt.c Normal file
View 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)
);
}

BIN
image.img Normal file

Binary file not shown.

View File

@ -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

View File

@ -2,10 +2,17 @@
#define RK_GDT_H_ #define RK_GDT_H_
#include <stdint.h> #include <stdint.h>
#include <mem.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_USER_CODE 3
#define GDT_USER_DATA 4
#define RING0 0
#define RING3 3
#define GDT_SEGMENT_SELECTOR(i, p) ((i << 3) | p) #define GDT_SEGMENT_SELECTOR(i, p) ((i << 3) | p)
struct gdt_entry { struct gdt_entry {
@ -47,4 +54,7 @@ struct tss_entry {
uint16_t iomap_base; uint16_t iomap_base;
} __attribute__((packed)); } __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 #endif

View File

@ -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_find_first_free_block(struct kernel_context *ctx);
void *mmap_block_to_physical(struct kernel_context *ctx, int block); 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 #endif

171
kmain.c
View File

@ -11,35 +11,51 @@
#include <ps2.h> #include <ps2.h>
#include <ide.h> #include <ide.h>
#include <mem.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 MAGIC_BREAKPOINT __asm__ volatile("xchgw %bx, %bx");
#define FD_STDOUT 0
#define FD_STDIN 1
#define USER_DS 0x23 // User data segment selector struct kernel_context ctx = {0};
#define USER_CS 0x1B // User code segment selector 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 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; struct tss_entry tss;
void tss_flush(uint16_t tss_selector) { struct stack_frame {
asm volatile ( uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
"ltr %0" };
: // no output
: "r" (tss_selector) 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() { void syscall_write(struct stack_frame regs) {
printf("\n\nHello from user mode!\n"); uint32_t fd = regs.edi;
for (;;) {} 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) { 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) { void kmain(struct multiboot_info *info) {
clear_screen(); clear_screen();
set_color(VGA_COLOR_CYAN); 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 = (struct multiboot_mmap_entry *)info->memMapAddress;
ctx.multi_mmap_size = info->memMapLength / sizeof(struct multiboot_mmap_entry); 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)) { if (!mmap_init(&ctx)) {
set_color(VGA_COLOR_RED); set_color(VGA_COLOR_RED);
printf("Failed to create memory map\n"); printf("Failed to create memory map\n");
goto halt; 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 // Create and load an IDT
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
@ -156,7 +144,7 @@ void kmain(struct multiboot_info *info) {
goto halt; goto halt;
} }
printf("Using ACPI v1.0\n"); printf("[KERNEL] Using ACPI v1.0\n");
struct fadt *fadt = acpi_locate_sdt(ctx.rsdt, "FACP"); struct fadt *fadt = acpi_locate_sdt(ctx.rsdt, "FACP");
if (!fadt) { if (!fadt) {
@ -164,9 +152,9 @@ void kmain(struct multiboot_info *info) {
printf("Failed to find FADT\n"); printf("Failed to find FADT\n");
goto halt; goto halt;
} }
printf("Found FADT at 0x%x\n", fadt); printf("[KERNEL] Found FADT at 0x%x\n", fadt);
if (fadt->Flags & 1) if (fadt->Flags & 1)
printf("Legacy devices are supported\n"); printf("[KERNEL] Legacy devices are supported\n");
else { else {
/* /*
set_color(VGA_COLOR_RED); set_color(VGA_COLOR_RED);
@ -176,10 +164,18 @@ void kmain(struct multiboot_info *info) {
} }
pic_remap(PIC_1_START, PIC_2_START); 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 // 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"); struct mcfg *mcfg = acpi_locate_sdt(ctx.rsdt, "MCFG");
if (!mcfg) { if (!mcfg) {
set_color(VGA_COLOR_RED); set_color(VGA_COLOR_RED);
@ -196,19 +192,62 @@ void kmain(struct multiboot_info *info) {
ide_identify(ATA_PRIMARY, ATA_MASTER, ide_buf); ide_identify(ATA_PRIMARY, ATA_MASTER, ide_buf);
} }
} }
*/
set_color(VGA_COLOR_WHITE); write_tss(&tss, gdt, 5, 0x10, 0x0);
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); 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_bottom = mmap_find_first_free_block(&ctx);
void *stack_top = stack_bottom + 4096; void *stack_top = stack_bottom + 0x1000;
switch_to_user_mode(stack_top, buf); MAGIC_BREAKPOINT
switch_to_user_mode(stack_top, page);
halt: halt:
for (;;) {} for (;;) {}
} }

10
mem.c
View File

@ -19,14 +19,18 @@ void *mmap_block_to_physical(struct kernel_context *ctx, int block) {
return 0; return 0;
} }
void *memset(void *s, int c, uint32_t len) { void memset(void *s, int c, uint32_t len) {
unsigned char *dst = s; unsigned char *dst = s;
while (len > 0) { while (len > 0) {
*dst = (unsigned char) c; *dst = (unsigned char) c;
dst++; dst++;
len--; 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; 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 // Loop again to find the first region with enough space to hold the memory map
int index = -1; int index = -1;
@ -113,6 +116,7 @@ void *mmap_find_first_free_block(struct kernel_context *ctx) {
uint32_t dword = ctx->mmap[index]; uint32_t dword = ctx->mmap[index];
if (!(dword & mask)) { if (!(dword & mask)) {
mmap_set_block(ctx, i);
return mmap_block_to_physical(ctx, i); return mmap_block_to_physical(ctx, i);
} }
} }

View File

@ -116,15 +116,45 @@ isr_stub_table:
global ps2_isr global ps2_isr
ps2_isr: ps2_isr:
cli
extern ps2_handler extern ps2_handler
pushad pushad
cld cld
and esp, 0xFFFFFFF0
call ps2_handler call ps2_handler
popad popad
iret 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 ; 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
global gdt global gdt
@ -167,6 +197,13 @@ gdtp:
dw gdt_end - gdt - 1 dw gdt_end - gdt - 1
dd gdt 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 ; Reserve 16KiB of kernel stack space
section .bss section .bss

3
ps2.c
View File

@ -5,6 +5,7 @@
#include <printf.h> #include <printf.h>
#include <strcmp.h> #include <strcmp.h>
#include <ide.h> #include <ide.h>
#include <mem.h>
#define cpu_relax asm volatile ("pause" ::); #define cpu_relax asm volatile ("pause" ::);
@ -54,6 +55,8 @@ void initialize_8042ps2() {
outportb(PS2_8042_DATA, config); outportb(PS2_8042_DATA, config);
} }
extern linked_mem_t stdin;
void ps2_handler() { void ps2_handler() {
uint8_t scancode = inportb(0x60); uint8_t scancode = inportb(0x60);

15
test.a Normal file
View File

@ -0,0 +1,15 @@
[org 0x6000]
[bits 32]
_start:
push ebp
mov ebp, esp
; Syscall #1 = write
mov eax, 1
; File descriptor = stdout
mov edi, 0
; ESI = buffer
mov esi, buf
int 0x80
jmp $
buf: db "Andew skibidi pomni", 0