grub-devel.gnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] io: Implement zstdio decompression
  2025-09-23 20:12 [PATCH 0/4] Add zstdio support for booting Trixie kernels in Xen Logan Gunthorpe via Grub-devel
@ 2025-09-23 20:12 ` Logan Gunthorpe via Grub-devel
  0 siblings, 0 replies; 9+ messages in thread
From: Logan Gunthorpe via Grub-devel @ 2025-09-23 20:12 UTC (permalink / raw)
  To: grub-devel, Daniel Kiper, Alex Burmashev,
	Vladimir 'phcoder' Serbinenko
  Cc: Logan Gunthorpe, Nagy Elemér Károly

Add zstd based io decompression.

Based largely on the existing xzio, implement the same features using
the zstd library already included in the project.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 Makefile.util.def           |   1 +
 grub-core/Makefile.core.def |   9 +-
 grub-core/io/zstdio.c       | 237 ++++++++++++++++++++++++++++++++++++
 include/grub/file.h         |   3 +-
 4 files changed, 248 insertions(+), 2 deletions(-)
 create mode 100644 grub-core/io/zstdio.c

diff --git a/Makefile.util.def b/Makefile.util.def
index 038253b37a42..74786177f908 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -162,6 +162,7 @@ library = {
   common = grub-core/io/gzio.c;
   common = grub-core/io/xzio.c;
   common = grub-core/io/lzopio.c;
+  common = grub-core/io/zstdio.c;
   common = grub-core/kern/ia64/dl_helper.c;
   common = grub-core/kern/arm/dl_helper.c;
   common = grub-core/kern/arm64/dl_helper.c;
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 0fcf67f9df7d..4c8005782e31 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -473,7 +473,7 @@ image = {
   i386_pc = boot/i386/pc/boot.S;
 
   cppflags = '-DHYBRID_BOOT=1';
-  
+
   i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
   i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
 
@@ -2486,6 +2486,13 @@ module = {
   cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
 };
 
+module = {
+  name = zstdio;
+  common = io/zstdio.c;
+  cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd';
+  cflags='-Wno-unreachable-code';
+};
+
 module = {
   name = testload;
   common = commands/testload.c;
diff --git a/grub-core/io/zstdio.c b/grub-core/io/zstdio.c
new file mode 100644
index 000000000000..b64655aa63e3
--- /dev/null
+++ b/grub-core/io/zstdio.c
@@ -0,0 +1,237 @@
+/* zstdio.c - decompression support for zstd */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#include "zstd.h"
+
+#define STREAM_HEADER_SIZE 16
+
+struct grub_zstdio
+{
+  grub_file_t file;
+  ZSTD_DCtx *dctx;
+  grub_size_t insize;
+  grub_size_t outsize;
+
+  ZSTD_outBuffer output;
+  ZSTD_inBuffer input;
+
+  grub_off_t saved_offset;
+  grub_uint8_t bufs[];
+};
+
+typedef struct grub_zstdio *grub_zstdio_t;
+static struct grub_fs grub_zstdio_fs;
+
+static int
+test_header (grub_file_t file)
+{
+  grub_zstdio_t zstdio = file->data;
+  size_t zret;
+
+  zstdio->input.pos = 0;
+  zstdio->output.pos = 0;
+  zstdio->output.size = zstdio->outsize;
+  zstdio->input.size = grub_file_read (zstdio->file, zstdio->bufs,
+				       STREAM_HEADER_SIZE);
+  if (zstdio->input.size != STREAM_HEADER_SIZE)
+    return 0;
+
+  zret = ZSTD_decompressStream(zstdio->dctx, &zstdio->output, &zstdio->input);
+  if (ZSTD_isError(zret))
+    return 0;
+
+  return 1;
+}
+
+static grub_file_t
+grub_zstdio_open (grub_file_t io, enum grub_file_type type)
+{
+  grub_file_t file;
+  grub_zstdio_t zstdio;
+
+  if (type & GRUB_FILE_TYPE_NO_DECOMPRESS)
+    return io;
+
+  file = (grub_file_t) grub_zalloc (sizeof (*file));
+  if (!file)
+    return 0;
+
+  zstdio = grub_zalloc (sizeof (*zstdio) + ZSTD_DStreamInSize() +
+			ZSTD_DStreamOutSize());
+  if (!zstdio)
+    {
+      grub_free (file);
+      return 0;
+    }
+
+  zstdio->file = io;
+  zstdio->insize = ZSTD_DStreamInSize();
+  zstdio->outsize = ZSTD_DStreamOutSize();
+  zstdio->input.src = zstdio->bufs;
+  zstdio->output.dst = &zstdio->bufs[zstdio->insize];
+
+  file->device = io->device;
+  file->data = zstdio;
+  file->fs = &grub_zstdio_fs;
+  file->size = GRUB_FILE_SIZE_UNKNOWN;
+  file->not_easily_seekable = 1;
+
+  if (grub_file_tell (zstdio->file) != 0)
+    grub_file_seek (zstdio->file, 0);
+
+  zstdio->dctx = ZSTD_createDCtx();
+  if (!zstdio->dctx)
+    {
+      grub_free (file);
+      grub_free (zstdio);
+      return 0;
+    }
+
+  if (!test_header (file))
+    {
+      grub_errno = GRUB_ERR_NONE;
+      grub_file_seek (io, 0);
+      ZSTD_freeDCtx(zstdio->dctx);
+      grub_free (zstdio);
+      grub_free (file);
+
+      return io;
+    }
+
+  return file;
+}
+
+static grub_ssize_t
+grub_zstdio_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  grub_zstdio_t zstdio = file->data;
+  grub_ssize_t ret = 0;
+  grub_ssize_t readret;
+  grub_off_t current_offset;
+  grub_size_t zret;
+
+  /* If seek backward need to reset decoder and start from beginning of file. */
+  if (file->offset < zstdio->saved_offset)
+    {
+      ZSTD_initDStream(zstdio->dctx);
+      zstdio->input.pos = 0;
+      zstdio->input.size = 0;
+      zstdio->output.pos = 0;
+      zstdio->saved_offset = 0;
+      grub_file_seek (zstdio->file, 0);
+    }
+
+  current_offset = zstdio->saved_offset;
+
+  while (len > 0)
+    {
+      zstdio->output.size = file->offset + ret + len - current_offset;
+      if (zstdio->output.size > zstdio->outsize)
+	zstdio->output.size = zstdio->outsize;
+      if (zstdio->input.pos == zstdio->input.size)
+	{
+	  readret = grub_file_read (zstdio->file, zstdio->bufs,
+				    zstdio->insize);
+	  if (readret < 0)
+	    return -1;
+	  zstdio->input.size = readret;
+	  zstdio->input.pos = 0;
+	}
+
+      zret = ZSTD_decompressStream(zstdio->dctx, &zstdio->output,
+				   &zstdio->input);
+      if (ZSTD_isError(zret))
+	{
+	  grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
+		      N_("zstd file corrupted or unsupported block options"));
+	  return -1;
+        }
+
+      grub_off_t new_offset = current_offset + zstdio->output.pos;
+
+      if (file->offset <= new_offset)
+	  /* Store first chunk of data in buffer.  */
+        {
+	  grub_size_t delta = new_offset - (file->offset + ret);
+	  grub_memmove (buf, (grub_uint8_t *)zstdio->output.dst +
+			(zstdio->output.pos - delta),
+	                delta);
+	  len -= delta;
+	  buf += delta;
+	  ret += delta;
+	}
+	current_offset = new_offset;
+
+	zstdio->output.pos = 0;
+
+	if (zstdio->input.pos == 0 && zstdio->output.pos == 0)
+	  break;
+    }
+
+  if (ret >= 0)
+    zstdio->saved_offset = file->offset + ret;
+
+  return ret;
+}
+
+/* Release everything, including the underlying file object.  */
+static grub_err_t
+grub_zstdio_close (grub_file_t file)
+{
+  grub_zstdio_t zstdio = file->data;
+
+  ZSTD_freeDCtx(zstdio->dctx);
+
+  grub_file_close (zstdio->file);
+  grub_free (zstdio);
+
+  /* Device must not be closed twice.  */
+  file->device = 0;
+  file->name = 0;
+  return grub_errno;
+}
+
+static struct grub_fs grub_zstdio_fs = {
+  .name = "zstdio",
+  .fs_dir = 0,
+  .fs_open = 0,
+  .fs_read = grub_zstdio_read,
+  .fs_close = grub_zstdio_close,
+  .fs_label = 0,
+  .next = 0
+};
+
+GRUB_MOD_INIT (zstdio)
+{
+  grub_file_filter_register (GRUB_FILE_FILTER_ZSTDIO, grub_zstdio_open);
+}
+
+GRUB_MOD_FINI (zstdio)
+{
+  grub_file_filter_unregister (GRUB_FILE_FILTER_ZSTDIO);
+}
diff --git a/include/grub/file.h b/include/grub/file.h
index a5bf3a792d6f..7c665730a090 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -186,9 +186,10 @@ typedef enum grub_file_filter_id
     GRUB_FILE_FILTER_GZIO,
     GRUB_FILE_FILTER_XZIO,
     GRUB_FILE_FILTER_LZOPIO,
+    GRUB_FILE_FILTER_ZSTDIO,
     GRUB_FILE_FILTER_MAX,
     GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO,
-    GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,
+    GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_ZSTDIO,
   } grub_file_filter_id_t;
 
 typedef grub_file_t (*grub_file_filter_t) (grub_file_t in, enum grub_file_type type);
-- 
2.47.3


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] io: Implement zstdio decompression
       [not found] <mailman.23.1758658751.1187.grub-devel@gnu.org>
@ 2025-10-09  6:26 ` Avnish Chouhan
  0 siblings, 0 replies; 9+ messages in thread
