SHA256
1
0
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:
Michael Chang 2022-11-24 03:05:20 +00:00 committed by Git OBS Bridge
parent 2edffea20f
commit 46c0e0c8b7
5 changed files with 239 additions and 551 deletions

View 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

View File

@ -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, &sectors, 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

View File

@ -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

View File

@ -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>

View File

@ -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