summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAhmad Fatoum <a.fatoum@pengutronix.de>2022-08-09 11:19:46 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2022-08-11 08:26:12 +0200
commit2ab6780b80e35796cbfd95bc8bbc0993f1df0bcd (patch)
tree5a86108bbb8d8f3d80a07c1f9bd51f7a9175004c /lib
parentf64e6124b4666f347524841d2bb2036d5897c299 (diff)
downloadbarebox-2ab6780b80e35796cbfd95bc8bbc0993f1df0bcd.tar.gz
barebox-2ab6780b80e35796cbfd95bc8bbc0993f1df0bcd.tar.xz
FIT: add first support for compressed images
FIT image contents are often compressed, but we got by so far, because a compressed initramfs is usually meant to be decompressed by the kernel (and so has compression = "none") and arm32 kernels had their own decompresser embedded. On ARM64, bootloader is responsible for uncompressing kernel, so we should properly process the compression property we so far ignored. The decompression isn't as efficient as one would hope for, because the FIT format only describes length of the compressed data. We thus have two options: - define an output size up-front, e.g. by guessing the uncompressed buffer size for decompression or hardcoding it (e.g. U-Boot's CONFIG_SYS_BOOTM_LEN). - Uncompress to a file descriptor We choose the second one to play it safe, but it comes with worse performance because of extra memory copies. Intention is to go with first option for the kernel image: We know how much size we can spare for the kernel image and can have bootm_load_os uncompress there directly without intermittent memory copies. This would involve slight change to the barebox decompresser API to align it with the kernel's, which allows to have it accept and observe an output buffer size. So far, we had the kernel PREBOOT API, which lacks such a parameter, but that's an optimization for another day. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> Link: https://lore.barebox.org/20220809091946.3906847-1-a.fatoum@pengutronix.de Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'lib')
-rw-r--r--lib/uncompress.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/lib/uncompress.c b/lib/uncompress.c
index 5c0d1e9f4d..0608e9f9d3 100644
--- a/lib/uncompress.c
+++ b/lib/uncompress.c
@@ -172,3 +172,43 @@ int uncompress_fd_to_buf(int infd, void *output,
return uncompress(NULL, 0, fill_fd, NULL, output, NULL, error_fn);
}
+
+int uncompress_buf_to_fd(const void *input, size_t input_len,
+ int outfd, void(*error_fn)(char *x))
+{
+ uncompress_outfd = outfd;
+
+ return uncompress((void *)input, input_len, NULL, flush_fd,
+ NULL, NULL, error_fn);
+}
+
+ssize_t uncompress_buf_to_buf(const void *input, size_t input_len,
+ void **buf, void(*error_fn)(char *x))
+{
+ char *dstpath;
+ size_t size;
+ int outfd, ret;
+
+ dstpath = make_temp("data-uncompressed");
+ if (!dstpath)
+ return -ENOMEM;
+
+ outfd = open(dstpath, O_CREAT | O_WRONLY);
+ if (outfd < 0) {
+ ret = -ENODEV;
+ goto free_temp;
+ }
+
+ ret = uncompress_buf_to_fd(input, input_len, outfd, uncompress_err_stdout);
+ if (ret)
+ goto close_outfd;
+
+ *buf = read_file(dstpath, &size);
+close_outfd:
+ close(outfd);
+ unlink(dstpath);
+free_temp:
+ free(dstpath);
+
+ return ret ?: size;
+}