HhhOS/arch/x86_64/kernel.c
2021-08-24 20:56:50 +03:00

167 lines
6.4 KiB
C

#include <types.h>
#include <stivale2.h>
#include <std/inline.h>
#include <std/util.h>
#include <stdbool.h>
#include <std/stdio.h>
#include <drivers/idt/isr.h>
#include <drivers/keyboard/keyboard.h>
#include <prog/shell.h>
#include <drivers/pic/pic.h>
#include <drivers/device/device.h>
#include <drivers/ide/ide.h>
#include <framebuffer.h>
#include <psf.h>
#include <paging.h>
#include <mem/mem.h>
#include <kernel.h>
static u8 stack[16384];
int keyboard_descriptor = 0;
int terminal_descriptor = 0;
// stivale2 uses a linked list of tags for both communicating TO the
// bootloader, or receiving info FROM it. More information about these tags
// is found in the stivale2 specification.
// We are now going to define a framebuffer header tag, which is mandatory when
// using the stivale2 terminal.
// This tag tells the bootloader that we want a graphical framebuffer instead
// of a CGA-compatible text mode. Omitting this tag will make the bootloader
// default to text mode, if available.
static struct stivale2_header_tag_framebuffer framebuffer_hdr_tag = {
// Same as above.
.tag = {
.identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID,
.next = 0
},
// set all the framebuffer specifics to 0 for it to pick the best it can.
.framebuffer_width = 800,
.framebuffer_height = 600,
.framebuffer_bpp = 32
};
// The stivale2 specification says we need to define a "header structure".
// This structure needs to reside in the .stivale2hdr ELF section in order
// for the bootloader to find it. We use this __attribute__ directive to
// tell the compiler to put the following structure in said section.
__attribute__((section(".stivale2hdr"), used))
static struct stivale2_header stivale_hdr = {
// The entry_point member is used to specify an alternative entry
// point that the bootloader should jump to instead of the executable's
// ELF entry point. We do not care about that so we leave it zeroed.
.entry_point = 0,
// Let's tell the bootloader where our stack is.
// We need to add the sizeof(stack) since in x86(_64) the stack grows
// downwards.
.stack = (uintptr_t)stack + sizeof(stack),
// Bit 1, if set, causes the bootloader to return to us pointers in the
// higher half, which we likely want.
.flags = (1 << 1),
// This header structure is the root of the linked list of header tags and
// points to the first one in the linked list.
.tags = (uintptr_t)&framebuffer_hdr_tag
};
void *stivale2_get_tag(struct stivale2_struct *stivale2_struct, u64 id) {
struct stivale2_tag *current_tag = (void *)stivale2_struct->tags;
for (;;) {
// If the tag pointer is NULL (end of linked list), we did not find
// the tag. Return NULL to signal this.
if (current_tag == NULL) {
return NULL;
}
// Check whether the identifier matches. If it does, return a pointer
// to the matching tag.
if (current_tag->identifier == id) {
return current_tag;
}
// Get a pointer to the next tag in the linked list and repeat.
current_tag = (void *)current_tag->next;
}
}
framebuffer_t *framebuffer;
extern usize _kernel_start;
extern usize _kernel_end;
u64 total_memory;
bool using_framebuffer = false;
void _start(struct stivale2_struct *stivale2_struct) {
struct stivale2_struct_tag_framebuffer *tag_fb = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID);
struct stivale2_struct_tag_memmap *tag_mmap = stivale2_get_tag(stivale2_struct, STIVALE2_STRUCT_TAG_MEMMAP_ID);
if (tag_fb == NULL || tag_mmap == NULL) {
printf("Requested stivale2 tags were not found, hanging...");
for (;;) {
asm ("hlt");
}
}
framebuffer->address = (u8*)tag_fb->framebuffer_addr;
framebuffer->width = tag_fb->framebuffer_width;
framebuffer->height = tag_fb->framebuffer_height;
framebuffer->depth = tag_fb->framebuffer_bpp;
framebuffer->pitch = tag_fb->framebuffer_pitch;
framebuffer->pixelwidth = tag_fb->framebuffer_bpp / 8;
terminal_descriptor = terminal_initialize(framebuffer);
using_framebuffer = true;
printf("Terminal initialized, descriptor: %d\n", terminal_descriptor);
printf("Framebuffer | addr: %#lX, width: %d, height: %d, depth: %d, pitch: %d\n", (usize)framebuffer->address, framebuffer->width, framebuffer->height, framebuffer->depth, framebuffer->pitch);
u64 largest_usable_base, largest_usable_size;
for (u64 i = 0; i < tag_mmap->entries; i++) {
struct stivale2_mmap_entry entry = tag_mmap->memmap[i];
char *entry_name;
switch (entry.type) {
case STIVALE2_MMAP_USABLE:
entry_name = "Usable";
if (entry.length > largest_usable_size) {
largest_usable_base = entry.base;
largest_usable_size = entry.length;
}
break;
case STIVALE2_MMAP_RESERVED: entry_name = "Reserved"; break;
case STIVALE2_MMAP_ACPI_RECLAIMABLE: entry_name = "ACPI Reclaimable"; break;
case STIVALE2_MMAP_ACPI_NVS: entry_name = "ACPI NVS"; break;
case STIVALE2_MMAP_BAD_MEMORY: entry_name = "Bad Memory"; break;
case STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE: entry_name = "Bootloader Reclaimable"; break;
case STIVALE2_MMAP_KERNEL_AND_MODULES: entry_name = "Kernel and Modules"; break;
case STIVALE2_MMAP_FRAMEBUFFER: entry_name = "Framebuffer"; break;
default: entry_name = "Unknown";
}
total_memory += entry.length;
printf("Memory map entry | name: %s, base: %#lX, length: %ld KiB\n", entry_name, entry.base, entry.length / 1024);
}
printf("Total memory: %ld KiB\n", total_memory / 1024);
printf("Memory map entry chosen for memory manager | base: %#lX, length: %ld KiB\n", largest_usable_base, largest_usable_size / 1024);
mem_populate_blocks(largest_usable_base);
printf("Preparing interrupts... ");
pic_init();
isr_install();
printf("done\n");
keyboard_descriptor = keyboard_init();
printf("Keyboard ready, descriptor: %d\n", keyboard_descriptor);
usize start_mem_addr = (usize)_start;
printf("_start memory address: %#lX\n", start_mem_addr);
shell_register_basic_commands();
shell_start(keyboard_descriptor);
}
bool is_using_framebuffer() {
return using_framebuffer;
}
u64 get_total_memory() {
return total_memory;
}