forked from pool/grub2
Accepting request 1037548 from home:michael-chang:branches:Base:System
- Make full utilization of btrfs bootloader area (bsc#1161823) * 0001-fs-btrfs-Use-full-btrfs-bootloader-area.patch * 0002-Mark-environmet-blocks-as-used-for-image-embedding.patch - Patch removed * 0001-i386-pc-build-btrfs-zstd-support-into-separate-modul.patch OBS-URL: https://build.opensuse.org/request/show/1037548 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=428
This commit is contained in:
parent
2edffea20f
commit
46c0e0c8b7
162
0001-fs-btrfs-Use-full-btrfs-bootloader-area.patch
Normal file
162
0001-fs-btrfs-Use-full-btrfs-bootloader-area.patch
Normal file
@ -0,0 +1,162 @@
|
||||
From b78aca6e1c4f72a6491457e849b76c8e0af77765 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Mon, 13 Dec 2021 14:25:49 +0800
|
||||
Subject: [PATCH 1/2] fs/btrfs: Use full btrfs bootloader area
|
||||
|
||||
Up to now GRUB can only embed to the first 64 KiB before primary
|
||||
superblock of btrfs, effectively limiting the GRUB core size. That
|
||||
could consequently pose restrictions to feature enablement like
|
||||
advanced zstd compression.
|
||||
|
||||
This patch attempts to utilize full unused area reserved by btrfs for
|
||||
the bootloader outlined in the document [1]:
|
||||
|
||||
The first 1MiB on each device is unused with the exception of primary
|
||||
superblock that is on the offset 64KiB and spans 4KiB.
|
||||
|
||||
Apart from that, adjacent sectors to superblock and first block group
|
||||
are not used for embedding in case of overflow and logged access to
|
||||
adjacent sectors could be useful for tracing it up.
|
||||
|
||||
This patch has been tested to provide out of the box support for btrfs
|
||||
zstd compression with which GRUB has been installed to the partition.
|
||||
|
||||
[1] https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/btrfs.c | 90 +++++++++++++++++++++++++++++++++++++-------
|
||||
include/grub/disk.h | 2 +
|
||||
2 files changed, 79 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 7007463c6..979ba1b28 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -2537,6 +2537,33 @@ grub_btrfs_label (grub_device_t device, char **label)
|
||||
}
|
||||
|
||||
#ifdef GRUB_UTIL
|
||||
+
|
||||
+struct embed_region {
|
||||
+ unsigned int start;
|
||||
+ unsigned int secs;
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs(5)#BOOTLOADER_SUPPORT
|
||||
+ * The first 1 MiB on each device is unused with the exception of primary
|
||||
+ * superblock that is on the offset 64 KiB and spans 4 KiB.
|
||||
+ */
|
||||
+
|
||||
+static const struct {
|
||||
+ struct embed_region available;
|
||||
+ struct embed_region used[6];
|
||||
+} btrfs_head = {
|
||||
+ .available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */
|
||||
+ .used = {
|
||||
+ {0, 1}, /* boot.S. */
|
||||
+ {GRUB_DISK_KiB_TO_SECTORS (64) - 1, 1}, /* Overflow guard. */
|
||||
+ {GRUB_DISK_KiB_TO_SECTORS (64), GRUB_DISK_KiB_TO_SECTORS (4)}, /* 4 KiB superblock. */
|
||||
+ {GRUB_DISK_KiB_TO_SECTORS (68), 1}, /* Overflow guard. */
|
||||
+ {GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */
|
||||
+ {0, 0} /* Array terminator. */
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
static grub_err_t
|
||||
grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
|
||||
unsigned int *nsectors,
|
||||
@@ -2544,25 +2571,62 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)),
|
||||
grub_embed_type_t embed_type,
|
||||
grub_disk_addr_t **sectors)
|
||||
{
|
||||
- unsigned i;
|
||||
+ unsigned int i, j, n = 0;
|
||||
+ const struct embed_region *u;
|
||||
+ grub_disk_addr_t *map;
|
||||
|
||||
if (embed_type != GRUB_EMBED_PCBIOS)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||
"BtrFS currently supports only PC-BIOS embedding");
|
||||
|
||||
- if (64 * 2 - 1 < *nsectors)
|
||||
- return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
- N_("your core.img is unusually large. "
|
||||
- "It won't fit in the embedding area"));
|
||||
-
|
||||
- *nsectors = 64 * 2 - 1;
|
||||
- if (*nsectors > max_nsectors)
|
||||
- *nsectors = max_nsectors;
|
||||
- *sectors = grub_calloc (*nsectors, sizeof (**sectors));
|
||||
- if (!*sectors)
|
||||
+ map = grub_calloc (btrfs_head.available.secs, sizeof (*map));
|
||||
+ if (map == NULL)
|
||||
return grub_errno;
|
||||
- for (i = 0; i < *nsectors; i++)
|
||||
- (*sectors)[i] = i + 1;
|
||||
+
|
||||
+ /*
|
||||
+ * Populating the map array so that it can be used to index if a disk
|
||||
+ * address is available to embed:
|
||||
+ * - 0: available,
|
||||
+ * - 1: unavailable.
|
||||
+ */
|
||||
+ for (u = btrfs_head.used; u->secs; ++u)
|
||||
+ {
|
||||
+ unsigned int end = u->start + u->secs;
|
||||
+
|
||||
+ if (end > btrfs_head.available.secs)
|
||||
+ end = btrfs_head.available.secs;
|
||||
+ for (i = u->start; i < end; ++i)
|
||||
+ map[i] = 1;
|
||||
+ }
|
||||
+
|
||||
+ /* Adding up n until it matches total size of available embedding area. */
|
||||
+ for (i = 0; i < btrfs_head.available.secs; ++i)
|
||||
+ if (map[i] == 0)
|
||||
+ n++;
|
||||
+
|
||||
+ if (n < *nsectors)
|
||||
+ {
|
||||
+ grub_free (map);
|
||||
+ return grub_error (GRUB_ERR_OUT_OF_RANGE,
|
||||
+ N_("your core.img is unusually large. "
|
||||
+ "It won't fit in the embedding area"));
|
||||
+ }
|
||||
+
|
||||
+ if (n > max_nsectors)
|
||||
+ n = max_nsectors;
|
||||
+
|
||||
+ /*
|
||||
+ * Populating the array so that it can used to index disk block address for
|
||||
+ * an image file's offset to be embedded on disk (the unit is in sectors):
|
||||
+ * - i: The disk block address relative to btrfs_head.available.start,
|
||||
+ * - j: The offset in image file.
|
||||
+ */
|
||||
+ for (i = 0, j = 0; i < btrfs_head.available.secs && j < n; ++i)
|
||||
+ if (map[i] == 0)
|
||||
+ map[j++] = btrfs_head.available.start + i;
|
||||
+
|
||||
+ *nsectors = n;
|
||||
+ *sectors = map;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
diff --git a/include/grub/disk.h b/include/grub/disk.h
|
||||
index 6d656c431..a10fa3bc7 100644
|
||||
--- a/include/grub/disk.h
|
||||
+++ b/include/grub/disk.h
|
||||
@@ -182,6 +182,8 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t;
|
||||
/* Return value of grub_disk_native_sectors() in case disk size is unknown. */
|
||||
#define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL
|
||||
|
||||
+#define GRUB_DISK_KiB_TO_SECTORS(x) ((x) << (10 - GRUB_DISK_SECTOR_BITS))
|
||||
+
|
||||
/* Convert sector number from one sector size to another. */
|
||||
static inline grub_disk_addr_t
|
||||
grub_convert_sector (grub_disk_addr_t sector,
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,550 +0,0 @@
|
||||
From e7fe15db1736e038a7705973424708d3151fde99 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Thu, 12 Aug 2021 21:43:22 +0800
|
||||
Subject: [PATCH] i386-pc: build btrfs zstd support into separate module
|
||||
|
||||
The zstd support in btrfs brings significant size increment to the
|
||||
on-disk image that it can no longer fit into btrfs bootloader area and
|
||||
short mbr gap.
|
||||
|
||||
In order to support grub update on outstanding i386-pc setup with these
|
||||
size constraints remain in place, here we build the zstd suppprt of
|
||||
btrfs into a separate module, named btrfs_zstd, to alleviate the size
|
||||
change. Please note this only makes it's way to i386-pc, other
|
||||
architecture is not affected.
|
||||
|
||||
Therefore if the system has enough space of embedding area for grub then
|
||||
zstd support for btrfs will be enabled automatically in the process of
|
||||
running grub-install through inserting btrfs_zstd module to the on-disk
|
||||
image, otherwise a warning will be logged on screen to indicate user
|
||||
that zstd support for btrfs is disabled due to the size limit.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
---
|
||||
Makefile.util.def | 1 +
|
||||
grub-core/Makefile.core.def | 11 ++++
|
||||
grub-core/fs/btrfs.c | 114 +++++---------------------------
|
||||
grub-core/fs/btrfs_zstd.c | 36 +++++++++++
|
||||
grub-core/lib/zstd.c | 126 ++++++++++++++++++++++++++++++++++++
|
||||
include/grub/btrfs.h | 6 ++
|
||||
include/grub/lib/zstd.h | 26 ++++++++
|
||||
include/grub/util/install.h | 2 +
|
||||
util/grub-install.c | 20 ++++++
|
||||
util/setup.c | 43 ++++++++++++
|
||||
10 files changed, 288 insertions(+), 97 deletions(-)
|
||||
create mode 100644 grub-core/fs/btrfs_zstd.c
|
||||
create mode 100644 grub-core/lib/zstd.c
|
||||
create mode 100644 include/grub/lib/zstd.h
|
||||
|
||||
diff --git a/Makefile.util.def b/Makefile.util.def
|
||||
index 2f2881cb7..ac2b6aab1 100644
|
||||
--- a/Makefile.util.def
|
||||
+++ b/Makefile.util.def
|
||||
@@ -176,6 +176,7 @@ library = {
|
||||
common = grub-core/lib/zstd/xxhash.c;
|
||||
common = grub-core/lib/zstd/zstd_common.c;
|
||||
common = grub-core/lib/zstd/zstd_decompress.c;
|
||||
+ common = grub-core/lib/zstd.c;
|
||||
};
|
||||
|
||||
program = {
|
||||
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||||
index dd1777bd3..b5328d7a0 100644
|
||||
--- a/grub-core/Makefile.core.def
|
||||
+++ b/grub-core/Makefile.core.def
|
||||
@@ -1370,10 +1370,21 @@ module = {
|
||||
name = btrfs;
|
||||
common = fs/btrfs.c;
|
||||
common = lib/crc.c;
|
||||
+ nopc = lib/zstd.c;
|
||||
cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||
+ i386_pc_cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H';
|
||||
cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -I$(srcdir)/lib/zstd -DMINILZO_HAVE_CONFIG_H';
|
||||
};
|
||||
|
||||
+module = {
|
||||
+ name = btrfs_zstd;
|
||||
+ common = fs/btrfs_zstd.c;
|
||||
+ common = lib/zstd.c;
|
||||
+ cflags = '$(CFLAGS_POSIX) -Wno-undef';
|
||||
+ cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/zstd';
|
||||
+ enable = i386_pc;
|
||||
+};
|
||||
+
|
||||
module = {
|
||||
name = archelp;
|
||||
common = fs/archelp.c;
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index c908b460f..9625bdf16 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -17,14 +17,6 @@
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
-/*
|
||||
- * Tell zstd to expose functions that aren't part of the stable API, which
|
||||
- * aren't safe to use when linking against a dynamic library. We vendor in a
|
||||
- * specific zstd version, so we know what we're getting. We need these unstable
|
||||
- * functions to provide our own allocator, which uses grub_malloc(), to zstd.
|
||||
- */
|
||||
-#define ZSTD_STATIC_LINKING_ONLY
|
||||
-
|
||||
#include <grub/err.h>
|
||||
#include <grub/file.h>
|
||||
#include <grub/mm.h>
|
||||
@@ -35,7 +27,9 @@
|
||||
#include <grub/lib/crc.h>
|
||||
#include <grub/deflate.h>
|
||||
#include <minilzo.h>
|
||||
-#include <zstd.h>
|
||||
+#ifndef GRUB_MACHINE_PCBIOS
|
||||
+#include <grub/lib/zstd.h>
|
||||
+#endif
|
||||
#include <grub/i18n.h>
|
||||
#include <grub/btrfs.h>
|
||||
#include <grub/crypto.h>
|
||||
@@ -61,12 +55,15 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
#define GRUB_BTRFS_LZO_BLOCK_MAX_CSIZE (GRUB_BTRFS_LZO_BLOCK_SIZE + \
|
||||
(GRUB_BTRFS_LZO_BLOCK_SIZE / 16) + 64 + 3)
|
||||
|
||||
-#define ZSTD_BTRFS_MAX_WINDOWLOG 17
|
||||
-#define ZSTD_BTRFS_MAX_INPUT (1 << ZSTD_BTRFS_MAX_WINDOWLOG)
|
||||
-
|
||||
typedef grub_uint8_t grub_btrfs_checksum_t[0x20];
|
||||
typedef grub_uint16_t grub_btrfs_uuid_t[8];
|
||||
|
||||
+#ifdef GRUB_MACHINE_PCBIOS
|
||||
+grub_ssize_t (*grub_btrfs_zstd_decompress_func) (char *ibuf,
|
||||
+ grub_size_t isize, grub_off_t off,
|
||||
+ char *obuf, grub_size_t osize) = NULL;
|
||||
+#endif
|
||||
+
|
||||
struct grub_btrfs_device
|
||||
{
|
||||
grub_uint64_t device_id;
|
||||
@@ -1392,94 +1389,17 @@ grub_btrfs_read_inode (struct grub_btrfs_data *data,
|
||||
return grub_btrfs_read_logical (data, elemaddr, inode, sizeof (*inode), 0);
|
||||
}
|
||||
|
||||
-static void *grub_zstd_malloc (void *state __attribute__((unused)), size_t size)
|
||||
-{
|
||||
- return grub_malloc (size);
|
||||
-}
|
||||
-
|
||||
-static void grub_zstd_free (void *state __attribute__((unused)), void *address)
|
||||
-{
|
||||
- return grub_free (address);
|
||||
-}
|
||||
-
|
||||
-static ZSTD_customMem grub_zstd_allocator (void)
|
||||
-{
|
||||
- ZSTD_customMem allocator;
|
||||
-
|
||||
- allocator.customAlloc = &grub_zstd_malloc;
|
||||
- allocator.customFree = &grub_zstd_free;
|
||||
- allocator.opaque = NULL;
|
||||
-
|
||||
- return allocator;
|
||||
-}
|
||||
-
|
||||
-static grub_ssize_t
|
||||
+static inline grub_ssize_t
|
||||
grub_btrfs_zstd_decompress (char *ibuf, grub_size_t isize, grub_off_t off,
|
||||
char *obuf, grub_size_t osize)
|
||||
{
|
||||
- void *allocated = NULL;
|
||||
- char *otmpbuf = obuf;
|
||||
- grub_size_t otmpsize = osize;
|
||||
- ZSTD_DCtx *dctx = NULL;
|
||||
- grub_size_t zstd_ret;
|
||||
- grub_ssize_t ret = -1;
|
||||
-
|
||||
- /*
|
||||
- * Zstd will fail if it can't fit the entire output in the destination
|
||||
- * buffer, so if osize isn't large enough, allocate a temporary buffer.
|
||||
- */
|
||||
- if (otmpsize < ZSTD_BTRFS_MAX_INPUT)
|
||||
- {
|
||||
- allocated = grub_malloc (ZSTD_BTRFS_MAX_INPUT);
|
||||
- if (!allocated)
|
||||
- {
|
||||
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed allocate a zstd buffer");
|
||||
- goto err;
|
||||
- }
|
||||
- otmpbuf = (char *) allocated;
|
||||
- otmpsize = ZSTD_BTRFS_MAX_INPUT;
|
||||
- }
|
||||
-
|
||||
- /* Create the ZSTD_DCtx. */
|
||||
- dctx = ZSTD_createDCtx_advanced (grub_zstd_allocator ());
|
||||
- if (!dctx)
|
||||
- {
|
||||
- /* ZSTD_createDCtx_advanced() only fails if it is out of memory. */
|
||||
- grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to create a zstd context");
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Get the real input size, there may be junk at the
|
||||
- * end of the frame.
|
||||
- */
|
||||
- isize = ZSTD_findFrameCompressedSize (ibuf, isize);
|
||||
- if (ZSTD_isError (isize))
|
||||
- {
|
||||
- grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "zstd data corrupted");
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- /* Decompress and check for errors. */
|
||||
- zstd_ret = ZSTD_decompressDCtx (dctx, otmpbuf, otmpsize, ibuf, isize);
|
||||
- if (ZSTD_isError (zstd_ret))
|
||||
- {
|
||||
- grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "zstd data corrupted");
|
||||
- goto err;
|
||||
- }
|
||||
-
|
||||
- /*
|
||||
- * Move the requested data into the obuf. obuf may be equal
|
||||
- * to otmpbuf, which is why grub_memmove() is required.
|
||||
- */
|
||||
- grub_memmove (obuf, otmpbuf + off, osize);
|
||||
- ret = osize;
|
||||
-
|
||||
-err:
|
||||
- grub_free (allocated);
|
||||
- ZSTD_freeDCtx (dctx);
|
||||
-
|
||||
- return ret;
|
||||
+#ifdef GRUB_MACHINE_PCBIOS
|
||||
+ if (!grub_btrfs_zstd_decompress_func)
|
||||
+ return -1;
|
||||
+ return grub_btrfs_zstd_decompress_func (ibuf, isize, off, obuf, osize);
|
||||
+#else
|
||||
+ return grub_zstd_decompress (ibuf, isize, off, obuf, osize);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static grub_ssize_t
|
||||
diff --git a/grub-core/fs/btrfs_zstd.c b/grub-core/fs/btrfs_zstd.c
|
||||
new file mode 100644
|
||||
index 000000000..d5d1e013c
|
||||
--- /dev/null
|
||||
+++ b/grub-core/fs/btrfs_zstd.c
|
||||
@@ -0,0 +1,36 @@
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2008 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/types.h>
|
||||
+#include <grub/dl.h>
|
||||
+/* For NULL. */
|
||||
+#include <grub/mm.h>
|
||||
+#include <grub/btrfs.h>
|
||||
+#include <grub/lib/zstd.h>
|
||||
+
|
||||
+GRUB_MOD_LICENSE ("GPLv3+");
|
||||
+
|
||||
+GRUB_MOD_INIT (btrfs_zstd)
|
||||
+{
|
||||
+ grub_btrfs_zstd_decompress_func = grub_zstd_decompress;
|
||||
+}
|
||||
+
|
||||
+GRUB_MOD_FINI (btrfs_zstd)
|
||||
+{
|
||||
+ grub_btrfs_zstd_decompress_func = NULL;
|
||||
+}
|
||||
diff --git a/grub-core/lib/zstd.c b/grub-core/lib/zstd.c
|
||||
new file mode 100644
|
||||
index 000000000..643e90d84
|
||||
--- /dev/null
|
||||
+++ b/grub-core/lib/zstd.c
|
||||
@@ -0,0 +1,126 @@
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2008 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/>.
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Tell zstd to expose functions that aren't part of the stable API, which
|
||||
+ * aren't safe to use when linking against a dynamic library. We vendor in a
|
||||
+ * specific zstd version, so we know what we're getting. We need these unstable
|
||||
+ * functions to provide our own allocator, which uses grub_malloc(), to zstd.
|
||||
+ */
|
||||
+#define ZSTD_STATIC_LINKING_ONLY
|
||||
+
|
||||
+#include <grub/types.h>
|
||||
+#include <grub/misc.h>
|
||||
+#include <grub/err.h>
|
||||
+#include <grub/mm.h>
|
||||
+#include <grub/lib/zstd.h>
|
||||
+#include <zstd.h>
|
||||
+
|
||||
+#define ZSTD_MAX_WINDOWLOG 17
|
||||
+#define ZSTD_MAX_INPUT (1 << ZSTD_MAX_WINDOWLOG)
|
||||
+
|
||||
+static void *grub_zstd_malloc (void *state __attribute__((unused)), size_t size)
|
||||
+{
|
||||
+ return grub_malloc (size);
|
||||
+}
|
||||
+
|
||||
+static void grub_zstd_free (void *state __attribute__((unused)), void *address)
|
||||
+{
|
||||
+ return grub_free (address);
|
||||
+}
|
||||
+
|
||||
+static ZSTD_customMem grub_zstd_allocator (void)
|
||||
+{
|
||||
+ ZSTD_customMem allocator;
|
||||
+
|
||||
+ allocator.customAlloc = &grub_zstd_malloc;
|
||||
+ allocator.customFree = &grub_zstd_free;
|
||||
+ allocator.opaque = NULL;
|
||||
+
|
||||
+ return allocator;
|
||||
+}
|
||||
+
|
||||
+grub_ssize_t
|
||||
+grub_zstd_decompress (char *ibuf, grub_size_t isize, grub_off_t off,
|
||||
+ char *obuf, grub_size_t osize)
|
||||
+{
|
||||
+ void *allocated = NULL;
|
||||
+ char *otmpbuf = obuf;
|
||||
+ grub_size_t otmpsize = osize;
|
||||
+ ZSTD_DCtx *dctx = NULL;
|
||||
+ grub_size_t zstd_ret;
|
||||
+ grub_ssize_t ret = -1;
|
||||
+
|
||||
+ /*
|
||||
+ * Zstd will fail if it can't fit the entire output in the destination
|
||||
+ * buffer, so if osize isn't large enough, allocate a temporary buffer.
|
||||
+ */
|
||||
+ if (otmpsize < ZSTD_MAX_INPUT)
|
||||
+ {
|
||||
+ allocated = grub_malloc (ZSTD_MAX_INPUT);
|
||||
+ if (!allocated)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed allocate a zstd buffer");
|
||||
+ goto err;
|
||||
+ }
|
||||
+ otmpbuf = (char *) allocated;
|
||||
+ otmpsize = ZSTD_MAX_INPUT;
|
||||
+ }
|
||||
+
|
||||
+ /* Create the ZSTD_DCtx. */
|
||||
+ dctx = ZSTD_createDCtx_advanced (grub_zstd_allocator ());
|
||||
+ if (!dctx)
|
||||
+ {
|
||||
+ /* ZSTD_createDCtx_advanced() only fails if it is out of memory. */
|
||||
+ grub_error (GRUB_ERR_OUT_OF_MEMORY, "failed to create a zstd context");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Get the real input size, there may be junk at the
|
||||
+ * end of the frame.
|
||||
+ */
|
||||
+ isize = ZSTD_findFrameCompressedSize (ibuf, isize);
|
||||
+ if (ZSTD_isError (isize))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "zstd data corrupted");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /* Decompress and check for errors. */
|
||||
+ zstd_ret = ZSTD_decompressDCtx (dctx, otmpbuf, otmpsize, ibuf, isize);
|
||||
+ if (ZSTD_isError (zstd_ret))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "zstd data corrupted");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Move the requested data into the obuf. obuf may be equal
|
||||
+ * to otmpbuf, which is why grub_memmove() is required.
|
||||
+ */
|
||||
+ grub_memmove (obuf, otmpbuf + off, osize);
|
||||
+ ret = osize;
|
||||
+
|
||||
+err:
|
||||
+ grub_free (allocated);
|
||||
+ ZSTD_freeDCtx (dctx);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
diff --git a/include/grub/btrfs.h b/include/grub/btrfs.h
|
||||
index 234ad9767..f8e551982 100644
|
||||
--- a/include/grub/btrfs.h
|
||||
+++ b/include/grub/btrfs.h
|
||||
@@ -69,4 +69,10 @@ struct grub_btrfs_inode_ref
|
||||
char name[0];
|
||||
};
|
||||
|
||||
+#ifdef GRUB_MACHINE_PCBIOS
|
||||
+extern grub_ssize_t (*EXPORT_VAR (grub_btrfs_zstd_decompress_func)) (char *ibuf,
|
||||
+ grub_size_t isize, grub_off_t off,
|
||||
+ char *obuf, grub_size_t osize);
|
||||
+#endif
|
||||
+
|
||||
#endif
|
||||
diff --git a/include/grub/lib/zstd.h b/include/grub/lib/zstd.h
|
||||
new file mode 100644
|
||||
index 000000000..0867b0c34
|
||||
--- /dev/null
|
||||
+++ b/include/grub/lib/zstd.h
|
||||
@@ -0,0 +1,26 @@
|
||||
+/*
|
||||
+ * GRUB -- GRand Unified Bootloader
|
||||
+ * Copyright (C) 2008 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/>.
|
||||
+ */
|
||||
+
|
||||
+#ifndef GRUB_ZSTD_HEADER
|
||||
+#define GRUB_ZSTD_HEADER 1
|
||||
+
|
||||
+grub_ssize_t
|
||||
+grub_zstd_decompress (char *ibuf, grub_size_t isize, grub_off_t off,
|
||||
+ char *obuf, grub_size_t osize);
|
||||
+
|
||||
+#endif /* ! GRUB_ZSTD_HEADER */
|
||||
diff --git a/include/grub/util/install.h b/include/grub/util/install.h
|
||||
index faf9ff1ab..9e83e1339 100644
|
||||
--- a/include/grub/util/install.h
|
||||
+++ b/include/grub/util/install.h
|
||||
@@ -208,6 +208,8 @@ grub_util_sparc_setup (const char *dir,
|
||||
const char *dest, int force,
|
||||
int fs_probe, int allow_floppy,
|
||||
int add_rs_codes, int warn_short_mbr_gap);
|
||||
+int
|
||||
+grub_util_try_partmap_embed (const char *dest, unsigned int *nsec);
|
||||
|
||||
char *
|
||||
grub_install_get_image_targets_string (void);
|
||||
diff --git a/util/grub-install.c b/util/grub-install.c
|
||||
index 891e3ced8..a2286b3dd 100644
|
||||
--- a/util/grub-install.c
|
||||
+++ b/util/grub-install.c
|
||||
@@ -1482,6 +1482,26 @@ main (int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
+ if (install_drive
|
||||
+ && platform == GRUB_INSTALL_PLATFORM_I386_PC
|
||||
+ && grub_strcmp (grub_fs->name, "btrfs") == 0)
|
||||
+ {
|
||||
+ char *mod;
|
||||
+ mod = grub_util_path_concat (2, grub_install_source_directory, "btrfs_zstd.mod");
|
||||
+ if (grub_util_is_regular (mod))
|
||||
+ {
|
||||
+ unsigned int nsec = GRUB_MIN_RECOMMENDED_MBR_GAP;
|
||||
+ int ret = grub_util_try_partmap_embed (install_drive, &nsec);
|
||||
+ if (ret == 0)
|
||||
+ grub_install_push_module ("btrfs_zstd");
|
||||
+ else if (ret == 1)
|
||||
+ grub_util_warn ("%s", _("btrfs zstd compression is disabled, please change install device to disk"));
|
||||
+ else
|
||||
+ grub_util_warn ("%s", _("btrfs zstd compression is disabled due to not enough space to embed image"));
|
||||
+ }
|
||||
+ grub_free (mod);
|
||||
+ }
|
||||
+
|
||||
if (!have_abstractions)
|
||||
{
|
||||
if ((disk_module && grub_strcmp (disk_module, "biosdisk") != 0)
|
||||
diff --git a/util/setup.c b/util/setup.c
|
||||
index 980e74374..6604d86bb 100644
|
||||
--- a/util/setup.c
|
||||
+++ b/util/setup.c
|
||||
@@ -241,6 +241,49 @@ identify_partmap (grub_disk_t disk __attribute__ ((unused)),
|
||||
return 1;
|
||||
}
|
||||
|
||||
+#ifdef GRUB_SETUP_BIOS
|
||||
+int
|
||||
+grub_util_try_partmap_embed (const char *dest, unsigned int *nsec)
|
||||
+{
|
||||
+ grub_device_t dest_dev;
|
||||
+
|
||||
+ dest_dev = grub_device_open (dest);
|
||||
+ if (! dest_dev)
|
||||
+ grub_util_error ("%s", grub_errmsg);
|
||||
+
|
||||
+ struct identify_partmap_ctx ctx = {
|
||||
+ .dest_partmap = NULL,
|
||||
+ .container = dest_dev->disk->partition,
|
||||
+ .multiple_partmaps = 0
|
||||
+ };
|
||||
+
|
||||
+ grub_partition_iterate (dest_dev->disk, identify_partmap, &ctx);
|
||||
+
|
||||
+ if (ctx.dest_partmap && ctx.dest_partmap->embed)
|
||||
+ {
|
||||
+ grub_err_t err;
|
||||
+
|
||||
+ grub_disk_addr_t *sectors = NULL;
|
||||
+
|
||||
+ err = ctx.dest_partmap->embed (dest_dev->disk, nsec, *nsec,
|
||||
+ GRUB_EMBED_PCBIOS, §ors, 0);
|
||||
+ if (err)
|
||||
+ {
|
||||
+ grub_errno = GRUB_ERR_NONE;
|
||||
+ goto no_embed;
|
||||
+ }
|
||||
+ grub_free (sectors);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+no_embed:
|
||||
+ grub_device_close (dest_dev);
|
||||
+ if (ctx.container)
|
||||
+ return 1;
|
||||
+ return 2;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
#ifdef GRUB_SETUP_BIOS
|
||||
#define SETUP grub_util_bios_setup
|
||||
#elif GRUB_SETUP_SPARC64
|
||||
--
|
||||
2.31.1
|
||||
|
@ -0,0 +1,66 @@
|
||||
From f01314a822dbe9ad39b2f7d0f3717ef6e4c24f4a Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Fri, 15 Apr 2022 21:45:04 +0800
|
||||
Subject: [PATCH 2/2] Mark environmet blocks as used for image embedding.
|
||||
|
||||
Now that grub will attempt to use full btrfs bootloader area, the
|
||||
embedded image could have overlapped with environment blocks if it's
|
||||
size grows too much. Let's define a dedicated area for environment
|
||||
blocks to the used block mappings for the embedding process so it can be
|
||||
skipped.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
---
|
||||
grub-core/fs/btrfs.c | 3 ++-
|
||||
include/grub/fs.h | 2 ++
|
||||
util/grub-editenv.c | 2 +-
|
||||
3 files changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 979ba1b28..7017248d1 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -2551,7 +2551,7 @@ struct embed_region {
|
||||
|
||||
static const struct {
|
||||
struct embed_region available;
|
||||
- struct embed_region used[6];
|
||||
+ struct embed_region used[7];
|
||||
} btrfs_head = {
|
||||
.available = {0, GRUB_DISK_KiB_TO_SECTORS (1024)}, /* The first 1 MiB. */
|
||||
.used = {
|
||||
@@ -2559,6 +2559,7 @@ static const struct {
|
||||
{GRUB_DISK_KiB_TO_SECTORS (64) - 1, 1}, /* Overflow guard. */
|
||||
{GRUB_DISK_KiB_TO_SECTORS (64), GRUB_DISK_KiB_TO_SECTORS (4)}, /* 4 KiB superblock. */
|
||||
{GRUB_DISK_KiB_TO_SECTORS (68), 1}, /* Overflow guard. */
|
||||
+ {GRUB_DISK_KiB_TO_SECTORS (ENV_BTRFS_OFFSET) - 1, 3}, /* Environment Block. */
|
||||
{GRUB_DISK_KiB_TO_SECTORS (1024) - 1, 1}, /* Overflow guard. */
|
||||
{0, 0} /* Array terminator. */
|
||||
}
|
||||
diff --git a/include/grub/fs.h b/include/grub/fs.h
|
||||
index 026bc3bb8..4c380e334 100644
|
||||
--- a/include/grub/fs.h
|
||||
+++ b/include/grub/fs.h
|
||||
@@ -128,4 +128,6 @@ grub_fs_unregister (grub_fs_t fs)
|
||||
|
||||
grub_fs_t EXPORT_FUNC(grub_fs_probe) (grub_device_t device);
|
||||
|
||||
+#define ENV_BTRFS_OFFSET (256)
|
||||
+
|
||||
#endif /* ! GRUB_FS_HEADER */
|
||||
diff --git a/util/grub-editenv.c b/util/grub-editenv.c
|
||||
index a02d3f2a6..af30aabe7 100644
|
||||
--- a/util/grub-editenv.c
|
||||
+++ b/util/grub-editenv.c
|
||||
@@ -128,7 +128,7 @@ struct fs_envblk_spec {
|
||||
int offset;
|
||||
int size;
|
||||
} fs_envblk_spec[] = {
|
||||
- { "btrfs", 256 * 1024, GRUB_DISK_SECTOR_SIZE },
|
||||
+ { "btrfs", ENV_BTRFS_OFFSET * 1024, GRUB_DISK_SECTOR_SIZE },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
--
|
||||
2.35.3
|
||||
|
@ -1,3 +1,12 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Nov 22 08:11:17 UTC 2022 - Michael Chang <mchang@suse.com>
|
||||
|
||||
- Make full utilization of btrfs bootloader area (bsc#1161823)
|
||||
* 0001-fs-btrfs-Use-full-btrfs-bootloader-area.patch
|
||||
* 0002-Mark-environmet-blocks-as-used-for-image-embedding.patch
|
||||
- Patch removed
|
||||
* 0001-i386-pc-build-btrfs-zstd-support-into-separate-modul.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Nov 21 02:10:28 UTC 2022 - Michael Chang <mchang@suse.com>
|
||||
|
||||
|
@ -313,7 +313,6 @@ Patch786: 0046-squash-verifiers-Move-verifiers-API-to-kernel-image.patch
|
||||
Patch788: 0001-ieee1275-Avoiding-many-unecessary-open-close.patch
|
||||
Patch789: 0001-Workaround-volatile-efi-boot-variable.patch
|
||||
Patch790: 0001-30_uefi-firmware-fix-printf-format-with-null-byte.patch
|
||||
Patch791: 0001-i386-pc-build-btrfs-zstd-support-into-separate-modul.patch
|
||||
Patch792: 0001-templates-Follow-the-path-of-usr-merged-kernel-confi.patch
|
||||
Patch793: 0001-tpm-Pass-unknown-error-as-non-fatal-but-debug-print-.patch
|
||||
Patch794: 0001-Filter-out-POSIX-locale-for-translation.patch
|
||||
@ -477,6 +476,8 @@ Patch946: 0009-font-Fix-an-integer-underflow-in-blit_comb.patch
|
||||
Patch947: 0010-font-Harden-grub_font_blit_glyph-and-grub_font_blit_.patch
|
||||
Patch948: 0011-font-Assign-null_font-to-glyphs-in-ascii_font_glyph.patch
|
||||
Patch949: 0012-normal-charset-Fix-an-integer-overflow-in-grub_unico.patch
|
||||
Patch950: 0001-fs-btrfs-Use-full-btrfs-bootloader-area.patch
|
||||
Patch951: 0002-Mark-environmet-blocks-as-used-for-image-embedding.patch
|
||||
|
||||
Requires: gettext-runtime
|
||||
%if 0%{?suse_version} >= 1140
|
||||
|
Loading…
Reference in New Issue
Block a user