From: Avnish Chouhan @ 2025-10-09  6:26 UTC (permalink / raw)
  To: logang; +Cc: grub-devel, Daniel Kiper, alexander.burmashev, phcoder

On 2025-09-24 01:49, grub-devel-request@gnu.org wrote:
> Message: 4
> Date: Tue, 23 Sep 2025 14:12:57 -0600
> From: Logan Gunthorpe <logang@deltatee.com>
> To: grub-devel@gnu.org, Daniel Kiper <daniel.kiper@oracle.com>, Alex
> 	Burmashev <alexander.burmashev@oracle.com>, Vladimir 'phcoder'
> 	Serbinenko <phcoder@gmail.com>
> Cc: Nagy Elemér Károly  <nagy.elemer.karoly@gmail.com>, Logan
> 	Gunthorpe <logang@deltatee.com>
> Subject: [PATCH 1/4] io: Implement zstdio decompression
> Message-ID: <20250923201300.3079-2-logang@deltatee.com>
> 
> Add zstd based io decompression.
> 
> Based largely on the existing xzio, implement the same features using
> the zstd library already included in the project.
> 
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---
>  Makefile.util.def           |   1 +
>  grub-core/Makefile.core.def |   9 +-
>  grub-core/io/zstdio.c       | 237 ++++++++++++++++++++++++++++++++++++
>  include/grub/file.h         |   3 +-
>  4 files changed, 248 insertions(+), 2 deletions(-)
>  create mode 100644 grub-core/io/zstdio.c
> 
> diff --git a/Makefile.util.def b/Makefile.util.def
> index 038253b37a42..74786177f908 100644
> --- a/Makefile.util.def
> +++ b/Makefile.util.def
> @@ -162,6 +162,7 @@ library = {
>    common = grub-core/io/gzio.c;
>    common = grub-core/io/xzio.c;
>    common = grub-core/io/lzopio.c;
> +  common = grub-core/io/zstdio.c;
>    common = grub-core/kern/ia64/dl_helper.c;
>    common = grub-core/kern/arm/dl_helper.c;
>    common = grub-core/kern/arm64/dl_helper.c;
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index 0fcf67f9df7d..4c8005782e31 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -473,7 +473,7 @@ image = {
>    i386_pc = boot/i386/pc/boot.S;
> 
>    cppflags = '-DHYBRID_BOOT=1';
> -
> +
>    i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)';
>    i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x7C00';
> 
> @@ -2486,6 +2486,13 @@ module = {
>    cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo
> -DMINILZO_HAVE_CONFIG_H';
>  };
> 
> +module = {
> +  name = zstdio;
> +  common = io/zstdio.c;
> +  cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd';
> +  cflags='-Wno-unreachable-code';
> +};
> +
>  module = {
>    name = testload;
>    common = commands/testload.c;
> diff --git a/grub-core/io/zstdio.c b/grub-core/io/zstdio.c
> new file mode 100644
> index 000000000000..b64655aa63e3
> --- /dev/null
> +++ b/grub-core/io/zstdio.c
> @@ -0,0 +1,237 @@
> +/* zstdio.c - decompression support for zstd */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2010  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published 
> by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/err.h>
> +#include <grub/mm.h>
> +#include <grub/misc.h>
> +#include <grub/file.h>
> +#include <grub/fs.h>
> +#include <grub/dl.h>
> +
> +GRUB_MOD_LICENSE ("GPLv3+");
> +
> +#include "zstd.h"
> +
> +#define STREAM_HEADER_SIZE 16
> +
> +struct grub_zstdio
> +{
> +  grub_file_t file;
> +  ZSTD_DCtx *dctx;
> +  grub_size_t insize;
> +  grub_size_t outsize;
> +
> +  ZSTD_outBuffer output;
> +  ZSTD_inBuffer input;
> +
> +  grub_off_t saved_offset;
> +  grub_uint8_t bufs[];
> +};
> +
> +typedef struct grub_zstdio *grub_zstdio_t;
> +static struct grub_fs grub_zstdio_fs;
> +
> +static int
> +test_header (grub_file_t file)
> +{
> +  grub_zstdio_t zstdio = file->data;
> +  size_t zret;
> +
> +  zstdio->input.pos = 0;
> +  zstdio->output.pos = 0;
> +  zstdio->output.size = zstdio->outsize;
> +  zstdio->input.size = grub_file_read (zstdio->file, zstdio->bufs,
> +				       STREAM_HEADER_SIZE);

Hi Logan,

Indentation seems little off in line "STREAM_HEADER_SIZE);" . Please 
recheck!

> +  if (zstdio->input.size != STREAM_HEADER_SIZE)
> +    return 0;
> +
> +  zret = ZSTD_decompressStream(zstdio->dctx, &zstdio->output, 
> &zstdio->input);

Missing empty space, "ZSTD_decompressStream (zstdio->dctx...."

> +  if (ZSTD_isError(zret))

Same as above. Missing empty space!

> +    return 0;
> +
> +  return 1;
> +}
> +
> +static grub_file_t
> +grub_zstdio_open (grub_file_t io, enum grub_file_type type)
> +{
> +  grub_file_t file;
> +  grub_zstdio_t zstdio;
> +
> +  if (type & GRUB_FILE_TYPE_NO_DECOMPRESS)
> +    return io;
> +
> +  file = (grub_file_t) grub_zalloc (sizeof (*file));

"grub_zalloc (sizeof (grub_file_t));" would be better!

> +  if (!file)

if (file == NULL)

> +    return 0;
> +
> +  zstdio = grub_zalloc (sizeof (*zstdio) + ZSTD_DStreamInSize() +
> +			ZSTD_DStreamOutSize());

zstdio = grub_zalloc (sizeof (grub_zstdio_t) + ZSTD_DStreamInSize () + 
ZSTD_DStreamOutSize ());

> +  if (!zstdio)

if (zstdio == NULL)

> +    {
> +      grub_free (file);
> +      return 0;
> +    }
> +
> +  zstdio->file = io;
> +  zstdio->insize = ZSTD_DStreamInSize();
> +  zstdio->outsize = ZSTD_DStreamOutSize();

zstdio->insize = ZSTD_DStreamInSize ();
zstdio->outsize = ZSTD_DStreamOutSize ();

Please add the empty space wherever missing!

> +  zstdio->input.src = zstdio->bufs;
> +  zstdio->output.dst = &zstdio->bufs[zstdio->insize];
> +
> +  file->device = io->device;
> +  file->data = zstdio;
> +  file->fs = &grub_zstdio_fs;
> +  file->size = GRUB_FILE_SIZE_UNKNOWN;
> +  file->not_easily_seekable = 1;
> +
> +  if (grub_file_tell (zstdio->file) != 0)
> +    grub_file_seek (zstdio->file, 0);
> +
> +  zstdio->dctx = ZSTD_createDCtx();
> +  if (!zstdio->dctx)

if (zstdio->dctx == NULL)

> +    {
> +      grub_free (file);
> +      grub_free (zstdio);
> +      return 0;
> +    }
> +
> +  if (!test_header (file))
> +    {
> +      grub_errno = GRUB_ERR_NONE;
> +      grub_file_seek (io, 0);
> +      ZSTD_freeDCtx(zstdio->dctx);

ZSTD_freeDCtx (zstdio->dctx);

> +      grub_free (zstdio);
> +      grub_free (file);
> +
> +      return io;
> +    }
> +
> +  return file;
> +}
> +
> +static grub_ssize_t
> +grub_zstdio_read (grub_file_t file, char *buf, grub_size_t len)
> +{
> +  grub_zstdio_t zstdio = file->data;
> +  grub_ssize_t ret = 0;
> +  grub_ssize_t readret;
> +  grub_off_t current_offset;
> +  grub_size_t zret;
> +
> +  /* If seek backward need to reset decoder and start from beginning
> of file. */
> +  if (file->offset < zstdio->saved_offset)
> +    {
> +      ZSTD_initDStream(zstdio->dctx);

ZSTD_initDStream (zstdio->dctx);

> +      zstdio->input.pos = 0;
> +      zstdio->input.size = 0;
> +      zstdio->output.pos = 0;
> +      zstdio->saved_offset = 0;
> +      grub_file_seek (zstdio->file, 0);
> +    }
> +
> +  current_offset = zstdio->saved_offset;
> +
> +  while (len > 0)
> +    {
> +      zstdio->output.size = file->offset + ret + len - current_offset;
> +      if (zstdio->output.size > zstdio->outsize)
> +	zstdio->output.size = zstdio->outsize;
> +      if (zstdio->input.pos == zstdio->input.size)
> +	{
> +	  readret = grub_file_read (zstdio->file, zstdio->bufs,
> +				    zstdio->insize);
> +	  if (readret < 0)
> +	    return -1;

Adding an empty line would be good here! And could you please recheck 
the indentation in this while loop. Seems little off.

> +	  zstdio->input.size = readret;
> +	  zstdio->input.pos = 0;
> +	}
> +
> +      zret = ZSTD_decompressStream(zstdio->dctx, &zstdio->output,

...ZSTD_decompressStream (zstdio...

> +				   &zstdio->input);
> +      if (ZSTD_isError(zret))

if (ZSTD_isError (zret))

> +	{
> +	  grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
> +		      N_("zstd file corrupted or unsupported block options"));
> +	  return -1;
> +        }
> +
> +      grub_off_t new_offset = current_offset + zstdio->output.pos;
> +
> +      if (file->offset <= new_offset)
> +	  /* Store first chunk of data in buffer.  */

/* Store first chunk of data in buffer.  */
if (file->offset <= new_offset)

> +        {
> +	  grub_size_t delta = new_offset - (file->offset + ret);
> +	  grub_memmove (buf, (grub_uint8_t *)zstdio->output.dst +

Empty space missing! "..., (grub_uint8_t *) zstdio..."

> +			(zstdio->output.pos - delta),
> +	                delta);
> +	  len -= delta;
> +	  buf += delta;
> +	  ret += delta;
> +	}
> +	current_offset = new_offset;
> +
> +	zstdio->output.pos = 0;
> +
> +	if (zstdio->input.pos == 0 && zstdio->output.pos == 0)
> +	  break;
> +    }
> +
> +  if (ret >= 0)
> +    zstdio->saved_offset = file->offset + ret;
> +
> +  return ret;
> +}
> +
> +/* Release everything, including the underlying file object.  */
> +static grub_err_t
> +grub_zstdio_close (grub_file_t file)
> +{
> +  grub_zstdio_t zstdio = file->data;
> +
> +  ZSTD_freeDCtx(zstdio->dctx);

ZSTD_freeDCtx (zstdio->dctx);

Thank you!

Regards,
Avnish Chouhan

> +
> +  grub_file_close (zstdio->file);
> +  grub_free (zstdio);
> +
> +  /* Device must not be closed twice.  */
> +  file->device = 0;
> +  file->name = 0;
> +  return grub_errno;
> +}
> +
> +static struct grub_fs grub_zstdio_fs = {
> +  .name = "zstdio",
> +  .fs_dir = 0,
> +  .fs_open = 0,
> +  .fs_read = grub_zstdio_read,
> +  .fs_close = grub_zstdio_close,
> +  .fs_label = 0,
> +  .next = 0
> +};
> +
> +GRUB_MOD_INIT (zstdio)
> +{
> +  grub_file_filter_register (GRUB_FILE_FILTER_ZSTDIO, 
> grub_zstdio_open);
> +}
> +
> +GRUB_MOD_FINI (zstdio)
> +{
> +  grub_file_filter_unregister (GRUB_FILE_FILTER_ZSTDIO);
> +}
> diff --git a/include/grub/file.h b/include/grub/file.h
> index a5bf3a792d6f..7c665730a090 100644
> --- a/include/grub/file.h
> +++ b/include/grub/file.h
> @@ -186,9 +186,10 @@ typedef enum grub_file_filter_id
>      GRUB_FILE_FILTER_GZIO,
>      GRUB_FILE_FILTER_XZIO,
>      GRUB_FILE_FILTER_LZOPIO,
> +    GRUB_FILE_FILTER_ZSTDIO,
>      GRUB_FILE_FILTER_MAX,
>      GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO,
> -    GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,
> +    GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_ZSTDIO,
>    } grub_file_filter_id_t;
> 
>  typedef grub_file_t (*grub_file_filter_t) (grub_file_t in, enum
> grub_file_type type);
> --
> 2.47.3
> 
> 
> 
> 
> ------------------------------
> 
> Subject: Digest Footer
> 
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
> 
> 
> ------------------------------
> 
> End of Grub-devel Digest, Vol 259, Issue 83
> *******************************************

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] io: Implement zstdio decompression
  2025-10-14 20:14 [PATCH 0/4] Add zstdio support for booting Trixie kernels in Xen Logan Gunthorpe via Grub-devel
