Merge pull request #121 from pitust/trunk

Introduce bootboot support
This commit is contained in:
mint 2021-11-02 19:54:42 +01:00 committed by GitHub
commit f3aee7feb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 549 additions and 30 deletions

View File

@ -99,6 +99,14 @@ Some keys take *URIs* as values; these are described in the next section.
Note that one can define this last variable multiple times to specify multiple Note that one can define this last variable multiple times to specify multiple
modules. modules.
* `RESOLUTION` - The resolution to be used. This setting takes the form of `<width>x<height>x<bpp>`. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32. * `RESOLUTION` - The resolution to be used. This setting takes the form of `<width>x<height>x<bpp>`. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
* Bootboot protocol:
* `KERNEL_PATH` - The URI path of the kernel.
* `INITRD_PATH` - The URI path to the ramdisk/initrd.
* `BOOTBOOT_ENV` - A configuration key to be passed into the kernel.
Note that one can define this last variable multiple times to specify multiple
environemnt keys.
* `RESOLUTION` - The resolution to be used. This setting takes the form of `<width>x<height>x<bpp>`. If the resolution is not available, Limine will pick another one automatically. Omitting `<bpp>` will default to 32.
* stivale and stivale2 protocols: * stivale and stivale2 protocols:
* `KERNEL_PATH` - The URI path of the kernel. * `KERNEL_PATH` - The URI path of the kernel.
* `MODULE_PATH` - The URI path to a module. * `MODULE_PATH` - The URI path to a module.

View File

