panic: Prevent recursive panics during early boot
diff --git a/Makefile b/Makefile
index 3eb9d8a1..46b2ea79 100644
--- a/Makefile
+++ b/Makefile
@@ -216,6 +216,12 @@ test.hdd:
parted -s test.hdd mklabel gpt
parted -s test.hdd mkpart primary 2048s 100%
+.PHONY: mbrtest.hdd
+mbrtest.hdd:
+ rm -f mbrtest.hdd
+ dd if=/dev/zero bs=1M count=0 seek=64 of=mbrtest.hdd
+ echo -e "o\nn\np\n1\n2048\n\nt\n6\na\nw\n" | fdisk mbrtest.hdd -H 16 -S 63
+
.PHONY: echfs-test
echfs-test:
$(MAKE) test-clean
@@ -326,6 +332,30 @@ fat16-test:
$(BINDIR)/limine-install test.hdd
qemu-system-x86_64 -net none -smp 4 -hda test.hdd -debugcon stdio
+.PHONY: legacy-fat16-test
+legacy-fat16-test:
+ $(MAKE) test-clean
+ $(MAKE) mbrtest.hdd
+ fdisk -l mbrtest.hdd
+ $(MAKE) limine-bios
+ $(MAKE) limine-install
+ $(MAKE) -C test
+ rm -rf test_image/
+ mkdir test_image
+ sudo losetup -Pf --show mbrtest.hdd > loopback_dev
+ sudo partprobe `cat loopback_dev`
+ sudo mkfs.fat -F 16 `cat loopback_dev`p1
+ sudo mount `cat loopback_dev`p1 test_image
+ sudo mkdir test_image/boot
+ sudo cp -rv $(BINDIR)/* test_image/boot/
+ sudo cp -rv test/* test_image/boot/
+ sync
+ sudo umount test_image/
+ sudo losetup -d `cat loopback_dev`
+ rm -rf test_image loopback_dev
+ $(BINDIR)/limine-install mbrtest.hdd
+ qemu-system-i386 -cpu pentium2 -m 16M -M isapc -net none -hda mbrtest.hdd -debugcon stdio
+
.PHONY: fat32-test
fat32-test:
$(MAKE) test-clean
diff --git a/stage23/lib/panic.s2.c b/stage23/lib/panic.s2.c
index 564458a2..20149836 100644
--- a/stage23/lib/panic.s2.c
+++ b/stage23/lib/panic.s2.c
@@ -13,6 +13,100 @@
#include <mm/pmm.h>
#include <menu.h>
+#if bios == 1
+void fallback_raw_putchar(uint8_t c) {
+ struct rm_regs r = {0};
+ r.eax = 0x0e00 | c;
+ rm_int(0x10, &r, &r);
+}
+
+void fallback_clear(bool move) {
+ (void)move;
+ struct rm_regs r = {0};
+ rm_int(0x11, &r, &r);
+ switch ((r.eax >> 4) & 3) {
+ case 0:
+ r.eax = 3;
+ break;
+ case 1:
+ r.eax = 1;
+ break;
+ case 2:
+ r.eax = 3;
+ break;
+ case 3:
+ r.eax = 7;
+ break;
+ }
+ rm_int(0x10, &r, &r);
+}
+
+void fallback_set_cursor_pos(size_t x, size_t y) {
+ struct rm_regs r = {0};
+ r.eax = 0x0200;
+ r.ebx = 0;
+ r.edx = (y << 8) + x;
+ rm_int(0x10, &r, &r);
+}
+
+void fallback_get_cursor_pos(size_t *x, size_t *y) {
+ struct rm_regs r = {0};
+ r.eax = 0x0300;
+ r.ebx = 0;
+ rm_int(0x10, &r, &r);
+ *x = r.edx & 0xff;
+ *y = r.edx >> 8;
+}
+
+#elif uefi == 1
+static int cursor_x = 0, cursor_y = 0;
+
+void fallback_raw_putchar(uint8_t c) {
+ CHAR16 string[2];
+ string[0] = c;
+ string[1] = 0;
+ gST->ConOut->OutputString(gST->ConOut, string);
+ switch (c) {
+ case 0x08:
+ if (cursor_x > 0)
+ cursor_x--;
+ break;
+ case 0x0A:
+ cursor_x = 0;
+ break;
+ case 0x0D:
+ if (cursor_y < 24)
+ cursor_y++;
+ break;
+ default:
+ if (++cursor_x > 80) {
+ cursor_x = 0;
+ if (cursor_y < 24)
+ cursor_y++;
+ }
+ }
+}
+
+void fallback_clear(bool move) {
+ (void)move;
+ gST->ConOut->ClearScreen(gST->ConOut);
+ cursor_x = cursor_y = 0;
+}
+
+void fallback_set_cursor_pos(size_t x, size_t y) {
+ if (x >= 80 || y >= 25)
+ return;
+ gST->ConOut->SetCursorPosition(gST->ConOut, x, y);
+ cursor_x = x;
+ cursor_y = y;
+}
+
+void fallback_get_cursor_pos(size_t *x, size_t *y) {
+ *x = cursor_x;
+ *y = cursor_y;
+}
+#endif
+
__attribute__((noreturn)) void panic(bool allow_menu, const char *fmt, ...) {
va_list args;
@@ -28,6 +122,26 @@ __attribute__((noreturn)) void panic(bool allow_menu, const char *fmt, ...) {
#endif
}
+ if (term_backend == NOT_READY) {
+#if uefi == 1
+ if (!efi_boot_services_exited) {
+ gST->ConOut->Reset(gST->ConOut, false);
+ gST->ConOut->SetMode(gST->ConOut, 0);
+ cursor_x = cursor_y = 0;
+#elif bios == 1
+ fallback_clear(true);
+#endif
+ term_notready();
+ raw_putchar = fallback_raw_putchar;
+ clear = fallback_clear;
+ set_cursor_pos = fallback_set_cursor_pos;
+ get_cursor_pos = fallback_get_cursor_pos;
+ term_backend = FALLBACK;
+#if uefi == 1
+ }
+#endif
+ }
+
print("\033[31mPANIC\033[37;1m\033[0m: ");
vprint(fmt, args);
diff --git a/stage23/lib/term.c b/stage23/lib/term.c
index be394736..21fa0dea 100644
--- a/stage23/lib/term.c
+++ b/stage23/lib/term.c
@@ -5,6 +5,7 @@
#include <lib/image.h>
#include <lib/blib.h>
#include <lib/gterm.h>
+#include <mm/pmm.h>
bool early_term = false;
@@ -20,7 +21,7 @@ void term_deinit(void) {
void term_vbe(size_t width, size_t height) {
term_notready();
- if (quiet) {
+ if (quiet || allocations_disallowed) {
return;
}
diff --git a/stage23/lib/term.h b/stage23/lib/term.h
index 6c284fa5..7c4ab431 100644
--- a/stage23/lib/term.h
+++ b/stage23/lib/term.h
@@ -35,7 +35,8 @@ extern struct term_context {
enum {
NOT_READY,
VBE,
- TEXTMODE
+ TEXTMODE,
+ FALLBACK
};
extern int current_video_mode;
diff --git a/stage23/lib/term.s2.c b/stage23/lib/term.s2.c
index 6e232c96..aa2667cd 100644
--- a/stage23/lib/term.s2.c
+++ b/stage23/lib/term.s2.c
@@ -7,6 +7,7 @@
#include <lib/blib.h>
#include <drivers/vga_textmode.h>
#include <lib/print.h>
+#include <mm/pmm.h>
// Tries to implement this standard for terminfo
// https://man7.org/linux/man-pages/man4/console_codes.4.html
@@ -157,7 +158,7 @@ void term_reinit(void) {
void term_textmode(void) {
term_notready();
- if (quiet) {
+ if (quiet || allocations_disallowed) {
return;
}
diff --git a/stage23/mm/pmm.h b/stage23/mm/pmm.h
index 5426e334..e06cebcb 100644
--- a/stage23/mm/pmm.h
+++ b/stage23/mm/pmm.h
@@ -37,6 +37,8 @@ extern struct e820_entry_t *untouched_memmap;
extern size_t untouched_memmap_entries;
#endif
+extern bool allocations_disallowed;
+
void init_memmap(void);
struct e820_entry_t *get_memmap(size_t *entries);
struct e820_entry_t *get_raw_memmap(size_t *entry_count);
diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c
index 037d27e6..d5e244d5 100644
--- a/stage23/mm/pmm.s2.c
+++ b/stage23/mm/pmm.s2.c
@@ -17,7 +17,7 @@
extern symbol bss_end;
#endif
-static bool allocations_disallowed = true;
+bool allocations_disallowed = true;
static void sanitise_entries(struct e820_entry_t *, size_t *, bool);
void *conv_mem_alloc(size_t count) {