@ 2025-10-14 20:14 ` Logan Gunthorpe via Grub-devel
  2025-10-15 15:52   ` Daniel Kiper
  0 siblings, 1 reply; 9+ messages in thread
From: Logan Gunthorpe via Grub-devel @ 2025-10-14 20:14 UTC (permalink / raw)
  To: grub-devel, Daniel Kiper, Alex Burmashev,
	Vladimir 'phcoder' Serbinenko
  Cc: Logan Gunthorpe, Nagy Elemér Károly

Add zstd based io decompression.

Based largely on the existing xzio, implement the same features using
the zstd library already included in the project.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 Makefile.util.def           |   1 +
 grub-core/Makefile.core.def |   7 ++
 grub-core/io/zstdio.c       | 237 ++++++++++++++++++++++++++++++++++++
 include/grub/file.h         |   3 +-
 4 files changed, 247 insertions(+), 1 deletion(-)
 create mode 100644 grub-core/io/zstdio.c

diff --git a/Makefile.util.def b/Makefile.util.def
index 038253b37a42..74786177f908 100644
--- a/Makefile.util.def
+++ b/Makefile.util.def
@@ -162,6 +162,7 @@ library = {
   common = grub-core/io/gzio.c;
   common = grub-core/io/xzio.c;
   common = grub-core/io/lzopio.c;
+  common = grub-core/io/zstdio.c;
   common = grub-core/kern/ia64/dl_helper.c;
   common = grub-core/kern/arm/dl_helper.c;
   common = grub-core/kern/arm64/dl_helper.c;
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index a729cb6a8e61..a2635d61b6e8 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -2512,6 +2512,13 @@ module = {
   cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
 };
 
+module = {
+  name = zstdio;
+  common = io/zstdio.c;
+  cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd';
+  cflags='-Wno-unreachable-code';
+};
+
 module = {
   name = testload;
   common = commands/testload.c;
diff --git a/grub-core/io/zstdio.c b/grub-core/io/zstdio.c
new file mode 100644
index 000000000000..01a5a45587a7
--- /dev/null
+++ b/grub-core/io/zstdio.c
@@ -0,0 +1,237 @@
+/* zstdio.c - decompression support for zstd */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2010  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/err.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/file.h>
+#include <grub/fs.h>
+#include <grub/dl.h>
+
+GRUB_MOD_LICENSE ("GPLv3+");
+
+#include "zstd.h"
+
+#define STREAM_HEADER_SIZE 16
+
+struct grub_zstdio
+{
+  grub_file_t file;
+  ZSTD_DCtx *dctx;
+  grub_size_t insize;
+  grub_size_t outsize;
+
+  ZSTD_outBuffer output;
+  ZSTD_inBuffer input;
+
+  grub_off_t saved_offset;
+  grub_uint8_t bufs[];
+};
+
+typedef struct grub_zstdio *grub_zstdio_t;
+static struct grub_fs grub_zstdio_fs;
+
+static int
+test_header (grub_file_t file)
+{
+  grub_zstdio_t zstdio = file->data;
+  size_t zret;
+
+  zstdio->input.pos = 0;
+  zstdio->output.pos = 0;
+  zstdio->output.size = zstdio->outsize;
+  zstdio->input.size = grub_file_read (zstdio->file, zstdio->bufs,
+                                       STREAM_HEADER_SIZE);
+  if (zstdio->input.size != STREAM_HEADER_SIZE)
+    return 0;
+
+  zret = ZSTD_decompressStream (zstdio->dctx, &zstdio->output, &zstdio->input);
+  if (ZSTD_isError (zret))
+    return 0;
+
+  return 1;
+}
+static grub_file_t
+grub_zstdio_open (grub_file_t io, enum grub_file_type type)
+{
+  grub_file_t file;
+  grub_zstdio_t zstdio;
+
+  if (type & GRUB_FILE_TYPE_NO_DECOMPRESS)
+    return io;
+
+  file = (grub_file_t) grub_zalloc (sizeof (grub_file_t));
+  if (file == NULL)
+    return 0;
+
+  zstdio = grub_zalloc (sizeof (grub_zstdio_t) + ZSTD_DStreamInSize () +
+                        ZSTD_DStreamOutSize ());
+  if (zstdio == NULL)
+    {
+      grub_free (file);
+      return 0;
+    }
+
+  zstdio->file = io;
+  zstdio->insize = ZSTD_DStreamInSize ();
+  zstdio->outsize = ZSTD_DStreamOutSize ();
+  zstdio->input.src = zstdio->bufs;
+  zstdio->output.dst = &zstdio->bufs[zstdio->insize];
+
+  file->device = io->device;
+  file->data = zstdio;
+  file->fs = &grub_zstdio_fs;
+  file->size = GRUB_FILE_SIZE_UNKNOWN;
+  file->not_easily_seekable = 1;
+
+  if (grub_file_tell (zstdio->file) != 0)
+    grub_file_seek (zstdio->file, 0);
+
+  zstdio->dctx = ZSTD_createDCtx ();
+  if (zstdio->dctx == NULL)
+    {
+      grub_free (file);
+      grub_free (zstdio);
+      return 0;
+    }
+
+  if (!test_header (file))
+    {
+      grub_errno = GRUB_ERR_NONE;
+      grub_file_seek (io, 0);
+      ZSTD_freeDCtx (zstdio->dctx);
+      grub_free (zstdio);
+      grub_free (file);
+
+      return io;
+    }
+
+  return file;
+}
+
+static grub_ssize_t
+grub_zstdio_read (grub_file_t file, char *buf, grub_size_t len)
+{
+  grub_zstdio_t zstdio = file->data;
+  grub_ssize_t ret = 0;
+  grub_ssize_t readret;
+  grub_off_t current_offset;
+  grub_size_t zret;
+
+  /* If seek backward need to reset decoder and start from beginning of file. */
+  if (file->offset < zstdio->saved_offset)
+    {
+      ZSTD_initDStream (zstdio->dctx);
+      zstdio->input.pos = 0;
+      zstdio->input.size = 0;
+      zstdio->output.pos = 0;
+      zstdio->saved_offset = 0;
+      grub_file_seek (zstdio->file, 0);
+    }
+
+  current_offset = zstdio->saved_offset;
+
+  while (len > 0)
+    {
+      zstdio->output.size = file->offset + ret + len - current_offset;
+      if (zstdio->output.size > zstdio->outsize)
+        zstdio->output.size = zstdio->outsize;
+      if (zstdio->input.pos == zstdio->input.size)
+        {
+	  readret = grub_file_read (zstdio->file, zstdio->bufs,
+	                            zstdio->insize);
+	  if (readret < 0)
+	    return -1;
+
+	  zstdio->input.size = readret;
+	  zstdio->input.pos = 0;
+	}
+
+      zret = ZSTD_decompressStream (zstdio->dctx, &zstdio->output,
+                                    &zstdio->input);
+      if (ZSTD_isError (zret))
+	{
+	  grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
+		      N_("zstd file corrupted or unsupported block options"));
+	  return -1;
+        }
+
+      grub_off_t new_offset = current_offset + zstdio->output.pos;
+
+      /* Store first chunk of data in buffer.  */
+      if (file->offset <= new_offset)
+        {
+	  grub_size_t delta = new_offset - (file->offset + ret);
+	  grub_memmove (buf, (grub_uint8_t *) zstdio->output.dst +
+                        (zstdio->output.pos - delta),
+                        delta);
+	  len -= delta;
+	  buf += delta;
+	  ret += delta;
+	}
+	current_offset = new_offset;
+
+	zstdio->output.pos = 0;
+
+	if (zstdio->input.pos == 0 && zstdio->output.pos == 0)
+	  break;
+    }
+
+  if (ret >= 0)
+    zstdio->saved_offset = file->offset + ret;
+
+  return ret;
+}
+
+/* Release everything, including the underlying file object.  */
+static grub_err_t
+grub_zstdio_close (grub_file_t file)
+{
+  grub_zstdio_t zstdio = file->data;
+
+  ZSTD_freeDCtx (zstdio->dctx);
+
+  grub_file_close (zstdio->file);
+  grub_free (zstdio);
+
+  /* Device must not be closed twice.  */
+  file->device = 0;
+  file->name = 0;
+  return grub_errno;
+}
+
+static struct grub_fs grub_zstdio_fs = {
+  .name = "zstdio",
+  .fs_dir = 0,
+  .fs_open = 0,
+  .fs_read = grub_zstdio_read,
+  .fs_close = grub_zstdio_close,
+  .fs_label = 0,
+  .next = 0
+};
+
+GRUB_MOD_INIT (zstdio)
+{
+  grub_file_filter_register (GRUB_FILE_FILTER_ZSTDIO, grub_zstdio_open);
+}
+
+GRUB_MOD_FINI (zstdio)
+{
+  grub_file_filter_unregister (GRUB_FILE_FILTER_ZSTDIO);
+}
diff --git a/include/grub/file.h b/include/grub/file.h
index 16a4b7d26437..d51834e6abd2 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -190,9 +190,10 @@ typedef enum grub_file_filter_id
     GRUB_FILE_FILTER_GZIO,
     GRUB_FILE_FILTER_XZIO,
     GRUB_FILE_FILTER_LZOPIO,
+    GRUB_FILE_FILTER_ZSTDIO,
     GRUB_FILE_FILTER_MAX,
     GRUB_FILE_FILTER_COMPRESSION_FIRST = GRUB_FILE_FILTER_GZIO,
-    GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_LZOPIO,
+    GRUB_FILE_FILTER_COMPRESSION_LAST = GRUB_FILE_FILTER_ZSTDIO,
   } grub_file_filter_id_t;
 
 typedef grub_file_t (*grub_file_filter_t) (grub_file_t in, enum grub_file_type type);
