mirror of
https://github.com/limine-bootloader/limine
synced 2024-12-12 17:47:19 +03:00
commit
6b4d5cb6be
@ -67,6 +67,9 @@ Some keys take *URIs* as values; these are described in the next section.
|
|||||||
* `BACKGROUND_STYLE` - The style which will be used to display the background image. Either `tiled` or `centered`. Default is `tiled`.
|
* `BACKGROUND_STYLE` - The style which will be used to display the background image. Either `tiled` or `centered`. Default is `tiled`.
|
||||||
* `BACKDROP_COLOUR` - When the background style is `centered`, this specifies the colour of the backdrop for parts of the screen not covered by the background image, in RRGGBB format.
|
* `BACKDROP_COLOUR` - When the background style is `centered`, this specifies the colour of the backdrop for parts of the screen not covered by the background image, in RRGGBB format.
|
||||||
* `BACKDROP_COLOR` - Alias of `BACKDROP_COLOUR`.
|
* `BACKDROP_COLOR` - Alias of `BACKDROP_COLOUR`.
|
||||||
|
* `EDITOR_ENABLED` - If set to `no`, the editor will not be accessible. Defaults to `yes`.
|
||||||
|
* `EDITOR_HIGHLIGHTING` - If set to `no`, syntax highlighting in the editor will be disabled. Defaults to `yes`.
|
||||||
|
* `EDITOR_VALIDATION` - If set to `no`, the editor will not alert you about invalid keys / syntax errors. Defaults to `yes`.
|
||||||
* `VERBOSE` - If set to `yes`, print additional information during boot. Defaults to not verbose.
|
* `VERBOSE` - If set to `yes`, print additional information during boot. Defaults to not verbose.
|
||||||
|
|
||||||
*Locally assignable (non protocol specific)* keys are:
|
*Locally assignable (non protocol specific)* keys are:
|
||||||
|
176
stage23/menu.c
176
stage23/menu.c
@ -16,6 +16,10 @@
|
|||||||
static char *menu_branding = NULL;
|
static char *menu_branding = NULL;
|
||||||
|
|
||||||
#define EDITOR_MAX_BUFFER_SIZE 4096
|
#define EDITOR_MAX_BUFFER_SIZE 4096
|
||||||
|
#define TOK_KEY 0
|
||||||
|
#define TOK_EQUALS 1
|
||||||
|
#define TOK_VALUE 2
|
||||||
|
#define TOK_BADKEY 3
|
||||||
|
|
||||||
static size_t get_line_offset(size_t *displacement, size_t index, const char *buffer) {
|
static size_t get_line_offset(size_t *displacement, size_t index, const char *buffer) {
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
@ -67,7 +71,69 @@ static size_t get_prev_line(size_t index, const char *buffer) {
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *config_entry_editor(const char *orig_entry) {
|
static const char *VALID_KEYS[] = {
|
||||||
|
"TIMEOUT",
|
||||||
|
"DEFAULT_ENTRY",
|
||||||
|
"GRAPHICS",
|
||||||
|
"MENU_RESOLUTION",
|
||||||
|
"MENU_BRANDING",
|
||||||
|
"MENU_FONT",
|
||||||
|
"TERMINAL_FONT",
|
||||||
|
"THEME_COLOURS",
|
||||||
|
"THEME_COLORS",
|
||||||
|
"THEME_BACKGROUND",
|
||||||
|
"THEME_FOREGROUND",
|
||||||
|
"THEME_MARGIN",
|
||||||
|
"THEME_MARGIN_GRADIENT",
|
||||||
|
"BACKGROUND_PATH",
|
||||||
|
"BACKGROUND_STYLE",
|
||||||
|
"BACKDROP_COLOUR",
|
||||||
|
"BACKDROP_COLOR",
|
||||||
|
"EDITOR_ENABLED",
|
||||||
|
"EDITOR_HIGHLIGHTING",
|
||||||
|
"EDITOR_VALIDATION",
|
||||||
|
"VERBOSE",
|
||||||
|
"PROTOCOL",
|
||||||
|
"CMDLINE",
|
||||||
|
"KERNEL_CMDLINE",
|
||||||
|
"KERNEL_PATH",
|
||||||
|
"MODULE_PATH",
|
||||||
|
"MODULE_STRING",
|
||||||
|
"RESOLUTION",
|
||||||
|
"KASLR",
|
||||||
|
"DRIVE",
|
||||||
|
"PARTITION",
|
||||||
|
"IMAGE_PATH",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool validation_enabled = true;
|
||||||
|
static bool invalid_syntax = false;
|
||||||
|
|
||||||
|
static int validate_line(const char *buffer) {
|
||||||
|
if (!validation_enabled) return TOK_KEY;
|
||||||
|
char keybuf[64];
|
||||||
|
int i;
|
||||||
|
for (i = 0; buffer[i] && i < 64; i++) {
|
||||||
|
if (buffer[i] == '=') goto found_equals;
|
||||||
|
keybuf[i] = buffer[i];
|
||||||
|
}
|
||||||
|
fail:
|
||||||
|
if (i < 64) keybuf[i] = 0;
|
||||||
|
if (keybuf[0] == '\n' || (!keybuf[0] && buffer[0] != '=')) return TOK_KEY; // blank line is valid
|
||||||
|
invalid_syntax = true;
|
||||||
|
return TOK_BADKEY;
|
||||||
|
found_equals:
|
||||||
|
if (i < 64) keybuf[i] = 0;
|
||||||
|
for (i = 0; VALID_KEYS[i]; i++) {
|
||||||
|
if (!strcmp(keybuf, VALID_KEYS[i])) {
|
||||||
|
return TOK_KEY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *config_entry_editor(const char *title, const char *orig_entry) {
|
||||||
size_t cursor_offset = 0;
|
size_t cursor_offset = 0;
|
||||||
size_t entry_size = strlen(orig_entry);
|
size_t entry_size = strlen(orig_entry);
|
||||||
size_t _window_size = term_rows - 11;
|
size_t _window_size = term_rows - 11;
|
||||||
@ -82,8 +148,17 @@ static char *config_entry_editor(const char *orig_entry) {
|
|||||||
entry_size--;
|
entry_size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry_size >= EDITOR_MAX_BUFFER_SIZE)
|
if (entry_size >= EDITOR_MAX_BUFFER_SIZE) {
|
||||||
panic("Entry is too big to be edited.");
|
panic("Entry is too big to be edited.");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool syntax_highlighting_enabled = true;
|
||||||
|
char *syntax_highlighting_enabled_config = config_get_value(NULL, 0, "EDITOR_HIGHLIGHTING");
|
||||||
|
if (!strcmp(syntax_highlighting_enabled_config, "no")) syntax_highlighting_enabled = false;
|
||||||
|
|
||||||
|
validation_enabled = true;
|
||||||
|
char *validation_enabled_config = config_get_value(NULL, 0, "EDITOR_VALIDATION");
|
||||||
|
if (!strcmp(validation_enabled_config, "no")) validation_enabled = false;
|
||||||
|
|
||||||
static char *buffer = NULL;
|
static char *buffer = NULL;
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
@ -92,12 +167,15 @@ static char *config_entry_editor(const char *orig_entry) {
|
|||||||
buffer[entry_size] = 0;
|
buffer[entry_size] = 0;
|
||||||
|
|
||||||
refresh:
|
refresh:
|
||||||
|
invalid_syntax = false;
|
||||||
|
|
||||||
clear(true);
|
clear(true);
|
||||||
disable_cursor();
|
disable_cursor();
|
||||||
print("\n\n \e[36m %s \e[37m\n\n\n", menu_branding);
|
print("\n\n \e[36m %s \e[37m\n\n\n", menu_branding);
|
||||||
|
|
||||||
print("Editing entry.\n");
|
//print("Editing \"%s\"\n", title);
|
||||||
print("Press esc to return to main menu and discard changes, press F10 to boot.\n");
|
print(" \e[32mESC\e[0m Discard and Exit \e[32mF10\e[0m Boot\n");
|
||||||
|
|
||||||
|
|
||||||
print("\n\xda");
|
print("\n\xda");
|
||||||
for (int i = 0; i < term_cols - 2; i++) {
|
for (int i = 0; i < term_cols - 2; i++) {
|
||||||
@ -108,8 +186,15 @@ refresh:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// FALLTHRU
|
// FALLTHRU
|
||||||
default:
|
default: {
|
||||||
print("\xc4");
|
int title_length = strlen(title);
|
||||||
|
if (i == (term_cols / 2) - (title_length / 2) - 1) {
|
||||||
|
print("%s", title);
|
||||||
|
i += title_length - 1;
|
||||||
|
} else {
|
||||||
|
print("\xc4");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print("\xbf\xb3");
|
print("\xbf\xb3");
|
||||||
@ -117,7 +202,9 @@ refresh:
|
|||||||
int cursor_x, cursor_y;
|
int cursor_x, cursor_y;
|
||||||
size_t current_line = 0, line_offset = 0, window_size = _window_size;
|
size_t current_line = 0, line_offset = 0, window_size = _window_size;
|
||||||
bool printed_cursor = false;
|
bool printed_cursor = false;
|
||||||
|
int token_type = validate_line(buffer);
|
||||||
for (size_t i = 0; ; i++) {
|
for (size_t i = 0; ; i++) {
|
||||||
|
// newline
|
||||||
if (buffer[i] == '\n'
|
if (buffer[i] == '\n'
|
||||||
&& current_line < window_offset + window_size
|
&& current_line < window_offset + window_size
|
||||||
&& current_line >= window_offset) {
|
&& current_line >= window_offset) {
|
||||||
@ -134,6 +221,7 @@ refresh:
|
|||||||
else
|
else
|
||||||
print("\xb3\xb3");
|
print("\xb3\xb3");
|
||||||
line_offset = 0;
|
line_offset = 0;
|
||||||
|
token_type = validate_line(buffer+i+1);
|
||||||
current_line++;
|
current_line++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -175,10 +263,48 @@ refresh:
|
|||||||
|
|
||||||
if (current_line >= window_offset) {
|
if (current_line >= window_offset) {
|
||||||
line_offset++;
|
line_offset++;
|
||||||
print("%c", buffer[i]);
|
|
||||||
|
// switch to token type 1 if equals sign
|
||||||
|
if (token_type == TOK_KEY && buffer[i] == '=') token_type = TOK_EQUALS;
|
||||||
|
|
||||||
|
// syntax highlighting
|
||||||
|
if (syntax_highlighting_enabled) {
|
||||||
|
switch (token_type) {
|
||||||
|
case TOK_KEY:
|
||||||
|
print("\e[36m%c\e[0m", buffer[i]);
|
||||||
|
break;
|
||||||
|
case TOK_EQUALS:
|
||||||
|
print("\e[32m%c\e[0m", buffer[i]);
|
||||||
|
break;
|
||||||
|
case TOK_VALUE:
|
||||||
|
print("\e[39m%c\e[0m", buffer[i]);
|
||||||
|
break;
|
||||||
|
case TOK_BADKEY:
|
||||||
|
print("\e[31m%c\e[0m", buffer[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("%c", buffer[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch to token type 2 after equals sign
|
||||||
|
if (token_type == TOK_EQUALS) token_type = TOK_VALUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// syntax error alert
|
||||||
|
if (validation_enabled) {
|
||||||
|
int x, y;
|
||||||
|
get_cursor_pos(&x, &y);
|
||||||
|
set_cursor_pos(0, term_rows-2);
|
||||||
|
if (invalid_syntax) {
|
||||||
|
print("\e[31mConfiguration is INVALID.\e[0m");
|
||||||
|
} else {
|
||||||
|
print("\e[32mConfiguration is valid.\e[0m");
|
||||||
|
}
|
||||||
|
set_cursor_pos(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
if (current_line - window_offset < window_size) {
|
if (current_line - window_offset < window_size) {
|
||||||
int x, y;
|
int x, y;
|
||||||
for (size_t i = 0; i < (window_size - (current_line - window_offset)) - 1; i++) {
|
for (size_t i = 0; i < (window_size - (current_line - window_offset)) - 1; i++) {
|
||||||
@ -349,6 +475,10 @@ char *menu(char **cmdline) {
|
|||||||
timeout = strtoui(timeout_config, NULL, 10);
|
timeout = strtoui(timeout_config, NULL, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool editor_enabled = true;
|
||||||
|
char *editor_enabled_config = config_get_value(NULL, 0, "EDITOR_ENABLED");
|
||||||
|
if (!strcmp(editor_enabled_config, "no")) editor_enabled = false;
|
||||||
|
|
||||||
if (!timeout) {
|
if (!timeout) {
|
||||||
// Use print tree to load up selected_menu_entry and determine if the
|
// Use print tree to load up selected_menu_entry and determine if the
|
||||||
// default entry is valid.
|
// default entry is valid.
|
||||||
@ -394,7 +524,7 @@ refresh:
|
|||||||
getchar();
|
getchar();
|
||||||
char *new_body = NULL;
|
char *new_body = NULL;
|
||||||
while (new_body == NULL)
|
while (new_body == NULL)
|
||||||
new_body = config_entry_editor("");
|
new_body = config_entry_editor("New Entry", "");
|
||||||
selected_menu_entry = ext_mem_alloc(sizeof(struct menu_entry));
|
selected_menu_entry = ext_mem_alloc(sizeof(struct menu_entry));
|
||||||
selected_menu_entry->body = new_body;
|
selected_menu_entry->body = new_body;
|
||||||
config_ready = true;
|
config_ready = true;
|
||||||
@ -406,7 +536,17 @@ refresh:
|
|||||||
int max_entries = print_tree(0, 0, selected_entry, menu_tree,
|
int max_entries = print_tree(0, 0, selected_entry, menu_tree,
|
||||||
&selected_menu_entry);
|
&selected_menu_entry);
|
||||||
|
|
||||||
print("\nArrows to select, enter to boot, 'e' to edit selected entry.");
|
{
|
||||||
|
int x, y;
|
||||||
|
get_cursor_pos(&x, &y);
|
||||||
|
set_cursor_pos(0, 4);
|
||||||
|
if (editor_enabled && selected_menu_entry->sub == NULL) {
|
||||||
|
print("\n \e[32mARROWS\e[0m Select \e[32mENTER\e[0m Boot \e[32mE\e[0m Edit");
|
||||||
|
} else {
|
||||||
|
print("\n \e[32mARROWS\e[0m Select \e[32mENTER\e[0m Boot");
|
||||||
|
}
|
||||||
|
set_cursor_pos(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
if (selected_menu_entry->sub != NULL)
|
if (selected_menu_entry->sub != NULL)
|
||||||
skip_timeout = true;
|
skip_timeout = true;
|
||||||
@ -461,14 +601,16 @@ timeout_aborted:
|
|||||||
term_double_buffer(false);
|
term_double_buffer(false);
|
||||||
return selected_menu_entry->body;
|
return selected_menu_entry->body;
|
||||||
case 'e': {
|
case 'e': {
|
||||||
if (selected_menu_entry->sub != NULL)
|
if (editor_enabled) {
|
||||||
goto refresh;
|
if (selected_menu_entry->sub != NULL)
|
||||||
enable_cursor();
|
goto refresh;
|
||||||
char *new_body = config_entry_editor(selected_menu_entry->body);
|
enable_cursor();
|
||||||
if (new_body == NULL)
|
char *new_body = config_entry_editor(selected_menu_entry->name, selected_menu_entry->body);
|
||||||
goto refresh;
|
if (new_body == NULL)
|
||||||
selected_menu_entry->body = new_body;
|
goto refresh;
|
||||||
goto autoboot;
|
selected_menu_entry->body = new_body;
|
||||||
|
goto autoboot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user