misc: Improve printing effectively on panics and errors

This commit is contained in:
mintsuki 2022-09-17 10:40:14 +02:00
parent 8773c36ab6
commit 3181293a04
12 changed files with 36 additions and 118 deletions

View File

@ -36,15 +36,13 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS status; EFI_STATUS status;
term_fallback();
status = gBS->SetWatchdogTimer(0, 0x10000, 0, NULL); status = gBS->SetWatchdogTimer(0, 0x10000, 0, NULL);
if (status) { if (status) {
term_vbe(NULL, 0, 0);
early_term = true;
print("WARNING: Failed to disable watchdog timer!\n"); print("WARNING: Failed to disable watchdog timer!\n");
} }
term_notready();
init_memmap(); init_memmap();
#if defined (__x86_64__) || defined (__i386__) #if defined (__x86_64__) || defined (__i386__)
@ -64,9 +62,6 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
EFI_HANDLE current_handle = ImageHandle; EFI_HANDLE current_handle = ImageHandle;
for (;;) { for (;;) {
if (current_handle == NULL) { if (current_handle == NULL) {
term_vbe(NULL, 0, 0);
early_term = true;
print("WARNING: Could not meaningfully match the boot device handle with a volume.\n"); print("WARNING: Could not meaningfully match the boot device handle with a volume.\n");
print(" Using the first volume containing a Limine configuration!\n"); print(" Using the first volume containing a Limine configuration!\n");
@ -94,8 +89,9 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
break; break;
} }
if (boot_volume != NULL) if (boot_volume != NULL) {
stage3_common(); stage3_common();
}
panic(false, "No volume contained a Limine configuration file"); panic(false, "No volume contained a Limine configuration file");
} }
@ -112,8 +108,9 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
boot_volume = disk_volume_from_efi_handle(loaded_image->DeviceHandle); boot_volume = disk_volume_from_efi_handle(loaded_image->DeviceHandle);
if (boot_volume != NULL) if (boot_volume != NULL) {
stage3_common(); stage3_common();
}
current_handle = loaded_image->ParentHandle; current_handle = loaded_image->ParentHandle;
} }
@ -121,8 +118,6 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
#endif #endif
noreturn void stage3_common(void) { noreturn void stage3_common(void) {
term_notready();
#if defined (__x86_64__) || defined (__i386__) #if defined (__x86_64__) || defined (__i386__)
init_flush_irqs(); init_flush_irqs();
init_io_apics(); init_io_apics();

View File

@ -617,7 +617,6 @@ bool gterm_init(char *config, size_t *_rows, size_t *_cols, size_t width, size_t
&& width == 0 && width == 0
&& height == 0 && height == 0
&& fbinfo.framebuffer_bpp == 32 && fbinfo.framebuffer_bpp == 32
&& !early_term
&& serial == last_serial && serial == last_serial
&& config == last_config) { && config == last_config) {
*_rows = rows; *_rows = rows;
@ -633,7 +632,6 @@ bool gterm_init(char *config, size_t *_rows, size_t *_cols, size_t width, size_t
&& fbinfo.framebuffer_width == width && fbinfo.framebuffer_width == width
&& fbinfo.framebuffer_height == height && fbinfo.framebuffer_height == height
&& fbinfo.framebuffer_bpp == 32 && fbinfo.framebuffer_bpp == 32
&& !early_term
&& serial == last_serial && serial == last_serial
&& config == last_config) { && config == last_config) {
*_rows = rows; *_rows = rows;
@ -642,8 +640,6 @@ bool gterm_init(char *config, size_t *_rows, size_t *_cols, size_t width, size_t
return true; return true;
} }
early_term = false;
// We force bpp to 32 // We force bpp to 32
if (!fb_init(&fbinfo, width, height, 32)) if (!fb_init(&fbinfo, width, height, 32))
return false; return false;

View File

@ -21,45 +21,11 @@ noreturn void panic(bool allow_menu, const char *fmt, ...) {
quiet = false; quiet = false;
static bool is_nested = false; if (term_backend != FALLBACK) {
if (is_nested) {
goto nested;
}
is_nested = true;
#if defined (BIOS)
if (stage3_loaded == true && term_backend == NOT_READY) {
early_term = true;
term_vbe(NULL, 0, 0);
}
#endif
#if defined (UEFI)
if (term_backend == NOT_READY) {
if (term_enabled_once) {
term_vbe(NULL, 0, 0);
} else {
term_fallback();
}
}
#endif
nested:
if (term_backend == NOT_READY) {
term_fallback();
}
#if defined (BIOS)
if (stage3_loaded) {
#endif
print("\033[31mPANIC\033[37;1m\033[0m: "); print("\033[31mPANIC\033[37;1m\033[0m: ");
#if defined (BIOS)
} else { } else {
print("PANIC: "); print("PANIC: ");
} }
#endif
vprint(fmt, args); vprint(fmt, args);
va_end(args); va_end(args);

View File

@ -11,29 +11,6 @@
#include <sys/cpu.h> #include <sys/cpu.h>
#include <drivers/serial.h> #include <drivers/serial.h>
#if defined (BIOS)
static void s2_print(const char *s, size_t len) {
for (size_t i = 0; i < len; i++) {
struct rm_regs r = {0};
char c = s[i];
switch (c) {
case '\n':
r.eax = 0x0e00 | '\r';
rm_int(0x10, &r, &r);
r = (struct rm_regs){0};
r.eax = 0x0e00 | '\n';
rm_int(0x10, &r, &r);
break;
default:
r.eax = 0x0e00 | s[i];
rm_int(0x10, &r, &r);
break;
}
}
}
#endif
static const char *base_digits = "0123456789abcdef"; static const char *base_digits = "0123456789abcdef";
#define PRINT_BUF_MAX 4096 #define PRINT_BUF_MAX 4096
@ -142,6 +119,10 @@ void print(const char *fmt, ...) {
static char print_buf[PRINT_BUF_MAX]; static char print_buf[PRINT_BUF_MAX];
void vprint(const char *fmt, va_list args) { void vprint(const char *fmt, va_list args) {
if (quiet) {
return;
}
size_t print_buf_i = 0; size_t print_buf_i = 0;
for (;;) { for (;;) {
@ -199,15 +180,7 @@ void vprint(const char *fmt, va_list args) {
} }
out: out:
#if defined (BIOS) term_write((uint64_t)(uintptr_t)print_buf, print_buf_i);
if (stage3_loaded) {
#endif
term_write((uint64_t)(uintptr_t)print_buf, print_buf_i);
#if defined (BIOS)
} else {
s2_print(print_buf, print_buf_i);
}
#endif
for (size_t i = 0; i < print_buf_i; i++) { for (size_t i = 0; i < print_buf_i; i++) {
#if defined (__x86_64__) || defined (__i386__) #if defined (__x86_64__) || defined (__i386__)
@ -215,7 +188,7 @@ out:
outb(0xe9, print_buf[i]); outb(0xe9, print_buf[i]);
} }
#endif #endif
if ((term_backend != NOT_READY && serial) || COM_OUTPUT) { if (serial || COM_OUTPUT) {
switch (print_buf[i]) { switch (print_buf[i]) {
case '\n': case '\n':
serial_out('\r'); serial_out('\r');

View File

@ -52,7 +52,7 @@ void term_deinit(void) {
gterm_deinit(); gterm_deinit();
} }
term_notready(); term_fallback();
} }
void term_vbe(char *config, size_t width, size_t height) { void term_vbe(char *config, size_t width, size_t height) {
@ -109,8 +109,6 @@ void term_vbe(char *config, size_t width, size_t height) {
term_context_restore = gterm_context_restore; term_context_restore = gterm_context_restore;
term_full_refresh = gterm_full_refresh; term_full_refresh = gterm_full_refresh;
term_enabled_once = true;
term_backend = VBE; term_backend = VBE;
} }
@ -183,8 +181,6 @@ void term_textmode(void) {
return; return;
} }
term_notready();
init_vga_textmode(&term_rows, &term_cols, true); init_vga_textmode(&term_rows, &term_cols, true);
if (serial) { if (serial) {
@ -222,8 +218,6 @@ void term_textmode(void) {
term_context_restore = text_context_restore; term_context_restore = text_context_restore;
term_full_refresh = text_full_refresh; term_full_refresh = text_full_refresh;
term_enabled_once = true;
term_backend = TEXTMODE; term_backend = TEXTMODE;
} }
#endif #endif
@ -260,9 +254,6 @@ static uint8_t xfer_buf[TERM_XFER_CHUNK];
bool term_autoflush = true; bool term_autoflush = true;
void term_write(uint64_t buf, uint64_t count) { void term_write(uint64_t buf, uint64_t count) {
if (term_backend == NOT_READY)
return;
switch (count) { switch (count) {
case TERM_CTX_SIZE: { case TERM_CTX_SIZE: {
uint64_t ret = context_size(); uint64_t ret = context_size();

View File

@ -39,7 +39,7 @@ extern struct term_context {
} term_context; } term_context;
enum { enum {
NOT_READY, _NOT_READY,
VBE, VBE,
TEXTMODE, TEXTMODE,
FALLBACK FALLBACK
@ -49,8 +49,6 @@ extern int current_video_mode;
extern int term_backend; extern int term_backend;
extern size_t term_rows, term_cols; extern size_t term_rows, term_cols;
extern bool term_runtime; extern bool term_runtime;
extern bool early_term;
extern bool term_enabled_once;
void term_fallback(void); void term_fallback(void);
@ -58,7 +56,6 @@ void term_reinit(void);
void term_deinit(void); void term_deinit(void);
void term_vbe(char *config, size_t width, size_t height); void term_vbe(char *config, size_t width, size_t height);
void term_textmode(void); void term_textmode(void);
void term_notready(void);
void term_putchar(uint8_t c); void term_putchar(uint8_t c);
void term_write(uint64_t buf, uint64_t count); void term_write(uint64_t buf, uint64_t count);

View File

@ -5,13 +5,10 @@
#include <lib/misc.h> #include <lib/misc.h>
#include <lib/real.h> #include <lib/real.h>
bool early_term = false;
no_unwind int current_video_mode = -1; no_unwind int current_video_mode = -1;
int term_backend = NOT_READY; int term_backend = _NOT_READY;
size_t term_rows, term_cols; size_t term_rows, term_cols;
bool term_runtime = false; bool term_runtime = false;
bool term_enabled_once = false;
void (*raw_putchar)(uint8_t c); void (*raw_putchar)(uint8_t c);
void (*clear)(bool move); void (*clear)(bool move);
@ -139,6 +136,8 @@ static void fallback_get_cursor_pos(size_t *x, size_t *y) {
} }
#endif #endif
static void term_notready(void);
void term_fallback(void) { void term_fallback(void) {
#if defined (UEFI) #if defined (UEFI)
if (!efi_boot_services_exited) { if (!efi_boot_services_exited) {
@ -194,9 +193,7 @@ static void notready_uint64_t(uint64_t n) {
(void)n; (void)n;
} }
void term_notready(void) { static void term_notready(void) {
term_backend = NOT_READY;
raw_putchar = notready_raw_putchar; raw_putchar = notready_raw_putchar;
clear = notready_clear; clear = notready_clear;
enable_cursor = notready_void; enable_cursor = notready_void;

View File

@ -598,8 +598,6 @@ noreturn void _menu(bool timeout_enabled) {
randomise_mem_str = config_get_value(NULL, 0, "RANDOMIZE_MEMORY"); randomise_mem_str = config_get_value(NULL, 0, "RANDOMIZE_MEMORY");
bool randomise_mem = randomise_mem_str != NULL && strcmp(randomise_mem_str, "yes") == 0; bool randomise_mem = randomise_mem_str != NULL && strcmp(randomise_mem_str, "yes") == 0;
if (randomise_mem) { if (randomise_mem) {
term_vbe(NULL, 0, 0);
early_term = true;
pmm_randomise_memory(); pmm_randomise_memory();
} }
@ -647,6 +645,7 @@ noreturn void _menu(bool timeout_enabled) {
// default entry is valid. // default entry is valid.
print_tree(NULL, 0, 0, selected_entry, menu_tree, &selected_menu_entry); print_tree(NULL, 0, 0, selected_entry, menu_tree, &selected_menu_entry);
if (selected_menu_entry == NULL || selected_menu_entry->sub != NULL) { if (selected_menu_entry == NULL || selected_menu_entry->sub != NULL) {
quiet = false;
print("Default entry is not valid or directory, booting to menu.\n"); print("Default entry is not valid or directory, booting to menu.\n");
skip_timeout = true; skip_timeout = true;
} else { } else {
@ -661,7 +660,6 @@ noreturn void _menu(bool timeout_enabled) {
char *graphics = "yes"; char *graphics = "yes";
#endif #endif
reterm:
if (graphics == NULL || strcmp(graphics, "no") != 0) { if (graphics == NULL || strcmp(graphics, "no") != 0) {
size_t req_width = 0, req_height = 0, req_bpp = 0; size_t req_width = 0, req_height = 0, req_bpp = 0;
@ -692,6 +690,7 @@ refresh:
} }
while (menu_tree == NULL) { while (menu_tree == NULL) {
quiet = false;
print("Config file %s.\n\n", config_ready ? "contains no valid entries" : "not found"); print("Config file %s.\n\n", config_ready ? "contains no valid entries" : "not found");
print("For information on the format of Limine config entries, consult CONFIG.md in\n"); print("For information on the format of Limine config entries, consult CONFIG.md in\n");
print("the root of the Limine source repository.\n\n"); print("the root of the Limine source repository.\n\n");
@ -762,14 +761,10 @@ refresh:
term_double_buffer_flush(); term_double_buffer_flush();
if ((c = pit_sleep_and_quit_on_keypress(1))) { if ((c = pit_sleep_and_quit_on_keypress(1))) {
skip_timeout = true; skip_timeout = true;
if (quiet) { quiet = false;
quiet = false; print("\e[2K");
goto reterm; term_double_buffer_flush();
} else { goto timeout_aborted;
print("\e[2K");
term_double_buffer_flush();
goto timeout_aborted;
}
} }
} }
goto autoboot; goto autoboot;
@ -823,10 +818,10 @@ timeout_aborted:
selected_menu_entry->expanded = !selected_menu_entry->expanded; selected_menu_entry->expanded = !selected_menu_entry->expanded;
goto refresh; goto refresh;
} }
if (term_backend == NOT_READY) { if (term_backend == FALLBACK) {
term_vbe(NULL, 0, 0); term_vbe(NULL, 0, 0);
#if defined (BIOS) #if defined (BIOS)
if (term_backend == NOT_READY) { if (term_backend == FALLBACK) {
term_textmode(); term_textmode();
} }
#endif #endif
@ -873,6 +868,7 @@ noreturn void boot(char *config) {
} }
if (!strcmp(proto, "stivale1") || !strcmp(proto, "stivale") || !strcmp(proto, "stivale2")) { if (!strcmp(proto, "stivale1") || !strcmp(proto, "stivale") || !strcmp(proto, "stivale2")) {
quiet = false;
print("The stivale and stivale2 protocols are no longer supported as of Limine 4.x\n"); print("The stivale and stivale2 protocols are no longer supported as of Limine 4.x\n");
print("Please notify kernel maintainers to move to the Limine boot protocol or\n"); print("Please notify kernel maintainers to move to the Limine boot protocol or\n");
print("roll back to Limine 3.x.\n\n"); print("roll back to Limine 3.x.\n\n");
@ -882,18 +878,21 @@ noreturn void boot(char *config) {
#if defined (__x86_64__) || defined (__i386__) #if defined (__x86_64__) || defined (__i386__)
linux_load(config, cmdline); linux_load(config, cmdline);
#else #else
quiet = false;
print("TODO: Linux is not available on aarch64.\n\n"); print("TODO: Linux is not available on aarch64.\n\n");
#endif #endif
} else if (!strcmp(proto, "multiboot1") || !strcmp(proto, "multiboot")) { } else if (!strcmp(proto, "multiboot1") || !strcmp(proto, "multiboot")) {
#if defined (__x86_64__) || defined (__i386__) #if defined (__x86_64__) || defined (__i386__)
multiboot1_load(config, cmdline); multiboot1_load(config, cmdline);
#else #else
quiet = false;
print("Multiboot 1 is not available on aarch64.\n\n"); print("Multiboot 1 is not available on aarch64.\n\n");
#endif #endif
} else if (!strcmp(proto, "multiboot2")) { } else if (!strcmp(proto, "multiboot2")) {
#if defined (__x86_64__) || defined (__i386__) #if defined (__x86_64__) || defined (__i386__)
multiboot2_load(config, cmdline); multiboot2_load(config, cmdline);
#else #else
quiet = false;
print("Multiboot 2 is not available on aarch64.\n\n"); print("Multiboot 2 is not available on aarch64.\n\n");
#endif #endif
} else if (!strcmp(proto, "chainload_next")) { } else if (!strcmp(proto, "chainload_next")) {
@ -902,5 +901,5 @@ noreturn void boot(char *config) {
chainload(config); chainload(config);
} }
panic(true, "Incorrect protocol specified for kernel."); panic(true, "Unsupported protocol specified for kernel.");
} }

View File

@ -738,6 +738,7 @@ FEAT_START
FEAT_END FEAT_END
term_deinit(); term_deinit();
quiet = true;
if (!fb_init(&fb, req_width, req_height, req_bpp)) { if (!fb_init(&fb, req_width, req_height, req_bpp)) {
panic(true, "limine: Could not acquire framebuffer"); panic(true, "limine: Could not acquire framebuffer");

View File

@ -496,6 +496,7 @@ noreturn void linux_load(char *config, char *cmdline) {
/////////////////////////////////////// ///////////////////////////////////////
term_deinit(); term_deinit();
quiet = true;
struct screen_info *screen_info = &boot_params->screen_info; struct screen_info *screen_info = &boot_params->screen_info;

View File

@ -303,6 +303,7 @@ noreturn void multiboot1_load(char *config, char *cmdline) {
multiboot1_info->flags |= (1 << 9); multiboot1_info->flags |= (1 << 9);
term_deinit(); term_deinit();
quiet = true;
if (header.flags & (1 << 2)) { if (header.flags & (1 << 2)) {
size_t req_width = header.fb_width; size_t req_width = header.fb_width;

View File

@ -498,6 +498,7 @@ noreturn void multiboot2_load(char *config, char* cmdline) {
tag->common.size = sizeof(struct multiboot_tag_framebuffer); tag->common.size = sizeof(struct multiboot_tag_framebuffer);
term_deinit(); term_deinit();
quiet = true;
if (fbtag) { if (fbtag) {
size_t req_width = fbtag->width; size_t req_width = fbtag->width;