-- 
2.47.3


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] io: Implement zstdio decompression
       [not found] <mailman.11310.1760472901.1111.grub-devel@gnu.org>
@ 2025-10-15 10:52 ` Avnish Chouhan
  2025-10-17 23:09   ` Logan Gunthorpe via Grub-devel
  0 siblings, 1 reply; 9+ messages in thread
From: Avnish Chouhan @ 2025-10-15 10:52 UTC (permalink / raw)
  To: logang
  Cc: grub-devel, Daniel Kiper, alexander.burmashev, phcoder,
	nagy.elemer.karoly

On 2025-10-15 01:45, grub-devel-request@gnu.org wrote:
> Message: 1
> Date: Tue, 14 Oct 2025 14:14:18 -0600
> From: Logan Gunthorpe <logang@deltatee.com>
> To: grub-devel@gnu.org, Daniel Kiper <daniel.kiper@oracle.com>, Alex
> 	Burmashev <alexander.burmashev@oracle.com>, Vladimir 'phcoder'
> 	Serbinenko <phcoder@gmail.com>
> Cc: Nagy Elemér Károly  <nagy.elemer.karoly@gmail.com>, Logan
> 	Gunthorpe <logang@deltatee.com>
> Subject: [PATCH 1/4] io: Implement zstdio decompression
> Message-ID: <20251014201421.5279-2-logang@deltatee.com>
> 
> Add zstd based io decompression.
> 
> Based largely on the existing xzio, implement the same features using
> the zstd library already included in the project.
> 
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>

