|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [XEN PATCH 2/2] x86/Dom0: Use streaming decompression for ZSTD compressed kernels
On Arch Linux kernel decompression will fail when Xen has been unified
with the kernel and initramfs as a single binary. This change works for
both streaming and non-streaming ZSTD content.
Signed-off-by: Rafaël Kooi <rafael_andreas@xxxxxxxxxxx>
---
xen/common/decompress.c | 37 +++++++++++++++++++++++++++++++------
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/xen/common/decompress.c b/xen/common/decompress.c
index 989336983f..cde754ffb1 100644
--- a/xen/common/decompress.c
+++ b/xen/common/decompress.c
@@ -3,11 +3,26 @@
#include <xen/string.h>
#include <xen/decompress.h>
+typedef struct _ZSTD_state
+{
+ void *write_buf;
+ unsigned int write_pos;
+} ZSTD_state;
+
static void __init cf_check error(const char *msg)
{
printk("%s\n", msg);
}
+static int __init cf_check ZSTD_flush(void *buf, unsigned int pos,
+ void *userptr)
+{
+ ZSTD_state *state = (ZSTD_state*)userptr;
+ memcpy(state->write_buf + state->write_pos, buf, pos);
+ state->write_pos += pos;
+ return pos;
+}
+
int __init decompress(void *inbuf, unsigned int len, void *outbuf)
{
#if 0 /* Not needed here yet. */
@@ -17,22 +32,32 @@ int __init decompress(void *inbuf, unsigned int len, void
*outbuf)
#endif
if ( len >= 3 && !memcmp(inbuf, "\x42\x5a\x68", 3) )
- return bunzip2(inbuf, len, NULL, NULL, outbuf, NULL, error);
+ return bunzip2(inbuf, len, NULL, NULL, outbuf, NULL, error, NULL);
if ( len >= 6 && !memcmp(inbuf, "\3757zXZ", 6) )
- return unxz(inbuf, len, NULL, NULL, outbuf, NULL, error);
+ return unxz(inbuf, len, NULL, NULL, outbuf, NULL, error, NULL);
if ( len >= 2 && !memcmp(inbuf, "\135\000", 2) )
- return unlzma(inbuf, len, NULL, NULL, outbuf, NULL, error);
+ return unlzma(inbuf, len, NULL, NULL, outbuf, NULL, error, NULL);
if ( len >= 5 && !memcmp(inbuf, "\x89LZO", 5) )
- return unlzo(inbuf, len, NULL, NULL, outbuf, NULL, error);
+ return unlzo(inbuf, len, NULL, NULL, outbuf, NULL, error, NULL);
if ( len >= 2 && !memcmp(inbuf, "\x02\x21", 2) )
- return unlz4(inbuf, len, NULL, NULL, outbuf, NULL, error);
+ return unlz4(inbuf, len, NULL, NULL, outbuf, NULL, error, NULL);
if ( len >= 4 && !memcmp(inbuf, "\x28\xb5\x2f\xfd", 4) )
- return unzstd(inbuf, len, NULL, NULL, outbuf, NULL, error);
+ {
+ // NOTE (Rafaël): On Arch Linux the kernel is compressed in a way
+ // that requires streaming ZSTD decompression. Otherwise decompression
+ // will fail when using a unified EFI binary. Somehow decompression
+ // works when not using a unified EFI binary, I suspect this is the
+ // kernel self decompressing. Or there is a code path that I am not
+ // aware of that takes care of the use case properly.
+
+ ZSTD_state state = (ZSTD_state){ outbuf, 0 };
+ return unzstd(inbuf, len, NULL, ZSTD_flush, NULL, NULL, error, &state);
+ }
return 1;
}
--
2.40.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |