:: commit a9ff406d31613de48a2efb650e2634b1bf423b02

mintsuki <mintsuki@protonmail.com> — 2020-12-26 23:27

parents: 9bff739de1

uri: Add support for gzip-compressed files

diff --git a/CONFIG.md b/CONFIG.md
index b8ebca0b..b4d7c975 100644
--- a/CONFIG.md
+++ b/CONFIG.md
@@ -105,3 +105,7 @@ A resource can be one of the following:
 * `guid` - The `root` takes the form of a GUID/UUID, such as `guid://736b5698-5ae1-4dff-be2c-ef8f44a61c52/...`. The GUID is that of either a filesystem, when available, or a GPT partition GUID, when using GPT, in a unified namespace.
 * `uuid` - Alias of `guid`.
 * `tftp` - The `root` is the IP address of the tftp server to load the file from. If the root is left empty (`tftp:///...`) the file will be loaded from the server Limine booted from. This resource is only available when booting off PXE.
+
+A URI can optionally be prefixed by a `$` character to indicate that the file
+pointed to be the URI is a gzip-compressed payload to be uncompressed on the
+fly. E.g.: `$boot:///somemodule.gz`.
diff --git a/Makefile b/Makefile
index 4969da33..70ca9c15 100644
--- a/Makefile
+++ b/Makefile
@@ -51,7 +51,7 @@ echfs-test: all limine-install test.hdd
 	rm -f limine.cfg.tmp part_guid
 	echfs-utils -g -p0 test.hdd import stage2.map boot/stage2.map
 	echfs-utils -g -p0 test.hdd import test/test.elf boot/test.elf
-	echfs-utils -g -p0 test.hdd import test/bg.bmp boot/bg.bmp
+	echfs-utils -g -p0 test.hdd import test/bg.bmp.gz boot/bg.bmp.gz
 	echfs-utils -g -p0 test.hdd import test/font.bin boot/font.bin
 	./limine-install limine.bin test.hdd
 	qemu-system-x86_64 -net none -smp 4 -enable-kvm -cpu host -hda test.hdd -debugcon stdio