Hi Logan,

Please recheck the indentation in "while" loop. For some reason, some 
places its still looks off!
Thank you!

Regards,
Avnish Chouhan

Reviewed-by: Avnish Chouhan <avnish@linux.ibm.com>

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] io: Implement zstdio decompression
  2025-10-14 20:14 ` [PATCH 1/4] io: Implement zstdio decompression Logan Gunthorpe via Grub-devel
@ 2025-10-15 15:52   ` Daniel Kiper
  2025-10-17 23:23     ` Logan Gunthorpe via Grub-devel
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Kiper @ 2025-10-15 15:52 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: grub-devel, Alex Burmashev, Vladimir 'phcoder' Serbinenko,
	Nagy Elemér Károly

On Tue, Oct 14, 2025 at 02:14:18PM -0600, Logan Gunthorpe via Grub-devel wrote:
> Add zstd based io decompression.
>
> Based largely on the existing xzio, implement the same features using
> the zstd library already included in the project.
>
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---
>  Makefile.util.def           |   1 +
>  grub-core/Makefile.core.def |   7 ++
>  grub-core/io/zstdio.c       | 237 ++++++++++++++++++++++++++++++++++++
>  include/grub/file.h         |   3 +-
>  4 files changed, 247 insertions(+), 1 deletion(-)
>  create mode 100644 grub-core/io/zstdio.c
>
> diff --git a/Makefile.util.def b/Makefile.util.def
> index 038253b37a42..74786177f908 100644
> --- a/Makefile.util.def
> +++ b/Makefile.util.def
> @@ -162,6 +162,7 @@ library = {
>    common = grub-core/io/gzio.c;
>    common = grub-core/io/xzio.c;
>    common = grub-core/io/lzopio.c;
> +  common = grub-core/io/zstdio.c;
>    common = grub-core/kern/ia64/dl_helper.c;
>    common = grub-core/kern/arm/dl_helper.c;
>    common = grub-core/kern/arm64/dl_helper.c;
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index a729cb6a8e61..a2635d61b6e8 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -2512,6 +2512,13 @@ module = {
>    cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
>  };
>
> +module = {
> +  name = zstdio;
> +  common = io/zstdio.c;
> +  cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd';
> +  cflags='-Wno-unreachable-code';
> +};
> +
>  module = {
>    name = testload;
>    common = commands/testload.c;
> diff --git a/grub-core/io/zstdio.c b/grub-core/io/zstdio.c
> new file mode 100644
> index 000000000000..01a5a45587a7
> --- /dev/null
> +++ b/grub-core/io/zstdio.c
> @@ -0,0 +1,237 @@
> +/* zstdio.c - decompression support for zstd */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2010  Free Software Foundation, Inc.

s/2010/2025/

> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <grub/err.h>
> +#include <grub/mm.h>
> +#include <grub/misc.h>
> +#include <grub/file.h>
> +#include <grub/fs.h>
> +#include <grub/dl.h>
> +
> +GRUB_MOD_LICENSE ("GPLv3+");
> +
> +#include "zstd.h"
> +
> +#define STREAM_HEADER_SIZE 16
> +
> +struct grub_zstdio

You do not need grub_ prefix if name is internal to the module.

> +{
> +  grub_file_t file;
> +  ZSTD_DCtx *dctx;
> +  grub_size_t insize;
> +  grub_size_t outsize;
> +
> +  ZSTD_outBuffer output;
> +  ZSTD_inBuffer input;
> +
> +  grub_off_t saved_offset;
> +  grub_uint8_t bufs[];
> +};
> +

Please drop this empty line...

> +typedef struct grub_zstdio *grub_zstdio_t;

... and add one here... :-)

> +static struct grub_fs grub_zstdio_fs;
> +
> +static int

Please use bool, including true/false, instead of int.

> +test_header (grub_file_t file)
> +{
> +  grub_zstdio_t zstdio = file->data;
> +  size_t zret;
> +
> +  zstdio->input.pos = 0;
> +  zstdio->output.pos = 0;
> +  zstdio->output.size = zstdio->outsize;
> +  zstdio->input.size = grub_file_read (zstdio->file, zstdio->bufs,
> +                                       STREAM_HEADER_SIZE);
> +  if (zstdio->input.size != STREAM_HEADER_SIZE)
> +    return 0;
> +
> +  zret = ZSTD_decompressStream (zstdio->dctx, &zstdio->output, &zstdio->input);
> +  if (ZSTD_isError (zret))
> +    return 0;
> +
> +  return 1;
> +}

Missing empty line here...

> +static grub_file_t
> +grub_zstdio_open (grub_file_t io, enum grub_file_type type)
> +{
> +  grub_file_t file;
> +  grub_zstdio_t zstdio;
> +
> +  if (type & GRUB_FILE_TYPE_NO_DECOMPRESS)
> +    return io;
> +
> +  file = (grub_file_t) grub_zalloc (sizeof (grub_file_t));
> +  if (file == NULL)
> +    return 0;

s/0/NULL/

> +  zstdio = grub_zalloc (sizeof (grub_zstdio_t) + ZSTD_DStreamInSize () +
> +                        ZSTD_DStreamOutSize ());
> +  if (zstdio == NULL)
> +    {
> +      grub_free (file);
> +      return 0;

Ditto...

In general please use NULL instead of 0.

> +    }
> +
> +  zstdio->file = io;
> +  zstdio->insize = ZSTD_DStreamInSize ();
> +  zstdio->outsize = ZSTD_DStreamOutSize ();
> +  zstdio->input.src = zstdio->bufs;
> +  zstdio->output.dst = &zstdio->bufs[zstdio->insize];
> +
> +  file->device = io->device;
> +  file->data = zstdio;
> +  file->fs = &grub_zstdio_fs;
> +  file->size = GRUB_FILE_SIZE_UNKNOWN;
> +  file->not_easily_seekable = 1;
> +
> +  if (grub_file_tell (zstdio->file) != 0)
> +    grub_file_seek (zstdio->file, 0);

grub_file_seek() may fail. Please always check for errors.

> +  zstdio->dctx = ZSTD_createDCtx ();
> +  if (zstdio->dctx == NULL)
> +    {
> +      grub_free (file);
> +      grub_free (zstdio);
> +      return 0;

Again, s/0/NULL/...

> +    }
> +
> +  if (!test_header (file))

if (test_header (file) == false)

> +    {
> +      grub_errno = GRUB_ERR_NONE;
> +      grub_file_seek (io, 0);
> +      ZSTD_freeDCtx (zstdio->dctx);
> +      grub_free (zstdio);
> +      grub_free (file);
> +
> +      return io;
> +    }
> +
> +  return file;
> +}
> +
> +static grub_ssize_t
> +grub_zstdio_read (grub_file_t file, char *buf, grub_size_t len)
> +{
> +  grub_zstdio_t zstdio = file->data;
> +  grub_ssize_t ret = 0;
> +  grub_ssize_t readret;
> +  grub_off_t current_offset;
> +  grub_size_t zret;
> +
> +  /* If seek backward need to reset decoder and start from beginning of file. */
> +  if (file->offset < zstdio->saved_offset)
> +    {
> +      ZSTD_initDStream (zstdio->dctx);
> +      zstdio->input.pos = 0;
> +      zstdio->input.size = 0;
> +      zstdio->output.pos = 0;
> +      zstdio->saved_offset = 0;
> +      grub_file_seek (zstdio->file, 0);

grub_file_seek() may fail...

> +    }
> +
> +  current_offset = zstdio->saved_offset;
> +
> +  while (len > 0)
> +    {
> +      zstdio->output.size = file->offset + ret + len - current_offset;

Is there any chance for overflow here? If yes then please use safe math
from include/grub/safemath.h.

> +      if (zstdio->output.size > zstdio->outsize)
> +        zstdio->output.size = zstdio->outsize;
> +      if (zstdio->input.pos == zstdio->input.size)
> +        {
> +	  readret = grub_file_read (zstdio->file, zstdio->bufs,
> +	                            zstdio->insize);
> +	  if (readret < 0)
> +	    return -1;
> +
> +	  zstdio->input.size = readret;
> +	  zstdio->input.pos = 0;
> +	}
> +
> +      zret = ZSTD_decompressStream (zstdio->dctx, &zstdio->output,
> +                                    &zstdio->input);
> +      if (ZSTD_isError (zret))
> +	{
> +	  grub_error (GRUB_ERR_BAD_COMPRESSED_DATA,
> +		      N_("zstd file corrupted or unsupported block options"));
> +	  return -1;
> +        }
> +
> +      grub_off_t new_offset = current_offset + zstdio->output.pos;

Please do not mix variable definitions with the code. Define all stuff
at the beginning of the function or block.

> +      /* Store first chunk of data in buffer.  */
> +      if (file->offset <= new_offset)
> +        {
> +	  grub_size_t delta = new_offset - (file->offset + ret);

OK, but missing empty line here.

> +	  grub_memmove (buf, (grub_uint8_t *) zstdio->output.dst +
> +                        (zstdio->output.pos - delta),

Safe math? In general please check all math in this patch and use safe
math macros where needed.

> +                        delta);
> +	  len -= delta;
> +	  buf += delta;
> +	  ret += delta;
> +	}
> +	current_offset = new_offset;
> +
> +	zstdio->output.pos = 0;
> +
> +	if (zstdio->input.pos == 0 && zstdio->output.pos == 0)
> +	  break;
> +    }
> +
> +  if (ret >= 0)
> +    zstdio->saved_offset = file->offset + ret;
> +
> +  return ret;
> +}

Daniel

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] io: Implement zstdio decompression
  2025-10-15 10:52 ` Avnish Chouhan
