From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Javier Martinez Canillas <javierm@redhat.com>
Date: Thu, 27 Sep 2018 10:49:14 +0200
Subject: [PATCH] Move quicksort function from kernel.exec to the blscfg module

The qsort function is defined in the grub2 kernel and exported for modules
to use. But this prevents the blscfg.mod to be loaded by old grub2 kernels
that don't export this symbol.

Loading the latest blscfg module might be useful on legacy BIOS systems to
avoid updating the first and second stage grub2 images in the boot device.

Since the only caller of the qsort function is the blscfg module, move the
qsort function out of the grub2 kernel and only have it in the blscfg.mod.

While being there, also remove the grub_bsearch() function that is unused.

Related: rhbz#1633646

Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
---
 grub-core/Makefile.core.def                      |  2 +-
 grub-core/commands/blscfg.c                      |  3 ++-
 grub-core/{kern/qsort.c => commands/bls_qsort.h} | 30 +++---------------------
 include/grub/misc.h                              | 15 ------------
 4 files changed, 6 insertions(+), 44 deletions(-)
 rename grub-core/{kern/qsort.c => commands/bls_qsort.h} (93%)

diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index fb0a1e0babb..3346d1be658 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -129,7 +129,6 @@ kernel = {
   common = kern/rescue_parser.c;
   common = kern/rescue_reader.c;
   common = kern/term.c;
-  common = kern/qsort.c;
   common = kern/backtrace.c;
   common = kern/tpm.c;
 
@@ -781,6 +780,7 @@ module = {
 module = {
   name = blscfg;
   common = commands/blscfg.c;
+  common = commands/bls_qsort.h;
   common = commands/loadenv.h;
   enable = efi;
   enable = i386_pc;
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
index abd6f00d0de..bec5a9ffe3e 100644
--- a/grub-core/commands/blscfg.c
+++ b/grub-core/commands/blscfg.c
@@ -36,6 +36,7 @@
 
 GRUB_MOD_LICENSE ("GPLv3+");
 
+#include "bls_qsort.h"
 #include "loadenv.h"
 
 #define GRUB_BLS_CONFIG_PATH "/loader/entries/"
@@ -717,7 +718,7 @@ read_fallback:
       use_version = false;
   }
 
-  grub_qsort(&entries[0], nentries, sizeof (struct bls_entry *), bls_cmp, &use_version);
+  bls_qsort(&entries[0], nentries, sizeof (struct bls_entry *), bls_cmp, &use_version);
 
   grub_dprintf ("blscfg", "%s Creating %d entries from bls\n", __func__, nentries);
   for (r = nentries - 1; r >= 0; r--)
diff --git a/grub-core/kern/qsort.c b/grub-core/commands/bls_qsort.h
similarity index 93%
rename from grub-core/kern/qsort.c
rename to grub-core/commands/bls_qsort.h
index 7f3fc9ffdae..572765fa3f2 100644
--- a/grub-core/kern/qsort.c
+++ b/grub-core/commands/bls_qsort.h
@@ -64,6 +64,7 @@ typedef struct
 #define	POP(low, high)	((void) (--top, (low = top->lo), (high = top->hi)))
 #define	STACK_NOT_EMPTY	(stack < top)
 
+typedef int (*grub_compar_d_fn_t) (const void *p0, const void *p1, void *state);
 
 /* Order size using quicksort.  This implementation incorporates
    four optimizations discussed in Sedgewick:
@@ -89,8 +90,8 @@ typedef struct
       smaller partition.  This *guarantees* no more than log (total_elems)
       stack size is needed (actually O(1) in this case)!  */
 
-void
-grub_qsort (void *const pbase, grub_size_t total_elems, grub_size_t size,
+static inline void UNUSED
+bls_qsort (void *const pbase, grub_size_t total_elems, grub_size_t size,
 	    grub_compar_d_fn_t cmp, void *arg)
 {
   char *base_ptr = (char *) pbase;
@@ -252,28 +253,3 @@ grub_qsort (void *const pbase, grub_size_t total_elems, grub_size_t size,
   }
 }
 
-void *
-grub_bsearch (const void *key, const void *base, grub_size_t nmemb, grub_size_t size,
-	 grub_compar_d_fn_t compar, void *state)
-{
-  grub_size_t l, u, idx;
-  const void *p;
-  int comparison;
-
-  l = 0;
-  u = nmemb;
-  while (l < u)
-    {
-      idx = (l + u) / 2;
-      p = (void *) (((const char *) base) + (idx * size));
-      comparison = (*compar) (key, p, state);
-      if (comparison < 0)
-	u = idx;
-      else if (comparison > 0)
-	l = idx + 1;
-      else
-	return (void *) p;
-    }
-
-  return NULL;
-}
diff --git a/include/grub/misc.h b/include/grub/misc.h
index 5f1c1c1be4e..de9016ab709 100644
--- a/include/grub/misc.h
+++ b/include/grub/misc.h
@@ -510,19 +510,4 @@ void EXPORT_FUNC(grub_real_boot_time) (const char *file,
 #define grub_max(a, b) (((a) > (b)) ? (a) : (b))
 #define grub_min(a, b) (((a) < (b)) ? (a) : (b))
 
-typedef int (*grub_compar_d_fn_t) (const void *p0, const void *p1, void *state);
-
-void *EXPORT_FUNC(grub_bsearch) (const void *key,
-			    const void *base,
-			    grub_size_t nmemb,
-			    grub_size_t size,
-			    grub_compar_d_fn_t compar,
-			    void *state);
-
-void EXPORT_FUNC(grub_qsort) (void *const pbase,
-			 grub_size_t total_elems,
-			 grub_size_t size,
-			 grub_compar_d_fn_t cmp,
-			 void *state);
-
 #endif /* ! GRUB_MISC_HEADER */
