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