@ 2025-10-17 23:09   ` Logan Gunthorpe via Grub-devel
  0 siblings, 0 replies; 9+ messages in thread
From: Logan Gunthorpe via Grub-devel @ 2025-10-17 23:09 UTC (permalink / raw)
  To: Avnish Chouhan
  Cc: Logan Gunthorpe, grub-devel, Daniel Kiper, alexander.burmashev,
	phcoder, nagy.elemer.karoly

Hi Avnish,

On 2025-10-15 04:52, Avnish Chouhan wrote:
> On 2025-10-15 01:45, grub-devel-request@gnu.org wrote:
> Please recheck the indentation in "while" loop. For some reason, some 
> places its still looks off!
> Thank you!

Thanks, for the review.

I'm not sure exactly the issue, but I've filtered the file and removed
all tab characters. Much of this comes from the xzio.c file that I
copied from. But if tab characters are not wanted they are easy for me
to remove.

I'll send a new version next week.

Logan

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] io: Implement zstdio decompression
  2025-10-15 15:52   ` Daniel Kiper
@ 2025-10-17 23:23     ` Logan Gunthorpe via Grub-devel
  2025-10-20 16:16       ` Daniel Kiper
  0 siblings, 1 reply; 9+ messages in thread
From: Logan Gunthorpe via Grub-devel @ 2025-10-17 23:23 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Logan Gunthorpe, grub-devel, Alex Burmashev,
	Vladimir 'phcoder' Serbinenko,
	Nagy Elemér Károly

