:: commit f650e4b41bda371dd8d6fd764bc2c77bcbc3f102

mintsuki <mintsuki@protonmail.com> — 2021-05-11 04:46

parents: 0eb5af44aa

misc: Add verbose config option

diff --git a/CONFIG.md b/CONFIG.md
index 5181e82b..572debd6 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -67,6 +67,7 @@ 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`.
 * `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`.
+* `VERBOSE` - If set to `yes`, print additional information during boot. Defaults to not verbose.
 
 *Locally assignable (non protocol specific)* keys are:
 * `PROTOCOL` - The boot protocol that will be used to boot the kernel. Valid protocols are: `linux`, `stivale`, `stivale2`, `chainload`.
diff --git a/Makefile b/Makefile
index 08cf0a39..7761ab24 100644
--- a/Makefile
+++ b/Makefile
@@ -182,6 +182,28 @@ ext2-test:
 	bin/limine-install test.hdd
 	qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -hda test.hdd -debugcon stdio
 
+.PHONY: fat12-test
+fat12-test:
+	$(MAKE) test-clean
+	$(MAKE) test.hdd
+	$(MAKE) limine-bios
+	$(MAKE) bin/limine-install
+	$(MAKE) -C test
+	rm -rf test_image/
+	mkdir test_image
+	sudo losetup -Pf --show test.hdd > loopback_dev
+	sudo partprobe `cat loopback_dev`
+	sudo mkfs.fat -F 12 `cat loopback_dev`p1
+	sudo mount `cat loopback_dev`p1 test_image
+	sudo mkdir test_image/boot
+	sudo cp -rv bin/* test/* test_image/boot/
+	sync
+	sudo umount test_image/
+	sudo losetup -d `cat loopback_dev`
+	rm -rf test_image loopback_dev
+	bin/limine-install test.hdd
+	qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -hda test.hdd -debugcon stdio
+
 .PHONY: fat16-test
 fat16-test:
 	$(MAKE) test-clean
@@ -277,8 +299,6 @@ full-hybrid-test:
 	rm -rf test_image/
 	mkdir -p test_image/boot
 	cp -rv bin/* test/* test_image/boot/
-	mkdir -p test_image/EFI/BOOT
-	cp -v bin/BOOTX64.EFI test_image/EFI/BOOT/
 	xorriso -as mkisofs -b boot/limine-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table -part_like_isohybrid -eltorito-alt-boot -e boot/limine-eltorito-efi.bin -no-emul-boot test_image/ -isohybrid-gpt-basdat -o test.iso
 	bin/limine-install test.iso
 	qemu-system-x86_64 -M q35 -L ovmf -bios ovmf/OVMF.fd -net none -smp 4 -enable-kvm -cpu host -cdrom test.iso -debugcon stdio
diff --git a/README.md b/README.md
index 49a8835a..eb50063d 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ Like Limine and want to support it? Donate Bitcoin to `bc1q00d59y75crpapw7qp8sea
 ### Supported filesystems
 * ext2/3/4
 * echfs
-* FAT16/32
+* FAT12/16/32
 * ISO9660 (CDs/DVDs)
 
 ### Supported partitioning schemes
