Preprocessor+Linker Voodoo for boot param decl

This commit is contained in:
Thomas Oltmann 2026-02-25 22:27:44 +01:00
parent 5b228625f6
commit 0d06d97edb
5 changed files with 34 additions and 62 deletions

View file

@ -1,7 +1,24 @@
#ifndef KARLOS_BOOTPARAM_H
#define KARLOS_BOOTPARAM_H
void bootparam_reset_values(void);
#define BOOTPARAM_(name_, symbol) const struct bootparam_spec _bootparam_spec_ ## symbol __attribute__((section(".rodata.bootparam"))) = { name_, &symbol };
#define BOOTPARAM_STRING(name_, symbol) BOOTPARAM_("S" name_, symbol)
#define BOOTPARAM_BOOL( name_, symbol) BOOTPARAM_("B" name_, symbol)
#define BOOTPARAM_INT( name_, symbol) BOOTPARAM_("I" name_, symbol)
#define BOOTPARAM_TYPE_STRING 'S'
#define BOOTPARAM_TYPE_BOOL 'B'
#define BOOTPARAM_TYPE_INT 'I'
// HACK: GCC seems to align global variables to multiples of 16.
// Since we want to iterate over the .rodata.bootparam section,
// the size of this struct needs to be a multiple of 16.
struct bootparam_spec {
const char *name; // First byte encodes type
void *var;
};
void bootparam_parse_config(char *text);
#endif

View file

@ -47,6 +47,9 @@ SECTIONS
KEEP(*(.text.boot)) *(.text .text.*) /* code */
} : text
.data : {
_bootparam_start = .;
*(.rodata.bootparam)
_bootparam_end = .;
*(.rodata .rodata.*) /* data */
*(.data .data.*)
} : text

View file

@ -1,41 +1,14 @@
#include <std.h>
#include <bootparam.h>
enum bootparam_type {
BOOTPARAM_TYPE_INT,
BOOTPARAM_TYPE_BOOL,
BOOTPARAM_TYPE_STRING,
};
const char *_bootparam_bb_kernel;
const char *_bootparam_bb_screen;
union bootparam_value {
int64_t i;
bool b;
const char *s;
};
BOOTPARAM_STRING("kernel", _bootparam_bb_kernel);
BOOTPARAM_STRING("screen", _bootparam_bb_screen);
struct bootparam_spec {
enum bootparam_type type;
union bootparam_value defval;
const char *name;
void *var;
};
extern bool ram_enable_logging;
const struct bootparam_spec bootparam_specs[] = {
{
.name = "screen",
.type = BOOTPARAM_TYPE_STRING,
.defval = { .s = "800x600" },
.var = NULL,
},
{
.name = "ram.enable_logging",
.type = BOOTPARAM_TYPE_BOOL,
.defval = { .b = false },
.var = &ram_enable_logging,
},
};
extern const struct bootparam_spec _bootparam_start[];
extern const struct bootparam_spec _bootparam_end[];
static bool
is_space_char(char c)
@ -55,9 +28,8 @@ parse_bootparam_value(unsigned lineno, char *key, char *val)
(void)lineno;
const struct bootparam_spec *spec = NULL;
for (unsigned i = 0; i < sizeof(bootparam_specs) / sizeof(bootparam_specs[0]); i++) {
const struct bootparam_spec *s = &bootparam_specs[i];
if (streq(key, s->name)) {
for (const struct bootparam_spec *s = _bootparam_start; s < _bootparam_end; s++) {
if (streq(key, s->name+1)) {
spec = s;
break;
}
@ -72,7 +44,7 @@ parse_bootparam_value(unsigned lineno, char *key, char *val)
return;
}
switch (spec->type) {
switch (spec->name[0]) {
case BOOTPARAM_TYPE_STRING:
*(const char **)spec->var = val;
break;
@ -219,25 +191,3 @@ bootparam_parse_config(char *text)
lineno++;
}
}
void
bootparam_reset_values(void)
{
for (unsigned i = 0; i < sizeof(bootparam_specs) / sizeof (bootparam_specs[0]); i++) {
const struct bootparam_spec *s = &bootparam_specs[i];
if (!s->var) {
continue;
}
switch (s->type) {
case BOOTPARAM_TYPE_STRING:
*(const char **)s->var = s->defval.s;
break;
case BOOTPARAM_TYPE_BOOL:
*(bool *)s->var = s->defval.b;
break;
case BOOTPARAM_TYPE_INT:
*(int64_t *)s->var = s->defval.i;
break;
}
}
}

View file

@ -38,7 +38,6 @@ void _start() {
__get_cpuid(0x1, &info[0], &info[1], &info[2], &info[3]);
unsigned procid = info[1] >> 24;
if (procid == bootboot.bspid) {
bootparam_reset_values();
bootparam_parse_config(environment);
cpu_init_bsp();
} else {

View file

@ -3,6 +3,7 @@
#include "ram.h"
#include "bootboot.h"
#include "mem_range.h"
#include "bootparam.h"
extern BOOTBOOT bootboot;
@ -30,7 +31,9 @@ bool ram_initialized = false;
#define CHECK_INIT do { } while (0)
#endif
bool ram_enable_logging;
bool ram_enable_logging = false;
BOOTPARAM_BOOL("ram.enable_logging", ram_enable_logging);
size_t frame_size_to_num_bytes(enum frame_size size) {