config: Implement macros

This commit is contained in:
mintsuki 2021-12-15 19:29:12 +01:00
parent 4cb616bcad
commit b5808884a3
2 changed files with 124 additions and 2 deletions

View File

@ -8,8 +8,8 @@ of either a `/limine.cfg`, `/boot/limine.cfg`, or a `/EFI/BOOT/limine.cfg` file,
If no config file is found in the aforementioned locations, Limine looks for the file on the fw_cfg
interface called `opt/org.limine-bootloader.config`. If that is not present and the kernel is found at
`opt/org.limine-bootloader.kernel`, Limine enters the so-called "simple mode", where the kernel is loaded from
`opt/org.limine-bootloader.kernel`, and, (if present), the background is loaded from
`opt/org.limine-bootloader.kernel`, Limine enters the so-called "simple mode", where the kernel is loaded from
`opt/org.limine-bootloader.kernel`, and, (if present), the background is loaded from
`opt/org.limine-bootloader.background`.
Once the file is located, Limine will use it as its config file. Other possible
@ -161,3 +161,18 @@ A resource can be one of the following:
A URI can optionally be prefixed by a `$` character to indicate that the file
pointed to be the URI is a gzip-compressed payload to be uncompressed on the
fly. E.g.: `$boot:///somemodule.gz`.
## Macros
Macros are strings that can be arbitrarily assigned to represent other strings. For example:
```
${MY_MACRO}=Some text
```
Now, whenever `${MY_MACRO}` is used in the config file (except for an assignment as above), it will
be replaced by the text `Some text`. For example:
```
CMDLINE=something before ${MY_MACRO} something after
```
Macros must always be placed inside `${...}` where `...` is the arbitrary macro name.

View File

@ -138,6 +138,14 @@ static struct menu_entry *create_menu_tree(struct menu_entry *parent,
struct menu_entry *menu_tree = NULL;
struct macro {
char name[1024];
char value[2048];
struct macro *next;
};
static struct macro *macros = NULL;
int init_config(size_t config_size) {
// remove windows carriage returns, if any
for (size_t i = 0; i < config_size; i++) {
@ -148,6 +156,105 @@ int init_config(size_t config_size) {
}
}
// Load macros
for (size_t i = 0; i < config_size;) {
if ((config_size - i >= 3 && memcmp(config_addr + i, "\n${", 3) == 0)
|| (config_size - i >= 2 && i == 0 && memcmp(config_addr, "${", 2) == 0)) {
struct macro *macro = ext_mem_alloc(sizeof(struct macro));
i += i ? 3 : 2;
size_t j;
for (j = 0; config_addr[i] != '}' && config_addr[i] != '\n' && config_addr[i] != 0; j++, i++) {
macro->name[j] = config_addr[i];
}
if (config_addr[i] == '\n' || config_addr[i] == 0 || config_addr[i+1] != '=') {
bad_config = true;
panic(true, "config: Malformed macro definition");
}
i += 2;
macro->name[j] = 0;
for (j = 0; config_addr[i] != '\n' && config_addr[i] != 0; j++, i++) {
macro->value[j] = config_addr[i];
}
macro->value[j] = 0;
macro->next = macros;
macros = macro;
continue;
}
i++;
}
// Expand macros
if (macros != NULL) {
char *new_config = ext_mem_alloc(config_size * 4);
size_t i, in;
for (i = 0, in = 0; i < config_size;) {
if ((config_size - i >= 3 && memcmp(config_addr + i, "\n${", 3) == 0)
|| (config_size - i >= 2 && i == 0 && memcmp(config_addr, "${", 2) == 0)) {
i += i ? 3 : 2;
while (config_addr[i] != '\n' && config_addr[i] != 0) {
i++;
}
continue;
}
if (config_size - i >= 2 && memcmp(config_addr + i, "${", 2) == 0) {
char *macro_name = ext_mem_alloc(1024);
i += 2;
size_t j;
for (j = 0; config_addr[i] != '}' && config_addr[i] != '\n' && config_addr[i] != 0; j++, i++) {
macro_name[j] = config_addr[i];
}
if (config_addr[i] != '}') {
bad_config = true;
panic(true, "config: Malformed macro usage");
}
i++;
macro_name[j] = 0;
char *macro_value = "";
struct macro *macro = macros;
for (;;) {
if (macro == NULL) {
break;
}
if (strcmp(macro->name, macro_name) == 0) {
macro_value = macro->value;
break;
}
macro = macro->next;
}
pmm_free(macro_name, 1024);
for (j = 0; macro_value[j] != 0; j++, in++) {
new_config[in] = macro_value[j];
}
continue;
}
new_config[in++] = config_addr[i++];
}
config_addr = new_config;
config_size = in;
// Free macros
struct macro *macro = macros;
for (;;) {
if (macro == NULL) {
break;
}
struct macro *next = macro->next;
pmm_free(macro, sizeof(struct macro));
macro = next;
}
}
config_ready = true;
menu_tree = create_menu_tree(NULL, 1, 0);