console: Introduce Limine console
This commit is contained in:
parent
1e26c5fa26
commit
2b11825b20
|
@ -0,0 +1,50 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <console.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <lib/print.h>
|
||||
#include <lib/readline.h>
|
||||
#include <lib/libc.h>
|
||||
#include <lib/blib.h>
|
||||
#include <lib/term.h>
|
||||
|
||||
static void console_help(void) {
|
||||
print(
|
||||
"Available commands:\n"
|
||||
"exit -- Return to boot menu.\n"
|
||||
"version -- Print version.\n"
|
||||
"copyright -- Print copyright.\n"
|
||||
"license -- Print license.\n"
|
||||
"help -- Print this help message.\n"
|
||||
);
|
||||
}
|
||||
|
||||
void console(void) {
|
||||
print("Welcome to the Limine console.\nType 'help' for more information.\n\n");
|
||||
|
||||
static char *prompt = NULL;
|
||||
if (prompt == NULL) {
|
||||
prompt = ext_mem_alloc(256);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
print(">>> ");
|
||||
readline("", prompt, 256);
|
||||
|
||||
if (strcmp(prompt, "help") == 0) {
|
||||
console_help();
|
||||
} else if (strcmp(prompt, "exit") == 0) {
|
||||
reset_term();
|
||||
return;
|
||||
} else if (strcmp(prompt, "version") == 0) {
|
||||
print(LIMINE_VERSION "\n");
|
||||
} else if (strcmp(prompt, "copyright") == 0) {
|
||||
print(LIMINE_COPYRIGHT "\n");
|
||||
print("Limine is distributed under the terms of the BSD-2-Clause license.\n");
|
||||
} else if (strcmp(prompt, "license") == 0) {
|
||||
print("%s", bsd_2_clause);
|
||||
} else if (*prompt != 0) {
|
||||
print("Invalid command: `%s`.\n", prompt);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __CONSOLE_H__
|
||||
#define __CONSOLE_H__
|
||||
|
||||
void console(void);
|
||||
|
||||
#endif
|
|
@ -79,8 +79,6 @@ void entry(uint8_t boot_drive, int boot_from) {
|
|||
|
||||
term_textmode();
|
||||
|
||||
copyright_notice();
|
||||
|
||||
init_idt();
|
||||
|
||||
disk_create_index();
|
||||
|
|
|
@ -58,16 +58,13 @@ void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
|||
|
||||
status = gBS->SetWatchdogTimer(0, 0x10000, 0, NULL);
|
||||
if (status) {
|
||||
term_vbe(0, 0);
|
||||
early_term = true;
|
||||
print("WARNING: Failed to disable watchdog timer!\n");
|
||||
}
|
||||
|
||||
init_memmap();
|
||||
|
||||
term_vbe(0, 0);
|
||||
early_term = true;
|
||||
|
||||
copyright_notice();
|
||||
|
||||
disk_create_index();
|
||||
|
||||
boot_volume = NULL;
|
||||
|
@ -75,6 +72,9 @@ void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
|||
EFI_HANDLE current_handle = ImageHandle;
|
||||
for (;;) {
|
||||
if (current_handle == NULL) {
|
||||
term_vbe(0, 0);
|
||||
early_term = true;
|
||||
|
||||
print("WARNING: Could not meaningfully match the boot device handle with a volume.\n");
|
||||
print(" Using the first volume containing a Limine configuration!\n");
|
||||
|
||||
|
@ -109,6 +109,8 @@ void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
|||
(void **)&loaded_image);
|
||||
|
||||
if (status) {
|
||||
term_vbe(0, 0);
|
||||
early_term = true;
|
||||
panic("HandleProtocol failure (%x)", status);
|
||||
}
|
||||
|
||||
|
|
|
@ -268,3 +268,25 @@ fail:
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char bsd_2_clause[] =
|
||||
"Redistribution and use in source and binary forms, with or without\n"
|
||||
"modification, are permitted provided that the following conditions are met:\n"
|
||||
"\n"
|
||||
"1. Redistributions of source code must retain the above copyright notice, this\n"
|
||||
" list of conditions and the following disclaimer.\n"
|
||||
"\n"
|
||||
"2. Redistributions in binary form must reproduce the above copyright notice,\n"
|
||||
" this list of conditions and the following disclaimer in the documentation\n"
|
||||
" and/or other materials provided with the distribution.\n"
|
||||
"\n"
|
||||
"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n"
|
||||
"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"
|
||||
"IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n"
|
||||
"DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n"
|
||||
"FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n"
|
||||
"DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n"
|
||||
"SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n"
|
||||
"CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n"
|
||||
"OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
|
||||
"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n";
|
||||
|
|
|
@ -24,7 +24,7 @@ extern bool efi_boot_services_exited;
|
|||
bool efi_exit_boot_services(void);
|
||||
#endif
|
||||
|
||||
void copyright_notice(void);
|
||||
extern const char bsd_2_clause[];
|
||||
|
||||
extern struct volume *boot_volume;
|
||||
|
||||
|
|
|
@ -5,12 +5,6 @@
|
|||
|
||||
bool verbose = true;
|
||||
|
||||
void copyright_notice(void) {
|
||||
print("Limine " LIMINE_VERSION "\n");
|
||||
print(LIMINE_COPYRIGHT "\n");
|
||||
print("This bootloader is distributed under the terms of the BSD-2-Clause license.\n\n");
|
||||
}
|
||||
|
||||
uint8_t bcd_to_int(uint8_t val) {
|
||||
return (val & 0x0f) + ((val & 0xf0) >> 4) * 10;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <drivers/vbe.h>
|
||||
|
||||
extern struct fb_info fbinfo;
|
||||
extern bool term_autoflush;
|
||||
|
||||
bool gterm_init(size_t *_rows, size_t *_cols, size_t width, size_t height);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
static const char *base_digits = "0123456789abcdef";
|
||||
|
||||
#define PRINT_BUF_MAX 512
|
||||
#define PRINT_BUF_MAX 4096
|
||||
|
||||
static void prn_str(char *print_buf, size_t *print_buf_i, const char *string) {
|
||||
size_t i;
|
||||
|
|
|
@ -232,3 +232,107 @@ again:
|
|||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void reprint_string(int x, int y, const char *s) {
|
||||
size_t orig_x, orig_y;
|
||||
disable_cursor();
|
||||
get_cursor_pos(&orig_x, &orig_y);
|
||||
set_cursor_pos(x, y);
|
||||
term_write((uintptr_t)s, strlen(s));
|
||||
set_cursor_pos(orig_x, orig_y);
|
||||
enable_cursor();
|
||||
}
|
||||
|
||||
static void cursor_back(void) {
|
||||
size_t x, y;
|
||||
get_cursor_pos(&x, &y);
|
||||
if (x) {
|
||||
x--;
|
||||
} else if (y) {
|
||||
y--;
|
||||
x = term_cols - 1;
|
||||
}
|
||||
set_cursor_pos(x, y);
|
||||
}
|
||||
|
||||
static void cursor_fwd(void) {
|
||||
size_t x, y;
|
||||
get_cursor_pos(&x, &y);
|
||||
if (x < term_cols - 1) {
|
||||
x++;
|
||||
} else if (y < term_rows - 1) {
|
||||
y++;
|
||||
x = 0;
|
||||
}
|
||||
set_cursor_pos(x, y);
|
||||
}
|
||||
|
||||
void readline(const char *orig_str, char *buf, size_t limit) {
|
||||
bool prev_autoflush = term_autoflush;
|
||||
term_autoflush = false;
|
||||
|
||||
size_t orig_str_len = strlen(orig_str);
|
||||
memmove(buf, orig_str, orig_str_len);
|
||||
buf[orig_str_len] = 0;
|
||||
|
||||
size_t orig_x, orig_y;
|
||||
get_cursor_pos(&orig_x, &orig_y);
|
||||
|
||||
term_write((uintptr_t)orig_str, orig_str_len);
|
||||
|
||||
for (size_t i = orig_str_len; ; ) {
|
||||
term_double_buffer_flush();
|
||||
int c = getchar();
|
||||
switch (c) {
|
||||
case GETCHAR_CURSOR_LEFT:
|
||||
if (i) {
|
||||
i--;
|
||||
cursor_back();
|
||||
}
|
||||
continue;
|
||||
case GETCHAR_CURSOR_RIGHT:
|
||||
if (i < strlen(buf)) {
|
||||
i++;
|
||||
cursor_fwd();
|
||||
}
|
||||
continue;
|
||||
case '\b':
|
||||
if (i) {
|
||||
i--;
|
||||
cursor_back();
|
||||
case GETCHAR_DELETE:;
|
||||
size_t j;
|
||||
for (j = i; ; j++) {
|
||||
buf[j] = buf[j+1];
|
||||
if (!buf[j]) {
|
||||
buf[j] = ' ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
reprint_string(orig_x, orig_y, buf);
|
||||
buf[j] = 0;
|
||||
}
|
||||
continue;
|
||||
case '\n':
|
||||
term_write((uintptr_t)"\n", 1);
|
||||
goto out;
|
||||
default: {
|
||||
if (strlen(buf) < limit - 1) {
|
||||
for (size_t j = strlen(buf); ; j--) {
|
||||
buf[j+1] = buf[j];
|
||||
if (j == i)
|
||||
break;
|
||||
}
|
||||
buf[i] = c;
|
||||
i++;
|
||||
cursor_fwd();
|
||||
reprint_string(orig_x, orig_y, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
term_double_buffer_flush();
|
||||
term_autoflush = prev_autoflush;
|
||||
}
|
||||
|
|
|
@ -92,4 +92,13 @@ extern void (*term_full_refresh)(void);
|
|||
|
||||
extern void (*term_callback)(uint64_t, uint64_t, uint64_t, uint64_t);
|
||||
|
||||
extern bool term_autoflush;
|
||||
|
||||
inline void reset_term(void) {
|
||||
term_autoflush = true;
|
||||
enable_cursor();
|
||||
clear(true);
|
||||
term_double_buffer_flush();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <lib/uri.h>
|
||||
#include <mm/pmm.h>
|
||||
#include <drivers/vbe.h>
|
||||
#include <console.h>
|
||||
|
||||
static char *menu_branding = NULL;
|
||||
static char *menu_branding_colour = NULL;
|
||||
|
@ -574,11 +575,11 @@ char *menu(char **cmdline) {
|
|||
term_vbe(req_width, req_height);
|
||||
}
|
||||
|
||||
refresh:
|
||||
disable_cursor();
|
||||
|
||||
term_autoflush = false;
|
||||
|
||||
refresh:
|
||||
clear(true);
|
||||
{
|
||||
size_t x, y;
|
||||
|
@ -644,6 +645,8 @@ refresh:
|
|||
print(" \e[32mARROWS\e[0m Select \e[32mENTER\e[0m %s",
|
||||
selected_menu_entry->expanded ? "Collapse" : "Expand");
|
||||
}
|
||||
set_cursor_pos(term_cols - 12, 3);
|
||||
print("\e[32mC\e[0m Console");
|
||||
set_cursor_pos(x, y);
|
||||
}
|
||||
|
||||
|
@ -700,7 +703,6 @@ timeout_aborted:
|
|||
selected_menu_entry->expanded = !selected_menu_entry->expanded;
|
||||
goto refresh;
|
||||
}
|
||||
enable_cursor();
|
||||
*cmdline = config_get_value(selected_menu_entry->body, 0, "KERNEL_CMDLINE");
|
||||
if (!*cmdline) {
|
||||
*cmdline = config_get_value(selected_menu_entry->body, 0, "CMDLINE");
|
||||
|
@ -708,8 +710,7 @@ timeout_aborted:
|
|||
if (!*cmdline) {
|
||||
*cmdline = "";
|
||||
}
|
||||
clear(true);
|
||||
term_autoflush = true;
|
||||
reset_term();
|
||||
return selected_menu_entry->body;
|
||||
case 'e': {
|
||||
if (editor_enabled) {
|
||||
|
@ -722,6 +723,12 @@ timeout_aborted:
|
|||
selected_menu_entry->body = new_body;
|
||||
goto autoboot;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'c': {
|
||||
reset_term();
|
||||
console();
|
||||
goto refresh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
DEFAULT_ENTRY=1
|
||||
TIMEOUT=3
|
||||
GRAPHICS=yes
|
||||
#GRAPHICS=yes
|
||||
VERBOSE=yes
|
||||
|
||||
THEME_BACKGROUND=50000000
|
||||
|
|
Loading…
Reference in New Issue