bootboot: add proper support for env and ramdisk
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 <stdint.h>
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 <stdint.h>
#include <stdbool.h>
-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
