From 6e3a41f3d6071fbe79f97cd76c1faa5b3587ffd4 Mon Sep 17 00:00:00 2001
From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Date: Mon, 27 Apr 2020 17:51:34 +0200
Subject: [PATCH 1/2] Warn if MBR gap is small and user uses advanced modules

We don't want to support small MBR gap in pair with anything but
the simplest config of biosdisk+part_msdos+simple filesystem. In this
path "simple filesystems" are all current filesystems except zfs and
btrfs.
---
 grub-core/partmap/gpt.c     |  9 ++++++++-
 grub-core/partmap/msdos.c   |  7 ++++++-
 include/grub/partition.h    |  4 +++-
 include/grub/util/install.h |  6 ++++--
 util/grub-install-common.c  | 25 +++++++++++++++++++++++++
 util/grub-install.c         | 13 +++++++++----
 util/grub-setup.c           |  2 +-
 util/setup.c                |  5 +++--
 8 files changed, 59 insertions(+), 12 deletions(-)

Index: grub-2.02/grub-core/partmap/gpt.c
===================================================================
--- grub-2.02.orig/grub-core/partmap/gpt.c
+++ grub-2.02/grub-core/partmap/gpt.c
@@ -25,6 +25,9 @@
 #include <grub/msdos_partition.h>
 #include <grub/gpt_partition.h>
 #include <grub/i18n.h>
+#ifdef GRUB_UTIL
+#include <grub/emu/misc.h>
+#endif
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
@@ -169,7 +172,8 @@ static grub_err_t
 gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
 			 unsigned int max_nsectors,
 			 grub_embed_type_t embed_type,
-			 grub_disk_addr_t **sectors)
+			 grub_disk_addr_t **sectors,
+			 int warn_short)
 {
   struct gpt_partition_map_embed_ctx ctx = {
     .start = 0,
@@ -191,6 +195,9 @@ gpt_partition_map_embed (struct grub_dis
 		       N_("this GPT partition label contains no BIOS Boot Partition;"
 			  " embedding won't be possible"));
 
+  if (ctx.len < GRUB_MIN_RECOMMENDED_MBRGAP) {
+    grub_util_warn("Your BIOS Boot Partition is under 1 MiB, please increase its size.");
+  }
   if (ctx.len < *nsectors)
     return grub_error (GRUB_ERR_OUT_OF_RANGE,
 		       N_("your BIOS Boot Partition is too small;"
Index: grub-2.02/grub-core/partmap/msdos.c
===================================================================
--- grub-2.02.orig/grub-core/partmap/msdos.c
+++ grub-2.02/grub-core/partmap/msdos.c
@@ -243,7 +243,8 @@ static grub_err_t
 pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors,
 			unsigned int max_nsectors,
 			grub_embed_type_t embed_type,
-			grub_disk_addr_t **sectors)
+			grub_disk_addr_t **sectors,
+			int warn_short)
 {
   grub_disk_addr_t end = ~0ULL;
   struct grub_msdos_partition_mbr mbr;
@@ -397,6 +398,10 @@ pc_partition_map_embed (struct grub_disk
       return GRUB_ERR_NONE;
     }
 
+  if (end < GRUB_MIN_RECOMMENDED_MBRGAP && warn_short) {
+    grub_util_warn("You have a short MBR gap and use advanced config. Please increase post-MBR gap");
+  }
+
   if (end <= 1)
     return grub_error (GRUB_ERR_FILE_NOT_FOUND,
 		       N_("this msdos-style partition label has no "
Index: grub-2.02/include/grub/partition.h
===================================================================
--- grub-2.02.orig/include/grub/partition.h
+++ grub-2.02/include/grub/partition.h
@@ -52,10 +52,12 @@ struct grub_partition_map
 			 grub_partition_iterate_hook_t hook, void *hook_data);
 #ifdef GRUB_UTIL
   /* Determine sectors available for embedding.  */
+#define GRUB_MIN_RECOMMENDED_MBRGAP 1900
   grub_err_t (*embed) (struct grub_disk *disk, unsigned int *nsectors,
 		       unsigned int max_nsectors,
 		       grub_embed_type_t embed_type,
-		       grub_disk_addr_t **sectors);
+		       grub_disk_addr_t **sectors,
+		       int warn_short);
 #endif
 };
 typedef struct grub_partition_map *grub_partition_map_t;
Index: grub-2.02/include/grub/util/install.h
===================================================================
--- grub-2.02.orig/include/grub/util/install.h
+++ grub-2.02/include/grub/util/install.h
@@ -187,13 +187,13 @@ grub_util_bios_setup (const char *dir,
 		      const char *boot_file, const char *core_file,
 		      const char *dest, int force,
 		      int fs_probe, int allow_floppy,
-		      int add_rs_codes);
+		      int add_rs_codes, int warn_short_mbr_gap);
 void
 grub_util_sparc_setup (const char *dir,
 		       const char *boot_file, const char *core_file,
 		       const char *dest, int force,
 		       int fs_probe, int allow_floppy,
-		       int add_rs_codes);
+		       int add_rs_codes, int warn_short_mbr_gap);
 
 char *
 grub_install_get_image_targets_string (void);
