2020-03-25 23:05:14 +03:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <protos/stivale.h>
|
|
|
|
#include <lib/elf.h>
|
2020-03-26 02:46:35 +03:00
|
|
|
#include <lib/blib.h>
|
2020-03-26 03:37:56 +03:00
|
|
|
#include <lib/acpi.h>
|
2020-03-27 04:10:22 +03:00
|
|
|
#include <lib/e820.h>
|
2020-03-30 23:27:15 +03:00
|
|
|
#include <lib/config.h>
|
2020-03-26 05:13:19 +03:00
|
|
|
#include <drivers/vbe.h>
|
2020-04-19 14:20:26 +03:00
|
|
|
#include <drivers/vga_textmode.h>
|
2020-04-14 06:20:55 +03:00
|
|
|
#include <fs/file.h>
|
2020-03-25 23:05:14 +03:00
|
|
|
|
|
|
|
struct stivale_header {
|
|
|
|
uint64_t stack;
|
2020-04-18 19:01:29 +03:00
|
|
|
// Flags
|
|
|
|
// bit 0 0 = text mode, 1 = graphics mode
|
|
|
|
uint16_t flags;
|
2020-03-26 05:13:19 +03:00
|
|
|
uint16_t framebuffer_width;
|
|
|
|
uint16_t framebuffer_height;
|
2020-03-27 07:58:37 +03:00
|
|
|
uint16_t framebuffer_bpp;
|
2020-03-26 02:46:35 +03:00
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
struct stivale_module {
|
|
|
|
uint64_t begin;
|
|
|
|
uint64_t end;
|
|
|
|
char string[128];
|
2020-03-30 23:27:15 +03:00
|
|
|
uint64_t next;
|
2020-03-26 02:46:35 +03:00
|
|
|
} __attribute__((packed));
|
|
|
|
|
|
|
|
struct stivale_struct {
|
2020-03-27 07:08:20 +03:00
|
|
|
uint64_t cmdline;
|
2020-03-26 02:46:35 +03:00
|
|
|
uint64_t memory_map_addr;
|
|
|
|
uint64_t memory_map_entries;
|
|
|
|
uint64_t framebuffer_addr;
|
|
|
|
uint16_t framebuffer_pitch;
|
|
|
|
uint16_t framebuffer_width;
|
|
|
|
uint16_t framebuffer_height;
|
|
|
|
uint16_t framebuffer_bpp;
|
2020-03-26 03:37:56 +03:00
|
|
|
uint64_t rsdp;
|
2020-03-26 02:46:35 +03:00
|
|
|
uint64_t module_count;
|
2020-03-30 23:27:15 +03:00
|
|
|
uint64_t modules;
|
2020-03-26 02:46:35 +03:00
|
|
|
} __attribute__((packed));
|
|
|
|
|
2020-03-26 06:06:23 +03:00
|
|
|
struct stivale_struct stivale_struct = {0};
|
2020-03-25 23:05:14 +03:00
|
|
|
|
2020-04-14 06:20:55 +03:00
|
|
|
void stivale_load(struct file_handle *fd, char *cmdline) {
|
2020-03-26 02:46:35 +03:00
|
|
|
struct stivale_header stivale_hdr;
|
2020-04-18 19:01:29 +03:00
|
|
|
|
|
|
|
int bits = elf_bits(fd);
|
|
|
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
print("stivale: %u-bit ELF file detected\n", bits);
|
|
|
|
|
|
|
|
switch (bits) {
|
|
|
|
case 64:
|
|
|
|
ret = elf64_load_section(fd, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header));
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
ret = elf32_load_section(fd, &stivale_hdr, ".stivalehdr", sizeof(struct stivale_header));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-03-26 02:46:35 +03:00
|
|
|
switch (ret) {
|
|
|
|
case 1:
|
2020-04-18 19:01:29 +03:00
|
|
|
panic("stivale: File is not a valid ELF.\n");
|
2020-03-26 02:46:35 +03:00
|
|
|
case 2:
|
2020-04-18 19:01:29 +03:00
|
|
|
panic("stivale: Section .stivalehdr not found.\n");
|
2020-03-26 02:46:35 +03:00
|
|
|
case 3:
|
2020-04-18 19:01:29 +03:00
|
|
|
panic("stivale: Section .stivalehdr exceeds the size of the struct.\n");
|
2020-03-26 02:46:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
print("stivale: Requested stack at %X\n", stivale_hdr.stack);
|
|
|
|
|
2020-04-18 19:01:29 +03:00
|
|
|
uint64_t entry_point = 0;
|
|
|
|
uint64_t top_used_addr = 0;
|
|
|
|
switch (bits) {
|
|
|
|
case 64:
|
|
|
|
elf64_load(fd, &entry_point, &top_used_addr);
|
|
|
|
break;
|
|
|
|
case 32:
|
|
|
|
elf32_load(fd, (uint32_t *)&entry_point, (uint32_t *)&top_used_addr);
|
|
|
|
break;
|
|
|
|
}
|
2020-03-30 23:27:15 +03:00
|
|
|
|
|
|
|
print("stivale: Top used address in ELF: %X\n", top_used_addr);
|
2020-03-25 23:05:14 +03:00
|
|
|
|
2020-03-27 04:10:22 +03:00
|
|
|
stivale_struct.memory_map_entries = (uint64_t)init_e820();
|
|
|
|
stivale_struct.memory_map_addr = (uint64_t)(size_t)e820_map;
|
|
|
|
|
2020-03-30 23:27:15 +03:00
|
|
|
stivale_struct.module_count = 0;
|
|
|
|
uint64_t *prev_mod_ptr = &stivale_struct.modules;
|
|
|
|
for (int i = 0; ; i++) {
|
|
|
|
char module_file[64];
|
|
|
|
if (!config_get_value(module_file, i, 64, "MODULE_PATH"))
|
|
|
|
break;
|
|
|
|
|
|
|
|
stivale_struct.module_count++;
|
|
|
|
|
|
|
|
struct stivale_module *m = balloc(sizeof(struct stivale_module));
|
|
|
|
|
|
|
|
config_get_value(m->string, i, 128, "MODULE_STRING");
|
|
|
|
|
|
|
|
int part; {
|
|
|
|
char buf[32];
|
|
|
|
config_get_value(buf, i, 32, "MODULE_PARTITION");
|
|
|
|
part = (int)strtoui(buf);
|
|
|
|
}
|
|
|
|
|
2020-04-14 06:20:55 +03:00
|
|
|
struct file_handle f;
|
|
|
|
fopen(&f, fd->disk, part, module_file);
|
2020-03-30 23:27:15 +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-04-14 06:20:55 +03:00
|
|
|
fread(&f, module_addr, 0, f.size);
|
2020-03-30 23:27:15 +03:00
|
|
|
|
|
|
|
m->begin = (uint64_t)(size_t)module_addr;
|
2020-04-14 06:20:55 +03:00
|
|
|
m->end = m->begin + f.size;
|
2020-03-30 23:27:15 +03:00
|
|
|
m->next = 0;
|
|
|
|
|
|
|
|
top_used_addr = (uint64_t)(size_t)m->end;
|
|
|
|
|
|
|
|
*prev_mod_ptr = (uint64_t)(size_t)m;
|
|
|
|
prev_mod_ptr = &m->next;
|
|
|
|
|
|
|
|
print("stivale: Requested module %u:\n", i);
|
|
|
|
print(" Path: %s\n", module_file);
|
|
|
|
print(" String: %s\n", m->string);
|
|
|
|
print(" Begin: %X\n", m->begin);
|
|
|
|
print(" End: %X\n", m->end);
|
|
|
|
}
|
|
|
|
|
2020-03-26 03:37:56 +03:00
|
|
|
stivale_struct.rsdp = (uint64_t)(size_t)get_rsdp();
|
|
|
|
|
2020-03-31 11:48:24 +03:00
|
|
|
stivale_struct.cmdline = (uint64_t)(size_t)cmdline;
|
|
|
|
|
2020-03-26 05:13:19 +03:00
|
|
|
stivale_struct.framebuffer_width = stivale_hdr.framebuffer_width;
|
|
|
|
stivale_struct.framebuffer_height = stivale_hdr.framebuffer_height;
|
2020-03-27 07:58:37 +03:00
|
|
|
stivale_struct.framebuffer_bpp = stivale_hdr.framebuffer_bpp;
|
2020-03-26 05:13:19 +03:00
|
|
|
|
2020-04-18 19:01:29 +03:00
|
|
|
if ((stivale_hdr.flags & 1) == 1) {
|
2020-03-26 05:13:19 +03:00
|
|
|
init_vbe(&stivale_struct.framebuffer_addr,
|
|
|
|
&stivale_struct.framebuffer_pitch,
|
|
|
|
&stivale_struct.framebuffer_width,
|
2020-03-27 07:58:37 +03:00
|
|
|
&stivale_struct.framebuffer_height,
|
|
|
|
&stivale_struct.framebuffer_bpp);
|
2020-04-19 14:20:26 +03:00
|
|
|
} else {
|
|
|
|
deinit_vga_textmode();
|
2020-03-26 05:13:19 +03:00
|
|
|
}
|
|
|
|
|
2020-04-18 19:01:29 +03:00
|
|
|
if (bits == 64) {
|
|
|
|
struct pagemap {
|
|
|
|
uint64_t pml4[512];
|
|
|
|
uint64_t pml3_lo[512];
|
|
|
|
uint64_t pml3_hi[512];
|
|
|
|
uint64_t pml2_0gb[512];
|
|
|
|
uint64_t pml2_1gb[512];
|
|
|
|
uint64_t pml2_2gb[512];
|
|
|
|
uint64_t pml2_3gb[512];
|
|
|
|
};
|
|
|
|
struct pagemap *pagemap = balloc_aligned(sizeof(struct pagemap), 0x1000);
|
|
|
|
|
|
|
|
// first, zero out the pagemap
|
|
|
|
for (uint64_t *p = (uint64_t *)pagemap; p < &pagemap->pml3_hi[512]; p++)
|
|
|
|
*p = 0;
|
|
|
|
|
|
|
|
pagemap->pml4[511] = (uint64_t)(size_t)pagemap->pml3_hi | 0x03;
|
|
|
|
pagemap->pml4[256] = (uint64_t)(size_t)pagemap->pml3_lo | 0x03;
|
|
|
|
pagemap->pml4[0] = (uint64_t)(size_t)pagemap->pml3_lo | 0x03;
|
|
|
|
pagemap->pml3_hi[510] = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
|
|
|
|
pagemap->pml3_hi[511] = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
|
|
|
|
pagemap->pml3_lo[0] = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
|
|
|
|
pagemap->pml3_lo[1] = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
|
|
|
|
pagemap->pml3_lo[2] = (uint64_t)(size_t)pagemap->pml2_2gb | 0x03;
|
|
|
|
pagemap->pml3_lo[3] = (uint64_t)(size_t)pagemap->pml2_3gb | 0x03;
|
|
|
|
|
|
|
|
// populate the page directories
|
|
|
|
for (size_t i = 0; i < 512 * 4; i++)
|
|
|
|
(&pagemap->pml2_0gb[0])[i] = (i * 0x200000) | 0x03 | (1 << 7);
|
|
|
|
|
|
|
|
asm volatile (
|
|
|
|
"cli\n\t"
|
|
|
|
"cld\n\t"
|
|
|
|
"mov cr3, eax\n\t"
|
|
|
|
"mov eax, cr4\n\t"
|
|
|
|
"or eax, 1 << 5\n\t"
|
|
|
|
"mov cr4, eax\n\t"
|
|
|
|
"mov ecx, 0xc0000080\n\t"
|
|
|
|
"rdmsr\n\t"
|
|
|
|
"or eax, 1 << 8\n\t"
|
|
|
|
"wrmsr\n\t"
|
|
|
|
"mov eax, cr0\n\t"
|
|
|
|
"or eax, 1 << 31\n\t"
|
|
|
|
"mov cr0, eax\n\t"
|
|
|
|
"jmp 0x28:1f\n\t"
|
|
|
|
"1: .code64\n\t"
|
|
|
|
"mov ax, 0x30\n\t"
|
|
|
|
"mov ds, ax\n\t"
|
|
|
|
"mov es, ax\n\t"
|
|
|
|
"mov fs, ax\n\t"
|
|
|
|
"mov gs, ax\n\t"
|
|
|
|
"mov ss, ax\n\t"
|
|
|
|
"mov rsp, [rsi]\n\t"
|
|
|
|
"call [rbx]\n\t"
|
|
|
|
".code32\n\t"
|
|
|
|
:
|
|
|
|
: "a" (pagemap), "b" (&entry_point),
|
|
|
|
"D" (&stivale_struct), "S" (&stivale_hdr.stack)
|
|
|
|
);
|
|
|
|
} else if (bits == 32) {
|
|
|
|
asm volatile (
|
|
|
|
"cli\n\t"
|
|
|
|
"cld\n\t"
|
|
|
|
"mov esp, [esi]\n\t"
|
|
|
|
"push edi\n\t"
|
|
|
|
"call [ebx]\n\t"
|
|
|
|
:
|
|
|
|
: "b" (&entry_point), "D" (&stivale_struct), "S" (&stivale_hdr.stack)
|
|
|
|
);
|
|
|
|
}
|
2020-03-25 23:05:14 +03:00
|
|
|
}
|