Working on loading modules from filesystem & Creating symbol file for modules to link against

This commit is contained in:
notsomeidiot123 2024-12-02 17:16:33 -05:00
parent 41ef288243
commit 7fba027497
6 changed files with 58 additions and 13 deletions

View File

@ -2,13 +2,13 @@
## Basic Information ## Basic Information
Kimi's Bootloader is a custom booting solution and the default bootloader for Kimi's OS on legacy BIOS systems. It loads the default x86 GDT to be used by the Kernel. Kimi's Bootloader is a custom booting solution and the default bootloader for Kimi's OS on legacy BIOS systems. It loads the default x86 GDT to be used by the Kernel, and maps the kernel to any address as specified in it's ELF program header.
The bootloader also sets the video mode to the closest mode present to Standard definition, and obtains the BIOS memory map to be passed to the Kernel. The bootloader also sets the video mode to the closest mode present to Standard definition, and obtains the BIOS memory map to be passed to the Kernel.
### Features ### Features
It's not very feature rich, cause it's whole purpose was to do the bare minimum for what i needed for my own project. While I've made bootloaders before, they've typically only consisted of some code that gets a memory map, sets up a gdt, and says "fuck it, i'll load these next 64 sectors, why not?" however i wanted to do everything a bit better, make things easier on me in the long run, and now i have a bootloader that does the same thing but It's not very feature rich, cause it's whole purpose was to do the bare minimum for what i needed for my own project. While I've made bootloaders before, they've typically only consisted of some code that gets a memory map, sets up a gdt, and says "screw it, i'll load these next 64 sectors, why not?" however i wanted to do everything a bit better, make things easier on me in the long run, and now i have a bootloader that does the same thing but
- searches and loads any file named "kernel.elf" into memory (only supports legacy filenames for now, LFNs to be supported at a later date - searches and loads any file named "kernel.elf" into memory (only supports legacy filenames for now, LFNs to be supported at a later date
@ -44,6 +44,8 @@ It's not very feature rich, cause it's whole purpose was to do the bare minimum
- Selecting better load/copy addresses - Selecting better load/copy addresses
On loading the kernel file, I just pick some arbitrary, pre-chosen spot and say "yeah, this is good enough", but in reality i have on average only 400-ish kb until i start to overwrite the EBDA (which is bad, i do enjoy having ACPI). Instead, I want to implement a function to actually look for a continuous point in memory that is large enough to hold the entire kernel (ELF headers and all) without accidentally overwriting important information or running into memory barriers/holes. On loading the kernel file, I just pick some arbitrary, pre-chosen spot and say "yeah, this is good enough", but in reality i have on average only 400-ish kb until i start to overwrite the EBDA (which is bad, i do enjoy having ACPI). Instead, I want to implement a function to actually look for a continuous point in memory that is large enough to hold the entire kernel (ELF headers and all) without accidentally overwriting important information or running into memory barriers/holes.
Edit (11/21/24) I actually added this a *while* ago, but never updated the docs cause I'm forgetful
### A20 Line ### A20 Line
@ -66,6 +68,7 @@ If all else fails, the bootloader will attempt to enable the a20 line by using t
While any GDT loaded for the Kernel will work, once the Kernel wants to load user processes, it will fail to locate user segments in the GDT if the one loaded is not the one expected. Because of this, the Kernel will need to load it's own if the one it wants is not loaded by this bootloader. To allow for detection, the key "0xaa55" is written at the end of the GDT, marking the last segment invalid, but allowing for the detection of the correct GDT being pre-loaded. This detection will only occurr during boot time, and unexpected writes will cause the Kernel to crash. While any GDT loaded for the Kernel will work, once the Kernel wants to load user processes, it will fail to locate user segments in the GDT if the one loaded is not the one expected. Because of this, the Kernel will need to load it's own if the one it wants is not loaded by this bootloader. To allow for detection, the key "0xaa55" is written at the end of the GDT, marking the last segment invalid, but allowing for the detection of the correct GDT being pre-loaded. This detection will only occurr during boot time, and unexpected writes will cause the Kernel to crash.
#### GDT Layout: #### GDT Layout:
|INDEX|ENTRY TYPE| |INDEX|ENTRY TYPE|
|-----|----------| |-----|----------|
|0x00 |Null Entry| |0x00 |Null Entry|

View File

@ -1,7 +1,7 @@
ENTRY(_start) ENTRY(_start)
OUTPUT_FORMAT(elf32-i386) OUTPUT_FORMAT(elf32-i386)
/* OUTPUT_FORMAT(binary) */ /* OUTPUT_FORMAT(binary) */
OUTPUT(kernel.elf) /* OUTPUT(kernel.elf) */
/* SEARCH_DIR(bin/kernel) */ /* SEARCH_DIR(bin/kernel) */
SECTIONS{ SECTIONS{
. = 0xc0000000; . = 0xc0000000;

View File

@ -22,7 +22,8 @@ kernel:
sh c_build_helper.sh sh c_build_helper.sh
nasm src/kernel/arch_i386/idt.s -o bin/kernel/idt.o -felf32 nasm src/kernel/arch_i386/idt.s -o bin/kernel/idt.o -felf32
# ld -T linker.ld bin/kernel/entry.o bin/kernel/*.o -melf_i386 # ld -T linker.ld bin/kernel/entry.o bin/kernel/*.o -melf_i386
ld -T linker.ld bin/kernel/*.o -melf_i386 ld -T linker.ld bin/kernel/*.o -melf_i386 -o kernel.elf
ld -T linker.ld -o kernel_interface.elf -r -R kernel.elf -melf_i386
# %.o: $(SRCS) # %.o: $(SRCS)
# mkdir -p bin/kernel/$(shell dirname $@) # mkdir -p bin/kernel/$(shell dirname $@)
# $(CC) $(CFLAGS) $< -o $@ # $(CC) $(CFLAGS) $< -o $@

View File

@ -306,6 +306,7 @@ part_2:
; debug ; debug
mov edi, kernel_file mov edi, kernel_file
call open_file call open_file
add edx, 0x40000;is 200 kb enough for a filesystem diver and a disk driver?
call find_kpaddr call find_kpaddr
; debug ; debug
mov esi, eax mov esi, eax
@ -317,6 +318,7 @@ part_2:
; debug ; debug
mov esi, [kload_paddr] mov esi, [kload_paddr]
call load_elf call load_elf
; debug ; debug
push eax push eax
cli cli
@ -705,7 +707,9 @@ load_elf:
je .map_next je .map_next
xor edx, edx xor edx, edx
shr ecx, 12 shr ecx, 12
add dword [kload_paddr], 0x1000
.mloop: .mloop:
add dword [kload_paddr], 0x1000;
call map_addr call map_addr
add edi, 0x1000 add edi, 0x1000
add esi, 0x1000 add esi, 0x1000
@ -768,7 +772,28 @@ map_addr:
pop ebp pop ebp
ret ret
jmp $ jmp $
map_pages_id:
;edx = page count
;eax = addr
push esi
push edi
push edx
cmp eax, 1 << 22
je .ret
mov esi, eax
.loop:
cmp edx, 0
je .ret
mov edi, esi
call map_addr
add esi, 0x1000
dec edx
jmp .loop
.ret:
pop edx
pop edi
pop esi
ret;
;kernel info ;kernel info
k_info: k_info:
.memory_map_ptr: dd 0x2000 .memory_map_ptr: dd 0x2000
@ -778,13 +803,16 @@ k_info:
.xres: dw 80 .xres: dw 80
.yres: dw 25 .yres: dw 25
.framebuffer_ptr: dd 0xb8000 .framebuffer_ptr: dd 0xb8000
.loaded_modules: dd 0 .loaded_modules: dd disk_module_struct
.loaded_module_c: dd 0
;loaded_modules points to a struct array containing a ptr to the entry point of each pre-loaded module to be executed during startup ;loaded_modules points to a struct array containing a ptr to the entry point of each pre-loaded module to be executed during startup
;module_struct: disk_module_struct:
;.entry_point: dd 0 .ptr: dd 0
; cr3_load: dd 0 .type: dd 1
;.type: db 0 .next_entry: dd fs_module_struct
fs_module_struct:
.ptr: dd 0
.type: dd 2
.next_entry: dd 0
kernel_file: db "kernel", 0x0, 0x0, "elf" kernel_file: db "kernel", 0x0, 0x0, "elf"
loaded_fat_block: dd 0 loaded_fat_block: dd 0
last_allocated_pgtb: dd 0x10000 last_allocated_pgtb: dd 0x10000

View File

@ -19,6 +19,7 @@ extern void kmain(kernel_info_t *kernel_info){
pic_setmask(0xfe, PIC1_DATA); pic_setmask(0xfe, PIC1_DATA);
//TODO: Map and load filesystem and disk modules //TODO: Map and load filesystem and disk modules
//TODO: Start Initial Process //TODO: Start Initial Process
init_scheduler(); init_scheduler();
thread_start(pid0); thread_start(pid0);
enable_interrupts(); enable_interrupts();

View File

@ -3,6 +3,12 @@
#include "../drivers/serial.h" #include "../drivers/serial.h"
#include "interrupts.h" #include "interrupts.h"
typedef struct module_linked_list{
void *ptr;
uint32_t type;
struct module_linked_list *link;
}__attribute__((packed)) kernel_module_t;
typedef struct kernel_info{ typedef struct kernel_info{
void *mmap_ptr; void *mmap_ptr;
uint16_t mmap_entry_count; uint16_t mmap_entry_count;
@ -11,8 +17,14 @@ typedef struct kernel_info{
uint16_t monitor_x_resolution; uint16_t monitor_x_resolution;
uint16_t monitor_y_resolution; uint16_t monitor_y_resolution;
void *framebuffer; void *framebuffer;
void *loaded_modues; kernel_module_t *loaded_modules;
uint32_t loaded_module_count; // uint32_t loaded_module_count;
}__attribute__((packed)) kernel_info_t; }__attribute__((packed)) kernel_info_t;
#define MODULE_TYPE_DISK 1
#define MODULE_TYPE_FS 2
#define MODULE_TYPE_EXT 3
#define MODULE_TYPE_VIDEO 4
#define PANIC(m) kernel_panic(m, 0) #define PANIC(m) kernel_panic(m, 0)