mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-10-28 11:25:21 +01:00
loader.efi: Add xz decompression
We can now decompress .xz compressed memory disks, like FreeBSD-15.1-RELEASE-amd64-disc1.iso.xz Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D58073
This commit is contained in:
1 parent
4d37c2ea3c
commit
dc6c193bb4
6 files changed
+117
-11
No files matched your search
@@ -190,6 +190,11 @@ BZIP2_CFLAGS=-I${SRCTOP}/contrib/bzip2 -DBZ_NO_STDIO -DBZ_NO_COMPRESS
|
||||
# ZSTD client cflags
|
||||
ZSTD_CFLAGS=-I${SYSDIR}/contrib/zstd/lib
|
||||
|
||||
# XZ flags
|
||||
XZ_DIR=${SRCTOP}/sys/contrib/xz-embedded
|
||||
XZ_CFLAGS=-DXZ_USE_CRC64 -I${XZ_DIR}/freebsd -I${XZ_DIR}/linux/include/linux
|
||||
|
||||
|
||||
# The boot loader build uses dd status=none, where possible, for reproducible
|
||||
# build output (since performance varies from run to run). Trouble is that
|
||||
# option was recently (10.3) added to FreeBSD and is non-standard. Only use it
|
||||
|
||||
@@ -47,7 +47,7 @@ HAVE_ZFS= yes
|
||||
|
||||
CFLAGS.bootinfo.c += -I$(SRCTOP)/sys/teken
|
||||
CFLAGS.bootinfo.c += -I${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.decompress.c += ${ZLIB_CFLAGS} ${BZIP2_CFLAGS} ${ZSTD_CFLAGS}
|
||||
CFLAGS.decompress.c += ${ZLIB_CFLAGS} ${BZIP2_CFLAGS} ${ZSTD_CFLAGS} ${XZ_CFLAGS}
|
||||
CFLAGS.framebuffer.c += -I$(SRCTOP)/sys/teken
|
||||
CFLAGS.framebuffer.c += -I${SRCTOP}/contrib/pnglite
|
||||
CFLAGS.main.c += -I$(SRCTOP)/sys/teken
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
|
||||
#include <zlib.h>
|
||||
#include <bzlib.h>
|
||||
#ifdef LOADER_ZFS_SUPPORT /* ZSTD only available with ZFS */
|
||||
#include <xz.h>
|
||||
#ifdef LOADER_ZFS_SUPPORT /* ZSTD and lzma only available with ZFS */
|
||||
#include <zstd.h>
|
||||
#endif
|
||||
#include <sys/_param.h>
|
||||
@@ -32,6 +33,7 @@ struct decomp_state
|
||||
union {
|
||||
z_stream zstrm;
|
||||
bz_stream bzstrm;
|
||||
struct xz_dec *xzstrm;
|
||||
#ifdef LOADER_ZFS_SUPPORT
|
||||
ZSTD_DStream *zstdstrm;
|
||||
#endif
|
||||
@@ -63,10 +65,10 @@ what_compressed(uint8_t *buf, size_t len)
|
||||
return (zstd);
|
||||
}
|
||||
if (memcmp(buf, "\xfd""7zXZ\x00", 6) == 0) {
|
||||
printf("xz -- unsupproted\n");
|
||||
} else {
|
||||
printf("Not compressed\n");
|
||||
printf("xz\n");
|
||||
return (xz);
|
||||
}
|
||||
printf("Not compressed\n");
|
||||
return (none);
|
||||
}
|
||||
|
||||
@@ -220,7 +222,7 @@ bzip2_step(decomp_state *dctx, uint8_t *buf, size_t len, size_t offset)
|
||||
|
||||
if (ret == BZ_STREAM_END)
|
||||
return (done);
|
||||
if (ret != Z_OK)
|
||||
if (ret != BZ_OK)
|
||||
return (err);
|
||||
if (dctx->buf_cur < dctx->buf_end) /* Have output space */
|
||||
return (ok);
|
||||
@@ -247,6 +249,90 @@ bzip2_fini(decomp_state *dctx, bool flush)
|
||||
free_buffer(dctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* XZ support
|
||||
*/
|
||||
static EFI_STATUS
|
||||
xz_init(decomp_state *dctx, uint8_t *first_buf, size_t buflen, size_t size_hint)
|
||||
{
|
||||
/*
|
||||
* Assume 4x compression, but start at 64MB
|
||||
*/
|
||||
dctx->size = max(size_hint * 4, M(64));
|
||||
EFI_STATUS status = alloc_buffer(dctx, dctx->size);
|
||||
if (EFI_ERROR(status))
|
||||
return (status);
|
||||
xz_crc32_init();
|
||||
xz_crc64_init();
|
||||
dctx->xzstrm = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1);
|
||||
return (dctx->xzstrm != NULL ? EFI_SUCCESS : EFI_VOLUME_CORRUPTED);
|
||||
}
|
||||
|
||||
|
||||
static enum step_return
|
||||
xz_step(decomp_state *dctx, uint8_t *buf, size_t len, size_t offset)
|
||||
{
|
||||
struct xz_dec *strm = dctx->xzstrm;
|
||||
size_t outlen = dctx->buf_end - dctx->buf_cur;
|
||||
struct xz_buf b = { .in = buf, .in_size = len, .in_pos = 0,
|
||||
.out = dctx->buf_cur, .out_size = outlen, .out_pos = 0 };
|
||||
int ret;
|
||||
|
||||
ret = xz_dec_run(strm, &b);
|
||||
dctx->buf_cur += b.out_pos;
|
||||
|
||||
if (ret == XZ_STREAM_END)
|
||||
return (done);
|
||||
if (ret != XZ_OK) {
|
||||
switch(ret) {
|
||||
case XZ_MEM_ERROR:
|
||||
printf("xz no memory ");
|
||||
break;
|
||||
case XZ_DATA_ERROR:
|
||||
printf("xz file corrupted ");
|
||||
break;
|
||||
case XZ_FORMAT_ERROR:
|
||||
printf("xz format not found ");
|
||||
break;
|
||||
case XZ_OPTIONS_ERROR:
|
||||
printf("unsupported xz option ");
|
||||
break;
|
||||
case XZ_MEMLIMIT_ERROR:
|
||||
printf("xz dictionary too small ");
|
||||
break;
|
||||
default:
|
||||
printf("xz step error %d ", ret);
|
||||
break;
|
||||
}
|
||||
printf(" len %d offset %d\n", (int)len, (int)offset);
|
||||
return (err);
|
||||
}
|
||||
if (dctx->buf_cur < dctx->buf_end) /* Have output space */
|
||||
return (ok);
|
||||
|
||||
/*
|
||||
* We're out of space, grow the buffer and try again if there's buffer
|
||||
* space. We try again recursively since we know that will usually go
|
||||
* only 1 deep.
|
||||
*/
|
||||
if (EFI_ERROR(grow_buffer(dctx)))
|
||||
return (err);
|
||||
if (b.in_pos == b.in_size)
|
||||
return (ok);
|
||||
size_t consumed = b.in_pos;
|
||||
return (xz_step(dctx, buf + consumed, len - consumed, offset + consumed));
|
||||
}
|
||||
|
||||
static void
|
||||
xz_fini(decomp_state *dctx, bool flush)
|
||||
{
|
||||
xz_dec_end(dctx->xzstrm);
|
||||
dctx->xzstrm = NULL;
|
||||
if (!flush)
|
||||
return;
|
||||
free_buffer(dctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* ZSTD supprot
|
||||
*/
|
||||
@@ -373,6 +459,11 @@ decomp_init(uint8_t *buf, size_t buflen, size_t size_hint)
|
||||
dctx->step = bzip2_step;
|
||||
dctx->fini = bzip2_fini;
|
||||
break;
|
||||
case xz:
|
||||
dctx->init = xz_init;
|
||||
dctx->step = xz_step;
|
||||
dctx->fini = xz_fini;
|
||||
break;
|
||||
#ifdef LOADER_ZFS_SUPPORT
|
||||
case zstd:
|
||||
dctx->init = zstd_init;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
enum compression { none, zlib, bzip2, zstd };
|
||||
enum compression { none, zlib, bzip2, xz, zstd };
|
||||
enum step_return { ok, done, err };
|
||||
|
||||
typedef struct decomp_state decomp_state;
|
||||
|
||||
@@ -110,6 +110,13 @@ SRCS+= ${i}
|
||||
SRCS+= lz4.c
|
||||
CFLAGS.lz4.c+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/common/lz4
|
||||
|
||||
# xz decompression
|
||||
.PATH: ${XZ_DIR}/linux/lib/xz
|
||||
.for i in xz_crc32.c xz_crc64.c xz_dec_bcj.c xz_dec_lzma2.c xz_dec_stream.c xz.c
|
||||
CFLAGS.${i}+=${XZ_CFLAGS}
|
||||
SRCS+= ${i}
|
||||
.endfor
|
||||
|
||||
# io routines
|
||||
SRCS+= closeall.c dev.c ioctl.c nullfs.c stat.c mount.c \
|
||||
fstat.c close.c lseek.c open.c read.c write.c readdir.c preload.c
|
||||
|
||||
@@ -27,10 +27,17 @@
|
||||
#ifndef __FREEBSD_XZ_CONFIG_H__
|
||||
#define __FREEBSD_XZ_CONFIG_H__
|
||||
|
||||
#if defined(_KERNEL)
|
||||
#include <sys/param.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/systm.h>
|
||||
#elif defined(_STANDALONE)
|
||||
#include "stand.h"
|
||||
#include <sys/param.h>
|
||||
#else
|
||||
/* nothing */
|
||||
#endif
|
||||
|
||||
#include <contrib/xz-embedded/linux/include/linux/xz.h>
|
||||
#include "xz_malloc.h"
|
||||
@@ -61,10 +68,6 @@
|
||||
#define memeq(a, b, size) (memcmp((a), (b), (size)) == 0)
|
||||
#define memzero(buf, size) bzero((buf), (size))
|
||||
|
||||
#ifndef min
|
||||
# define min(x, y) MIN((x), (y))
|
||||
#endif
|
||||
|
||||
#define min_t(type, x, y) min((x), (y))
|
||||
|
||||
#define get_le32(ptr) le32toh(*(const uint32_t *)(ptr))
|
||||
|
||||
Reference in new issue
Block a user