diff --git a/stage23/drivers/disk.s2.c b/stage23/drivers/disk.s2.c
index 84385b8b..20598f32 100644
--- a/stage23/drivers/disk.s2.c
+++ b/stage23/drivers/disk.s2.c
@@ -78,7 +78,7 @@ bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t
 void disk_create_index(void) {
     size_t volume_count = 0;
 
-    print("Detected volumes:\n");
+    printv("Detected volumes:\n");
 
     for (uint8_t drive = 0x80; ; drive++) {
         if (drive == 0x90)
@@ -177,7 +177,7 @@ void disk_create_index(void) {
             block->guid_valid = true;
         }
 
-        print("    %x\n", block->drive);
+        printv("    %x\n", block->drive);
 
         volume_index[volume_index_i++] = block;
 
@@ -190,7 +190,7 @@ void disk_create_index(void) {
             if (ret == NO_PARTITION)
                 continue;
 
-            print("    %x:%u\n", block->drive, part);
+            printv("    %x:%u\n", block->drive, part);
 
             volume_index[volume_index_i++] = p;
 
@@ -343,7 +343,7 @@ void disk_create_index(void) {
 
     volume_index = ext_mem_alloc(sizeof(struct volume) * volume_count);
 
-    print("Detected volumes:\n");
+    printv("Detected volumes:\n");
 
     size_t drives_counter = 0x80, optical_counter = 0xe0;
 
@@ -388,7 +388,7 @@ void disk_create_index(void) {
             block->guid_valid = true;
         }
 
-        print("    %x\n", block->drive);
+        printv("    %x\n", block->drive);
 
         volume_index[volume_index_i++] = block;
 
@@ -401,7 +401,7 @@ void disk_create_index(void) {
             if (ret == NO_PARTITION)
                 continue;
 
-            print("    %x:%u\n", block->drive, part);
+            printv("    %x:%u\n", block->drive, part);
 
             volume_index[volume_index_i++] = p;
 
diff --git a/stage23/drivers/edid.c b/stage23/drivers/edid.c
index 398561d8..1f8f054e 100644
--- a/stage23/drivers/edid.c
+++ b/stage23/drivers/edid.c
@@ -35,11 +35,11 @@ struct edid_info_struct *get_edid_info(void) {
             goto success;
 
 fail:
-    print("edid: Could not fetch EDID data.\n");
+    printv("edid: Could not fetch EDID data.\n");
     return NULL;
 
 success:
-    print("edid: Success.\n");
+    printv("edid: Success.\n");
     return buf;
 }
 
@@ -91,11 +91,11 @@ struct edid_info_struct *get_edid_info(void) {
             goto success;
 
 fail:
-    print("edid: Could not fetch EDID data.\n");
+    printv("edid: Could not fetch EDID data.\n");
     return NULL;
 
 success:
-    print("edid: Success.\n");
+    printv("edid: Success.\n");
     return buf;
 }
 
diff --git a/stage23/drivers/gop.c b/stage23/drivers/gop.c
index 4d53fcf6..e7eb929a 100644
--- a/stage23/drivers/gop.c
+++ b/stage23/drivers/gop.c
@@ -97,16 +97,16 @@ static bool try_mode(struct fb_info *ret, size_t mode, int width, int height, in
             return false;
     }
 
-    print("gop: Found matching mode %x, attempting to set...\n", mode);
+    printv("gop: Found matching mode %x, attempting to set...\n", mode);
 
     if ((int)mode == current_video_mode) {
-        print("gop: Mode was already set, perfect!\n");
+        printv("gop: Mode was already set, perfect!\n");
     } else {
         status = uefi_call_wrapper(gop->SetMode, 2, gop, mode);
 
         if (status) {
             current_video_mode = -2;
-            print("gop: Failed to set video mode %x, moving on...\n", mode);
+            printv("gop: Failed to set video mode %x, moving on...\n", mode);
             return false;
         }
     }
@@ -181,15 +181,15 @@ bool init_gop(struct fb_info *ret,
                 target_width  = edid_width;
                 target_height = edid_height;
                 target_bpp    = 32;
-                print("gop: EDID detected screen resolution of %ux%u\n",
-                      target_width, target_height);
+                printv("gop: EDID detected screen resolution of %ux%u\n",
+                       target_width, target_height);
                 goto retry;
             }
         }
         goto fallback;
     } else {
-        print("gop: Requested resolution of %ux%ux%u\n",
-              target_width, target_height, target_bpp);
+        printv("gop: Requested resolution of %ux%ux%u\n",
+               target_width, target_height, target_bpp);
     }
 
 retry:
diff --git a/stage23/drivers/vbe.c b/stage23/drivers/vbe.c
index 8bd0378a..b7af7556 100644
--- a/stage23/drivers/vbe.c
+++ b/stage23/drivers/vbe.c
@@ -118,7 +118,7 @@ static int set_vbe_mode(uint16_t mode) {
 
 bool init_vbe(struct fb_info *ret,
               uint16_t target_width, uint16_t target_height, uint16_t target_bpp) {
-    print("vbe: Initialising...\n");
+    printv("vbe: Initialising...\n");
 
     ret->default_res = false;
 
@@ -127,11 +127,11 @@ bool init_vbe(struct fb_info *ret,
     struct vbe_info_struct vbe_info;
     get_vbe_info(&vbe_info);
 
-    print("vbe: Version: %u.%u\n", vbe_info.version_maj, vbe_info.version_min);
-    print("vbe: OEM: %s\n", (char *)rm_desegment(vbe_info.oem_seg, vbe_info.oem_off));
-    print("vbe: Graphics vendor: %s\n", (char *)rm_desegment(vbe_info.vendor_seg, vbe_info.vendor_off));
-    print("vbe: Product name: %s\n", (char *)rm_desegment(vbe_info.prod_name_seg, vbe_info.prod_name_off));
-    print("vbe: Product revision: %s\n", (char *)rm_desegment(vbe_info.prod_rev_seg, vbe_info.prod_rev_off));
+    printv("vbe: Version: %u.%u\n", vbe_info.version_maj, vbe_info.version_min);
+    printv("vbe: OEM: %s\n", (char *)rm_desegment(vbe_info.oem_seg, vbe_info.oem_off));
+    printv("vbe: Graphics vendor: %s\n", (char *)rm_desegment(vbe_info.vendor_seg, vbe_info.vendor_off));
+    printv("vbe: Product name: %s\n", (char *)rm_desegment(vbe_info.prod_name_seg, vbe_info.prod_name_off));
+    printv("vbe: Product revision: %s\n", (char *)rm_desegment(vbe_info.prod_rev_seg, vbe_info.prod_rev_off));
 
     uint16_t *vid_modes = (uint16_t *)rm_desegment(vbe_info.vid_modes_seg,
                                                    vbe_info.vid_modes_off);
@@ -155,15 +155,15 @@ bool init_vbe(struct fb_info *ret,
                 target_width  = edid_width;
                 target_height = edid_height;
                 target_bpp    = 32;
-                print("vbe: EDID detected screen resolution of %ux%u\n",
-                      target_width, target_height);
+                printv("vbe: EDID detected screen resolution of %ux%u\n",
+                       target_width, target_height);
                 goto retry;
             }
         }
         goto fallback;
     } else {
-        print("vbe: Requested resolution of %ux%ux%u\n",
-              target_width, target_height, target_bpp);
+        printv("vbe: Requested resolution of %ux%ux%u\n",
+               target_width, target_height, target_bpp);
     }
 
 retry:
@@ -179,17 +179,17 @@ retry:
             // We only support linear modes
             if (!(vbe_mode_info.mode_attributes & (1 << 7)))
                 continue;
-            print("vbe: Found matching mode %x, attempting to set...\n", vid_modes[i]);
+            printv("vbe: Found matching mode %x, attempting to set...\n", vid_modes[i]);
             if (vid_modes[i] == current_video_mode) {
-                print("vbe: Mode was already set, perfect!\n");
+                printv("vbe: Mode was already set, perfect!\n");
             } else if (set_vbe_mode(vid_modes[i]) == 0x01) {
                 current_video_mode = -2;
-                print("vbe: Failed to set video mode %x, moving on...\n", vid_modes[i]);
+                printv("vbe: Failed to set video mode %x, moving on...\n", vid_modes[i]);
                 continue;
             }
             current_video_mode = vid_modes[i];
 
-            print("vbe: Framebuffer address: %x\n", vbe_mode_info.framebuffer_addr);
+            printv("vbe: Framebuffer address: %x\n", vbe_mode_info.framebuffer_addr);
             ret->memory_model       = vbe_mode_info.memory_model;
             ret->framebuffer_addr   = vbe_mode_info.framebuffer_addr;
             ret->framebuffer_width  = vbe_mode_info.res_x;
diff --git a/stage23/entry.s3.c b/stage23/entry.s3.c
index 4b39c0d3..5597f859 100644
--- a/stage23/entry.s3.c
+++ b/stage23/entry.s3.c
@@ -89,14 +89,18 @@ __attribute__((noreturn))
 void stage3_common(void) {
     volume_iterate_parts(boot_volume,
         if (!init_config_disk(_PART)) {
-            print("Config file found and loaded.\n");
             boot_volume = _PART;
             break;
         }
     );
 
-    print("Boot drive: %x\n", boot_volume->drive);
-    print("Boot partition: %d\n", boot_volume->partition);
+    char *verbose_str = config_get_value(NULL, 0, "VERBOSE");
+    verbose = verbose_str != NULL && strcmp(verbose_str, "yes") == 0;
+
+    if (verbose) {
+        print("Boot drive: %x\n", boot_volume->drive);
+        print("Boot partition: %d\n", boot_volume->partition);
+    }
 
     char *cmdline;
     char *config = menu(&cmdline);
diff --git a/stage23/lib/acpi.c b/stage23/lib/acpi.c
index 04bebdc0..28f35be7 100644
--- a/stage23/lib/acpi.c
+++ b/stage23/lib/acpi.c
@@ -26,7 +26,7 @@ void *acpi_get_rsdp(void) {
         }
         if (!memcmp((char *)i, "RSD PTR ", 8)
          && !acpi_checksum((void *)i, sizeof(struct rsdp))) {
-            print("acpi: Found RSDP at %x\n", i);
+            printv("acpi: Found RSDP at %x\n", i);
             return (void *)i;
         }
     }
@@ -41,7 +41,7 @@ void acpi_get_smbios(void **smbios32, void **smbios64) {
     for (size_t i = 0xf0000; i < 0x100000; i += 16) {
         if (!memcmp((char *)i, "_SM_", 4)
          && !acpi_checksum((void *)i, *((uint8_t *)(i + 5)))) {
-            print("acpi: Found SMBIOS 32-bit entry point at %x\n", i);
+            printv("acpi: Found SMBIOS 32-bit entry point at %x\n", i);
             *smbios32 = (void *)i;
             break;
         }
@@ -50,7 +50,7 @@ void acpi_get_smbios(void **smbios32, void **smbios64) {
     for (size_t i = 0xf0000; i < 0x100000; i += 16) {
         if (!memcmp((char *)i, "_SM3_", 5)
          && !acpi_checksum((void *)i, *((uint8_t *)(i + 6)))) {
-            print("acpi: Found SMBIOS 64-bit entry point at %x\n", i);
+            printv("acpi: Found SMBIOS 64-bit entry point at %x\n", i);
             *smbios64 = (void *)i;
             break;
         }
@@ -74,7 +74,7 @@ void *acpi_get_rsdp(void) {
         if (acpi_checksum(cur_table->VendorTable, sizeof(struct rsdp)) != 0)
             continue;
 
-        print("acpi: Found RSDP at %X\n", cur_table->VendorTable);
+        printv("acpi: Found RSDP at %X\n", cur_table->VendorTable);
 
         return (void *)cur_table->VendorTable;
     }
@@ -97,7 +97,7 @@ void acpi_get_smbios(void **smbios32, void **smbios64) {
                           *((uint8_t *)(cur_table->VendorTable + 5))) != 0)
             continue;
 
-        print("acpi: Found SMBIOS 32-bit entry point at %X\n", cur_table->VendorTable);
+        printv("acpi: Found SMBIOS 32-bit entry point at %X\n", cur_table->VendorTable);
 
         *smbios32 = cur_table->VendorTable;
 
@@ -115,7 +115,7 @@ void acpi_get_smbios(void **smbios32, void **smbios64) {
                           *((uint8_t *)(cur_table->VendorTable + 6))) != 0)
             continue;
 
-        print("acpi: Found SMBIOS 64-bit entry point at %X\n", cur_table->VendorTable);
+        printv("acpi: Found SMBIOS 64-bit entry point at %X\n", cur_table->VendorTable);
 
         *smbios64 = cur_table->VendorTable;
 
@@ -155,11 +155,11 @@ void *acpi_get_table(const char *signature, int index) {
         if (!memcmp(ptr->signature, signature, 4)
          && !acpi_checksum(ptr, ptr->length)
          && cnt++ == index) {
-            print("acpi: Found \"%s\" at %x\n", signature, ptr);
+            printv("acpi: Found \"%s\" at %x\n", signature, ptr);
             return ptr;
         }
     }
 
-    print("acpi: \"%s\" not found\n", signature);
+    printv("acpi: \"%s\" not found\n", signature);
     return NULL;
 }
diff --git a/stage23/lib/blib.c b/stage23/lib/blib.c
index ba0e947d..c18929b5 100644
--- a/stage23/lib/blib.c
+++ b/stage23/lib/blib.c
@@ -18,6 +18,8 @@ EFI_MEMORY_DESCRIPTOR *efi_mmap = NULL;
 UINTN efi_mmap_size = 0, efi_desc_size = 0, efi_desc_ver = 0;
 #endif
 
+bool verbose = false;
+
 bool parse_resolution(int *width, int *height, int *bpp, const char *buf) {
     int res[3] = {0};
 
@@ -93,7 +95,7 @@ bool efi_exit_boot_services(void) {
 
     efi_boot_services_exited = true;
 
-    print("efi: Exited boot services.\n");
+    printv("efi: Exited boot services.\n");
 
     return true;
 }
diff --git a/stage23/lib/blib.h b/stage23/lib/blib.h
index 837b38b6..31395cf9 100644
--- a/stage23/lib/blib.h
+++ b/stage23/lib/blib.h
@@ -28,6 +28,8 @@ extern struct volume *boot_volume;
 extern bool stage3_loaded;
 #endif
 
+extern bool verbose;
+
 bool parse_resolution(int *width, int *height, int *bpp, const char *buf);
 
 uint64_t sqrt(uint64_t a_nInput);
diff --git a/stage23/lib/config.c b/stage23/lib/config.c
index aa322486..43e09c62 100644
--- a/stage23/lib/config.c
+++ b/stage23/lib/config.c
@@ -36,15 +36,12 @@ int init_config_disk(struct volume *part) {
 #if defined (bios)
 int init_config_pxe(void) {
     struct tftp_file_handle cfg;
-    if (tftp_open(&cfg, 0, 69, "limine.cfg")
-     && tftp_open(&cfg, 0, 69, "tomatboot.cfg")) {
+    if (tftp_open(&cfg, 0, 69, "limine.cfg")) {
         return -1;
     }
     config_addr = ext_mem_alloc(cfg.file_size);
     tftp_read(&cfg, config_addr, 0, cfg.file_size);
 
-    print("\nconfig: %s\n", config_addr);
-
     return init_config(cfg.file_size);
 }
 #endif
diff --git a/stage23/lib/elf.c b/stage23/lib/elf.c
index 8e15474f..fefc39b8 100644
--- a/stage23/lib/elf.c
+++ b/stage23/lib/elf.c
@@ -297,17 +297,17 @@ int elf64_load(uint8_t *elf, uint64_t *entry_point, uint64_t *_slide, uint32_t a
     memcpy(&hdr, elf + (0), sizeof(struct elf64_hdr));
 
     if (strncmp((char *)hdr.ident, "\177ELF", 4)) {
-        print("Not a valid ELF file.\n");
+        print("elf: Not a valid ELF file.\n");
         return -1;
     }
 
     if (hdr.ident[EI_DATA] != BITS_LE) {
-        print("Not a Little-endian ELF file.\n");
+        print("elf: Not a Little-endian ELF file.\n");
         return -1;
     }
 
     if (hdr.machine != ARCH_X86_64) {
-        print("Not an x86_64 ELF file.\n");
+        print("elf: Not an x86_64 ELF file.\n");
         return -1;
     }
 
@@ -378,17 +378,17 @@ int elf32_load(uint8_t *elf, uint32_t *entry_point, uint32_t alloc_type) {
     memcpy(&hdr, elf + (0), sizeof(struct elf32_hdr));
 
     if (strncmp((char *)hdr.ident, "\177ELF", 4)) {
-        print("Not a valid ELF file.\n");
+        print("elf: Not a valid ELF file.\n");
         return -1;
     }
 
     if (hdr.ident[EI_DATA] != BITS_LE) {
-        print("Not a Little-endian ELF file.\n");
+        print("elf: Not a Little-endian ELF file.\n");
         return -1;
     }
 
     if (hdr.machine != ARCH_X86_32) {
-        print("Not an x86_32 ELF file.\n");
+        print("elf: Not an x86_32 ELF file.\n");
         return -1;
     }
 
diff --git a/stage23/lib/print.h b/stage23/lib/print.h
index fad90a86..4a7d1d1b 100644
--- a/stage23/lib/print.h
+++ b/stage23/lib/print.h
@@ -6,4 +6,6 @@
 void print(const char *fmt, ...);
 void vprint(const char *fmt, va_list args);
 
+#define printv(FMT, ...) ({ if (verbose) print(FMT, ##__VA_ARGS__); })
+
 #endif
diff --git a/stage23/lib/uri.c b/stage23/lib/uri.c
index a0237079..c8f7c423 100644
--- a/stage23/lib/uri.c
+++ b/stage23/lib/uri.c
@@ -159,7 +159,6 @@ static bool uri_tftp_dispatch(struct file_handle *fd, char *root, char *path) {
         if (inet_pton(root, &ip)) {
             panic("invalid ipv4 address: %s", root);
         }
-        print("\nip: %x\n", ip);
     }
 
     struct tftp_file_handle *cfg = ext_mem_alloc(sizeof(struct tftp_file_handle));
diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c
index 76508f3b..47452b7a 100644
--- a/stage23/mm/pmm.s2.c
+++ b/stage23/mm/pmm.s2.c
@@ -78,11 +78,11 @@ static const char *memmap_type(uint32_t type) {
 
 void print_memmap(struct e820_entry_t *mm, size_t size) {
     for (size_t i = 0; i < size; i++) {
-        print("[%X -> %X] : %X  <%s>\n",
-              mm[i].base,
-              mm[i].base + mm[i].length,
-              mm[i].length,
-              memmap_type(mm[i].type));
+        printv("[%X -> %X] : %X  <%s>\n",
+               mm[i].base,
+               mm[i].base + mm[i].length,
+               mm[i].length,
+               memmap_type(mm[i].type));
     }
 }
 
diff --git a/stage23/protos/linux.c b/stage23/protos/linux.c
index 190c1891..2425ea44 100644
--- a/stage23/protos/linux.c
+++ b/stage23/protos/linux.c
@@ -385,8 +385,8 @@ void linux_load(char *config, char *cmdline) {
 
     fread(kernel, setup_header, 0x1f1, setup_header_end - 0x1f1);
 
-    print("linux: Boot protocol: %u.%u\n",
-          setup_header->version >> 8, setup_header->version & 0xff);
+    printv("linux: Boot protocol: %u.%u\n",
+           setup_header->version >> 8, setup_header->version & 0xff);
 
     if (setup_header->version < 0x203) {
         panic("Linux protocols < 2.03 are not supported");
@@ -397,10 +397,12 @@ void linux_load(char *config, char *cmdline) {
     // vid_mode. 0xffff means "normal"
     setup_header->vid_mode = 0xffff;
 
-    char *kernel_version = ext_mem_alloc(128);
-    if (setup_header->kernel_version != 0) {
-        fread(kernel, kernel_version, setup_header->kernel_version + 0x200, 128);
-        print("linux: Kernel version: %s\n", kernel_version);
+    if (verbose) {
+        char *kernel_version = ext_mem_alloc(128);
+        if (setup_header->kernel_version != 0) {
+            fread(kernel, kernel_version, setup_header->kernel_version + 0x200, 128);
+            print("linux: Kernel version: %s\n", kernel_version);
+        }
     }
 
     setup_header->type_of_loader = 0xff;
@@ -413,7 +415,7 @@ void linux_load(char *config, char *cmdline) {
 
     // load kernel
     uintptr_t kernel_load_addr = 0x100000;
-    print("linux: Loading kernel...\n");
+    print("linux: Loading kernel `%s`...\n", kernel_path);
     for (;;) {
         if (memmap_alloc_range(kernel_load_addr,
                 ALIGN_UP(kernel->size - real_mode_code_size, 4096),
diff --git a/stage23/protos/stivale.c b/stage23/protos/stivale.c
index 01134665..2f4dc51b 100644
--- a/stage23/protos/stivale.c
+++ b/stage23/protos/stivale.c
@@ -43,6 +43,8 @@ void stivale_load(char *config, char *cmdline) {
     if (kernel_path == NULL)
         panic("KERNEL_PATH not specified");
 
+    print("stivale: Loading kernel `%s`...\n", kernel_path);
+
     if (!uri_open(kernel_file, kernel_path))
         panic("Could not open kernel resource");
 
@@ -73,7 +75,7 @@ void stivale_load(char *config, char *cmdline) {
             }
             // Check if 5-level paging is available
             if (cpuid(0x00000007, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 16))) {
-                print("stivale: CPU has 5-level paging support\n");
+                printv("stivale: CPU has 5-level paging support\n");
                 level5pg = true;
             }
 
@@ -96,7 +98,7 @@ void stivale_load(char *config, char *cmdline) {
             panic("stivale: Not 32 nor 64 bit x86 ELF file.");
     }
 
-    print("stivale: %u-bit ELF file detected\n", bits);
+    printv("stivale: %u-bit ELF file detected\n", bits);
 
     switch (ret) {
         case 1:
@@ -118,10 +120,12 @@ void stivale_load(char *config, char *cmdline) {
     if (stivale_hdr.entry_point != 0)
         entry_point = stivale_hdr.entry_point;
 
-    print("stivale: Kernel slide: %X\n", slide);
+    if (verbose) {
+        print("stivale: Kernel slide: %X\n", slide);
 
-    print("stivale: Entry point at: %X\n", entry_point);
-    print("stivale: Requested stack at: %X\n", stivale_hdr.stack);
+        print("stivale: Entry point at: %X\n", entry_point);
+        print("stivale: Requested stack at: %X\n", stivale_hdr.stack);
+    }
 
     stivale_struct.module_count = 0;
     uint64_t *prev_mod_ptr = &stivale_struct.modules;
@@ -158,11 +162,13 @@ void stivale_load(char *config, char *cmdline) {
         *prev_mod_ptr = REPORTED_ADDR((uint64_t)(size_t)m);
         prev_mod_ptr  = &m->next;
 
-        print("stivale: Requested module %u:\n", i);
-        print("         Path:   %s\n", module_path);
-        print("         String: %s\n", m->string);
-        print("         Begin:  %X\n", m->begin);
-        print("         End:    %X\n", m->end);
+        if (verbose) {
+            print("stivale: Requested module %u:\n", i);
+            print("         Path:   %s\n", module_path);
+            print("         String: %s\n", m->string);
+            print("         Begin:  %X\n", m->begin);
+            print("         End:    %X\n", m->end);
+        }
     }
 
     uint64_t rsdp = (uint64_t)(size_t)acpi_get_rsdp();
@@ -181,7 +187,7 @@ void stivale_load(char *config, char *cmdline) {
     stivale_struct.cmdline = REPORTED_ADDR((uint64_t)(size_t)cmdline);
 
     stivale_struct.epoch = time();
-    print("stivale: Current epoch: %U\n", stivale_struct.epoch);
+    printv("stivale: Current epoch: %U\n", stivale_struct.epoch);
 
     term_deinit();
 
diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c
index 3b83f292..62b524a5 100644
--- a/stage23/protos/stivale2.c
+++ b/stage23/protos/stivale2.c
@@ -65,6 +65,8 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
     if (kernel_path == NULL)
         panic("KERNEL_PATH not specified");
 
+    print("stivale2: Loading kernel `%s`...\n", kernel_path);
+
     if (!uri_open(kernel_file, kernel_path))
         panic("Could not open kernel resource");
 
@@ -95,7 +97,7 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
             }
             // Check if 5-level paging is available
             if (cpuid(0x00000007, 0, &eax, &ebx, &ecx, &edx) && (ecx & (1 << 16))) {
-                print("stivale2: CPU has 5-level paging support\n");
+                printv("stivale2: CPU has 5-level paging support\n");
                 level5pg = true;
             }
 
@@ -118,7 +120,7 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
             panic("stivale2: Not 32 nor 64 bit x86 ELF file.");
     }
 
-    print("stivale2: %u-bit ELF file detected\n", bits);
+    printv("stivale2: %u-bit ELF file detected\n", bits);
 
     switch (ret) {
         case 1:
@@ -140,10 +142,12 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
     if (stivale2_hdr.entry_point != 0)
         entry_point = stivale2_hdr.entry_point;
 
-    print("stivale2: Kernel slide: %X\n", slide);
+    if (verbose) {
+        print("stivale2: Kernel slide: %X\n", slide);
 
-    print("stivale2: Entry point at: %X\n", entry_point);
-    print("stivale2: Requested stack at: %X\n", stivale2_hdr.stack);
+        print("stivale2: Entry point at: %X\n", entry_point);
+        print("stivale2: Requested stack at: %X\n", stivale2_hdr.stack);
+    }
 
     strcpy(stivale2_struct.bootloader_brand, "Limine");
     strcpy(stivale2_struct.bootloader_version, LIMINE_VERSION);
@@ -229,11 +233,13 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
         m->begin = REPORTED_ADDR((uint64_t)(size_t)freadall(&f, STIVALE2_MMAP_KERNEL_AND_MODULES));
         m->end   = m->begin + f.size;
 
-        print("stivale2: Requested module %u:\n", i);
-        print("          Path:   %s\n", module_path);
-        print("          String: %s\n", m->string);
-        print("          Begin:  %X\n", m->begin);
-        print("          End:    %X\n", m->end);
+        if (verbose) {
+            print("stivale2: Requested module %u:\n", i);
+            print("          Path:   %s\n", module_path);
+            print("          String: %s\n", m->string);
+            print("          Begin:  %X\n", m->begin);
+            print("          End:    %X\n", m->end);
+        }
     }
 
     append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
@@ -291,7 +297,7 @@ void stivale2_load(char *config, char *cmdline, bool pxe, void *efi_system_table
     tag->tag.identifier = STIVALE2_STRUCT_TAG_EPOCH_ID;
 
     tag->epoch = time();
-    print("stivale2: Current epoch: %U\n", tag->epoch);
+    printv("stivale2: Current epoch: %U\n", tag->epoch);
 
     append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
     }
@@ -495,14 +501,16 @@ skip_modeset:;
     //////////////////////////////////////////////
     // List tags
     //////////////////////////////////////////////
-    print("stivale2: Generated tags:\n");
-    struct stivale2_tag *taglist = (void*)(size_t)stivale2_struct.tags;
-    for (size_t i = 0; ; i++) {
-        print("          Tag #%u  ID: %X\n", i, taglist->identifier);
-        if (taglist->next)
-            taglist = (void*)(size_t)taglist->next;
-        else
-            break;
+    if (verbose) {
+        print("stivale2: Generated tags:\n");
+        struct stivale2_tag *taglist = (void*)(size_t)stivale2_struct.tags;
+        for (size_t i = 0; ; i++) {
+            print("          Tag #%u  ID: %X\n", i, taglist->identifier);
+            if (taglist->next)
+                taglist = (void*)(size_t)taglist->next;
+            else
+                break;
+        }
     }
 
     // Clear terminal for kernels that will use the stivale2 terminal
diff --git a/stage23/pxe/pxe.s2.c b/stage23/pxe/pxe.s2.c
index dac2c765..95b7d4bd 100644
--- a/stage23/pxe/pxe.s2.c
+++ b/stage23/pxe/pxe.s2.c
@@ -50,7 +50,7 @@ void pxe_init(void) {
         panic("!pxe signature corrupted");
     }
     set_pxe_fp(bangpxe->rm_entry);
-    print("Successfully initialized pxe");
+    printv("pxe: Successfully initialized");
 }
 
 #endif
diff --git a/stage23/pxe/tftp.s2.c b/stage23/pxe/tftp.s2.c
index 8ac88265..3d1e6498 100644
--- a/stage23/pxe/tftp.s2.c
+++ b/stage23/pxe/tftp.s2.c
@@ -60,7 +60,7 @@ int tftp_open(struct tftp_file_handle *handle, uint32_t server_ip, uint16_t serv
     strcpy((char*)open.name, name);
     ret = pxe_call(TFTP_OPEN, ((uint16_t)rm_seg(&open)), (uint16_t)rm_off(&open));
     if (ret) {
-        print("failed to open file %x or bad packet size", open.status);
+        print("tftp: Failed to open file %x or bad packet size", open.status);
         return -1;
     }
     mtu = open.packet_size;
@@ -86,7 +86,7 @@ int tftp_open(struct tftp_file_handle *handle, uint32_t server_ip, uint16_t serv
 
         if (read.bsize < mtu && !slow) {
             slow = true;
-            print("Server is sending the file in smaller packets (it sent %d bytes), download might take longer.\n", read.bsize);
+            print("tftp: Server is sending the file in smaller packets (it sent %d bytes), download might take longer.\n", read.bsize);
         }
         to_transfer -= read.bsize;
         progress += read.bsize;
diff --git a/stage23/sys/smp.c b/stage23/sys/smp.c
index 805de7e4..68957d36 100644
--- a/stage23/sys/smp.c
+++ b/stage23/sys/smp.c
@@ -222,7 +222,7 @@ struct smp_information *init_smp(size_t    header_hack_size,
                     continue;
                 }
 
-                print("smp: [xAPIC] Found candidate AP for bring-up. LAPIC ID: %u\n", lapic->lapic_id);
+                printv("smp: [xAPIC] Found candidate AP for bring-up. LAPIC ID: %u\n", lapic->lapic_id);
 
                 // Try to start the AP
                 if (!smp_start_ap(lapic->lapic_id, &gdtr, info_struct,
@@ -232,7 +232,7 @@ struct smp_information *init_smp(size_t    header_hack_size,
                     continue;
                 }
 
-                print("smp: Successfully brought up AP\n");
+                printv("smp: Successfully brought up AP\n");
 
                 (*cpu_count)++;
                 continue;
@@ -259,7 +259,7 @@ struct smp_information *init_smp(size_t    header_hack_size,
                     continue;
                 }
 
-                print("smp: [x2APIC] Found candidate AP for bring-up. LAPIC ID: %u\n", x2apic->x2apic_id);
+                printv("smp: [x2APIC] Found candidate AP for bring-up. LAPIC ID: %u\n", x2apic->x2apic_id);
 
                 // Try to start the AP
                 if (!smp_start_ap(x2apic->x2apic_id, &gdtr, info_struct,
@@ -269,7 +269,7 @@ struct smp_information *init_smp(size_t    header_hack_size,
                     continue;
                 }
 
-                print("smp: Successfully brought up AP\n");
+                printv("smp: Successfully brought up AP\n");
 
                 (*cpu_count)++;
                 continue;
diff --git a/test/limine.cfg b/test/limine.cfg
index 5c46ad67..21102ba1 100644
--- a/test/limine.cfg
+++ b/test/limine.cfg
@@ -2,6 +2,7 @@ DEFAULT_ENTRY=1
 TIMEOUT=3
 GRAPHICS=yes
 MENU_FONT=boot:///boot/font.bin
+VERBOSE=yes
 
 THEME_BACKGROUND=60000000
 THEME_MARGIN=64
tab: 248 wrap: offon