From 46c0e0c8b70b75d5a082ab33c0ca0b9ae55923ef385bc5759c045f460668e7cc Mon Sep 17 00:00:00 2001 From: Michael Chang Date: Thu, 24 Nov 2022 03:05:20 +0000 Subject: [PATCH] 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 --- ...btrfs-Use-full-btrfs-bootloader-area.patch | 162 ++++++ ...rfs-zstd-support-into-separate-modul.patch | 550 ------------------ ...t-blocks-as-used-for-image-embedding.patch | 66 +++ grub2.changes | 9 + grub2.spec | 3 +- 5 files changed, 239 insertions(+), 551 deletions(-) create mode 100644 0001-fs-btrfs-Use-full-btrfs-bootloader-area.patch delete mode 100644 0001-i386-pc-build-btrfs-zstd-support-into-separate-modul.patch create mode 100644 0002-Mark-environmet-blocks-as-used-for-image-embedding.patch diff --git a/0001-fs-btrfs-Use-full-btrfs-bootloader-area.patch b/0001-fs-btrfs-Use-full-btrfs-bootloader-area.patch new file mode 100644 index 0000000..0130b96 --- /dev/null +++ b/0001-fs-btrfs-Use-full-btrfs-bootloader-area.patch @@ -0,0 +1,162 @@ +From b78aca6e1c4f72a6491457e849b76c8e0af77765 Mon Sep 17 00:00:00 2001 +From: Michael Chang +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 +Reviewed-by: Daniel Kiper +--- + 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 + diff --git a/0001-i386-pc-build-btrfs-zstd-support-into-separate-modul.patch b/0001-i386-pc-build-btrfs-zstd-support-into-separate-modul.patch deleted file mode 100644 index 8eb6f08..0000000 --- a/0001-i386-pc-build-btrfs-zstd-support-into-separate-modul.patch +++ /dev/null @@ -1,550 +0,0 @@ -From e7fe15db1736e038a7705973424708d3151fde99 Mon Sep 17 00:00:00 2001 -From: Michael Chang -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 ---- - 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 . - */ - --/* -- * 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 - #include - #include -@@ -35,7 +27,9 @@ - #include - #include - #include --#include -+#ifndef GRUB_MACHINE_PCBIOS -+#include -+#endif - #include - #include - #include -@@ -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 . -+ */ -+ -+#include -+#include -+/* For NULL. */ -+#include -+#include -+#include -+ -+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 . -+ */ -+ -+/* -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+#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 . -+ */ -+ -+#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 - diff --git a/0002-Mark-environmet-blocks-as-used-for-image-embedding.patch b/0002-Mark-environmet-blocks-as-used-for-image-embedding.patch new file mode 100644 index 0000000..5378617 --- /dev/null +++ b/0002-Mark-environmet-blocks-as-used-for-image-embedding.patch @@ -0,0 +1,66 @@ +From f01314a822dbe9ad39b2f7d0f3717ef6e4c24f4a Mon Sep 17 00:00:00 2001 +From: Michael Chang +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 +--- + 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 + diff --git a/grub2.changes b/grub2.changes index e88a97b..308f8e9 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Tue Nov 22 08:11:17 UTC 2022 - Michael Chang + +- 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 diff --git a/grub2.spec b/grub2.spec index 15dc922..d719180 100644 --- a/grub2.spec +++ b/grub2.spec @@ -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