@@ -259,4 +259,6 @@ grub_util_get_target_name (const struct
 extern char *grub_install_copy_buffer;
 #define GRUB_INSTALL_COPY_BUFFER_SIZE 1048576
 
+int
+grub_install_is_short_mbrgap_supported(void);
 #endif
Index: grub-2.02/util/grub-install-common.c
===================================================================
--- grub-2.02.orig/util/grub-install-common.c
+++ grub-2.02/util/grub-install-common.c
@@ -228,6 +228,31 @@ char *grub_install_source_directory = NU
 char *grub_install_locale_directory = NULL;
 char *grub_install_themes_directory = NULL;
 
+int
+grub_install_is_short_mbrgap_supported()
+{
+  int i, j;
+  static const char *whitelist[] =
+    {
+     "part_msdos", "biosdisk", "affs", "afs", "bfs", "archelp",
+     "cpio", "cpio_be", "newc", "odc", "ext2", "fat", "exfat",
+     "f2fs", "fshelp", "hfs", "hfsplus", "hfspluscomp",
+     "iso9660", "jfs", "minix", "minix2", "minix3", "minix_be",
+     "minix2_be", "minix2_be", "nilfs2", "ntfs", "ntfscomp",
+     "reiserfs", "romfs", "sfs", "squash4", "tar", "udf",
+     "ufs1", "ufs1_be", "ufs2", "xfs"
+    };
+  for (i = 0; i < modules.n_entries; i++)
+    {
+      for (j = 0; j < ARRAY_SIZE (whitelist); j++)
+	if (strcmp(modules.entries[i], whitelist[j]) == 0)
+	  break;
+      if (j == ARRAY_SIZE (whitelist))
+	return 0;
+    }
+  return 1;
+}
+
 void
 grub_install_push_module (const char *val)
 {
Index: grub-2.02/util/grub-install.c
===================================================================
--- grub-2.02.orig/util/grub-install.c
+++ grub-2.02/util/grub-install.c
@@ -1784,9 +1784,14 @@ main (int argc, char *argv[])
 			
 	/*  Now perform the installation.  */
 	if (install_bootsector)
-	  grub_util_bios_setup (platdir, "boot.img", "core.img",
-				install_drive, force,
-				fs_probe, allow_floppy, add_rs_codes);
+	  {
+	    int warn_short_mbr_gap = !grub_install_is_short_mbrgap_supported();
+
+	    grub_util_bios_setup (platdir, "boot.img", "core.img",
+				  install_drive, force,
+				  fs_probe, allow_floppy, add_rs_codes,
+				  warn_short_mbr_gap);
+	  }
 	break;
       }
     case GRUB_INSTALL_PLATFORM_SPARC64_IEEE1275:
@@ -1813,7 +1818,7 @@ main (int argc, char *argv[])
 	  grub_util_sparc_setup (platdir, "boot.img", "core.img",
 				 install_drive, force,
 				 fs_probe, allow_floppy,
-				 0 /* unused */ );
+				 0 /* unused */, 0 /* unused */ );
 	break;
       }
 
Index: grub-2.02/util/grub-setup.c
===================================================================
--- grub-2.02.orig/util/grub-setup.c
+++ grub-2.02/util/grub-setup.c
@@ -315,7 +315,7 @@ main (int argc, char *argv[])
 		   arguments.core_file ? : DEFAULT_CORE_FILE,
 		   dest_dev, arguments.force,
 		   arguments.fs_probe, arguments.allow_floppy,
-		   arguments.add_rs_codes);
+		   arguments.add_rs_codes, 0);
 
   /* Free resources.  */
   grub_fini_all ();
Index: grub-2.02/util/setup.c
===================================================================
--- grub-2.02.orig/util/setup.c
+++ grub-2.02/util/setup.c
@@ -249,7 +249,8 @@ SETUP (const char *dir,
        const char *boot_file, const char *core_file,
        const char *dest, int force,
        int fs_probe, int allow_floppy,
-       int add_rs_codes __attribute__ ((unused))) /* unused on sparc64 */
+       int add_rs_codes __attribute__ ((unused)), /* unused on sparc64 */
+       int warn_small)
 {
   char *core_path;
   char *boot_img, *core_img, *boot_path;
@@ -513,7 +514,7 @@ SETUP (const char *dir,
     else if (ctx.dest_partmap)
       {
         err = ctx.dest_partmap->embed (dest_dev->disk, &nsec, maxsec,
-				       GRUB_EMBED_PCBIOS, &sectors);
+				       GRUB_EMBED_PCBIOS, &sectors, warn_small);
 #ifdef GRUB_SETUP_BIOS
         if (err == GRUB_ERR_OUT_OF_RANGE
             && dest_dev->disk->id == root_dev->disk->id
