From 6443900f2bc723a438c429274a274e6f4d7ce0aa Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 17:13:08 +0000 Subject: [PATCH 01/12] bootboot: introduce support for the bootboot protocol --- stage23/entry.s3.c | 8 + stage23/protos/bootboot.32.c | 90 ++++++++++ stage23/protos/bootboot.c | 310 +++++++++++++++++++++++++++++++++++ stage23/protos/bootboot.h | 133 +++++++++++++++ 4 files changed, 541 insertions(+) create mode 100644 stage23/protos/bootboot.32.c create mode 100644 stage23/protos/bootboot.c create mode 100644 stage23/protos/bootboot.h diff --git a/stage23/entry.s3.c b/stage23/entry.s3.c index 72d5a790..626d6076 100644 --- a/stage23/entry.s3.c +++ b/stage23/entry.s3.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -177,6 +178,13 @@ void stage3_common(void) { multiboot1_load(config, cmdline); } else if (!strcmp(proto, "multiboot2")) { multiboot2_load(config, cmdline); + } else if (!strcmp(proto, "bootboot")) { +#if bios == 1 + void *efi_system_table = NULL; +#elif uefi == 1 + void *efi_system_table = gST; +#endif + bootboot_load(config, cmdline, efi_system_table); } panic("Invalid protocol specified"); diff --git a/stage23/protos/bootboot.32.c b/stage23/protos/bootboot.32.c new file mode 100644 index 00000000..f1a2b2d4 --- /dev/null +++ b/stage23/protos/bootboot.32.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include + +__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(); +} diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c new file mode 100644 index 00000000..12c30cb7 --- /dev/null +++ b/stage23/protos/bootboot.c @@ -0,0 +1,310 @@ +#include "lib/gterm.h" +#include "sys/smp.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +__attribute__((noreturn)) void bootboot_spinup( + pagemap_t *pagemap, + uint64_t entry_point, uint64_t stack, + size_t numcores, struct smp_information* cores); +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; +}; +#define BOOTBOOT_FB 0xfffffffffc000000 +#define BOOTBOOT_INFO 0xffffffffffe00000 +#define BOOTBOOT_ENV 0xffffffffffe01000 +#define BOOTBOOT_CORE 0xffffffffffe02000 + +void bootboot_load(char *config, char *cmdline, void *efi_system_table) { + uint64_t fb_vaddr = BOOTBOOT_FB; + uint64_t struct_vaddr = BOOTBOOT_INFO; + uint64_t cmdline_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 *ramdisk = config_get_value(config, 0, "RAMDISK"); + if (ramdisk == NULL) { + print("bootboot: no ramdisk!\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; + struct elf64_shdr* string_table; + for(uint32_t i = 0; i < elf_header->sh_num; i++){ + struct elf64_shdr* section_header = ESECTION(i); + char* secname = §ion_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* symbol = &symbol_strings[symbols[i].st_name]; + uint64_t symaddr = symbols[i].st_value; + + print("bootboot: symbol `%s`\n", symbol); + + if(!strcmp(symbol, "bootboot")) struct_vaddr = symaddr; + if(!strcmp(symbol, "environment")) cmdline_vaddr = symaddr; + if(!strcmp(symbol, "fb")) fb_vaddr = symaddr; + if(!strcmp(symbol, "initstack")) init_stack_size = symaddr; + } + } + + 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)bootboot, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); + + char** env = (char**)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); + map_page(pmap, cmdline_vaddr, (uint64_t)env, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); + memcpy(env, cmdline, strlen(cmdline)); + + 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); + } + + /// Ramdisk loading /// + uint64_t ramdisk_start = 0, ramdisk_size = 0; + if (ramdisk) { + struct file_handle* ramdisk_file; + if ((ramdisk_file = uri_open(ramdisk)) == NULL) + panic("bootboot: Failed to open ramdisk with path `%s`. Is the path correct?\n", ramdisk); + + uint8_t* ramdisk_data = freadall(ramdisk_file, MEMMAP_KERNEL_AND_MODULES); + ramdisk_size = ramdisk_file->size; + ramdisk_start = (uint64_t)ramdisk_data; + } + + /// Header info /// + memcpy(bootboot->magic, "BOOT", 4); +#if bios + bootboot->protocol = 2 | (0 << 2); +#elif uefi + bootboot->protocol = 2 | (1 << 2); +#else +#error bootboot: unknown target, not uefi or bios, what the fuck? +#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)ext_mem_alloc(init_stack_size)) + init_stack_size; + } + + /// Time stubs /// + print("bootboot: todo/help wanted: if you feel like adding support for weird time bullshit, please contribute\n"); + bootboot->timezone = 0; + memset(bootboot->datetime, 0, 8); + + /// Ramdisk /// + bootboot->initrd_ptr = ramdisk_start; + bootboot->initrd_size = ramdisk_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)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) { + term_reinit(); + size_t rows, cols; + gterm_init(&rows, &cols, 0, 0); + 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; +// #define MEMMAP_USABLE 1 +// #define MEMMAP_RESERVED 2 +// #define MEMMAP_ACPI_RECLAIMABLE 3 +// #define MEMMAP_ACPI_NVS 4 +// #define MEMMAP_BAD_MEMORY 5 +// #define MEMMAP_BOOTLOADER_RECLAIMABLE 0x1000 +// #define MEMMAP_KERNEL_AND_MODULES 0x1001 +// #define MEMMAP_FRAMEBUFFER 0x1002 +// #define MEMMAP_EFI_RECLAIMABLE 0x2000 +// #define MEMMAP_EFI_BOOTSERVICES 0x2001 + if (e820e[i].type == 1) btype = 1; + if (e820e[i].type == 3) btype = 2; + if (e820e[i].type == 4) btype = 2; + + print("mapping the type %x to bootboot type %x\n", e820e[i].type, btype); + bootboot->mmap[i].size = (e820e[i].length & 0xF) | btype; + bootboot->mmap[i].ptr = e820e[i].base; + } + bootboot->size = 128 + mmapent * 16; + } + + /// Late framebuffer init /// + memset((void*)(size_t)fbi.framebuffer_addr, 0, fb_size); + + /// Spinup /// + bootboot_spinup(&pmap, entry, cores[0].stack_addr, numcores, cores); + +} + +__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); + +__attribute__((noreturn)) void bootboot_spinup( + pagemap_t *pagemap, + uint64_t entry_point, uint64_t stack, + size_t numcores, struct smp_information* cores) { +#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 + + pic_mask_all(); + io_apic_mask_all(); + + irq_flush_type = IRQ_PIC_APIC_FLUSH; + + for (size_t i = 0;i < numcores;i++) { + cores[i].extra_argument = 0; + cores[i].goto_address = entry_point; + } + + common_spinup(bootboot_spinup_32, 10, + (uint32_t)(uintptr_t)pagemap->top_level, + (uint32_t)entry_point, (uint32_t)(entry_point >> 32), + (uint32_t)stack, (uint32_t)(stack >> 32)); +} diff --git a/stage23/protos/bootboot.h b/stage23/protos/bootboot.h new file mode 100644 index 00000000..1151f771 --- /dev/null +++ b/stage23/protos/bootboot.h @@ -0,0 +1,133 @@ +#ifndef __PROTOS__BOOTBOOT_H__ +#define __PROTOS__BOOTBOOT_H__ + +#include +#include + +void bootboot_load(char *config, char *cmdline, void *efi_system_table); + +/* + * 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 */ + +/* minimum protocol level: + * hardcoded kernel name, static kernel memory addresses */ +#define PROTOCOL_MINIMAL 0 +/* static protocol level: + * kernel name parsed from environment, static kernel memory addresses */ +#define PROTOCOL_STATIC 1 +/* dynamic protocol level: + * kernel name parsed, kernel memory addresses from ELF or PE symbols */ +#define PROTOCOL_DYNAMIC 2 +/* big-endian flag */ +#define PROTOCOL_BIGENDIAN 0x80 + +/* loader types, just informational */ +#define LOADER_BIOS (0<<2) +#define LOADER_UEFI (1<<2) +#define LOADER_RPI (2<<2) +#define LOADER_COREBOOT (3<<2) + +/* framebuffer pixel format, only 32 bits supported */ +#define FB_ARGB 0 +#define FB_RGBA 1 +#define FB_ABGR 2 +#define FB_BGRA 3 + +/* mmap entry, type is stored in least significant tetrad (half byte) of size + * this means size described in 16 byte units (not a problem, most modern + * firmware report memory in pages, 4096 byte units anyway). */ +typedef struct { + uint64_t ptr; + uint64_t size; +} MMapEnt; +#define MMapEnt_Ptr(a) ((a)->ptr) +#define MMapEnt_Size(a) ((a)->size & 0xFFFFFFFFFFFFFFF0) +#define MMapEnt_Type(a) ((a)->size & 0xF) +#define MMapEnt_IsFree(a) (((a)->size&0xF)==1) +#define MMapEnt_Combine(addr, type) (((addr) & ~0xF) | ((type))) + +#define MMAP_USED 0 /* don't use. Reserved or unknown regions */ +#define MMAP_FREE 1 /* usable memory */ +#define MMAP_ACPI 2 /* acpi memory, volatile and non-volatile as well */ +#define MMAP_MMIO 3 /* memory mapped IO region */ + +#define INITRD_MAXSIZE 16 /* Mb */ + +typedef struct { + /* first 64 bytes is platform independent */ + uint8_t magic[4]; /* 'BOOT' magic */ + uint32_t size; /* length of bootboot structure, minimum 128 */ + uint8_t protocol; /* 1, static addresses, see PROTOCOL_* and LOADER_* above */ + uint8_t fb_type; /* framebuffer type, see FB_* above */ + uint16_t numcores; /* number of processor cores */ + uint16_t bspid; /* Bootsrap processor ID (Local APIC Id on x86_64) */ + int16_t timezone; /* in minutes -1440..1440 */ + uint8_t datetime[8]; /* in BCD yyyymmddhhiiss UTC (independent to timezone) */ + uint64_t initrd_ptr; /* ramdisk image position and size */ + uint64_t initrd_size; + uint64_t fb_ptr; /* framebuffer pointer and dimensions */ + uint32_t fb_size; + uint32_t fb_width; + uint32_t fb_height; + uint32_t fb_scanline; + + /* the rest (64 bytes) is platform specific */ + 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; + + /* from 128th byte, MMapEnt[], more records may follow */ + MMapEnt mmap[]; + /* use like this: + * MMapEnt *mmap_ent = &bootboot.mmap; mmap_ent++; + * until you reach bootboot->size, while(mmap_ent < bootboot + bootboot->size) */ +} BOOTBOOT; + +#endif From a72a68486d763cb6fe6718d3836d72c02fa38f7e Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 20:38:36 +0000 Subject: [PATCH 02/12] bootboot: add proper support for env and ramdisk --- stage23/entry.s3.c | 2 +- stage23/lib/blib.h | 1 + stage23/lib/blib.s2.c | 3 ++ stage23/lib/time.c | 31 ++++++++++++++++++ stage23/lib/time.h | 4 ++- stage23/menu.c | 2 ++ stage23/protos/bootboot.c | 60 +++++++++++++++++++++------------- stage23/protos/bootboot.h | 68 +++++++-------------------------------- 8 files changed, 90 insertions(+), 81 deletions(-) diff --git a/stage23/entry.s3.c b/stage23/entry.s3.c index 626d6076..4230e114 100644 --- a/stage23/entry.s3.c +++ b/stage23/entry.s3.c @@ -184,7 +184,7 @@ void stage3_common(void) { #elif uefi == 1 void *efi_system_table = gST; #endif - bootboot_load(config, cmdline, efi_system_table); + bootboot_load(config, efi_system_table); } panic("Invalid protocol specified"); diff --git a/stage23/lib/blib.h b/stage23/lib/blib.h index 1a4ca703..f626d625 100644 --- a/stage23/lib/blib.h +++ b/stage23/lib/blib.h @@ -43,6 +43,7 @@ size_t get_trailing_zeros(uint64_t val); int digit_to_int(char c); uint8_t bcd_to_int(uint8_t val); +uint8_t int_to_bcd(uint8_t val); __attribute__((noreturn)) void panic(const char *fmt, ...); diff --git a/stage23/lib/blib.s2.c b/stage23/lib/blib.s2.c index 9513fb13..a2a73c43 100644 --- a/stage23/lib/blib.s2.c +++ b/stage23/lib/blib.s2.c @@ -8,6 +8,9 @@ bool verbose = true; uint8_t bcd_to_int(uint8_t val) { 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) { if (c >= 'a' && c <= 'f') { diff --git a/stage23/lib/time.c b/stage23/lib/time.c index 19e59b52..b7fe1aa5 100644 --- a/stage23/lib/time.c +++ b/stage23/lib/time.c @@ -46,6 +46,28 @@ uint64_t time(void) { uint8_t hour = bcd_to_int((r.ecx & 0xff00) >> 8); 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 @@ -57,4 +79,13 @@ uint64_t time(void) { return get_unix_epoch(time.Second, time.Minute, time.Hour, 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 diff --git a/stage23/lib/time.h b/stage23/lib/time.h index 60da1a3d..6ad30de5 100644 --- a/stage23/lib/time.h +++ b/stage23/lib/time.h @@ -4,5 +4,7 @@ #include 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 diff --git a/stage23/menu.c b/stage23/menu.c index dac3624b..2a1e92bd 100644 --- a/stage23/menu.c +++ b/stage23/menu.c @@ -75,6 +75,7 @@ static size_t get_prev_line(size_t index, const char *buffer) { } static const char *VALID_KEYS[] = { + "BOOTBOOT_ENV", "TIMEOUT", "DEFAULT_ENTRY", "GRAPHICS", @@ -108,6 +109,7 @@ static const char *VALID_KEYS[] = { "VERBOSE", "RANDOMISE_MEMORY", "RANDOMIZE_MEMORY", + "RAMDISK", "COMMENT", "PROTOCOL", "CMDLINE", diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index 12c30cb7..60859597 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -70,10 +70,10 @@ struct elf64_sym { #define BOOTBOOT_ENV 0xffffffffffe01000 #define BOOTBOOT_CORE 0xffffffffffe02000 -void bootboot_load(char *config, char *cmdline, void *efi_system_table) { +void bootboot_load(char *config, void *efi_system_table) { uint64_t fb_vaddr = BOOTBOOT_FB; uint64_t struct_vaddr = BOOTBOOT_INFO; - uint64_t cmdline_vaddr = BOOTBOOT_ENV; + uint64_t env_vaddr = BOOTBOOT_ENV; uint64_t init_stack_size = 1024; /// Config /// @@ -86,7 +86,6 @@ void bootboot_load(char *config, char *cmdline, void *efi_system_table) { print("bootboot: no ramdisk!\n"); } - /// Kernel loading code /// print("bootboot: Loading kernel `%s`...\n", kernel_path); struct file_handle* kernel_file; @@ -120,15 +119,15 @@ void bootboot_load(char *config, char *cmdline, void *efi_system_table) { char* symbol = &symbol_strings[symbols[i].st_name]; uint64_t symaddr = symbols[i].st_value; - print("bootboot: symbol `%s`\n", symbol); - if(!strcmp(symbol, "bootboot")) struct_vaddr = symaddr; - if(!strcmp(symbol, "environment")) cmdline_vaddr = symaddr; + if(!strcmp(symbol, "environment")) env_vaddr = symaddr; if(!strcmp(symbol, "fb")) fb_vaddr = symaddr; if(!strcmp(symbol, "initstack")) init_stack_size = symaddr; } } + print("bootboot: mapping struct to %X", struct_vaddr); + uint64_t entry, top, slide, rangecount, physbase, virtbase = 0; struct elf_range* ranges; @@ -149,9 +148,27 @@ void bootboot_load(char *config, char *cmdline, void *efi_system_table) { BOOTBOOT* bootboot = (BOOTBOOT*)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); map_page(pmap, struct_vaddr, (uint64_t)bootboot, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); - char** env = (char**)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); - map_page(pmap, cmdline_vaddr, (uint64_t)env, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); - memcpy(env, cmdline, strlen(cmdline)); + /// Environment /// + { + char* env = (char*)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); + map_page(pmap, env_vaddr, (uint64_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); @@ -206,9 +223,19 @@ void bootboot_load(char *config, char *cmdline, void *efi_system_table) { } /// Time stubs /// + uint32_t year, month, day, hour, minute, second; + bootboot_time(&day, &month, &year, &second, &minute, &hour); print("bootboot: todo/help wanted: if you feel like adding support for weird time bullshit, please contribute\n"); bootboot->timezone = 0; - memset(bootboot->datetime, 0, 8); + 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 = ramdisk_start; @@ -239,27 +266,14 @@ void bootboot_load(char *config, char *cmdline, void *efi_system_table) { struct e820_entry_t* e820e = get_memmap(&mmapent); if (mmapent > 248) { term_reinit(); - size_t rows, cols; - gterm_init(&rows, &cols, 0, 0); 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; -// #define MEMMAP_USABLE 1 -// #define MEMMAP_RESERVED 2 -// #define MEMMAP_ACPI_RECLAIMABLE 3 -// #define MEMMAP_ACPI_NVS 4 -// #define MEMMAP_BAD_MEMORY 5 -// #define MEMMAP_BOOTLOADER_RECLAIMABLE 0x1000 -// #define MEMMAP_KERNEL_AND_MODULES 0x1001 -// #define MEMMAP_FRAMEBUFFER 0x1002 -// #define MEMMAP_EFI_RECLAIMABLE 0x2000 -// #define MEMMAP_EFI_BOOTSERVICES 0x2001 if (e820e[i].type == 1) btype = 1; if (e820e[i].type == 3) btype = 2; if (e820e[i].type == 4) btype = 2; - print("mapping the type %x to bootboot type %x\n", e820e[i].type, btype); bootboot->mmap[i].size = (e820e[i].length & 0xF) | btype; bootboot->mmap[i].ptr = e820e[i].base; } diff --git a/stage23/protos/bootboot.h b/stage23/protos/bootboot.h index 1151f771..23341706 100644 --- a/stage23/protos/bootboot.h +++ b/stage23/protos/bootboot.h @@ -4,10 +4,10 @@ #include #include -void bootboot_load(char *config, char *cmdline, void *efi_system_table); +void bootboot_load(char *config, void *efi_system_table); /* - * bootboot.h + * what follows is (modified) bootboot.h * https://gitlab.com/bztsrc/bootboot * * Copyright (C) 2021 pitust (piotr@stelmaszek.com) @@ -47,69 +47,29 @@ void bootboot_load(char *config, char *cmdline, void *efi_system_table); #define BOOTBOOT_ENV 0xffffffffffe01000 /* environment string virtual address */ #define BOOTBOOT_CORE 0xffffffffffe02000 /* core loadable segment start */ -/* minimum protocol level: - * hardcoded kernel name, static kernel memory addresses */ -#define PROTOCOL_MINIMAL 0 -/* static protocol level: - * kernel name parsed from environment, static kernel memory addresses */ -#define PROTOCOL_STATIC 1 -/* dynamic protocol level: - * kernel name parsed, kernel memory addresses from ELF or PE symbols */ -#define PROTOCOL_DYNAMIC 2 -/* big-endian flag */ -#define PROTOCOL_BIGENDIAN 0x80 -/* loader types, just informational */ -#define LOADER_BIOS (0<<2) -#define LOADER_UEFI (1<<2) -#define LOADER_RPI (2<<2) -#define LOADER_COREBOOT (3<<2) - -/* framebuffer pixel format, only 32 bits supported */ -#define FB_ARGB 0 -#define FB_RGBA 1 -#define FB_ABGR 2 -#define FB_BGRA 3 - -/* mmap entry, type is stored in least significant tetrad (half byte) of size - * this means size described in 16 byte units (not a problem, most modern - * firmware report memory in pages, 4096 byte units anyway). */ typedef struct { uint64_t ptr; uint64_t size; } MMapEnt; -#define MMapEnt_Ptr(a) ((a)->ptr) -#define MMapEnt_Size(a) ((a)->size & 0xFFFFFFFFFFFFFFF0) -#define MMapEnt_Type(a) ((a)->size & 0xF) -#define MMapEnt_IsFree(a) (((a)->size&0xF)==1) -#define MMapEnt_Combine(addr, type) (((addr) & ~0xF) | ((type))) - -#define MMAP_USED 0 /* don't use. Reserved or unknown regions */ -#define MMAP_FREE 1 /* usable memory */ -#define MMAP_ACPI 2 /* acpi memory, volatile and non-volatile as well */ -#define MMAP_MMIO 3 /* memory mapped IO region */ - -#define INITRD_MAXSIZE 16 /* Mb */ typedef struct { - /* first 64 bytes is platform independent */ - uint8_t magic[4]; /* 'BOOT' magic */ - uint32_t size; /* length of bootboot structure, minimum 128 */ - uint8_t protocol; /* 1, static addresses, see PROTOCOL_* and LOADER_* above */ - uint8_t fb_type; /* framebuffer type, see FB_* above */ - uint16_t numcores; /* number of processor cores */ - uint16_t bspid; /* Bootsrap processor ID (Local APIC Id on x86_64) */ - int16_t timezone; /* in minutes -1440..1440 */ - uint8_t datetime[8]; /* in BCD yyyymmddhhiiss UTC (independent to timezone) */ - uint64_t initrd_ptr; /* ramdisk image position and size */ + 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; /* framebuffer pointer and dimensions */ + uint64_t fb_ptr; uint32_t fb_size; uint32_t fb_width; uint32_t fb_height; uint32_t fb_scanline; - /* the rest (64 bytes) is platform specific */ union { struct { uint64_t acpi_ptr; @@ -123,11 +83,7 @@ typedef struct { } x86_64; } arch; - /* from 128th byte, MMapEnt[], more records may follow */ MMapEnt mmap[]; - /* use like this: - * MMapEnt *mmap_ent = &bootboot.mmap; mmap_ent++; - * until you reach bootboot->size, while(mmap_ent < bootboot + bootboot->size) */ } BOOTBOOT; #endif From b6169503855bee310076eb17d376cc9b244b95eb Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 20:42:22 +0000 Subject: [PATCH 03/12] bootboot: document the protocol and it's configuration options --- CONFIG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CONFIG.md b/CONFIG.md index c1fe14ad..31a2d30c 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -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 modules. * `RESOLUTION` - The resolution to be used. This setting takes the form of `xx`. If the resolution is not available, Limine will pick another one automatically. Omitting `` will default to 32. +* Bootboot protocol: + * `KERNEL_PATH` - The URI path of the kernel. + * `RAMDISK` - 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 `xx`. If the resolution is not available, Limine will pick another one automatically. Omitting `` will default to 32. * stivale and stivale2 protocols: * `KERNEL_PATH` - The URI path of the kernel. * `MODULE_PATH` - The URI path to a module. From b17a650317534c78cd6591ea423b18fd41beb598 Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 21:04:14 +0000 Subject: [PATCH 04/12] bootboot: fix the CI --- stage23/protos/bootboot.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index 60859597..4bc02786 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -102,8 +102,8 @@ void bootboot_load(char *config, void *efi_system_table) { 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; - struct elf64_shdr* string_table; + 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 = §ion_header_strings[section_header->sh_name]; @@ -116,13 +116,13 @@ void bootboot_load(char *config, void *efi_system_table) { 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* symbol = &symbol_strings[symbols[i].st_name]; + char* elf_sym = &symbol_strings[symbols[i].st_name]; uint64_t symaddr = symbols[i].st_value; - if(!strcmp(symbol, "bootboot")) struct_vaddr = symaddr; - if(!strcmp(symbol, "environment")) env_vaddr = symaddr; - if(!strcmp(symbol, "fb")) fb_vaddr = symaddr; - if(!strcmp(symbol, "initstack")) init_stack_size = symaddr; + 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; } } From 643db03ac079b2f2dda97bf6085e2c9330662101 Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 21:12:15 +0000 Subject: [PATCH 05/12] bootboot: fix the CI, again --- stage23/protos/bootboot.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index 4bc02786..738b7155 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -146,12 +146,12 @@ void bootboot_load(char *config, void *efi_system_table) { } } BOOTBOOT* bootboot = (BOOTBOOT*)ext_mem_alloc_type_aligned(4096, MEMMAP_BOOTLOADER_RECLAIMABLE, 4096); - map_page(pmap, struct_vaddr, (uint64_t)bootboot, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); + 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)env, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); + 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 { @@ -207,8 +207,6 @@ void bootboot_load(char *config, void *efi_system_table) { bootboot->protocol = 2 | (0 << 2); #elif uefi bootboot->protocol = 2 | (1 << 2); -#else -#error bootboot: unknown target, not uefi or bios, what the fuck? #endif /// SMP info /// @@ -219,7 +217,7 @@ void bootboot_load(char *config, void *efi_system_table) { bootboot->numcores = numcores; bootboot->bspid = bsplapic; for (size_t i = 0;i < numcores;i++) { - cores[i].stack_addr = ((uint64_t)ext_mem_alloc(init_stack_size)) + init_stack_size; + cores[i].stack_addr = ((uint64_t)(size_t)ext_mem_alloc(init_stack_size)) + init_stack_size; } /// Time stubs /// @@ -257,7 +255,7 @@ void bootboot_load(char *config, void *efi_system_table) { 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)efi_system_table; + bootboot->arch.x86_64.efi_ptr = (uint64_t)(size_t)efi_system_table; bootboot->arch.x86_64.mp_ptr = 0; /// Memory map /// From dfd347db02b9f2bc9c11e7176bb31ababb72e06b Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 21:14:27 +0000 Subject: [PATCH 06/12] bootboot: i swear this is the last CI fix --- stage23/protos/bootboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index 738b7155..e3298c26 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -198,7 +198,7 @@ void bootboot_load(char *config, void *efi_system_table) { uint8_t* ramdisk_data = freadall(ramdisk_file, MEMMAP_KERNEL_AND_MODULES); ramdisk_size = ramdisk_file->size; - ramdisk_start = (uint64_t)ramdisk_data; + ramdisk_start = (uint64_t)(size_t)ramdisk_data; } /// Header info /// From 24d27f769ac4fc85e52519d09c0a1cfc74f6d0bd Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 21:18:06 +0000 Subject: [PATCH 07/12] bootboot: don't mask IRQs --- stage23/protos/bootboot.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index e3298c26..1856b577 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -305,9 +305,6 @@ __attribute__((noreturn)) void bootboot_spinup( rm_int(0x15, &r, &r); #endif - pic_mask_all(); - io_apic_mask_all(); - irq_flush_type = IRQ_PIC_APIC_FLUSH; for (size_t i = 0;i < numcores;i++) { From e9dadcef840dce4f97068a80a181d499369aafe7 Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 21:21:29 +0000 Subject: [PATCH 08/12] bootboot: don't zero out the framebuffer --- stage23/protos/bootboot.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index 1856b577..234a6000 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -278,9 +278,6 @@ void bootboot_load(char *config, void *efi_system_table) { bootboot->size = 128 + mmapent * 16; } - /// Late framebuffer init /// - memset((void*)(size_t)fbi.framebuffer_addr, 0, fb_size); - /// Spinup /// bootboot_spinup(&pmap, entry, cores[0].stack_addr, numcores, cores); From 7d55fee08707124a8fc05dd844c887df48858abf Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 21:37:20 +0000 Subject: [PATCH 09/12] bootboot+elf: deduplicate ELF structures --- stage23/lib/elf.c | 29 ----------------------------- stage23/lib/elf.h | 37 +++++++++++++++++++++++++++++++++++++ stage23/protos/bootboot.c | 39 ++------------------------------------- 3 files changed, 39 insertions(+), 66 deletions(-) diff --git a/stage23/lib/elf.c b/stage23/lib/elf.c index 361c55d5..48960fea 100644 --- a/stage23/lib/elf.c +++ b/stage23/lib/elf.c @@ -26,22 +26,6 @@ #define EI_VERSION 6 #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 { uint8_t ident[16]; @@ -82,19 +66,6 @@ struct elf32_phdr { 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 { uint32_t sh_name; uint32_t sh_type; diff --git a/stage23/lib/elf.h b/stage23/lib/elf.h index 8db57f91..98af704c 100644 --- a/stage23/lib/elf.h +++ b/stage23/lib/elf.h @@ -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); 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 diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index 234a6000..0cf9bd62 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -29,42 +29,7 @@ __attribute__((noreturn)) void bootboot_spinup( pagemap_t *pagemap, uint64_t entry_point, uint64_t stack, size_t numcores, struct smp_information* cores); -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; -}; + #define BOOTBOOT_FB 0xfffffffffc000000 #define BOOTBOOT_INFO 0xffffffffffe00000 #define BOOTBOOT_ENV 0xffffffffffe01000 @@ -199,6 +164,7 @@ void bootboot_load(char *config, void *efi_system_table) { uint8_t* ramdisk_data = freadall(ramdisk_file, MEMMAP_KERNEL_AND_MODULES); ramdisk_size = ramdisk_file->size; ramdisk_start = (uint64_t)(size_t)ramdisk_data; + fclose(ramdisk_file); } /// Header info /// @@ -263,7 +229,6 @@ void bootboot_load(char *config, void *efi_system_table) { size_t mmapent; struct e820_entry_t* e820e = get_memmap(&mmapent); if (mmapent > 248) { - term_reinit(); 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++) { From e4ff1ecbace5fbe9594b2b101ca4f0f242ff4541 Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 21:38:21 +0000 Subject: [PATCH 10/12] bootboot: reaorder includes --- stage23/protos/bootboot.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index 0cf9bd62..05f2ff20 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -1,5 +1,3 @@ -#include "lib/gterm.h" -#include "sys/smp.h" #include #include #include @@ -20,6 +18,7 @@ #include #include #include +#include #include #include #include From f1849007b69ec035b2ca7cb7e4cf3db90f4a3ec8 Mon Sep 17 00:00:00 2001 From: pitust Date: Mon, 1 Nov 2021 21:40:32 +0000 Subject: [PATCH 11/12] bootboot: use printv where appropriate, and promote "no ramdisk" to a warning, also print more info about the symbols --- stage23/protos/bootboot.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index 05f2ff20..4c487cc9 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -47,7 +47,7 @@ void bootboot_load(char *config, void *efi_system_table) { char *ramdisk = config_get_value(config, 0, "RAMDISK"); if (ramdisk == NULL) { - print("bootboot: no ramdisk!\n"); + print("bootboot: warning: no ramdisk!\n"); } /// Kernel loading code /// @@ -90,7 +90,10 @@ void bootboot_load(char *config, void *efi_system_table) { } } - print("bootboot: mapping struct to %X", struct_vaddr); + 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; @@ -188,7 +191,6 @@ void bootboot_load(char *config, void *efi_system_table) { /// Time stubs /// uint32_t year, month, day, hour, minute, second; bootboot_time(&day, &month, &year, &second, &minute, &hour); - print("bootboot: todo/help wanted: if you feel like adding support for weird time bullshit, please contribute\n"); bootboot->timezone = 0; bootboot->datetime[0] = int_to_bcd(year / 100); bootboot->datetime[1] = int_to_bcd(year % 100); From db3af4b523442d2e53a8d714d1722c7a9d16a352 Mon Sep 17 00:00:00 2001 From: pitust Date: Tue, 2 Nov 2021 06:59:04 +0000 Subject: [PATCH 12/12] bootboot: RAMDISK->INITRD_PATH, don't pass gST around for no reason, unsplit bootboot_spinup, flush the PIC only --- CONFIG.md | 2 +- README.md | 1 + stage23/entry.s3.c | 7 +--- stage23/menu.c | 2 +- stage23/protos/bootboot.c | 67 +++++++++++++++++++-------------------- stage23/protos/bootboot.h | 2 +- 6 files changed, 38 insertions(+), 43 deletions(-) diff --git a/CONFIG.md b/CONFIG.md index 31a2d30c..96022982 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -101,7 +101,7 @@ Some keys take *URIs* as values; these are described in the next section. * `RESOLUTION` - The resolution to be used. This setting takes the form of `xx`. If the resolution is not available, Limine will pick another one automatically. Omitting `` will default to 32. * Bootboot protocol: * `KERNEL_PATH` - The URI path of the kernel. - * `RAMDISK` - The URI path to the ramdisk/initrd. + * `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 diff --git a/README.md b/README.md index 44b61fc9..0998da3d 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Like Limine and want to support it? Donate Bitcoin to ### Supported boot protocols * 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 * Multiboot 1 * Multiboot 2 diff --git a/stage23/entry.s3.c b/stage23/entry.s3.c index 4230e114..f5c91104 100644 --- a/stage23/entry.s3.c +++ b/stage23/entry.s3.c @@ -179,12 +179,7 @@ void stage3_common(void) { } else if (!strcmp(proto, "multiboot2")) { multiboot2_load(config, cmdline); } else if (!strcmp(proto, "bootboot")) { -#if bios == 1 - void *efi_system_table = NULL; -#elif uefi == 1 - void *efi_system_table = gST; -#endif - bootboot_load(config, efi_system_table); + bootboot_load(config); } panic("Invalid protocol specified"); diff --git a/stage23/menu.c b/stage23/menu.c index 2a1e92bd..f893ea59 100644 --- a/stage23/menu.c +++ b/stage23/menu.c @@ -109,12 +109,12 @@ static const char *VALID_KEYS[] = { "VERBOSE", "RANDOMISE_MEMORY", "RANDOMIZE_MEMORY", - "RAMDISK", "COMMENT", "PROTOCOL", "CMDLINE", "KERNEL_CMDLINE", "KERNEL_PATH", + "INITRD_PATH", "MODULE_PATH", "MODULE_STRING", "RESOLUTION", diff --git a/stage23/protos/bootboot.c b/stage23/protos/bootboot.c index 4c487cc9..9f5726c4 100644 --- a/stage23/protos/bootboot.c +++ b/stage23/protos/bootboot.c @@ -34,7 +34,18 @@ __attribute__((noreturn)) void bootboot_spinup( #define BOOTBOOT_ENV 0xffffffffffe01000 #define BOOTBOOT_CORE 0xffffffffffe02000 -void bootboot_load(char *config, void *efi_system_table) { + +__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; @@ -45,9 +56,9 @@ void bootboot_load(char *config, void *efi_system_table) { if (kernel_path == NULL) panic("bootboot: KERNEL_PATH not specified"); - char *ramdisk = config_get_value(config, 0, "RAMDISK"); - if (ramdisk == NULL) { - print("bootboot: warning: no ramdisk!\n"); + char *initrd = config_get_value(config, 0, "INITRD"); + if (initrd == NULL) { + print("bootboot: warning: no initrd!\n"); } /// Kernel loading code /// @@ -156,17 +167,17 @@ void bootboot_load(char *config, void *efi_system_table) { map_page(pmap, fb_vaddr + current, fbi.framebuffer_addr + current, VMM_FLAG_PRESENT | VMM_FLAG_WRITE, false); } - /// Ramdisk loading /// - uint64_t ramdisk_start = 0, ramdisk_size = 0; - if (ramdisk) { - struct file_handle* ramdisk_file; - if ((ramdisk_file = uri_open(ramdisk)) == NULL) - panic("bootboot: Failed to open ramdisk with path `%s`. Is the path correct?\n", ramdisk); + /// 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* ramdisk_data = freadall(ramdisk_file, MEMMAP_KERNEL_AND_MODULES); - ramdisk_size = ramdisk_file->size; - ramdisk_start = (uint64_t)(size_t)ramdisk_data; - fclose(ramdisk_file); + 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 /// @@ -203,8 +214,8 @@ void bootboot_load(char *config, void *efi_system_table) { /// Ramdisk /// - bootboot->initrd_ptr = ramdisk_start; - bootboot->initrd_size = ramdisk_size; + bootboot->initrd_ptr = initrd_start; + bootboot->initrd_size = initrd_size; /// Framebuffer /// bootboot->fb_ptr = fbi.framebuffer_addr; @@ -245,19 +256,6 @@ void bootboot_load(char *config, void *efi_system_table) { } /// Spinup /// - bootboot_spinup(&pmap, entry, cores[0].stack_addr, numcores, cores); - -} - -__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); - -__attribute__((noreturn)) void bootboot_spinup( - pagemap_t *pagemap, - uint64_t entry_point, uint64_t stack, - size_t numcores, struct smp_information* cores) { #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 @@ -268,15 +266,16 @@ __attribute__((noreturn)) void bootboot_spinup( rm_int(0x15, &r, &r); #endif - irq_flush_type = IRQ_PIC_APIC_FLUSH; + 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_point; + cores[i].goto_address = entry; } common_spinup(bootboot_spinup_32, 10, - (uint32_t)(uintptr_t)pagemap->top_level, - (uint32_t)entry_point, (uint32_t)(entry_point >> 32), - (uint32_t)stack, (uint32_t)(stack >> 32)); + (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)); + } diff --git a/stage23/protos/bootboot.h b/stage23/protos/bootboot.h index 23341706..4b275dee 100644 --- a/stage23/protos/bootboot.h +++ b/stage23/protos/bootboot.h @@ -4,7 +4,7 @@ #include #include -void bootboot_load(char *config, void *efi_system_table); +void bootboot_load(char *config); /* * what follows is (modified) bootboot.h