2020-08-11 18:43:39 +03:00
|
|
|
#include <stdint.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdbool.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/real.h>
|
|
|
|
#include <lib/libc.h>
|
2021-04-07 03:10:28 +03:00
|
|
|
#include <lib/gterm.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>
|
2021-03-02 08:21:05 +03:00
|
|
|
#include <lib/fb.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-12-10 16:10:47 +03:00
|
|
|
#include <pxe/tftp.h>
|
2021-03-14 08:13:19 +03:00
|
|
|
#include <drivers/edid.h>
|
2021-04-04 05:51:55 +03:00
|
|
|
#include <drivers/vga_textmode.h>
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2021-05-05 00:00:26 +03:00
|
|
|
#define REPORTED_ADDR(PTR) \
|
|
|
|
((PTR) + ((stivale2_hdr.flags & (1 << 1)) ? \
|
|
|
|
(want_5lv ? 0xff00000000000000 : 0xffff800000000000) : 0))
|
|
|
|
|
2020-08-11 18:43:39 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-22 11:13:06 +03:00
|
|
|
#define append_tag(S, TAG) ({ \
|
|
|
|
(TAG)->next = (S)->tags; \
|
|
|
|
(S)->tags = REPORTED_ADDR((uint64_t)(uintptr_t)TAG); \
|
|
|
|
})
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2021-07-20 14:35:43 +03:00
|
|
|
#if defined (__i386__)
|
2021-04-07 03:10:28 +03:00
|
|
|
extern symbol stivale2_term_write_entry;
|
2021-07-20 14:35:43 +03:00
|
|
|
void *stivale2_rt_stack = NULL;
|
|
|
|
void *stivale2_term_buf = NULL;
|
2021-04-07 03:10:28 +03:00
|
|
|
#endif
|
|
|
|
|
2021-03-14 08:13:19 +03:00
|
|
|
void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table) {
|
2021-03-28 16:46:59 +03:00
|
|
|
struct file_handle *kernel_file = ext_mem_alloc(sizeof(struct file_handle));
|
2020-10-17 07:23:11 +03:00
|
|
|
|
2020-11-27 21:33:34 +03:00
|
|
|
char *kernel_path = config_get_value(config, 0, "KERNEL_PATH");
|
|
|
|
if (kernel_path == NULL)
|
2021-05-20 02:16:39 +03:00
|
|
|
panic("stivale2: KERNEL_PATH not specified");
|
2020-10-17 07:23:11 +03:00
|
|
|
|
2021-05-11 07:46:42 +03:00
|
|
|
print("stivale2: Loading kernel `%s`...\n", kernel_path);
|
|
|
|
|
2021-03-28 16:46:59 +03:00
|
|
|
if (!uri_open(kernel_file, kernel_path))
|
2021-06-30 19:44:31 +03:00
|
|
|
panic("stivale2: Failed to open kernel with path `%s`. Is the path correct?", kernel_path);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
char *kaslr_s = config_get_value(config, 0, "KASLR");
|
|
|
|
bool kaslr = true;
|
|
|
|
if (kaslr_s != NULL && strcmp(kaslr_s, "no") == 0)
|
|
|
|
kaslr = false;
|
|
|
|
|
2020-08-11 18:43:39 +03:00
|
|
|
struct stivale2_header stivale2_hdr;
|
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
bool level5pg = false;
|
|
|
|
uint64_t slide = 0;
|
|
|
|
uint64_t entry_point = 0;
|
2021-03-28 16:46:59 +03:00
|
|
|
|
2021-07-15 17:20:29 +03:00
|
|
|
struct elf_range *ranges;
|
|
|
|
uint64_t ranges_count;
|
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
uint8_t *kernel = freadall(kernel_file, STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE);
|
2020-10-17 07:23:11 +03:00
|
|
|
int bits = elf_bits(kernel);
|
2021-07-05 11:20:35 +03:00
|
|
|
bool loaded_by_anchor = false;
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
if (bits == -1) {
|
2021-07-05 13:20:47 +03:00
|
|
|
struct stivale2_anchor *anchor;
|
2021-07-05 23:51:03 +03:00
|
|
|
if (!stivale_load_by_anchor((void **)&anchor, "STIVALE2 ANCHOR", kernel, kernel_file->size)) {
|
2021-07-05 11:20:35 +03:00
|
|
|
panic("stivale2: Not a valid ELF or anchored file.");
|
|
|
|
}
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
bits = anchor->bits;
|
2021-03-26 17:47:59 +03:00
|
|
|
|
2021-07-05 13:20:47 +03:00
|
|
|
memcpy(&stivale2_hdr, (void *)(uintptr_t)anchor->phys_stivale2hdr,
|
2021-07-05 11:20:35 +03:00
|
|
|
sizeof(struct stivale2_header));
|
2021-04-15 05:32:49 +03:00
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
loaded_by_anchor = true;
|
|
|
|
}
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2021-07-15 17:20:29 +03:00
|
|
|
bool want_pmrs = false;
|
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
int ret = 0;
|
2020-08-11 18:43:39 +03:00
|
|
|
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))) {
|
2021-03-26 17:47:59 +03:00
|
|
|
panic("stivale2: 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))) {
|
2021-05-11 07:46:42 +03:00
|
|
|
printv("stivale2: CPU has 5-level paging support\n");
|
2020-08-11 18:43:39 +03:00
|
|
|
level5pg = true;
|
|
|
|
}
|
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
if (!loaded_by_anchor) {
|
2021-07-15 17:20:29 +03:00
|
|
|
ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
|
|
|
sizeof(struct stivale2_header), 0);
|
|
|
|
if (ret) {
|
|
|
|
goto failed_to_load_header_section;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((stivale2_hdr.flags & (1 << 2))) {
|
|
|
|
if (bits == 32) {
|
|
|
|
panic("stivale2: PMRs are not supported for 32-bit kernels");
|
|
|
|
} else if (loaded_by_anchor) {
|
|
|
|
panic("stivale2: PMRs are not supported for anchored kernels");
|
|
|
|
}
|
|
|
|
want_pmrs = true;
|
|
|
|
}
|
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
if (elf64_load(kernel, &entry_point, NULL, &slide,
|
2021-07-15 14:34:24 +03:00
|
|
|
STIVALE2_MMAP_KERNEL_AND_MODULES, kaslr, false,
|
2021-07-15 17:20:29 +03:00
|
|
|
want_pmrs ? &ranges : NULL,
|
|
|
|
want_pmrs ? &ranges_count : NULL))
|
2021-07-05 11:20:35 +03:00
|
|
|
panic("stivale2: ELF64 load failure");
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
ret = elf64_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
|
|
|
sizeof(struct stivale2_header), slide);
|
|
|
|
}
|
2020-12-28 01:11:11 +03:00
|
|
|
|
2020-08-11 18:43:39 +03:00
|
|
|
break;
|
|
|
|
}
|
2021-03-26 17:47:59 +03:00
|
|
|
case 32: {
|
2021-07-05 11:20:35 +03:00
|
|
|
if (!loaded_by_anchor) {
|
|
|
|
if (elf32_load(kernel, (uint32_t *)&entry_point, NULL, 10))
|
|
|
|
panic("stivale2: ELF32 load failure");
|
2021-03-26 17:47:59 +03:00
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
ret = elf32_load_section(kernel, &stivale2_hdr, ".stivale2hdr",
|
|
|
|
sizeof(struct stivale2_header));
|
|
|
|
}
|
2021-03-26 17:47:59 +03:00
|
|
|
|
2020-08-11 18:43:39 +03:00
|
|
|
break;
|
2021-03-26 17:47:59 +03:00
|
|
|
}
|
2020-08-11 18:43:39 +03:00
|
|
|
default:
|
2021-07-05 11:20:35 +03:00
|
|
|
panic("stivale2: Not 32 nor 64-bit kernel. What is this?");
|
2020-08-11 18:43:39 +03:00
|
|
|
}
|
|
|
|
|
2021-07-05 11:20:35 +03:00
|
|
|
printv("stivale2: %u-bit kernel detected\n", bits);
|
2021-05-11 07:12:47 +03:00
|
|
|
|
2021-07-15 17:20:29 +03:00
|
|
|
failed_to_load_header_section:
|
2020-08-11 18:43:39 +03:00
|
|
|
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.");
|
|
|
|
}
|
|
|
|
|
2021-05-05 01:53:18 +03:00
|
|
|
if ((stivale2_hdr.flags & (1 << 1)) && bits == 32) {
|
|
|
|
panic("stivale2: Higher half addresses header flag not supported in 32-bit mode.");
|
|
|
|
}
|
|
|
|
|
2021-05-05 00:00:26 +03:00
|
|
|
bool want_5lv = (get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_5LV_PAGING_ID) ? true : false) && level5pg;
|
|
|
|
|
2020-08-11 18:43:39 +03:00
|
|
|
if (stivale2_hdr.entry_point != 0)
|
|
|
|
entry_point = stivale2_hdr.entry_point;
|
|
|
|
|
2021-05-11 07:46:42 +03:00
|
|
|
if (verbose) {
|
|
|
|
print("stivale2: Kernel slide: %X\n", slide);
|
2021-05-11 07:12:47 +03:00
|
|
|
|
2021-05-11 07:46:42 +03:00
|
|
|
print("stivale2: Entry point at: %X\n", entry_point);
|
|
|
|
print("stivale2: Requested stack at: %X\n", stivale2_hdr.stack);
|
|
|
|
}
|
2021-05-11 07:12:47 +03:00
|
|
|
|
2021-07-26 20:25:59 +03:00
|
|
|
// The spec says the stack has to be 16-byte aligned
|
|
|
|
if ((stivale2_hdr.stack & (16 - 1)) != 0) {
|
|
|
|
panic("stivale2: Requested stack is not 16-byte aligned");
|
|
|
|
}
|
|
|
|
|
|
|
|
// It also says the stack cannot be NULL for 32-bit kernels
|
|
|
|
if (bits == 32 && stivale2_hdr.stack == 0) {
|
|
|
|
panic("stivale2: The stack cannot be 0 for 32-bit kernels");
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2021-03-28 16:46:59 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create kernel file struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
struct stivale2_struct_tag_kernel_file *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_kernel_file));
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_KERNEL_FILE_ID;
|
|
|
|
|
2021-05-05 00:00:26 +03:00
|
|
|
tag->kernel_file = REPORTED_ADDR((uint64_t)(uintptr_t)kernel);
|
2021-03-28 16:46:59 +03:00
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
2021-08-10 09:22:16 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create kernel file v2 struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
struct stivale2_struct_tag_kernel_file_v2 *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_kernel_file_v2));
|
|
|
|
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_KERNEL_FILE_V2_ID;
|
|
|
|
tag->kernel_file = REPORTED_ADDR((uint64_t)(uintptr_t)kernel);
|
|
|
|
tag->kernel_size = kernel_file->size;
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
2021-03-28 17:20:23 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create kernel slide struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
struct stivale2_struct_tag_kernel_slide *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_kernel_slide));
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_KERNEL_SLIDE_ID;
|
|
|
|
|
|
|
|
tag->kernel_slide = slide;
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
2020-08-11 18:43:39 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create firmware struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2020-12-31 05:26:19 +03:00
|
|
|
struct stivale2_struct_tag_firmware *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_firmware));
|
2020-08-11 18:43:39 +03:00
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_FIRMWARE_ID;
|
|
|
|
|
2021-07-15 11:03:47 +03:00
|
|
|
#if bios == 1
|
2020-08-11 18:43:39 +03:00
|
|
|
tag->flags = 1 << 0; // bit 0 = BIOS boot
|
2021-03-12 02:04:37 +03:00
|
|
|
#endif
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
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++) {
|
2020-11-27 21:33:34 +03:00
|
|
|
char *module_file = config_get_value(config, module_count, "MODULE_PATH");
|
|
|
|
if (module_file == NULL)
|
2020-10-20 09:51:56 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct stivale2_struct_tag_modules *tag =
|
2020-12-31 05:26:19 +03:00
|
|
|
ext_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
|
|
|
|
2020-11-27 21:33:34 +03:00
|
|
|
for (size_t i = 0; i < module_count; i++) {
|
|
|
|
char *module_path = config_get_value(config, i, "MODULE_PATH");
|
2020-08-11 18:43:39 +03:00
|
|
|
|
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-27 21:33:34 +03:00
|
|
|
char *module_string = config_get_value(config, i, "MODULE_STRING");
|
|
|
|
if (module_string == NULL) {
|
2020-08-11 18:43:39 +03:00
|
|
|
m->string[0] = '\0';
|
2020-11-27 21:33:34 +03:00
|
|
|
} else {
|
|
|
|
// TODO perhaps change this to be a pointer
|
|
|
|
size_t str_len = strlen(module_string);
|
|
|
|
if (str_len > 127)
|
|
|
|
str_len = 127;
|
|
|
|
memcpy(m->string, module_string, str_len);
|
2020-08-11 18:43:39 +03:00
|
|
|
}
|
|
|
|
|
2021-01-02 23:44:27 +03:00
|
|
|
print("stivale2: Loading module `%s`...\n", module_path);
|
|
|
|
|
2020-08-11 18:43:39 +03:00
|
|
|
struct file_handle f;
|
2020-11-27 21:33:34 +03:00
|
|
|
if (!uri_open(&f, module_path))
|
2021-06-30 19:44:31 +03:00
|
|
|
panic("stivale2: Failed to open module with path `%s`. Is the path correct?", module_path);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
2021-05-05 00:00:26 +03:00
|
|
|
m->begin = REPORTED_ADDR((uint64_t)(size_t)freadall(&f, STIVALE2_MMAP_KERNEL_AND_MODULES));
|
2020-08-11 18:43:39 +03:00
|
|
|
m->end = m->begin + f.size;
|
2021-05-11 07:12:47 +03:00
|
|
|
|
2021-05-11 07:46:42 +03:00
|
|
|
if (verbose) {
|
|
|
|
print("stivale2: Requested module %u:\n", i);
|
|
|
|
print(" Path: %s\n", module_path);
|
|
|
|
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-12-31 05:26:19 +03:00
|
|
|
struct stivale2_struct_tag_rsdp *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_rsdp));
|
2020-08-11 18:43:39 +03:00
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_RSDP_ID;
|
|
|
|
|
2021-05-05 00:00:26 +03:00
|
|
|
uint64_t rsdp = (uint64_t)(size_t)acpi_get_rsdp();
|
|
|
|
if (rsdp)
|
|
|
|
tag->rsdp = REPORTED_ADDR(rsdp);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
2021-04-28 21:15:24 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create SMBIOS struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
struct stivale2_struct_tag_smbios *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_smbios));
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_SMBIOS_ID;
|
|
|
|
|
2021-05-05 00:00:26 +03:00
|
|
|
uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0;
|
|
|
|
acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64);
|
|
|
|
|
|
|
|
if (smbios_entry_32)
|
|
|
|
tag->smbios_entry_32 = REPORTED_ADDR(smbios_entry_32);
|
|
|
|
if (smbios_entry_64)
|
|
|
|
tag->smbios_entry_64 = REPORTED_ADDR(smbios_entry_64);
|
2021-04-28 21:15:24 +03:00
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
2020-08-11 18:43:39 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create cmdline struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2020-12-31 05:26:19 +03:00
|
|
|
struct stivale2_struct_tag_cmdline *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_cmdline));
|
2020-08-11 18:43:39 +03:00
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_CMDLINE_ID;
|
|
|
|
|
2021-05-05 00:00:26 +03:00
|
|
|
tag->cmdline = REPORTED_ADDR((uint64_t)(size_t)cmdline);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create epoch struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2020-12-31 05:26:19 +03:00
|
|
|
struct stivale2_struct_tag_epoch *tag = ext_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();
|
2021-05-11 07:46:42 +03:00
|
|
|
printv("stivale2: Current epoch: %U\n", tag->epoch);
|
2020-08-11 18:43:39 +03:00
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create framebuffer struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2021-04-07 03:10:28 +03:00
|
|
|
|
|
|
|
struct fb_info *fb = NULL;
|
|
|
|
struct fb_info _fb;
|
|
|
|
|
2021-07-11 10:47:57 +03:00
|
|
|
struct stivale2_header_tag_any_video *avtag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_ANY_VIDEO_ID);
|
|
|
|
|
2021-04-11 02:26:50 +03:00
|
|
|
struct stivale2_header_tag_framebuffer *hdrtag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_FRAMEBUFFER_ID);
|
|
|
|
|
2021-07-11 10:47:57 +03:00
|
|
|
int req_width = 0, req_height = 0, req_bpp = 0;
|
2021-04-11 03:30:48 +03:00
|
|
|
|
|
|
|
if (hdrtag != NULL) {
|
|
|
|
req_width = hdrtag->framebuffer_width;
|
|
|
|
req_height = hdrtag->framebuffer_height;
|
|
|
|
req_bpp = hdrtag->framebuffer_bpp;
|
|
|
|
|
|
|
|
char *resolution = config_get_value(config, 0, "RESOLUTION");
|
|
|
|
if (resolution != NULL)
|
|
|
|
parse_resolution(&req_width, &req_height, &req_bpp, resolution);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct stivale2_header_tag_terminal *terminal_hdr_tag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_TERMINAL_ID);
|
|
|
|
|
2021-04-09 05:57:52 +03:00
|
|
|
if (bits == 64 && terminal_hdr_tag != NULL && hdrtag != NULL) {
|
2021-04-11 03:30:48 +03:00
|
|
|
term_vbe(req_width, req_height);
|
2021-04-09 05:57:52 +03:00
|
|
|
|
|
|
|
if (current_video_mode < 0) {
|
|
|
|
panic("stivale2: Failed to initialise terminal");
|
|
|
|
}
|
|
|
|
|
2021-04-07 03:10:28 +03:00
|
|
|
fb = &fbinfo;
|
|
|
|
|
|
|
|
struct stivale2_struct_tag_terminal *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_terminal));
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_TERMINAL_ID;
|
|
|
|
|
2021-07-11 09:51:22 +03:00
|
|
|
// We provide max allowed string length
|
|
|
|
tag->flags |= (1 << 1);
|
|
|
|
|
2021-07-20 14:35:43 +03:00
|
|
|
#if defined (__i386__)
|
|
|
|
if (stivale2_rt_stack == NULL) {
|
|
|
|
stivale2_rt_stack = ext_mem_alloc(8192);
|
|
|
|
}
|
|
|
|
|
|
|
|
stivale2_term_buf = ext_mem_alloc(8192);
|
|
|
|
|
2021-04-07 03:10:28 +03:00
|
|
|
tag->term_write = (uintptr_t)(void *)stivale2_term_write_entry;
|
2021-07-20 14:35:43 +03:00
|
|
|
tag->max_length = 8192;
|
|
|
|
#elif defined (__x86_64__)
|
2021-04-07 03:10:28 +03:00
|
|
|
tag->term_write = (uintptr_t)term_write;
|
2021-07-11 09:51:22 +03:00
|
|
|
tag->max_length = 0;
|
2021-04-07 03:10:28 +03:00
|
|
|
#endif
|
|
|
|
|
2021-04-14 11:44:55 +03:00
|
|
|
// We provide rows and cols
|
|
|
|
tag->flags |= (1 << 0);
|
|
|
|
tag->cols = term_cols;
|
|
|
|
tag->rows = term_rows;
|
|
|
|
|
2021-04-07 03:10:28 +03:00
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
|
|
|
|
goto skip_modeset;
|
|
|
|
} else {
|
|
|
|
fb = &_fb;
|
|
|
|
}
|
|
|
|
|
2021-07-15 11:03:47 +03:00
|
|
|
if (hdrtag != NULL || (avtag != NULL && uefi)
|
|
|
|
|| (avtag != NULL && avtag->preference == 0)) {
|
2021-04-07 03:10:28 +03:00
|
|
|
term_deinit();
|
|
|
|
|
|
|
|
if (fb_init(fb, req_width, req_height, req_bpp)) {
|
|
|
|
skip_modeset:;
|
2020-12-31 05:26:19 +03:00
|
|
|
struct stivale2_struct_tag_framebuffer *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_framebuffer));
|
2020-11-08 13:59:23 +03:00
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID;
|
|
|
|
|
2021-04-11 02:38:06 +03:00
|
|
|
memmap_alloc_range(fb->framebuffer_addr,
|
|
|
|
(uint64_t)fb->framebuffer_pitch * fb->framebuffer_height,
|
|
|
|
MEMMAP_FRAMEBUFFER, false, false, false, true);
|
|
|
|
|
2020-11-08 13:59:23 +03:00
|
|
|
tag->memory_model = STIVALE2_FBUF_MMODEL_RGB;
|
2021-05-05 00:00:26 +03:00
|
|
|
tag->framebuffer_addr = REPORTED_ADDR(fb->framebuffer_addr);
|
2021-04-07 03:10:28 +03:00
|
|
|
tag->framebuffer_width = fb->framebuffer_width;
|
|
|
|
tag->framebuffer_height = fb->framebuffer_height;
|
|
|
|
tag->framebuffer_bpp = fb->framebuffer_bpp;
|
|
|
|
tag->framebuffer_pitch = fb->framebuffer_pitch;
|
|
|
|
tag->red_mask_size = fb->red_mask_size;
|
|
|
|
tag->red_mask_shift = fb->red_mask_shift;
|
|
|
|
tag->green_mask_size = fb->green_mask_size;
|
|
|
|
tag->green_mask_shift = fb->green_mask_shift;
|
|
|
|
tag->blue_mask_size = fb->blue_mask_size;
|
|
|
|
tag->blue_mask_shift = fb->blue_mask_shift;
|
2020-11-08 13:59:23 +03:00
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
2021-03-31 02:48:27 +03:00
|
|
|
} else {
|
2021-07-15 11:03:47 +03:00
|
|
|
#if uefi == 1
|
2021-03-31 02:48:27 +03:00
|
|
|
panic("stivale2: Cannot use text mode with UEFI.");
|
2021-07-15 11:03:47 +03:00
|
|
|
#elif bios == 1
|
2021-04-04 05:51:55 +03:00
|
|
|
int rows, cols;
|
|
|
|
init_vga_textmode(&rows, &cols, false);
|
2021-07-11 11:07:43 +03:00
|
|
|
|
|
|
|
struct stivale2_struct_tag_textmode *tmtag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_textmode));
|
2021-07-31 20:59:05 +03:00
|
|
|
tmtag->tag.identifier = STIVALE2_STRUCT_TAG_TEXTMODE_ID;
|
2021-07-11 11:07:43 +03:00
|
|
|
|
|
|
|
tmtag->address = 0xb8000;
|
|
|
|
tmtag->rows = 25;
|
|
|
|
tmtag->cols = 80;
|
|
|
|
tmtag->bytes_per_char = 2;
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tmtag);
|
2021-03-31 02:48:27 +03:00
|
|
|
#endif
|
2020-08-11 18:43:39 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-14 08:13:19 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create EDID struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
struct edid_info_struct *edid_info = get_edid_info();
|
|
|
|
|
|
|
|
if (edid_info != NULL) {
|
|
|
|
struct stivale2_struct_tag_edid *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_edid) + sizeof(struct edid_info_struct));
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_EDID_ID;
|
|
|
|
|
|
|
|
tag->edid_size = sizeof(struct edid_info_struct);
|
|
|
|
|
|
|
|
memcpy(tag->edid_information, edid_info, sizeof(struct edid_info_struct));
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-15 11:03:47 +03:00
|
|
|
#if bios == 1
|
2021-04-14 12:06:14 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create PXE struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
if (pxe) {
|
|
|
|
struct stivale2_struct_tag_pxe_server_info *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_pxe_server_info));
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_PXE_SERVER_INFO;
|
|
|
|
tag->server_ip = get_boot_server_info();
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
(void)pxe;
|
|
|
|
#endif
|
|
|
|
|
2021-07-15 17:20:29 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create PMRs struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
if (want_pmrs) {
|
|
|
|
struct stivale2_struct_tag_pmrs *tag =
|
|
|
|
ext_mem_alloc(sizeof(struct stivale2_struct_tag_pmrs)
|
|
|
|
+ ranges_count * sizeof(struct stivale2_pmr));
|
|
|
|
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_PMRS_ID;
|
|
|
|
|
|
|
|
tag->entries = ranges_count;
|
|
|
|
|
|
|
|
memcpy(tag->pmrs, ranges, ranges_count * sizeof(struct stivale2_pmr));
|
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-14 08:13:19 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create EFI system table struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
|
|
|
if (efi_system_table != NULL) {
|
|
|
|
struct stivale2_struct_tag_efi_system_table *tag = ext_mem_alloc(sizeof(struct stivale2_struct_tag_efi_system_table));
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_EFI_SYSTEM_TABLE_ID;
|
|
|
|
|
2021-05-05 00:00:26 +03:00
|
|
|
tag->system_table = REPORTED_ADDR((uint64_t)(uintptr_t)efi_system_table);
|
2021-03-14 08:13:19 +03:00
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-04-14 12:06:14 +03:00
|
|
|
bool unmap_null = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_UNMAP_NULL_ID) ? true : false;
|
2020-09-26 16:06:59 +03:00
|
|
|
|
|
|
|
pagemap_t pagemap = {0};
|
|
|
|
if (bits == 64)
|
2021-07-15 17:20:29 +03:00
|
|
|
pagemap = stivale_build_pagemap(want_5lv, unmap_null,
|
|
|
|
want_pmrs ? ranges : NULL,
|
|
|
|
want_pmrs ? ranges_count : 0);
|
2020-09-11 17:17:55 +03:00
|
|
|
|
2021-07-15 11:03:47 +03:00
|
|
|
#if uefi == 1
|
2021-03-07 08:50:04 +03:00
|
|
|
efi_exit_boot_services();
|
|
|
|
#endif
|
|
|
|
|
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,
|
2021-05-05 00:00:26 +03:00
|
|
|
bits == 64, want_5lv,
|
2021-07-15 17:20:29 +03:00
|
|
|
pagemap, smp_hdr_tag->flags & 1, want_pmrs);
|
2020-10-20 03:38:01 +03:00
|
|
|
|
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-11-14 15:29:30 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// Create memmap struct tag
|
|
|
|
//////////////////////////////////////////////
|
|
|
|
{
|
2021-04-15 03:21:38 +03:00
|
|
|
struct stivale2_struct_tag_memmap *tag =
|
|
|
|
ext_mem_alloc(sizeof(struct stivale2_struct_tag_memmap) +
|
|
|
|
sizeof(struct e820_entry_t) * 256);
|
|
|
|
|
2021-04-15 05:08:20 +03:00
|
|
|
// Reserve 32K at 0x70000
|
|
|
|
memmap_alloc_range(0x70000, 0x8000, MEMMAP_USABLE, true, true, false, false);
|
|
|
|
|
2021-07-06 06:17:18 +03:00
|
|
|
size_t mmap_entries;
|
|
|
|
struct e820_entry_t *mmap = get_memmap(&mmap_entries);
|
2020-11-14 15:29:30 +03:00
|
|
|
|
|
|
|
tag->tag.identifier = STIVALE2_STRUCT_TAG_MEMMAP_ID;
|
2021-07-06 06:17:18 +03:00
|
|
|
tag->entries = (uint64_t)mmap_entries;
|
2020-11-14 15:29:30 +03:00
|
|
|
|
|
|
|
memcpy((void*)tag + sizeof(struct stivale2_struct_tag_memmap),
|
2021-07-06 06:17:18 +03:00
|
|
|
mmap, sizeof(struct e820_entry_t) * mmap_entries);
|
2020-11-14 15:29:30 +03:00
|
|
|
|
|
|
|
append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
|
|
|
|
}
|
|
|
|
|
2021-05-11 07:12:47 +03:00
|
|
|
//////////////////////////////////////////////
|
|
|
|
// List tags
|
|
|
|
//////////////////////////////////////////////
|
2021-05-11 07:46:42 +03:00
|
|
|
if (verbose) {
|
|
|
|
print("stivale2: Generated tags:\n");
|
2021-05-22 23:20:26 +03:00
|
|
|
struct stivale2_tag *taglist =
|
|
|
|
(void*)(uintptr_t)(stivale2_struct.tags & (uint64_t)0xffffffff);
|
2021-05-11 07:46:42 +03:00
|
|
|
for (size_t i = 0; ; i++) {
|
|
|
|
print(" Tag #%u ID: %X\n", i, taglist->identifier);
|
2021-05-22 23:20:26 +03:00
|
|
|
if (taglist->next) {
|
|
|
|
taglist = (void*)(uintptr_t)(taglist->next & (uint64_t)0xffffffff);
|
|
|
|
} else {
|
2021-05-11 07:46:42 +03:00
|
|
|
break;
|
2021-05-22 23:20:26 +03:00
|
|
|
}
|
2021-05-11 07:46:42 +03:00
|
|
|
}
|
2021-05-11 07:12:47 +03:00
|
|
|
}
|
|
|
|
|
2021-04-11 11:15:14 +03:00
|
|
|
// Clear terminal for kernels that will use the stivale2 terminal
|
|
|
|
term_write("\e[2J\e[H", 7);
|
|
|
|
|
2021-05-05 00:00:26 +03:00
|
|
|
stivale_spinup(bits, want_5lv, &pagemap, entry_point,
|
2021-05-23 04:34:36 +03:00
|
|
|
REPORTED_ADDR((uint64_t)(uintptr_t)&stivale2_struct),
|
2021-07-15 17:20:29 +03:00
|
|
|
stivale2_hdr.stack, want_pmrs);
|
2020-08-11 18:43:39 +03:00
|
|
|
}
|