:: commit 65bebbbfef198ba05bd46649a190fe12a3436ac8

lukflug <lukflug@googlemail.com> — 2021-12-14 05:47

parents: 987740691c

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) {
tab: 248 wrap: offon