15a2072
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
15a2072
From: Javier Martinez Canillas <javierm@redhat.com>
15a2072
Date: Fri, 11 May 2018 23:47:31 +0200
15a2072
Subject: [PATCH] Simplify BLS entry key val pairs lookup
15a2072
15a2072
The <key,value> pairs found in the BLS are being sorted but this isn't
15a2072
really needed and it makes the implementation complex and error prone.
15a2072
15a2072
For example, the current implementation has the following issues:
15a2072
15a2072
1) Fields not present in the grub2 menu entry
15a2072
15a2072
  linux /linuz
15a2072
  initrd /foo
15a2072
  initrd /bar
15a2072
15a2072
  load_video
15a2072
  set gfx_payload=keep
15a2072
  insmod gzio
15a2072
  linux /boot/linuz
15a2072
  initrd /boot/bar
15a2072
15a2072
2) Fields present but in the wrong order
15a2072
15a2072
  title Fedora (4.16.6-300.fc28.x86_64-tuned) 28 (Twenty Eight)
15a2072
  version 4.16.6-300.fc28.x86_64
15a2072
  linux /vmlinuz-4.16.6-300.fc28.x86_64
15a2072
  initrd /foo.img
15a2072
  initrd /bar.img
15a2072
  options $kernelopts
15a2072
  id fedora-20180430150025-4.16.6-300.fc28.x86_64
15a2072
15a2072
  load_video
15a2072
  set gfx_payload=keep
15a2072
  insmod gzio
15a2072
  linux /boot/vmlinuz-4.16.6-300.fc28.x86_64 $kernelopts
15a2072
  initrd /boot/bar.img /boot/foo.img
15a2072
15a2072
It's important to preserve the order in which fields have been defined
15a2072
in the BLS fragment since for some of the fields the order has meaning.
15a2072
For example, initramfs images have to be passed to the kernel in order
15a2072
that were defined in the BLS fragment.
15a2072
15a2072
This patch simplifies the <key,value> pairs storage and lookup. Rather
15a2072
than sorting and attempt to later figure out what's the expected order,
15a2072
just store it in the same order as they were defined in the BLS config
15a2072
file and return in that same order to callers when these look them up.
15a2072
15a2072
Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
15a2072
---
15a2072
 grub-core/commands/blscfg.c | 88 ++++++++++-----------------------------------
15a2072
 1 file changed, 18 insertions(+), 70 deletions(-)
15a2072
15a2072
diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
15a2072
index c52d2b2e05a..fb08d8e4c12 100644
15a2072
--- a/grub-core/commands/blscfg.c
15a2072
+++ b/grub-core/commands/blscfg.c
15a2072
@@ -169,84 +169,35 @@ static void bls_free_entry(struct bls_entry *entry)
15a2072
   grub_free (entry);
15a2072
 }
15a2072
 
15a2072
-static int keyval_cmp (const void *p0, const void *p1,
15a2072
-		       void *state UNUSED)
15a2072
-{
15a2072
-  const struct keyval *kv0 = *(struct keyval * const *)p0;
15a2072
-  const struct keyval *kv1 = *(struct keyval * const *)p1;
15a2072
-  int rc;
15a2072
-
15a2072
-  rc = grub_strcmp(kv0->key, kv1->key);
15a2072
-
15a2072
-  return rc;
15a2072
-}
15a2072
-
15a2072
 /* Find they value of the key named by keyname.  If there are allowed to be
15a2072
  * more than one, pass a pointer to an int set to -1 the first time, and pass
15a2072
  * the same pointer through each time after, and it'll return them in sorted
15a2072
- * order. */
15a2072
+ * order as defined in the BLS fragment file */
15a2072
 static char *bls_get_val(struct bls_entry *entry, const char *keyname, int *last)
15a2072
 {
15a2072
-  char *foo = (char *)"";
15a2072
-  struct keyval *kv = NULL, **kvp, key = {keyname, foo}, *keyp = &ke;;
15a2072
+  int idx, start = 0;
15a2072
+  struct keyval *kv = NULL;
15a2072
 
15a2072
-  /* if we've already found an entry that matches, just iterate */
15a2072
-  if (last && *last >= 0)
15a2072
-    {
15a2072
-      int next = ++last[0];
15a2072
+  if (last)
15a2072
+    start = *last + 1;
15a2072
 
15a2072
-      if (next == entry->nkeyvals)
15a2072
-	{
15a2072
-done:
15a2072
-	  *last = -1;
15a2072
-	  return NULL;
15a2072
-	}
15a2072
+  for (idx = start; idx < entry->nkeyvals; idx++) {
15a2072
+    kv = entry->keyvals[idx];
15a2072
 
15a2072
-      kv = entry->keyvals[next];
15a2072
-      if (grub_strcmp (keyname, kv->key))
15a2072
-	goto done;
15a2072
+    if (!grub_strcmp (keyname, kv->key))
15a2072
+      break;
15a2072
+  }
15a2072
 
15a2072
-      return kv->val;
15a2072
-    }
15a2072
+  if (idx == entry->nkeyvals) {
15a2072
+    if (last)
15a2072
+      *last = -1;
15a2072
+    return NULL;
15a2072
+  }
15a2072
 
15a2072
-  kvp = grub_bsearch(&keyp, &entry->keyvals[0], entry->nkeyvals,
15a2072
-		    sizeof (struct keyval *), keyval_cmp, NULL);
15a2072
-  if (kvp)
15a2072
-    kv = *kvp;
15a2072
+  if (last)
15a2072
+    *last = idx;
15a2072
 
15a2072
-  if (kv)
15a2072
-    {
15a2072
-      /* if we've got uninitialized but present state, track back until we find
15a2072
-       * the first match */
15a2072
-      if (last)
15a2072
-	{
15a2072
-	  grub_dprintf("blscfg", "%s trying to find another entry because last was set\n", __func__);
15a2072
-	  /* figure out the position of this entry in the array */
15a2072
-	  int idx;
15a2072
-	  for (idx = 0 ; idx < entry->nkeyvals; idx++)
15a2072
-	    if (entry->keyvals[idx] == kv)
15a2072
-	      break;
15a2072
-	  *last = idx;
15a2072
-
15a2072
-	  while (idx > 0)
15a2072
-	    {
15a2072
-	      struct keyval *kvtmp = entry->keyvals[idx-1];
15a2072
-	      if (idx == 0 || grub_strcmp (keyname, kvtmp->key))
15a2072
-		{
15a2072
-		  /* if we're at the start, or if the previous entry doesn't
15a2072
-		   * match, then we're done */
15a2072
-		  *last = idx;
15a2072
-		  break;
15a2072
-		}
15a2072
-	      else
15a2072
-		/* but if it does match, keep going backwards */
15a2072
-		idx--;
15a2072
-	    }
15a2072
-	}
15a2072
-
15a2072
-      return kv->val;
15a2072
-    }
15a2072
-  return NULL;
15a2072
+  return kv->val;
15a2072
 }
15a2072
 
15a2072
 #define goto_return(x) ({ ret = (x); goto finish; })
15a2072
@@ -503,9 +454,6 @@ static int read_entry (
15a2072
 	break;
15a2072
     }
15a2072
 
15a2072
-  grub_qsort(&entry->keyvals[0], entry->nkeyvals, sizeof (struct keyval *),
15a2072
-	     keyval_cmp, NULL);
15a2072
-
15a2072
 finish:
15a2072
   grub_free (p);
15a2072