:: commit a72a68486d763cb6fe6718d3836d72c02fa38f7e

pitust <piotr@stelmaszek.com> — 2021-11-01 20:38

parents: 6443900f2b

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
tab: 248 wrap: offon