2020-08-11 18:43:39 +03:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdbool.h>
|
2020-08-29 21:02:16 +03:00
|
|
|
#include <limine.h>
|
2020-09-02 10:55:56 +03:00
|
|
|
#include <protos/stivale.h>
|
2020-08-11 18:43:39 +03:00
|
|
|
#include <protos/stivale2.h>
|
|
|
|
#include <lib/elf.h>
|
|
|
|
#include <lib/blib.h>
|
|
|
|
#include <lib/acpi.h>
|
|
|
|
#include <lib/config.h>
|
|
|
|
#include <lib/time.h>
|
|
|
|
#include <lib/print.h>
|
|
|
|
#include <lib/rand.h>
|
|
|
|
#include <lib/real.h>
|
|
|
|
#include <lib/libc.h>
|
2020-11-02 11:20:34 +03:00
|
|
|
#include <lib/uri.h>
|
2020-09-18 21:02:10 +03:00
|
|
|
#include <sys/smp.h>
|
2020-10-12 22:49:17 +03:00
|
|
|
#include <sys/cpu.h>
|
2020-08-11 18:43:39 +03:00
|
|
|
#include <drivers/vbe.h>
|
2020-09-02 10:55:56 +03:00
|
|
|
#include <lib/term.h>
|
2020-09-18 21:02:10 +03:00
|
|
|
#include <sys/pic.h>
|
2020-09-27 02:32:47 +03:00
|
|
|
#include <sys/lapic.h>
|
2020-08-11 18:43:39 +03:00
|
|
|
#include <fs/file.h>
|
2020-09-20 13:03:44 +03:00
|
|
|
#include <mm/pmm.h>
|
2020-09-18 13:51:26 +03:00
|
|
|
#include <stivale/stivale2.h>
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
#define KASLR_SLIDE_BITMASK 0x03FFFF000u
|
|
|
|
|
|
|
|
struct stivale2_struct stivale2_struct = {0};
|
|
|
|
|
|
|
|
inline static size_t get_phys_addr(uint64_t addr) {
|
|
|
|
if (addr & ((uint64_t)1 << 63))
|
|
|
|
return addr - FIXED_HIGHER_HALF_OFFSET_64;
|
|
|
|
return addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *get_tag(struct stivale2_header *s, uint64_t id) {
|
|
|
|
struct stivale2_tag *tag = (void*)get_phys_addr(s->tags);
|
|
|
|
for (;;) {
|
|
|
|
if (tag == NULL)
|
|
|
|
return NULL;
|
|
|
|
if (tag->identifier == id)
|
|
|
|
return tag;
|
|
|
|
tag = (void*)get_phys_addr(tag->next);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void append_tag(struct stivale2_struct *s, struct stivale2_tag *tag) {
|
|
|
|
tag->next = s->tags;
|
|
|
|
s->tags = (uint64_t)(size_t)tag;
|
|
|
|
}
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
void stivale2_load(char *config, char *cmdline) {
|
2020-10-17 07:23:11 +03:00
|
|
|
char buf[128];
|
|
|
|
|
|
|
|
struct file_handle *kernel = conv_mem_alloc(sizeof(struct file_handle));
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
if (!config_get_value(config, buf, 0, 128, "KERNEL_PATH"))
|
2020-10-17 07:23:11 +03:00
|
|
|
panic("KERNEL_PATH not specified");
|
|
|
|
|
|
|
|
if (!uri_open(kernel, buf))
|
|
|
|
panic("Could not open kernel resource");
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
struct stivale2_header stivale2_hdr;
|
|
|
|
|
2020-10-17 07:23:11 +03:00
|
|
|
int bits = elf_bits(kernel);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
uint64_t slide = 0;
|
|
|
|
|
|
|
|
bool level5pg = false;
|
|
|
|
switch (bits) {
|
|
|
|
case 64: {
|
|
|
|
// Check if 64 bit CPU
|
|
|
|
uint32_t eax, ebx, ecx, edx;
|
2020-11-16 23:23:11 +03:00
|
|
|
if (!cpuid(0x80000001, 0, &eax, &ebx, &ecx, &edx) || !(edx & (1 << 29))) {
|
|
|
|
panic("stivale: This CPU does not support 64-bit mode.");
|
2020-08-11 18:43:39 +03:00
|
|
|
}
|
|
|
|
// Check if 5-level paging is available
|
2020-11-16 23:23:11 +03:00
|
|
|
if (cpuid(0x00000007, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 16))) {
|
|
|
|
print("stivale: CPU has 5-level paging support\n");
|
2020-08-11 18:43:39 +03:00
|
|
|
level5pg = true;
|
|
|
|
}
|
|
|
|
|
2020-10-17 07:23:11 +03:00
|
|
|
ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), slide);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
if (!ret && (stivale2_hdr.flags & 1)) {
|
|
|
|
// KASLR is enabled, set the slide
|
|
|
|
slide = rand64() & KASLR_SLIDE_BITMASK;
|
|
|
|
|
|
|
|
// Re-read the .stivale2hdr with slid relocations
|
2020-10-17 07:23:11 +03:00
|
|
|
ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header), slide);
|
2020-08-11 18:43:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 32:
|
2020-10-17 07:23:11 +03:00
|
|
|
ret = elf32_load_section(kernel, &stivale2_hdr, ".stivale2hdr", sizeof(struct stivale2_header));
|
2020-08-11 18:43:39 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
panic("stivale2: Not 32 nor 64 bit x86 ELF file.");
|
|
|
|
}
|
|
|
|
|
|
|
|
print("stivale2: %u-bit ELF file detected\n", bits);
|
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
case 1:
|
|
|
|
panic("stivale2: File is not a valid ELF.");
|
|
|
|
case 2:
|
|
|
|
panic("stivale2: Section .stivale2hdr not found.");
|
|
|
|
case 3:
|
|
|
|
panic("stivale2: Section .stivale2hdr exceeds the size of the struct.");
|
|
|
|
case 4:
|
|
|
|
panic("stivale2: Section .stivale2hdr is smaller than size of the struct.");
|
|
|
|
}
|
|
|
|
|
|
|
|
print("stivale2: Requested stack at %X\n", stivale2_hdr.stack);
|
|
|
|
|
|
|
|
uint64_t entry_point = 0;
|
|
|
|
uint64_t top_used_addr = 0;
|
|
|
|
|
|
|
|
switch (bits) {
|
|
|
|
case 64:
|
2020-10-17 07:23:11 +03:00
|
|
|
elf64_load(kernel, &entry_point, &top_used_addr, slide, 0x1001);
|
2020-08-11 18:43:39 +03:00
|
|
|
break;
|
|
|
|
case 32:
|
2020-10-17 07:23:11 +03:00
|
|
|
elf32_load(kernel, (uint32_t *)&entry_point, (uint32_t *)&top_used_addr, 0x1001);
|
2020-08-11 18:43:39 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stivale2_hdr.entry_point != 0)
|
|
|
|
entry_point = stivale2_hdr.entry_point;
|
|
|
|
|
|
|
|
print("stivale2: Kernel slide: %X\n", slide);
|
|
|
|
|
|
|
|
print("stivale2: Top used address in ELF: %X\n", top_used_addr);
|
|
|
|
|
2020-08-29 21:02:16 +03:00
|
|
|
strcpy(stivale2_struct.bootloader_brand, "Limine");
|
|
|
|
strcpy(stivale2_struct.bootloader_version, LIMINE_VERSION);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create firmware struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2020-09-20 13:03:44 +03:00
|
|
|
struct stivale2_struct_tag_firmware *tag = conv_mem_alloc(sizeof(struct stivale2_struct_tag_firmware));
|
2020-08-11 18:43:39 +03:00
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_FIRMWARE_ID;
|
|
|
|
|
|
|
|
tag->flags = 1 << 0; // bit 0 = BIOS boot
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create modules struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2020-10-20 09:51:56 +03:00
|
|
|
size_t module_count;
|
|
|
|
for (module_count = 0; ; module_count++) {
|
|
|
|
char module_file[64];
|
2020-11-17 01:31:03 +03:00
|
|
|
if (!config_get_value(config, module_file, module_count, 64, "MODULE_PATH"))
|
2020-10-20 09:51:56 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct stivale2_struct_tag_modules *tag =
|
|
|
|
conv_mem_alloc(sizeof(struct stivale2_struct_tag_modules)
|
|
|
|
+ sizeof(struct stivale2_module) * module_count);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2020-10-20 09:51:56 +03:00
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_MODULES_ID;
|
|
|
|
tag->module_count = module_count;
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
for (int i = 0; ; i++) {
|
2020-11-18 02:53:11 +03:00
|
|
|
if (!config_get_value(config, buf, i, 128, "MODULE_PATH"))
|
2020-08-11 18:43:39 +03:00
|
|
|
break;
|
|
|
|
|
2020-10-20 09:51:56 +03:00
|
|
|
struct stivale2_module *m = &tag->modules[i];
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
if (!config_get_value(config, m->string, i, 128, "MODULE_STRING")) {
|
2020-08-11 18:43:39 +03:00
|
|
|
m->string[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
struct file_handle f;
|
2020-11-18 02:53:11 +03:00
|
|
|
if (!uri_open(&f, buf))
|
|
|
|
panic("Requested module with path \"%s\" not found!", buf);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
void *module_addr = (void *)(((uint32_t)top_used_addr & 0xfff) ?
|
|
|
|
((uint32_t)top_used_addr & ~((uint32_t)0xfff)) + 0x1000 :
|
|
|
|
(uint32_t)top_used_addr);
|
|
|
|
|
2020-11-18 02:53:11 +03:00
|
|
|
print("stivale2: Loading module `%s`...\n", buf);
|
2020-10-16 17:04:30 +03:00
|
|
|
|
2020-08-11 19:00:51 +03:00
|
|
|
memmap_alloc_range((size_t)module_addr, f.size, 0x1001);
|
2020-08-11 18:43:39 +03:00
|
|
|
fread(&f, module_addr, 0, f.size);
|
|
|
|
|
|
|
|
m->begin = (uint64_t)(size_t)module_addr;
|
|
|
|
m->end = m->begin + f.size;
|
|
|
|
|
|
|
|
top_used_addr = (uint64_t)(size_t)m->end;
|
|
|
|
|
|
|
|
print("stivale2: Requested module %u:\n", i);
|
2020-11-18 02:53:11 +03:00
|
|
|
print(" Path: %s\n", buf);
|
2020-08-11 19:00:51 +03:00
|
|
|
print(" String: %s\n", m->string);
|
|
|
|
print(" Begin: %X\n", m->begin);
|
|
|
|
print(" End: %X\n", m->end);
|
2020-08-11 18:43:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create RSDP struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2020-09-20 13:03:44 +03:00
|
|
|
struct stivale2_struct_tag_rsdp *tag = conv_mem_alloc(sizeof(struct stivale2_struct_tag_rsdp));
|
2020-08-11 18:43:39 +03:00
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_RSDP_ID;
|
|
|
|
|
2020-09-17 13:06:35 +03:00
|
|
|
tag->rsdp = (uint64_t)(size_t)acpi_get_rsdp();
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create cmdline struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2020-09-20 13:03:44 +03:00
|
|
|
struct stivale2_struct_tag_cmdline *tag = conv_mem_alloc(sizeof(struct stivale2_struct_tag_cmdline));
|
2020-08-11 18:43:39 +03:00
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_CMDLINE_ID;
|
|
|
|
|
|
|
|
tag->cmdline = (uint64_t)(size_t)cmdline;
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create epoch struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2020-09-20 13:03:44 +03:00
|
|
|
struct stivale2_struct_tag_epoch *tag = conv_mem_alloc(sizeof(struct stivale2_struct_tag_epoch));
|
2020-08-11 18:43:39 +03:00
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_EPOCH_ID;
|
|
|
|
|
|
|
|
tag->epoch = time();
|
|
|
|
print("stivale2: Current epoch: %U\n", tag->epoch);
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create framebuffer struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2020-09-18 13:51:26 +03:00
|
|
|
struct stivale2_header_tag_framebuffer *hdrtag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_FRAMEBUFFER_ID);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2020-09-02 10:55:56 +03:00
|
|
|
term_deinit();
|
|
|
|
|
|
|
|
if (hdrtag != NULL) {
|
2020-11-09 14:31:47 +03:00
|
|
|
int req_width = hdrtag->framebuffer_width;
|
|
|
|
int req_height = hdrtag->framebuffer_height;
|
|
|
|
int req_bpp = hdrtag->framebuffer_bpp;
|
|
|
|
|
2020-11-17 01:31:03 +03:00
|
|
|
if (config_get_value(config, buf, 0, 128, "RESOLUTION"))
|
2020-11-09 14:31:47 +03:00
|
|
|
parse_resolution(&req_width, &req_height, &req_bpp, buf);
|
|
|
|
|
2020-11-08 13:59:23 +03:00
|
|
|
struct vbe_framebuffer_info fbinfo;
|
2020-11-09 14:31:47 +03:00
|
|
|
if (init_vbe(&fbinfo, req_width, req_height, req_bpp)) {
|
2020-11-08 13:59:23 +03:00
|
|
|
struct stivale2_struct_tag_framebuffer *tag = conv_mem_alloc(sizeof(struct stivale2_struct_tag_framebuffer));
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID;
|
|
|
|
|
|
|
|
tag->memory_model = STIVALE2_FBUF_MMODEL_RGB;
|
2020-11-09 14:31:47 +03:00
|
|
|
tag->framebuffer_addr = fbinfo.framebuffer_addr;
|
2020-11-08 13:59:23 +03:00
|
|
|
tag->framebuffer_width = fbinfo.framebuffer_width;
|
|
|
|
tag->framebuffer_height = fbinfo.framebuffer_height;
|
|
|
|
tag->framebuffer_bpp = fbinfo.framebuffer_bpp;
|
|
|
|
tag->framebuffer_pitch = fbinfo.framebuffer_pitch;
|
|
|
|
tag->red_mask_size = fbinfo.red_mask_size;
|
|
|
|
tag->red_mask_shift = fbinfo.red_mask_shift;
|
|
|
|
tag->green_mask_size = fbinfo.green_mask_size;
|
|
|
|
tag->green_mask_shift = fbinfo.green_mask_shift;
|
|
|
|
tag->blue_mask_size = fbinfo.blue_mask_size;
|
|
|
|
tag->blue_mask_shift = fbinfo.blue_mask_shift;
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
2020-08-11 18:43:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-26 16:06:59 +03:00
|
|
|
// Check if 5-level paging tag is requesting support
|
|
|
|
bool level5pg_requested = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_5LV_PAGING_ID) ? true : false;
|
|
|
|
|
|
|
|
pagemap_t pagemap = {0};
|
|
|
|
if (bits == 64)
|
2020-11-08 01:50:01 +03:00
|
|
|
pagemap = stivale_build_pagemap(level5pg && level5pg_requested);
|
2020-09-11 17:17:55 +03:00
|
|
|
|
2020-09-18 15:39:29 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create SMP struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
struct stivale2_header_tag_smp *smp_hdr_tag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_SMP_ID);
|
|
|
|
if (smp_hdr_tag != NULL) {
|
2020-10-25 14:41:13 +03:00
|
|
|
struct stivale2_struct_tag_smp *tag;
|
2020-10-20 03:38:01 +03:00
|
|
|
struct smp_information *smp_info;
|
|
|
|
size_t cpu_count;
|
2020-10-25 06:58:53 +03:00
|
|
|
uint32_t bsp_lapic_id;
|
2020-10-25 14:41:13 +03:00
|
|
|
smp_info = init_smp(sizeof(struct stivale2_struct_tag_smp), (void **)&tag,
|
|
|
|
&cpu_count, &bsp_lapic_id,
|
2020-10-25 06:58:53 +03:00
|
|
|
bits == 64, level5pg && level5pg_requested,
|
2020-10-20 03:38:01 +03:00
|
|
|
pagemap, smp_hdr_tag->flags & 1);
|
|
|
|
|
2020-10-22 16:25:10 +03:00
|
|
|
if (smp_info != NULL) {
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_SMP_ID;
|
2020-10-25 06:58:53 +03:00
|
|
|
tag->bsp_lapic_id = bsp_lapic_id;
|
2020-10-22 16:25:10 +03:00
|
|
|
tag->cpu_count = cpu_count;
|
|
|
|
tag->flags |= (smp_hdr_tag->flags & 1) && x2apic_check();
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
2020-09-18 15:39:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-19 01:15:31 +03:00
|
|
|
print("Generated tags:\n");
|
|
|
|
struct stivale2_tag *taglist = (void*)(size_t)stivale2_struct.tags;
|
|
|
|
for (size_t i = 0; ; i++) {
|
|
|
|
print("Tag #%u ID: %X\n", i, taglist->identifier);
|
|
|
|
if (taglist->next)
|
|
|
|
taglist = (void*)(size_t)taglist->next;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-11-14 15:29:30 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create memmap struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
size_t memmap_entries;
|
|
|
|
struct e820_entry_t *memmap = get_memmap(&memmap_entries);
|
|
|
|
|
|
|
|
struct stivale2_struct_tag_memmap *tag =
|
|
|
|
conv_mem_alloc(sizeof(struct stivale2_struct_tag_memmap) +
|
|
|
|
sizeof(struct e820_entry_t) * memmap_entries);
|
|
|
|
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_MEMMAP_ID;
|
|
|
|
tag->entries = (uint64_t)memmap_entries;
|
|
|
|
|
|
|
|
memcpy((void*)tag + sizeof(struct stivale2_struct_tag_memmap),
|
|
|
|
memmap, sizeof(struct e820_entry_t) * memmap_entries);
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
2020-09-18 15:39:29 +03:00
|
|
|
stivale_spinup(bits, level5pg && level5pg_requested, pagemap,
|
|
|
|
entry_point, &stivale2_struct, stivale2_hdr.stack);
|
2020-08-11 18:43:39 +03:00
|
|
|
}
|