diff --git a/decompressor/main.c b/decompressor/main.c
index 6ef54587..de6c6f64 100644
--- a/decompressor/main.c
+++ b/decompressor/main.c
@@ -12,12 +12,13 @@ void entry(uint8_t *compressed_stage2, size_t stage2_size, uint8_t boot_drive, i
     asm volatile (
         "mov esp, 0x7c00\n\t"
         "xor ebp, ebp\n\t"
+        "push %2\n\t"
         "push %1\n\t"
         "push %0\n\t"
         "push 0\n\t"
         "jmp 0x8000\n\t"
         :
-        : "r" ((uint32_t)boot_drive), "r" (pxe)
+        : "r" ((uint32_t)boot_drive), "r" (pxe), "r" (tinf_gzip_uncompress)
         : "memory"
     );
 
diff --git a/limine-pxe.bin b/limine-pxe.bin
index 038b2693..30de5b01 100644
Binary files a/limine-pxe.bin and b/limine-pxe.bin differ
diff --git a/limine.bin b/limine.bin
index 2b3f7454..4b923158 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2.map b/stage2.map
index 99f8fa9e..f3911588 100644
Binary files a/stage2.map and b/stage2.map differ
diff --git a/stage2/lib/tinf.c b/stage2/lib/tinf.c
new file mode 100644
index 00000000..fc743120
--- /dev/null
+++ b/stage2/lib/tinf.c
@@ -0,0 +1,4 @@
+#include <lib/tinf.h>
+
+int (*tinf_gzip_uncompress)(void *dest,
+                            const void *source, unsigned int sourceLen);
diff --git a/stage2/lib/tinf.h b/stage2/lib/tinf.h
new file mode 100644
index 00000000..313aa39c
--- /dev/null
+++ b/stage2/lib/tinf.h
@@ -0,0 +1,7 @@
+#ifndef __LIB__TINF_H__
+#define __LIB__TINF_H__
+
+extern int (*tinf_gzip_uncompress)(void *dest,
+                                   const void *source, unsigned int sourceLen);
+
+#endif
diff --git a/stage2/lib/uri.c b/stage2/lib/uri.c
index feee80c0..e4fab567 100644
--- a/stage2/lib/uri.c
+++ b/stage2/lib/uri.c
@@ -8,6 +8,7 @@
 #include <mm/pmm.h>
 #include <lib/print.h>
 #include <pxe/tftp.h>
+#include <lib/tinf.h>
 
 // A URI takes the form of: resource://root/path
 // The following function splits up a URI into its componenets
@@ -170,7 +171,14 @@ static bool uri_tftp_dispatch(struct file_handle *fd, char *root, char *path) {
     return true;
 }
 
+static int mem_read(void *fd, void *buf, uint64_t loc, uint64_t count) {
+    memcpy(buf, fd + loc, count);
+    return 0;
+}
+
 bool uri_open(struct file_handle *fd, char *uri) {
+    bool ret;
+
     char *resource, *root, *path;
     uri_resolve(uri, &resource, &root, &path);
 
@@ -178,17 +186,37 @@ bool uri_open(struct file_handle *fd, char *uri) {
         panic("No resource specified for URI `%s`.", uri);
     }
 
+    bool compressed = false;
+    if (*resource == '$') {
+        compressed = true;
+        resource++;
+    }
+
     if (!strcmp(resource, "bios")) {
-        return uri_bios_dispatch(fd, root, path);
+        ret = uri_bios_dispatch(fd, root, path);
     } else if (!strcmp(resource, "boot")) {
-        return uri_boot_dispatch(fd, root, path);
+        ret = uri_boot_dispatch(fd, root, path);
     } else if (!strcmp(resource, "guid")) {
-        return uri_guid_dispatch(fd, root, path);
+        ret = uri_guid_dispatch(fd, root, path);
     } else if (!strcmp(resource, "uuid")) {
-        return uri_guid_dispatch(fd, root, path);
+        ret = uri_guid_dispatch(fd, root, path);
     } else if (!strcmp(resource, "tftp")) {
-        return uri_tftp_dispatch(fd, root, path);
+        ret = uri_tftp_dispatch(fd, root, path);
     } else {
         panic("Resource `%s` not valid.", resource);
     }
+
+    if (compressed && ret) {
+        struct file_handle compressed_fd = {0};
+        fread(fd, &compressed_fd.size, fd->size - 4, sizeof(uint32_t));
+        compressed_fd.fd = ext_mem_alloc(compressed_fd.size);
+        void *src = ext_mem_alloc(fd->size);
+        fread(fd, src, 0, fd->size);
+        if (tinf_gzip_uncompress(compressed_fd.fd, src, fd->size))
+            panic("tinf error");
+        compressed_fd.read = mem_read;
+        *fd = compressed_fd;
+    }
+
+    return ret;
 }
diff --git a/stage2/main.c b/stage2/main.c
index 6df9a322..ecbdf1ae 100644
--- a/stage2/main.c
+++ b/stage2/main.c
@@ -20,9 +20,11 @@
 #include <menu.h>
 #include <pxe/pxe.h>
 #include <pxe/tftp.h>
+#include <lib/tinf.h>
 
-void entry(uint8_t _boot_drive, int pxe_boot) {
+void entry(uint8_t _boot_drive, int pxe_boot, void *_tinf_gzip_uncompress) {
     boot_drive = _boot_drive;
+    tinf_gzip_uncompress = _tinf_gzip_uncompress;
 
     mtrr_save();
 
diff --git a/stage2/mm/pmm.c b/stage2/mm/pmm.c
index c3d5695b..48749cbe 100644
--- a/stage2/mm/pmm.c
+++ b/stage2/mm/pmm.c
@@ -311,18 +311,13 @@ void memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type) {
 
 extern symbol bss_end;
 static size_t bump_allocator_base = (size_t)bss_end;
-static size_t bump_allocator_limit = 0;
+static size_t bump_allocator_limit = 0x70000;
 
 void *conv_mem_alloc(size_t count) {
     return conv_mem_alloc_aligned(count, 4);
 }
 
 void *conv_mem_alloc_aligned(size_t count, size_t alignment) {
-    if (!bump_allocator_limit) {
-        // The balloc limit is the beginning of the EBDA
-        bump_allocator_limit = *((uint16_t *)0x40e) << 4;
-    }
-
     size_t new_base = ALIGN_UP(bump_allocator_base, alignment);
     void *ret = (void *)new_base;
     new_base += count;
diff --git a/test/bg.bmp b/test/bg.bmp
deleted file mode 100644
index 37d8026e..00000000
Binary files a/test/bg.bmp and /dev/null differ
diff --git a/test/bg.bmp.gz b/test/bg.bmp.gz
new file mode 100644
index 00000000..d41594f2
Binary files /dev/null and b/test/bg.bmp.gz differ
diff --git a/test/limine.cfg b/test/limine.cfg
index 5b974048..0f5d7e22 100644
--- a/test/limine.cfg
+++ b/test/limine.cfg
@@ -10,7 +10,7 @@ STAGE2_MAP=bios://:1/boot/stage2.map
 THEME_COLOURS=60000000;aa0000;00aaff;aa5500;0000aa;aa00aa;9076de;aaaaaa
 THEME_MARGIN=64
 
-BACKGROUND_PATH=bios://:1/boot/bg.bmp
+BACKGROUND_PATH=$bios://:1/boot/bg.bmp.gz
 
 :+Legacy
 
@@ -23,7 +23,7 @@ KERNEL_CMDLINE=Hi! This is an example!
 MODULE_PATH=bios://:1/boot/test.elf
 MODULE_STRING=yooooo
 
-MODULE_PATH=bios://:1/boot/bg.bmp
+MODULE_PATH=$bios://:1/boot/bg.bmp.gz
 MODULE_STRING=yooooo
 
 :Stivale2 Test
@@ -33,5 +33,5 @@ RESOLUTION=640x480x16
 KERNEL_PATH=bios://:1/boot/test.elf
 KERNEL_CMDLINE=Woah! Another example!
 
-MODULE_PATH=bios://:1/boot/bg.bmp
+MODULE_PATH=$bios://:1/boot/bg.bmp.gz
 MODULE_STRING=yooooo
tab: 248 wrap: offon