Hi Daniel,

On 2025-10-15 09:52, Daniel Kiper wrote:
> On Tue, Oct 14, 2025 at 02:14:18PM -0600, Logan Gunthorpe via Grub-devel wrote:
>> +  while (len > 0)
>> +    {
>> +      zstdio->output.size = file->offset + ret + len - current_offset;
> 
> Is there any chance for overflow here? If yes then please use safe math
> from include/grub/safemath.h.

My read is that unless we are dealing with files greater than the two
offsets are 64bits and unlikely to ever see a file that doesn't fit.

len is going to be the size of a memory buffer and ret is going to be
less than or equal to ret. So it doesn't seem like an overflow is possible.

>> +	  grub_size_t delta = new_offset - (file->offset + ret);
>> +	  grub_memmove (buf, (grub_uint8_t *) zstdio->output.dst +
>> +                        (zstdio->output.pos - delta),
> 
> Safe math? In general please check all math in this patch and use safe
> math macros where needed.


output.pos must be less than outsize which is defined by
ZSTD_DStreamOutSize () and will be much less than even a 32bit type.

delta is by definition less than pos.

(new_offset - file->offset) must be less than len.

This code is very similar to code in xzio.c and did not need any safe
math functions.

Please let me know if you disagree, otherwise I'll send a new version
next week.

Thanks,

Logan


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] io: Implement zstdio decompression
  2025-10-17 23:23     ` Logan Gunthorpe via Grub-devel
@ 2025-10-20 16:16       ` Daniel Kiper
  2025-10-20 16:37         ` Logan Gunthorpe via Grub-devel
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Kiper @ 2025-10-20 16:16 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: grub-devel, Alex Burmashev, Vladimir 'phcoder' Serbinenko,
	Nagy Elemér Károly

On Fri, Oct 17, 2025 at 05:23:48PM -0600, Logan Gunthorpe via Grub-devel wrote:
> Hi Daniel,
>
> On 2025-10-15 09:52, Daniel Kiper wrote:
> > On Tue, Oct 14, 2025 at 02:14:18PM -0600, Logan Gunthorpe via Grub-devel wrote:
> >> +  while (len > 0)
> >> +    {
> >> +      zstdio->output.size = file->offset + ret + len - current_offset;
> >
> > Is there any chance for overflow here? If yes then please use safe math
> > from include/grub/safemath.h.
>
> My read is that unless we are dealing with files greater than the two
> offsets are 64bits and unlikely to ever see a file that doesn't fit.

First of all, please remember that the GRUB can be compiled for 32-bit
targets. So, zstdio->output.size can be 32-bit...

> len is going to be the size of a memory buffer and ret is going to be
> less than or equal to ret. So it doesn't seem like an overflow is possible.

I think you meant "less than or equal to len"...

> >> +	  grub_size_t delta = new_offset - (file->offset + ret);
> >> +	  grub_memmove (buf, (grub_uint8_t *) zstdio->output.dst +
> >> +                        (zstdio->output.pos - delta),
> >
> > Safe math? In general please check all math in this patch and use safe
> > math macros where needed.
>
> output.pos must be less than outsize which is defined by
> ZSTD_DStreamOutSize () and will be much less than even a 32bit type.
>
> delta is by definition less than pos.
>
> (new_offset - file->offset) must be less than len.
>
> This code is very similar to code in xzio.c and did not need any safe
> math functions.

IIRC it predates safe math and it may not be (fully) correct..

> Please let me know if you disagree, otherwise I'll send a new version
> next week.

I am not saying I disagree. I rather have some reservations. However, if
you convince me it is not possible or it is very difficult to blow up
this code using malformed zstd archives than I am OK with it.

Daniel

PS I am going to cut GRUB 2.14~rc1 in second half of the week. So, it
   would be nice to have these patches before that...

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] io: Implement zstdio decompression
  2025-10-20 16:16       ` Daniel Kiper
@ 2025-10-20 16:37         ` Logan Gunthorpe via Grub-devel
  0 siblings, 0 replies; 9+ messages in thread
From: Logan Gunthorpe via Grub-devel @ 2025-10-20 16:37 UTC (permalink / raw)
  To: Daniel Kiper
  Cc: Logan Gunthorpe, grub-devel, Alex Burmashev,
	Vladimir 'phcoder' Serbinenko,
	Nagy Elemér Károly



On 2025-10-20 10:16, Daniel Kiper wrote:
> On Fri, Oct 17, 2025 at 05:23:48PM -0600, Logan Gunthorpe via Grub-devel wrote:
>> My read is that unless we are dealing with files greater than the two
>> offsets are 64bits and unlikely to ever see a file that doesn't fit.
> 
> First of all, please remember that the GRUB can be compiled for 32-bit
> targets. So, zstdio->output.size can be 32-bit...

Yes, but zstdio->output.size is always less than the relatively small
buffer size returned by ZSTD_DStreamOutSize ().

The only values that could conceivably be larger than 32-bits are the
offsets within the file which are of type grup_off_t, which is a typedef
of grub_uint64_t and, by my read of the code, it looks like it should be
64-bits on all platforms.

>> len is going to be the size of a memory buffer and ret is going to be
>> less than or equal to ret. So it doesn't seem like an overflow is possible.
> 
> I think you meant "less than or equal to len"...

Yes, sorry.

> I am not saying I disagree. I rather have some reservations. However, if
> you convince me it is not possible or it is very difficult to blow up
> this code using malformed zstd archives than I am OK with it.

I'm just worried the change is a bit tricky to get right needing to
convert it to a string of grub_add() calls. And the conversion seems
risky especially given the existing code it was copied from has been
around for a while without issue (as far as I'm aware).


> PS I am going to cut GRUB 2.14~rc1 in second half of the week. So, it
>    would be nice to have these patches before that...
Ok, well except for this issue I should be good to send the next version
today or, at worst tomorrow.

Thanks,

Logan

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-10-20 16:37 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <mailman.23.1758658751.1187.grub-devel@gnu.org>
2025-10-09  6:26 ` [PATCH 1/4] io: Implement zstdio decompression Avnish Chouhan
     [not found] <mailman.11310.1760472901.1111.grub-devel@gnu.org>
2025-10-15 10:52 ` Avnish Chouhan
2025-10-17 23:09   ` Logan Gunthorpe via Grub-devel
2025-10-14 20:14 [PATCH 0/4] Add zstdio support for booting Trixie kernels in Xen Logan Gunthorpe via Grub-devel
2025-10-14 20:14 ` [PATCH 1/4] io: Implement zstdio decompression Logan Gunthorpe via Grub-devel
2025-10-15 15:52   ` Daniel Kiper
2025-10-17 23:23     ` Logan Gunthorpe via Grub-devel
2025-10-20 16:16       ` Daniel Kiper
2025-10-20 16:37         ` Logan Gunthorpe via Grub-devel
  -- strict thread matches above, loose matches on Subject: below --
2025-09-23 20:12 [PATCH 0/4] Add zstdio support for booting Trixie kernels in Xen Logan Gunthorpe via Grub-devel
2025-09-23 20:12 ` [PATCH 1/4] io: Implement zstdio decompression Logan Gunthorpe via Grub-devel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).