@ -18,6 +18,7 @@ Like Limine and want to support it? Donate Bitcoin to
### Supported boot protocols ### Supported boot protocols
* stivale and stivale2 (Limine's native boot protocols, see [their specifications](https://github.com/stivale/stivale) for details) * stivale and stivale2 (Limine's native boot protocols, see [their specifications](https://github.com/stivale/stivale) for details)
* Bootboot (Another hobby OS boot protocol designed for microkernels, see the [specification](https://gitlab.com/bztsrc/bootboot) for details)
* Linux * Linux
* Multiboot 1 * Multiboot 1
* Multiboot 2 * Multiboot 2

View File

@ -14,6 +14,7 @@
#include <mm/pmm.h> #include <mm/pmm.h>
#include <protos/stivale.h> #include <protos/stivale.h>
#include <protos/stivale2.h> #include <protos/stivale2.h>
#include <protos/bootboot.h>
#include <protos/linux.h> #include <protos/linux.h>
#include <protos/chainload.h> #include <protos/chainload.h>
#include <protos/multiboot1.h> #include <protos/multiboot1.h>
@ -177,6 +178,8 @@ void stage3_common(void) {
multiboot1_load(config, cmdline); multiboot1_load(config, cmdline);
} else if (!strcmp(proto, "multiboot2")) { } else if (!strcmp(proto, "multiboot2")) {
multiboot2_load(config, cmdline); multiboot2_load(config, cmdline);
} else if (!strcmp(proto, "bootboot")) {
bootboot_load(config);
} }
panic("Invalid protocol specified"); panic("Invalid protocol specified");

View File

@ -43,6 +43,7 @@ size_t get_trailing_zeros(uint64_t val);
int digit_to_int(char c); int digit_to_int(char c);
uint8_t bcd_to_int(uint8_t val); uint8_t bcd_to_int(uint8_t val);
uint8_t int_to_bcd(uint8_t val);
__attribute__((noreturn)) void panic(const char *fmt, ...); __attribute__((noreturn)) void panic(const char *fmt, ...);

View File

@ -8,6 +8,9 @@ bool verbose = true;
uint8_t bcd_to_int(uint8_t val) { uint8_t bcd_to_int(uint8_t val) {
return (val & 0x0f) + ((val & 0xf0) >> 4) * 10; return (val & 0x0f) + ((val & 0xf0) >> 4) * 10;
} }
uint8_t int_to_bcd(uint8_t val) {
return (val % 10) | (val / 10) << 4;
}
int digit_to_int(char c) { int digit_to_int(char c) {
if (c >= 'a' && c <= 'f') { if (c >= 'a' && c <= 'f') {

View File

@ -26,22 +26,6 @@
#define EI_VERSION 6 #define EI_VERSION 6
#define EI_OSABI 7 #define EI_OSABI 7
struct elf64_hdr {
uint8_t ident[16];
uint16_t type;
uint16_t machine;
uint32_t version;
uint64_t entry;
uint64_t phoff;
uint64_t shoff;
uint32_t flags;
uint16_t hdr_size;
uint16_t phdr_size;
uint16_t ph_num;
uint16_t shdr_size;
uint16_t sh_num;
uint16_t shstrndx;
};
struct elf32_hdr { struct elf32_hdr {
uint8_t ident[16]; uint8_t ident[16];
@ -82,19 +66,6 @@ struct elf32_phdr {
uint32_t p_align; uint32_t p_align;
}; };
struct elf64_shdr {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
};
struct elf32_shdr { struct elf32_shdr {
uint32_t sh_name; uint32_t sh_name;
uint32_t sh_type; uint32_t sh_type;

View File

@ -35,4 +35,41 @@ int elf32_load(uint8_t *elf, uint32_t *entry_point, uint32_t *top, uint32_t allo
int elf32_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit); int elf32_load_section(uint8_t *elf, void *buffer, const char *name, size_t limit);
struct elf_section_hdr_info* elf32_section_hdr_info(uint8_t *elf); struct elf_section_hdr_info* elf32_section_hdr_info(uint8_t *elf);
struct elf64_hdr {
uint8_t ident[16];
uint16_t type;
uint16_t machine;
uint32_t version;
uint64_t entry;
uint64_t phoff;
uint64_t shoff;
uint32_t flags;
uint16_t hdr_size;
uint16_t phdr_size;
uint16_t ph_num;
uint16_t shdr_size;
uint16_t sh_num;
uint16_t shstrndx;
};
struct elf64_shdr {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
uint64_t sh_addr;
uint64_t sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
};
struct elf64_sym {
uint32_t st_name;
uint8_t st_info;
uint8_t st_other;
uint16_t st_shndx;
uint64_t st_value;
uint64_t st_size;
};
#endif #endif

View File

@ -46,6 +46,28 @@ uint64_t time(void) {
uint8_t hour = bcd_to_int((r.ecx & 0xff00) >> 8); uint8_t hour = bcd_to_int((r.ecx & 0xff00) >> 8);
return get_unix_epoch(second, minute, hour, day, month, year); return get_unix_epoch(second, minute, hour, day, month, year);
}
void bootboot_time(
uint32_t* day, uint32_t* month, uint32_t* year,
uint32_t* second, uint32_t* minute, uint32_t* hour) {
struct rm_regs r = {0};
r.eax = 0x0400;
rm_int(0x1a, &r, &r);
*day = bcd_to_int( r.edx & 0x00ff);
*month = bcd_to_int((r.edx & 0xff00) >> 8);
*year = bcd_to_int( r.ecx & 0x00ff) +
/* century */ bcd_to_int((r.ecx & 0xff00) >> 8) * 100;
r.eax = 0x0200;
rm_int(0x1a, &r, &r);
*second = bcd_to_int((r.edx & 0xff00) >> 8);
*minute = bcd_to_int( r.ecx & 0x00ff);
*hour = bcd_to_int((r.ecx & 0xff00) >> 8);
} }
#endif #endif
@ -57,4 +79,13 @@ uint64_t time(void) {
return get_unix_epoch(time.Second, time.Minute, time.Hour, return get_unix_epoch(time.Second, time.Minute, time.Hour,
time.Day, time.Month, time.Year); time.Day, time.Month, time.Year);
} }
void bootboot_time(
uint32_t* day, uint32_t* month, uint32_t* year,
uint32_t* second, uint32_t* minute, uint32_t* hour) {
EFI_TIME time;
gRT->GetTime(&time, NULL);
*day = time.Day; *month = time.Month; *year = time.Year;
*second = time.Second; *minute = time.Minute; *hour = time.Hour;
}
#endif #endif

View File

@ -4,5 +4,7 @@
#include <stdint.h> #include <stdint.h>
uint64_t time(void); uint64_t time(void);
void bootboot_time(
uint32_t* day, uint32_t* month, uint32_t* year,
uint32_t* second, uint32_t* minute, uint32_t* hour);
#endif #endif

View File

@ -75,6 +75,7 @@ static size_t get_prev_line(size_t index, const char *buffer) {
} }
static const char *VALID_KEYS[] = { static const char *VALID_KEYS[] = {
"BOOTBOOT_ENV",
"TIMEOUT", "TIMEOUT",
"DEFAULT_ENTRY", "DEFAULT_ENTRY",
"GRAPHICS", "GRAPHICS",
@ -113,6 +114,7 @@ static const char *VALID_KEYS[] = {
"CMDLINE", "CMDLINE",
"KERNEL_CMDLINE", "KERNEL_CMDLINE",
"KERNEL_PATH", "KERNEL_PATH",
"INITRD_PATH",
"MODULE_PATH", "MODULE_PATH",
"MODULE_STRING", "MODULE_STRING",
"RESOLUTION", "RESOLUTION",

View File

@ -0,0 +1,90 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <mm/vmm.h>
__attribute__((noreturn)) void bootboot_spinup_32(
uint32_t pagemap_top_lv,
uint32_t entry_point_lo, uint32_t entry_point_hi,
uint32_t stack_lo, uint32_t stack_hi) {
uint64_t casted_to_64[] = {
(uint64_t)entry_point_lo | ((uint64_t)entry_point_hi << 32),
(uint64_t)stack_lo | ((uint64_t)stack_hi << 32)
};
asm volatile (
"cld\n\t"
"movl %%eax, %%cr3\n\t"
"movl %%cr4, %%eax\n\t"
"btsl $5, %%eax\n\t"
"movl %%eax, %%cr4\n\t"
"movl $0xc0000080, %%ecx\n\t"
"rdmsr\n\t"
"btsl $8, %%eax\n\t"
"wrmsr\n\t"
"movl %%cr0, %%eax\n\t"
"btsl $31, %%eax\n\t"
"movl %%eax, %%cr0\n\t"
"call 1f\n\t"
"1: popl %%eax\n\t"
"addl $8, %%eax\n\t"
"pushl $0x28\n\t"
"pushl %%eax\n\t"
"lret\n\t"
".code64\n\t"
"movl $0x30, %%eax\n\t"
"movl %%eax, %%ds\n\t"
"movl %%eax, %%es\n\t"
"movl %%eax, %%fs\n\t"
"movl %%eax, %%gs\n\t"
"movl %%eax, %%ss\n\t"
// Since we don't really know what is now present in the upper
// 32 bits of the 64 bit registers, clear up the upper bits
// of the register that points to the 64-bit casted value array.
"movl %%esi, %%esi\n\t"
// Move in 64-bit values
"movq 0x00(%%rsi), %%rbx\n\t"
"movq 0x08(%%rsi), %%rsi\n\t"
// Let's pretend we push a return address
"testq %%rsi, %%rsi\n\t"
"jz 1f\n\t"
"subq $8, %%rsi\n\t"
"movq $0, (%%rsi)\n\t"
"1:\n\t"
"pushq $0x30\n\t"
"pushq %%rsi\n\t"
"pushfq\n\t"
"pushq $0x28\n\t"
"pushq %%rbx\n\t"
"xorl %%eax, %%eax\n\t"
"xorl %%ebx, %%ebx\n\t"
"xorl %%ecx, %%ecx\n\t"
"xorl %%edx, %%edx\n\t"
"xorl %%edi, %%edi\n\t"
"xorl %%esi, %%esi\n\t"
"xorl %%ebp, %%ebp\n\t"
"xorq %%r8, %%r8\n\t"
"xorq %%r9, %%r9\n\t"
"xorq %%r10, %%r10\n\t"
"xorq %%r11, %%r11\n\t"
"xorq %%r12, %%r12\n\t"
"xorq %%r13, %%r13\n\t"
"xorq %%r14, %%r14\n\t"
"xorq %%r15, %%r15\n\t"
"iretq\n\t"
".code32\n\t"
:
: "a" (pagemap_top_lv), "S" (casted_to_64)
: "memory"
);
__builtin_unreachable();
}

281
stage23/protos/bootboot.c Normal file
View File

@ -0,0 +1,281 @@
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <protos/bootboot.h>
#include <lib/libc.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/uri.h>
#include <lib/fb.h>
#include <lib/term.h>
#include <sys/pic.h>
#include <sys/cpu.h>
#include <sys/gdt.h>
#include <sys/idt.h>
#include <sys/lapic.h>
#include <sys/smp.h>
#include <fs/file.h>
#include <mm/vmm.h>
#include <mm/pmm.h>
#include <drivers/vga_textmode.h>
__attribute__((noreturn)) void bootboot_spinup(
pagemap_t *pagemap,
uint64_t entry_point, uint64_t stack,
size_t numcores, struct smp_information* cores);
#define BOOTBOOT_FB 0xfffffffffc000000
#define BOOTBOOT_INFO 0xffffffffffe00000
#define BOOTBOOT_ENV 0xffffffffffe01000
#define BOOTBOOT_CORE 0xffffffffffe02000
__attribute__((noreturn)) void bootboot_spinup_32(
uint32_t pagemap_top_lv,
uint32_t entry_point_lo, uint32_t entry_point_hi,
uint32_t stack_lo, uint32_t stack_hi);
void bootboot_load(char *config) {
#if bios
void *efi_system_table = NULL;
#elif uefi
void *efi_system_table = gST;
#endif
uint64_t fb_vaddr = BOOTBOOT_FB;
uint64_t struct_vaddr = BOOTBOOT_INFO;
uint64_t env_vaddr = BOOTBOOT_ENV;
uint64_t init_stack_size = 1024;
/// Config ///
char *kernel_path = config_get_value(config, 0, "KERNEL_PATH");
if (kernel_path == NULL)
panic("bootboot: KERNEL_PATH not specified");
char *initrd = config_get_value(config, 0, "INITRD");
if (initrd == NULL) {
print("bootboot: warning: no initrd!\n");
}
/// Kernel loading code ///
print("bootboot: Loading kernel `%s`...\n", kernel_path);
struct file_handle* kernel_file;
if ((kernel_file = uri_open(kernel_path)) == NULL)
panic("bootboot: Failed to open kernel with path `%s`. Is the path correct?\n", kernel_path);
uint8_t* kernel = freadall(kernel_file, MEMMAP_KERNEL_AND_MODULES);
/// Funky macros ///
#define KOFFSET(type, off) (type)&kernel[(off)]
#define ESECTION(idx) KOFFSET(struct elf64_shdr*, elf_header->shoff + elf_header->shdr_size * (idx))
/// Bootboot symbols ///
struct elf64_hdr* elf_header = (struct elf64_hdr*)kernel;
struct elf64_shdr* section_header_strings_section = ESECTION(elf_header->shstrndx);
char* section_header_strings = KOFFSET(char*, section_header_strings_section->sh_offset);
struct elf64_shdr* symbol_table = NULL;
struct elf64_shdr* string_table = NULL;
for(uint32_t i = 0; i < elf_header->sh_num; i++){
struct elf64_shdr* section_header = ESECTION(i);
char* secname = &section_header_strings[section_header->sh_name];
if(!strcmp(secname, ".symtab")) symbol_table = section_header;
if(!strcmp(secname, ".strtab")) string_table = section_header;
}
if (!symbol_table || !string_table) {
print("bootboot: warning: no symbol/string tables in the ELF!");
} else {
struct elf64_sym* symbols = KOFFSET(struct elf64_sym*, symbol_table->sh_offset);
char* symbol_strings = KOFFSET(char*, string_table->sh_offset);
for (uint32_t i = 0, symcount = symbol_table->sh_size / sizeof(struct elf64_sym);i < symcount;i++) {
char* elf_sym = &symbol_strings[symbols[i].st_name];
uint64_t symaddr = symbols[i].st_value;
if(!strcmp(elf_sym, "bootboot")) struct_vaddr = symaddr;
if(!strcmp(elf_sym, "environment")) env_vaddr = symaddr;
if(!strcmp(elf_sym, "fb")) fb_vaddr = symaddr;
if(!strcmp(elf_sym, "initstack")) init_stack_size = symaddr;
}
}
printv("bootboot: mapping struct to %X", struct_vaddr);
printv("bootboot: mapping environemnt to %X", env_vaddr);
printv("bootboot: mapping framebuffer to %X", fb_vaddr);
printv("bootboot: the init stack is %X bytes", init_stack_size);
uint64_t entry, top, slide, rangecount, physbase, virtbase = 0;
struct elf_range* ranges;
/// Memory mappings ///
pagemap_t pmap = new_pagemap(4);
/// Load kernel ///
{
if (elf64_load(
kernel, &entry, &top, &slide, MEMMAP_KERNEL_AND_MODULES,
false, false, &ranges, &rangecount, true, &physbase, &virtbase)) {
panic("bootboot: elf64 load failed");
}
for (uint64_t mapvirt = virtbase, mapphys = physbase; mapphys < top;mapvirt += 0x1000, mapphys += 0x1000) {
map_page(pmap, mapvirt, mapphys, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false);
}
}
BOOTBOOT* bootboot = (BOOTBOOT*)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096);
map_page(pmap, struct_vaddr, (uint64_t)(size_t)bootboot, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false);
/// Environment ///
{
char* env = (char*)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096);
map_page(pmap, env_vaddr, (uint64_t)(size_t)env, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false);
uint32_t index = 0, offset = 0;
char* cfgent = NULL;
do {
cfgent = config_get_value(config, index++, "BOOTBOOT_ENV");
if (cfgent) {
uint32_t off = strlen(cfgent);
if (offset + off + 1 > 4095) {
panic("Too much config options! we only have 4k of env vars!");
}
memcpy(&env[offset], cfgent, off);
offset += off;
env[offset++] = '\n';
}
} while (cfgent);
cfgent[offset] = 0;
}
for (uint64_t i = 0; i < 0x400000000; i += 0x200000) {
map_page(pmap, i, i, 0x03, true);
}
/// Framebuffer init ///
size_t fbwidth = 0, fbheight = 0, fbbpp = 32;
struct fb_info fbi;
char *resolution = config_get_value(config, 0, "RESOLUTION");
if (resolution != NULL)
parse_resolution(&fbwidth, &fbheight, &fbbpp, resolution);
term_deinit();
fb_init(&fbi, fbwidth, fbheight, fbbpp);
uint64_t fb_size = fbi.framebuffer_height * fbi.framebuffer_pitch;
for (uint64_t current = 0;current < fb_size;current += 0x1000) {
map_page(pmap, fb_vaddr + current, fbi.framebuffer_addr + current, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false);
}
/// Initrd loading ///
uint64_t initrd_start = 0, initrd_size = 0;
if (initrd) {
struct file_handle* initrd_file;
if ((initrd_file = uri_open(initrd)) == NULL)
panic("bootboot: Failed to open initrd with path `%s`. Is the path correct?\n", initrd);
uint8_t* initrd_data = freadall(initrd_file, MEMMAP_KERNEL_AND_MODULES);
initrd_size = initrd_file->size;
initrd_start = (uint64_t)(size_t)initrd_data;
fclose(initrd_file);
}
/// Header info ///
memcpy(bootboot->magic, "BOOT", 4);
#if bios
bootboot->protocol = 2 | (0 << 2);
#elif uefi
bootboot->protocol = 2 | (1 << 2);
#endif
/// SMP info ///
size_t numcores;
uint32_t bsplapic;
struct smp_information* cores;
init_smp(0, (void**)&cores, &numcores, &bsplapic, true, false, pmap, false, false);
bootboot->numcores = numcores;
bootboot->bspid = bsplapic;
for (size_t i = 0;i < numcores;i++) {
cores[i].stack_addr = ((uint64_t)(size_t)ext_mem_alloc(init_stack_size)) + init_stack_size;
}
/// Time stubs ///
uint32_t year, month, day, hour, minute, second;
bootboot_time(&day, &month, &year, &second, &minute, &hour);
bootboot->timezone = 0;
bootboot->datetime[0] = int_to_bcd(year / 100);
bootboot->datetime[1] = int_to_bcd(year % 100);
bootboot->datetime[2] = int_to_bcd(month);
bootboot->datetime[3] = int_to_bcd(day);
bootboot->datetime[4] = int_to_bcd(hour);
bootboot->datetime[5] = int_to_bcd(minute);
bootboot->datetime[6] = int_to_bcd(second);
bootboot->datetime[7] = 0;
/// Ramdisk ///
bootboot->initrd_ptr = initrd_start;
bootboot->initrd_size = initrd_size;
/// Framebuffer ///
bootboot->fb_ptr = fbi.framebuffer_addr;
bootboot->fb_size = fb_size;
bootboot->fb_width = fbi.framebuffer_width;
bootboot->fb_height = fbi.framebuffer_height;
bootboot->fb_scanline = fbi.framebuffer_pitch;
bootboot->fb_type = 1;
/// SMBIOS and ACPI ///
uint64_t smbios_entry_32 = 0, smbios_entry_64 = 0;
acpi_get_smbios((void **)&smbios_entry_32, (void **)&smbios_entry_64);
bootboot->arch.x86_64.acpi_ptr = (uint64_t)(size_t)acpi_get_rsdp();
if (smbios_entry_64) bootboot->arch.x86_64.smbi_ptr = smbios_entry_64;
else if (smbios_entry_32) bootboot->arch.x86_64.smbi_ptr = smbios_entry_32;
else bootboot->arch.x86_64.smbi_ptr = 0;
bootboot->arch.x86_64.efi_ptr = (uint64_t)(size_t)efi_system_table;
bootboot->arch.x86_64.mp_ptr = 0;
/// Memory map ///
{
size_t mmapent;
struct e820_entry_t* e820e = get_memmap(&mmapent);
if (mmapent > 248) {
panic("Too much memory entries! our god bzt decided that %d entries is too much, max is 248", mmapent);
}
for (uint32_t i = 0;i < mmapent;i++) {
uint32_t btype = 0;
if (e820e[i].type == 1) btype = 1;
if (e820e[i].type == 3) btype = 2;
if (e820e[i].type == 4) btype = 2;
bootboot->mmap[i].size = (e820e[i].length & 0xF) | btype;
bootboot->mmap[i].ptr = e820e[i].base;
}
bootboot->size = 128 + mmapent * 16;
}
/// Spinup ///
#if bios == 1
// If we're going 64, we might as well call this BIOS interrupt
// to tell the BIOS that we are entering Long Mode, since it is in
// the specification.
struct rm_regs r = {0};
r.eax = 0xec00;
r.ebx = 0x02; // Long mode only
rm_int(0x15, &r, &r);
#endif
irq_flush_type = IRQ_PIC_ONLY_FLUSH;
for (size_t i = 0;i < numcores;i++) {
cores[i].extra_argument = 0;
cores[i].goto_address = entry;
}
common_spinup(bootboot_spinup_32, 10,
(uint32_t)(uintptr_t)pmap.top_level,
(uint32_t)entry, (uint32_t)(entry >> 32),
(uint32_t)cores[0].stack_addr, (uint32_t)(cores[0].stack_addr >> 32));
}

89
stage23/protos/bootboot.h Normal file
View File

@ -0,0 +1,89 @@
#ifndef __PROTOS__BOOTBOOT_H__
#define __PROTOS__BOOTBOOT_H__
#include <stdint.h>
#include <stdbool.h>
void bootboot_load(char *config);
/*
* what follows is (modified) bootboot.h
* https://gitlab.com/bztsrc/bootboot
*
* Copyright (C) 2021 pitust (piotr@stelmaszek.com)
* Copyright (C) 2017 - 2021 bzt (bztsrc@gitlab)
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* This file is part of the BOOTBOOT Protocol package.
* @brief The BOOTBOOT structure
*
*/
#define BOOTBOOT_MAGIC "BOOT"
/* default virtual addresses for level 0 and 1 static loaders */
#define BOOTBOOT_MMIO 0xfffffffff8000000 /* memory mapped IO virtual address */
#define BOOTBOOT_FB 0xfffffffffc000000 /* frame buffer virtual address */
#define BOOTBOOT_INFO 0xffffffffffe00000 /* bootboot struct virtual address */
#define BOOTBOOT_ENV 0xffffffffffe01000 /* environment string virtual address */
#define BOOTBOOT_CORE 0xffffffffffe02000 /* core loadable segment start */
typedef struct {
uint64_t ptr;
uint64_t size;
} MMapEnt;
typedef struct {
uint8_t magic[4];
uint32_t size;
uint8_t protocol;
uint8_t fb_type;
uint16_t numcores;
uint16_t bspid;
int16_t timezone;
uint8_t datetime[8];
uint64_t initrd_ptr;
uint64_t initrd_size;
uint64_t fb_ptr;
uint32_t fb_size;
uint32_t fb_width;
uint32_t fb_height;
uint32_t fb_scanline;
union {
struct {
uint64_t acpi_ptr;
uint64_t smbi_ptr;
uint64_t efi_ptr;
uint64_t mp_ptr;
uint64_t unused0;
uint64_t unused1;
uint64_t unused2;
uint64_t unused3;
} x86_64;
} arch;
MMapEnt mmap[];
} BOOTBOOT;
#endif