]> git.pld-linux.org Git - packages/grub2.git/commitdiff
synced bls patch with fedora; rel 1 auto/th/grub2-2.04-1
authorJan Palus <atler@pld-linux.org>
Sat, 7 Sep 2019 15:59:27 +0000 (17:59 +0200)
committerJan Palus <atler@pld-linux.org>
Sat, 7 Sep 2019 15:59:27 +0000 (17:59 +0200)
blscfg.patch
grub2.spec

index 407e83254b89285e67f54e6da3fd896dbedabfb3..ada4564e039709e8e7108dd74aeafa57adde6d88 100644 (file)
@@ -1,50 +1,67 @@
-From ddfb160353df14e9f88affe7498512a553146872 Mon Sep 17 00:00:00 2001
-From: Fedora Ninjas <grub2-owner@fedoraproject.org>
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Peter Jones <pjones@redhat.com>
 Date: Tue, 22 Jan 2013 06:31:38 +0100
-Subject: [PATCH 101/152] blscfg: add blscfg module to parse Boot Loader
Specification snippets
+Subject: [PATCH] blscfg: add blscfg module to parse Boot Loader Specification
+ snippets
 
-http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec
+The BootLoaderSpec (BLS) defines a scheme where different bootloaders can
+share a format for boot items and a configuration directory that accepts
+these common configurations as drop-in files.
 
-Works like this:
-
- insmod blscfg
- bls_import
-
-Done! You should now have menu items for your snippets in place.
-
-Signed-off-by: Peter Jones <grub2-owner@fedoraproject.org>
+Signed-off-by: Peter Jones <pjones@redhat.com>
+Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
+[wjt: some cleanups and fixes]
+Signed-off-by: Will Thompson <wjt@endlessm.com>
 ---
- grub-core/Makefile.core.def |   8 ++
- grub-core/commands/blscfg.c | 201 ++++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 209 insertions(+)
+ grub-core/Makefile.core.def    |   11 +
+ grub-core/commands/blscfg.c    | 1096 ++++++++++++++++++++++++++++++++++++++++
+ grub-core/commands/legacycfg.c |    5 +-
+ grub-core/commands/loadenv.c   |   77 +--
+ grub-core/commands/menuentry.c |   20 +-
+ grub-core/normal/main.c        |    6 +
+ grub-core/commands/loadenv.h   |   93 ++++
+ include/grub/compiler.h        |    2 +
+ include/grub/menu.h            |   13 +
+ include/grub/normal.h          |    2 +-
+ 10 files changed, 1243 insertions(+), 82 deletions(-)
  create mode 100644 grub-core/commands/blscfg.c
+ create mode 100644 grub-core/commands/loadenv.h
 
 diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
-index ec46506..7bf1c8a 100644
+index 41b5e16a3ce..57e253ab1a1 100644
 --- a/grub-core/Makefile.core.def
 +++ b/grub-core/Makefile.core.def
-@@ -747,6 +747,14 @@ module = {
+@@ -811,6 +811,16 @@ module = {
+   common = commands/blocklist.c;
  };
  
- module = {
++module = {
 +  name = blscfg;
 +  common = commands/blscfg.c;
-+  enable = i386_efi;
-+  enable = x86_64_efi;
++  common = commands/loadenv.h;
++  enable = powerpc_ieee1275;
++  enable = efi;
 +  enable = i386_pc;
++  enable = emu;
 +};
 +
-+module = {
+ module = {
    name = boot;
    common = commands/boot.c;
-   i386_pc = lib/i386/pc/biosnum.c;
+@@ -988,6 +998,7 @@ module = {
+ module = {
+   name = loadenv;
+   common = commands/loadenv.c;
++  common = commands/loadenv.h;
+   common = lib/envblk.c;
+ };
 diff --git a/grub-core/commands/blscfg.c b/grub-core/commands/blscfg.c
 new file mode 100644
-index 0000000..4274aca
+index 00000000000..54458b14518
 --- /dev/null
 +++ b/grub-core/commands/blscfg.c
-@@ -0,0 +1,201 @@
+@@ -0,0 +1,1096 @@
 +/*-*- Mode: C; c-basic-offset: 2; indent-tabs-mode: t -*-*/
 +
 +/* bls.c - implementation of the boot loader spec */
@@ -66,6 +83,7 @@ index 0000000..4274aca
 + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
 + */
 +
++#include <grub/list.h>
 +#include <grub/types.h>
 +#include <grub/misc.h>
 +#include <grub/mm.h>
@@ -77,143 +95,936 @@ index 0000000..4274aca
 +#include <grub/env.h>
 +#include <grub/file.h>
 +#include <grub/normal.h>
++#include <grub/lib/envblk.h>
++
++#include <stdbool.h>
 +
 +GRUB_MOD_LICENSE ("GPLv3+");
 +
-+#ifdef GRUB_MACHINE_EFI
-+#define GRUB_LINUX_CMD "linuxefi"
-+#define GRUB_INITRD_CMD "initrdefi"
-+#define GRUB_BLS_CONFIG_PATH "/EFI/fedora/loader/entries/"
-+#define GRUB_BOOT_DEVICE "($boot)"
-+#else
-+#define GRUB_LINUX_CMD "linux"
-+#define GRUB_INITRD_CMD "initrd"
++#include "loadenv.h"
++
 +#define GRUB_BLS_CONFIG_PATH "/loader/entries/"
++#ifdef GRUB_MACHINE_EMU
++#define GRUB_BOOT_DEVICE "/boot"
++#else
 +#define GRUB_BOOT_DEVICE "($root)"
 +#endif
 +
-+static int parse_entry (
++struct keyval
++{
++  const char *key;
++  char *val;
++};
++
++static struct bls_entry *entries = NULL;
++
++#define FOR_BLS_ENTRIES(var) FOR_LIST_ELEMENTS (var, entries)
++
++static int bls_add_keyval(struct bls_entry *entry, char *key, char *val)
++{
++  char *k, *v;
++  struct keyval **kvs, *kv;
++  int new_n = entry->nkeyvals + 1;
++
++  kvs = grub_realloc (entry->keyvals, new_n * sizeof (struct keyval *));
++  if (!kvs)
++    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
++                     "couldn't find space for BLS entry");
++  entry->keyvals = kvs;
++
++  kv = grub_malloc (sizeof (struct keyval));
++  if (!kv)
++    return grub_error (GRUB_ERR_OUT_OF_MEMORY,
++                     "couldn't find space for BLS entry");
++
++  k = grub_strdup (key);
++  if (!k)
++    {
++      grub_free (kv);
++      return grub_error (GRUB_ERR_OUT_OF_MEMORY,
++                       "couldn't find space for BLS entry");
++    }
++
++  v = grub_strdup (val);
++  if (!v)
++    {
++      grub_free (k);
++      grub_free (kv);
++      return grub_error (GRUB_ERR_OUT_OF_MEMORY,
++                       "couldn't find space for BLS entry");
++    }
++
++  kv->key = k;
++  kv->val = v;
++
++  entry->keyvals[entry->nkeyvals] = kv;
++  grub_dprintf("blscfg", "new keyval at %p:%s:%s\n", entry->keyvals[entry->nkeyvals], k, v);
++  entry->nkeyvals = new_n;
++
++  return 0;
++}
++
++/* Find they value of the key named by keyname.  If there are allowed to be
++ * more than one, pass a pointer to an int set to -1 the first time, and pass
++ * the same pointer through each time after, and it'll return them in sorted
++ * order as defined in the BLS fragment file */
++static char *bls_get_val(struct bls_entry *entry, const char *keyname, int *last)
++{
++  int idx, start = 0;
++  struct keyval *kv = NULL;
++
++  if (last)
++    start = *last + 1;
++
++  for (idx = start; idx < entry->nkeyvals; idx++) {
++    kv = entry->keyvals[idx];
++
++    if (!grub_strcmp (keyname, kv->key))
++      break;
++  }
++
++  if (idx == entry->nkeyvals) {
++    if (last)
++      *last = -1;
++    return NULL;
++  }
++
++  if (last)
++    *last = idx;
++
++  return kv->val;
++}
++
++#define goto_return(x) ({ ret = (x); goto finish; })
++
++/* compare alpha and numeric segments of two versions */
++/* return 1: a is newer than b */
++/*        0: a and b are the same version */
++/*       -1: b is newer than a */
++static int vercmp(const char * a, const char * b)
++{
++    char oldch1, oldch2;
++    char *abuf, *bbuf;
++    char *str1, *str2;
++    char * one, * two;
++    int rc;
++    int isnum;
++    int ret = 0;
++
++    grub_dprintf("blscfg", "%s comparing %s and %s\n", __func__, a, b);
++    if (!grub_strcmp(a, b))
++          return 0;
++
++    abuf = grub_malloc(grub_strlen(a) + 1);
++    bbuf = grub_malloc(grub_strlen(b) + 1);
++    str1 = abuf;
++    str2 = bbuf;
++    grub_strcpy(str1, a);
++    grub_strcpy(str2, b);
++
++    one = str1;
++    two = str2;
++
++    /* loop through each version segment of str1 and str2 and compare them */
++    while (*one || *two) {
++      while (*one && !grub_isalnum(*one) && *one != '~') one++;
++      while (*two && !grub_isalnum(*two) && *two != '~') two++;
++
++      /* handle the tilde separator, it sorts before everything else */
++      if (*one == '~' || *two == '~') {
++          if (*one != '~') goto_return (1);
++          if (*two != '~') goto_return (-1);
++          one++;
++          two++;
++          continue;
++      }
++
++      /* If we ran to the end of either, we are finished with the loop */
++      if (!(*one && *two)) break;
++
++      str1 = one;
++      str2 = two;
++
++      /* grab first completely alpha or completely numeric segment */
++      /* leave one and two pointing to the start of the alpha or numeric */
++      /* segment and walk str1 and str2 to end of segment */
++      if (grub_isdigit(*str1)) {
++          while (*str1 && grub_isdigit(*str1)) str1++;
++          while (*str2 && grub_isdigit(*str2)) str2++;
++          isnum = 1;
++      } else {
++          while (*str1 && grub_isalpha(*str1)) str1++;
++          while (*str2 && grub_isalpha(*str2)) str2++;
++          isnum = 0;
++      }
++
++      /* save character at the end of the alpha or numeric segment */
++      /* so that they can be restored after the comparison */
++      oldch1 = *str1;
++      *str1 = '\0';
++      oldch2 = *str2;
++      *str2 = '\0';
++
++      /* this cannot happen, as we previously tested to make sure that */
++      /* the first string has a non-null segment */
++      if (one == str1) goto_return(-1);       /* arbitrary */
++
++      /* take care of the case where the two version segments are */
++      /* different types: one numeric, the other alpha (i.e. empty) */
++      /* numeric segments are always newer than alpha segments */
++      /* XXX See patch #60884 (and details) from bugzilla #50977. */
++      if (two == str2) goto_return (isnum ? 1 : -1);
++
++      if (isnum) {
++          grub_size_t onelen, twolen;
++          /* this used to be done by converting the digit segments */
++          /* to ints using atoi() - it's changed because long  */
++          /* digit segments can overflow an int - this should fix that. */
++
++          /* throw away any leading zeros - it's a number, right? */
++          while (*one == '0') one++;
++          while (*two == '0') two++;
++
++          /* whichever number has more digits wins */
++          onelen = grub_strlen(one);
++          twolen = grub_strlen(two);
++          if (onelen > twolen) goto_return (1);
++          if (twolen > onelen) goto_return (-1);
++      }
++
++      /* grub_strcmp will return which one is greater - even if the two */
++      /* segments are alpha or if they are numeric.  don't return  */
++      /* if they are equal because there might be more segments to */
++      /* compare */
++      rc = grub_strcmp(one, two);
++      if (rc) goto_return (rc < 1 ? -1 : 1);
++
++      /* restore character that was replaced by null above */
++      *str1 = oldch1;
++      one = str1;
++      *str2 = oldch2;
++      two = str2;
++    }
++
++    /* this catches the case where all numeric and alpha segments have */
++    /* compared identically but the segment sepparating characters were */
++    /* different */
++    if ((!*one) && (!*two)) goto_return (0);
++
++    /* whichever version still has characters left over wins */
++    if (!*one) goto_return (-1); else goto_return (1);
++
++finish:
++    grub_free (abuf);
++    grub_free (bbuf);
++    return ret;
++}
++
++/* returns name/version/release */
++/* NULL string pointer returned if nothing found */
++static void
++split_package_string (char *package_string, char **name,
++                     char **version, char **release)
++{
++  char *package_version, *package_release;
++
++  /* Release */
++  package_release = grub_strrchr (package_string, '-');
++
++  if (package_release != NULL)
++      *package_release++ = '\0';
++
++  *release = package_release;
++
++  if (name == NULL)
++    {
++      *version = package_string;
++    }
++  else
++    {
++      /* Version */
++      package_version = grub_strrchr(package_string, '-');
++
++      if (package_version != NULL)
++      *package_version++ = '\0';
++
++      *version = package_version;
++      /* Name */
++      *name = package_string;
++    }
++
++  /* Bubble up non-null values from release to name */
++  if (name != NULL && *name == NULL)
++    {
++      *name = (*version == NULL ? *release : *version);
++      *version = *release;
++      *release = NULL;
++    }
++  if (*version == NULL)
++    {
++      *version = *release;
++      *release = NULL;
++    }
++}
++
++static int
++split_cmp(char *nvr0, char *nvr1, int has_name)
++{
++  int ret = 0;
++  char *name0, *version0, *release0;
++  char *name1, *version1, *release1;
++
++  split_package_string(nvr0, has_name ? &name0 : NULL, &version0, &release0);
++  split_package_string(nvr1, has_name ? &name1 : NULL, &version1, &release1);
++
++  if (has_name)
++    {
++      ret = vercmp(name0 == NULL ? "" : name0,
++                 name1 == NULL ? "" : name1);
++      if (ret != 0)
++      return ret;
++    }
++
++  ret = vercmp(version0 == NULL ? "" : version0,
++             version1 == NULL ? "" : version1);
++  if (ret != 0)
++    return ret;
++
++  ret = vercmp(release0 == NULL ? "" : release0,
++             release1 == NULL ? "" : release1);
++  return ret;
++}
++
++/* return 1: e0 is newer than e1 */
++/*        0: e0 and e1 are the same version */
++/*       -1: e1 is newer than e0 */
++static int bls_cmp(const struct bls_entry *e0, const struct bls_entry *e1)
++{
++  char *id0, *id1;
++  int r;
++
++  id0 = grub_strdup(e0->filename);
++  id1 = grub_strdup(e1->filename);
++
++  r = split_cmp(id0, id1, 1);
++
++  grub_free(id0);
++  grub_free(id1);
++
++  return r;
++}
++
++static void list_add_tail(struct bls_entry *head, struct bls_entry *item)
++{
++  item->next = head;
++  if (head->prev)
++    head->prev->next = item;
++  item->prev = head->prev;
++  head->prev = item;
++}
++
++static int bls_add_entry(struct bls_entry *entry)
++{
++  struct bls_entry *e, *last = NULL;
++  int rc;
++
++  if (!entries) {
++    grub_dprintf ("blscfg", "Add entry with id \"%s\"\n", entry->filename);
++    entries = entry;
++    return 0;
++  }
++
++  FOR_BLS_ENTRIES(e) {
++    rc = bls_cmp(entry, e);
++
++    if (!rc)
++      return GRUB_ERR_BAD_ARGUMENT;
++
++    if (rc == 1) {
++      grub_dprintf ("blscfg", "Add entry with id \"%s\"\n", entry->filename);
++      list_add_tail (e, entry);
++      if (e == entries) {
++      entries = entry;
++      entry->prev = NULL;
++      }
++      return 0;
++    }
++    last = e;
++  }
++
++  if (last) {
++    grub_dprintf ("blscfg", "Add entry with id \"%s\"\n", entry->filename);
++    last->next = entry;
++    entry->prev = last;
++  }
++
++  return 0;
++}
++
++struct read_entry_info {
++  const char *devid;
++  const char *dirname;
++  grub_file_t file;
++};
++
++static int read_entry (
 +    const char *filename,
-+    const struct grub_dirhook_info *info __attribute__ ((unused)),
-+    void *data __attribute__ ((unused)))
++    const struct grub_dirhook_info *dirhook_info UNUSED,
++    void *data)
 +{
-+  grub_size_t n;
-+  char *p;
++  grub_size_t m = 0, n, clip = 0;
++  int rc = 0;
++  char *p = NULL;
 +  grub_file_t f = NULL;
-+  grub_off_t sz;
-+  char *title = NULL, *options = NULL, *clinux = NULL, *initrd = NULL, *src = NULL;
-+  const char *args[2] = { NULL, NULL };
++  struct bls_entry *entry;
++  struct read_entry_info *info = (struct read_entry_info *)data;
 +
-+  if (filename[0] == '.')
-+    return 0;
++  grub_dprintf ("blscfg", "filename: \"%s\"\n", filename);
 +
 +  n = grub_strlen (filename);
-+  if (n <= 5)
-+    return 0;
 +
-+  if (grub_strcmp (filename + n - 5, ".conf") != 0)
-+    return 0;
++  if (info->file)
++    {
++      f = info->file;
++    }
++  else
++    {
++      if (filename[0] == '.')
++      return 0;
++
++      if (n <= 5)
++      return 0;
++
++      if (grub_strcmp (filename + n - 5, ".conf") != 0)
++      return 0;
 +
-+  p = grub_xasprintf (GRUB_BLS_CONFIG_PATH "%s", filename);
++      p = grub_xasprintf ("(%s)%s/%s", info->devid, info->dirname, filename);
 +
-+  f = grub_file_open (p);
-+  if (!f)
++      f = grub_file_open (p, GRUB_FILE_TYPE_CONFIG);
++      if (!f)
++      goto finish;
++    }
++
++  entry = grub_zalloc (sizeof (*entry));
++  if (!entry)
 +    goto finish;
 +
-+  sz = grub_file_size (f);
-+  if (sz == GRUB_FILE_SIZE_UNKNOWN || sz > 1024*1024)
++  if (info->file)
++    {
++      char *slash;
++
++      if (n > 5 && !grub_strcmp (filename + n - 5, ".conf") == 0)
++      clip = 5;
++
++      slash = grub_strrchr (filename, '/');
++      if (!slash)
++      slash = grub_strrchr (filename, '\\');
++
++      while (*slash == '/' || *slash == '\\')
++      slash++;
++
++      m = slash ? slash - filename : 0;
++    }
++  else
++    {
++      m = 0;
++      clip = 5;
++    }
++  n -= m;
++
++  entry->filename = grub_strndup(filename + m, n - clip);
++  if (!entry->filename)
 +    goto finish;
 +
++  entry->filename[n - 5] = '\0';
++
 +  for (;;)
 +    {
 +      char *buf;
++      char *separator;
 +
 +      buf = grub_file_getline (f);
 +      if (!buf)
 +      break;
 +
-+      if (grub_strncmp (buf, "title ", 6) == 0)
++      while (buf && buf[0] && (buf[0] == ' ' || buf[0] == '\t'))
++      buf++;
++      if (buf[0] == '#')
++      continue;
++
++      separator = grub_strchr (buf, ' ');
++
++      if (!separator)
++      separator = grub_strchr (buf, '\t');
++
++      if (!separator || separator[1] == '\0')
 +      {
-+        grub_free (title);
-+        title = grub_strdup (buf + 6);
-+        if (!title)
-+          goto finish;
++        grub_free (buf);
++        break;
 +      }
-+      else if (grub_strncmp (buf, "options ", 8) == 0)
++
++      separator[0] = '\0';
++
++      do {
++      separator++;
++      } while (*separator == ' ' || *separator == '\t');
++
++      rc = bls_add_keyval (entry, buf, separator);
++      grub_free (buf);
++      if (rc < 0)
++      break;
++    }
++
++    if (!rc)
++      bls_add_entry(entry);
++
++finish:
++  if (p)
++    grub_free (p);
++
++  if (f)
++    grub_file_close (f);
++
++  return 0;
++}
++
++static grub_envblk_t saved_env = NULL;
++
++static int UNUSED
++save_var (const char *name, const char *value, void *whitelist UNUSED)
++{
++  const char *val = grub_env_get (name);
++  grub_dprintf("blscfg", "saving \"%s\"\n", name);
++
++  if (val)
++    grub_envblk_set (saved_env, name, value);
++
++  return 0;
++}
++
++static int UNUSED
++unset_var (const char *name, const char *value UNUSED, void *whitelist)
++{
++  grub_dprintf("blscfg", "restoring \"%s\"\n", name);
++  if (! whitelist)
++    {
++      grub_env_unset (name);
++      return 0;
++    }
++
++  if (test_whitelist_membership (name,
++                               (const grub_env_whitelist_t *) whitelist))
++    grub_env_unset (name);
++
++  return 0;
++}
++
++static char **bls_make_list (struct bls_entry *entry, const char *key, int *num)
++{
++  int last = -1;
++  char *val;
++
++  int nlist = 0;
++  char **list = NULL;
++
++  list = grub_malloc (sizeof (char *));
++  if (!list)
++    return NULL;
++  list[0] = NULL;
++
++  while (1)
++    {
++      char **new;
++
++      val = bls_get_val (entry, key, &last);
++      if (!val)
++      break;
++
++      new = grub_realloc (list, (nlist + 2) * sizeof (char *));
++      if (!new)
++      break;
++
++      list = new;
++      list[nlist++] = val;
++      list[nlist] = NULL;
++  }
++
++  if (num)
++    *num = nlist;
++
++  return list;
++}
++
++static char *field_append(bool is_var, char *buffer, char *start, char *end)
++{
++  char *temp = grub_strndup(start, end - start + 1);
++  const char *field = temp;
++
++  if (is_var) {
++    field = grub_env_get (temp);
++    if (!field)
++      return buffer;
++  }
++
++  if (!buffer) {
++    buffer = grub_strdup(field);
++    if (!buffer)
++      return NULL;
++  } else {
++    buffer = grub_realloc (buffer, grub_strlen(buffer) + grub_strlen(field));
++    if (!buffer)
++      return NULL;
++
++    grub_stpcpy (buffer + grub_strlen(buffer), field);
++  }
++
++  return buffer;
++}
++
++static char *expand_val(char *value)
++{
++  char *buffer = NULL;
++  char *start = value;
++  char *end = value;
++  bool is_var = false;
++
++  if (!value)
++    return NULL;
++
++  while (*value) {
++    if (*value == '$') {
++      if (start != end) {
++      buffer = field_append(is_var, buffer, start, end);
++      if (!buffer)
++        return NULL;
++      }
++
++      is_var = true;
++      start = value + 1;
++    } else if (is_var) {
++      if (!grub_isalnum(*value) && *value != '_') {
++      buffer = field_append(is_var, buffer, start, end);
++      is_var = false;
++      start = value;
++      }
++    }
++
++    end = value;
++    value++;
++  }
++
++  if (start != end) {
++    buffer = field_append(is_var, buffer, start, end);
++    if (!buffer)
++      return NULL;
++  }
++
++  return buffer;
++}
++
++static char **early_initrd_list (const char *initrd)
++{
++  int nlist = 0;
++  char **list = NULL;
++  char *separator;
++
++  while ((separator = grub_strchr (initrd, ' ')))
++    {
++      list = grub_realloc (list, (nlist + 2) * sizeof (char *));
++      if (!list)
++        return NULL;
++
++      list[nlist++] = grub_strndup(initrd, separator - initrd);
++      list[nlist] = NULL;
++      initrd = separator + 1;
++  }
++
++  list = grub_realloc (list, (nlist + 2) * sizeof (char *));
++  if (!list)
++    return NULL;
++
++  list[nlist++] = grub_strndup(initrd, grub_strlen(initrd));
++  list[nlist] = NULL;
++
++  return list;
++}
++
++static void create_entry (struct bls_entry *entry)
++{
++  int argc = 0;
++  const char **argv = NULL;
++
++  char *title = NULL;
++  char *clinux = NULL;
++  char *options = NULL;
++  char **initrds = NULL;
++  char *initrd = NULL;
++  const char *early_initrd = NULL;
++  char **early_initrds = NULL;
++  char *initrd_prefix = NULL;
++  char *id = entry->filename;
++  char *dotconf = id;
++  char *hotkey = NULL;
++
++  char *users = NULL;
++  char **classes = NULL;
++
++  char **args = NULL;
++
++  char *src = NULL;
++  int i, index;
++
++  grub_dprintf("blscfg", "%s got here\n", __func__);
++  clinux = bls_get_val (entry, "linux", NULL);
++  if (!clinux)
++    {
++      grub_dprintf ("blscfg", "Skipping file %s with no 'linux' key.\n", entry->filename);
++      goto finish;
++    }
++
++  /*
++   * strip the ".conf" off the end before we make it our "id" field.
++   */
++  do
++    {
++      dotconf = grub_strstr(dotconf, ".conf");
++    } while (dotconf != NULL && dotconf[5] != '\0');
++  if (dotconf)
++    dotconf[0] = '\0';
++
++  title = bls_get_val (entry, "title", NULL);
++  options = expand_val (bls_get_val (entry, "options", NULL));
++
++  if (!options)
++    options = expand_val (grub_env_get("default_kernelopts"));
++
++  initrds = bls_make_list (entry, "initrd", NULL);
++
++  hotkey = bls_get_val (entry, "grub_hotkey", NULL);
++  users = expand_val (bls_get_val (entry, "grub_users", NULL));
++  classes = bls_make_list (entry, "grub_class", NULL);
++  args = bls_make_list (entry, "grub_arg", &argc);
++
++  argc += 1;
++  argv = grub_malloc ((argc + 1) * sizeof (char *));
++  argv[0] = title ? title : clinux;
++  for (i = 1; i < argc; i++)
++    argv[i] = args[i-1];
++  argv[argc] = NULL;
++
++  early_initrd = grub_env_get("early_initrd");
++
++  grub_dprintf ("blscfg", "adding menu entry for \"%s\" with id \"%s\"\n",
++              title, id);
++  if (early_initrd)
++    {
++      early_initrds = early_initrd_list(early_initrd);
++      if (!early_initrds)
++      {
++      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++      goto finish;
++      }
++
++      if (initrds != NULL && initrds[0] != NULL)
 +      {
-+        grub_free (options);
-+        options = grub_strdup (buf + 8);
-+        if (!options)
-+          goto finish;
++        initrd_prefix = grub_strrchr (initrds[0], '/');
++        initrd_prefix = grub_strndup(initrds[0], initrd_prefix - initrds[0] + 1);
 +      }
-+      else if (grub_strncmp (buf, "linux ", 6) == 0)
++      else
 +      {
-+        grub_free (clinux);
-+        clinux = grub_strdup (buf + 6);
-+        if (!clinux)
-+          goto finish;
++        initrd_prefix = grub_strrchr (clinux, '/');
++        initrd_prefix = grub_strndup(clinux, initrd_prefix - clinux + 1);
 +      }
-+      else if (grub_strncmp (buf, "initrd ", 7) == 0)
++
++      if (!initrd_prefix)
 +      {
-+        grub_free (initrd);
-+        initrd = grub_strdup (buf + 7);
-+        if (!initrd)
-+          goto finish;
++        grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++        goto finish;
 +      }
-+
-+      grub_free(buf);
 +    }
 +
-+  if (!linux)
++  if (early_initrds || initrds)
 +    {
-+      grub_printf ("Skipping file %s with no 'linux' key.", p);
-+      goto finish;
-+    }
++      int initrd_size = sizeof ("initrd");
++      char *tmp;
++
++      for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
++      initrd_size += sizeof (" " GRUB_BOOT_DEVICE) \
++                     + grub_strlen(initrd_prefix)  \
++                     + grub_strlen (early_initrds[i]) + 1;
++
++      for (i = 0; initrds != NULL && initrds[i] != NULL; i++)
++      initrd_size += sizeof (" " GRUB_BOOT_DEVICE) \
++                     + grub_strlen (initrds[i]) + 1;
++      initrd_size += 1;
++
++      initrd = grub_malloc (initrd_size);
++      if (!initrd)
++      {
++        grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
++        goto finish;
++      }
 +
-+  args[0] = title ? title : filename;
++
++      tmp = grub_stpcpy(initrd, "initrd");
++      for (i = 0; early_initrds != NULL && early_initrds[i] != NULL; i++)
++      {
++        grub_dprintf ("blscfg", "adding early initrd %s\n", early_initrds[i]);
++        tmp = grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
++        tmp = grub_stpcpy (tmp, initrd_prefix);
++        tmp = grub_stpcpy (tmp, early_initrds[i]);
++        grub_free(early_initrds[i]);
++      }
++
++      for (i = 0; initrds != NULL && initrds[i] != NULL; i++)
++      {
++        grub_dprintf ("blscfg", "adding initrd %s\n", initrds[i]);
++        tmp = grub_stpcpy (tmp, " " GRUB_BOOT_DEVICE);
++        tmp = grub_stpcpy (tmp, initrds[i]);
++      }
++      tmp = grub_stpcpy (tmp, "\n");
++    }
 +
 +  src = grub_xasprintf ("load_video\n"
-+                      "set gfx_payload=keep\n"
++                      "set gfxpayload=keep\n"
 +                      "insmod gzio\n"
-+                      GRUB_LINUX_CMD " %s%s%s%s\n"
-+                      "%s%s%s%s",
++                      "linux %s%s%s%s\n"
++                      "%s",
 +                      GRUB_BOOT_DEVICE, clinux, options ? " " : "", options ? options : "",
-+                      initrd ? GRUB_INITRD_CMD " " : "", initrd ? GRUB_BOOT_DEVICE : "", initrd ? initrd : "", initrd ? "\n" : "");
++                      initrd ? initrd : "");
 +
-+  grub_normal_add_menu_entry (1, args, NULL, NULL, "bls", NULL, NULL, src, 0);
++  grub_normal_add_menu_entry (argc, argv, classes, id, users, hotkey, NULL, src, 0, &index, entry);
++  grub_dprintf ("blscfg", "Added entry %d id:\"%s\"\n", index, id);
 +
 +finish:
-+  grub_free (p);
-+  grub_free (title);
-+  grub_free (options);
-+  grub_free (clinux);
 +  grub_free (initrd);
++  grub_free (initrd_prefix);
++  grub_free (early_initrds);
++  grub_free (initrds);
++  grub_free (options);
++  grub_free (classes);
++  grub_free (args);
++  grub_free (argv);
 +  grub_free (src);
++}
 +
-+  if (f)
-+    grub_file_close (f);
++struct find_entry_info {
++      const char *dirname;
++      const char *devid;
++      grub_device_t dev;
++      grub_fs_t fs;
++};
++
++/*
++ * info: the filesystem object the file is on.
++ */
++static int find_entry (struct find_entry_info *info)
++{
++  struct read_entry_info read_entry_info;
++  grub_fs_t blsdir_fs = NULL;
++  grub_device_t blsdir_dev = NULL;
++  const char *blsdir = info->dirname;
++  int fallback = 0;
++  int r = 0;
++
++  if (!blsdir) {
++    blsdir = grub_env_get ("blsdir");
++    if (!blsdir)
++      blsdir = GRUB_BLS_CONFIG_PATH;
++  }
++
++  read_entry_info.file = NULL;
++  read_entry_info.dirname = blsdir;
++
++  grub_dprintf ("blscfg", "scanning blsdir: %s\n", blsdir);
++
++  blsdir_dev = info->dev;
++  blsdir_fs = info->fs;
++  read_entry_info.devid = info->devid;
++
++read_fallback:
++  r = blsdir_fs->fs_dir (blsdir_dev, read_entry_info.dirname, read_entry,
++                       &read_entry_info);
++  if (r != 0) {
++      grub_dprintf ("blscfg", "read_entry returned error\n");
++      grub_err_t e;
++      do
++      {
++        e = grub_error_pop();
++      } while (e);
++  }
++
++  if (r && !info->dirname && !fallback) {
++    read_entry_info.dirname = "/boot" GRUB_BLS_CONFIG_PATH;
++    grub_dprintf ("blscfg", "Entries weren't found in %s, fallback to %s\n",
++                blsdir, read_entry_info.dirname);
++    fallback = 1;
++    goto read_fallback;
++  }
 +
 +  return 0;
 +}
 +
 +static grub_err_t
-+grub_cmd_bls_import (grub_extcmd_context_t ctxt __attribute__ ((unused)),
-+                   int argc __attribute__ ((unused)),
-+                   char **args __attribute__ ((unused)))
++bls_load_entries (const char *path)
 +{
++  grub_size_t len;
 +  grub_fs_t fs;
 +  grub_device_t dev;
 +  static grub_err_t r;
-+  const char *devid;
++  const char *devid = NULL;
++  char *blsdir = NULL;
++  struct find_entry_info info = {
++      .dev = NULL,
++      .fs = NULL,
++      .dirname = NULL,
++  };
++  struct read_entry_info rei = {
++      .devid = NULL,
++      .dirname = NULL,
++  };
++
++  if (path) {
++    len = grub_strlen (path);
++    if (grub_strcmp (path + len - 5, ".conf") == 0) {
++      rei.file = grub_file_open (path, GRUB_FILE_TYPE_CONFIG);
++      if (!rei.file)
++      return grub_errno;
++      /*
++       * read_entry() closes the file
++       */
++      return read_entry(path, NULL, &rei);
++    } else if (path[0] == '(') {
++      devid = path + 1;
++
++      blsdir = grub_strchr (path, ')');
++      if (!blsdir)
++      return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Filepath isn't correct"));
 +
-+  devid = grub_env_get ("root");
-+  if (!devid)
-+    return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "root");
++      *blsdir = '\0';
++      blsdir = blsdir + 1;
++    }
++  }
++
++  if (!devid) {
++#ifdef GRUB_MACHINE_EMU
++    devid = "host";
++#elif defined(GRUB_MACHINE_EFI)
++    devid = grub_env_get ("root");
++#else
++    devid = grub_env_get ("boot");
++#endif
++    if (!devid)
++      return grub_error (GRUB_ERR_FILE_NOT_FOUND,
++                       N_("variable `%s' isn't set"), "boot");
++  }
 +
++  grub_dprintf ("blscfg", "opening %s\n", devid);
 +  dev = grub_device_open (devid);
 +  if (!dev)
 +    return grub_errno;
 +
++  grub_dprintf ("blscfg", "probing fs\n");
 +  fs = grub_fs_probe (dev);
 +  if (!fs)
 +    {
@@ -221,7 +1032,11 @@ index 0000000..4274aca
 +      goto finish;
 +    }
 +
-+  r = fs->dir (dev, GRUB_BLS_CONFIG_PATH, parse_entry, NULL);
++  info.dirname = blsdir;
++  info.devid = devid;
++  info.dev = dev;
++  info.fs = fs;
++  find_entry(&info);
 +
 +finish:
 +  if (dev)
@@ -230,22 +1045,484 @@ index 0000000..4274aca
 +  return r;
 +}
 +
++static bool
++is_default_entry(const char *def_entry, struct bls_entry *entry, int idx)
++{
++  const char *title;
++  int def_idx;
++
++  if (!def_entry)
++    return false;
++
++  if (grub_strcmp(def_entry, entry->filename) == 0)
++    return true;
++
++  title = bls_get_val(entry, "title", NULL);
++
++  if (title && grub_strcmp(def_entry, title) == 0)
++    return true;
++
++  def_idx = (int)grub_strtol(def_entry, NULL, 0);
++  if (grub_errno == GRUB_ERR_BAD_NUMBER) {
++    grub_errno = GRUB_ERR_NONE;
++    return false;
++  }
++
++  if (def_idx == idx)
++    return true;
++
++  return false;
++}
++
++static grub_err_t
++bls_create_entries (bool show_default, bool show_non_default, char *entry_id)
++{
++  const char *def_entry = NULL;
++  struct bls_entry *entry = NULL;
++  int idx = 0;
++
++  def_entry = grub_env_get("default");
++
++  grub_dprintf ("blscfg", "%s Creating entries from bls\n", __func__);
++  FOR_BLS_ENTRIES(entry) {
++    if (entry->visible) {
++      idx++;
++      continue;
++    }
++
++    if ((show_default && is_default_entry(def_entry, entry, idx)) ||
++      (show_non_default && !is_default_entry(def_entry, entry, idx)) ||
++      (entry_id && grub_strcmp(entry_id, entry->filename) == 0)) {
++      create_entry(entry);
++      entry->visible = 1;
++    }
++    idx++;
++  }
++
++  return GRUB_ERR_NONE;
++}
++
++static grub_err_t
++grub_cmd_blscfg (grub_extcmd_context_t ctxt UNUSED,
++               int argc, char **args)
++{
++  grub_err_t r;
++  char *path = NULL;
++  char *entry_id = NULL;
++  bool show_default = true;
++  bool show_non_default = true;
++
++  if (argc == 1) {
++    if (grub_strcmp (args[0], "default") == 0) {
++      show_non_default = false;
++    } else if (grub_strcmp (args[0], "non-default") == 0) {
++      show_default = false;
++    } else if (args[0][0] == '(') {
++      path = args[0];
++    } else {
++      entry_id = args[0];
++      show_default = false;
++      show_non_default = false;
++    }
++  }
++
++  r = bls_load_entries(path);
++  if (r)
++    return r;
++
++  return bls_create_entries(show_default, show_non_default, entry_id);
++}
++
 +static grub_extcmd_t cmd;
++static grub_extcmd_t oldcmd;
 +
-+GRUB_MOD_INIT(bls)
++GRUB_MOD_INIT(blscfg)
 +{
-+  cmd = grub_register_extcmd ("bls_import",
-+                            grub_cmd_bls_import,
++  grub_dprintf("blscfg", "%s got here\n", __func__);
++  cmd = grub_register_extcmd ("blscfg",
++                            grub_cmd_blscfg,
 +                            0,
 +                            NULL,
 +                            N_("Import Boot Loader Specification snippets."),
 +                            NULL);
++  oldcmd = grub_register_extcmd ("bls_import",
++                               grub_cmd_blscfg,
++                               0,
++                               NULL,
++                               N_("Import Boot Loader Specification snippets."),
++                               NULL);
 +}
 +
-+GRUB_MOD_FINI(bls)
++GRUB_MOD_FINI(blscfg)
 +{
 +  grub_unregister_extcmd (cmd);
++  grub_unregister_extcmd (oldcmd);
 +}
--- 
-1.9.3
-
+diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c
+index db7a8f00273..891eac5a33f 100644
+--- a/grub-core/commands/legacycfg.c
++++ b/grub-core/commands/legacycfg.c
+@@ -133,7 +133,7 @@ legacy_file (const char *filename)
+           args[0] = oldname;
+           grub_normal_add_menu_entry (1, args, NULL, NULL, "legacy",
+                                       NULL, NULL,
+-                                      entrysrc, 0);
++                                      entrysrc, 0, NULL, NULL);
+           grub_free (args);
+           entrysrc[0] = 0;
+           grub_free (oldname);
+@@ -186,7 +186,8 @@ legacy_file (const char *filename)
+       }
+       args[0] = entryname;
+       grub_normal_add_menu_entry (1, args, NULL, NULL, NULL,
+-                                NULL, NULL, entrysrc, 0);
++                                NULL, NULL, entrysrc, 0, NULL,
++                                NULL);
+       grub_free (args);
+     }
+diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c
+index 3fd664aac33..163b9a09042 100644
+--- a/grub-core/commands/loadenv.c
++++ b/grub-core/commands/loadenv.c
+@@ -28,6 +28,8 @@
+ #include <grub/extcmd.h>
+ #include <grub/i18n.h>
++#include "loadenv.h"
++
+ GRUB_MOD_LICENSE ("GPLv3+");
+ static const struct grub_arg_option options[] =
+@@ -79,81 +81,6 @@ open_envblk_file (char *filename,
+   return file;
+ }
+-static grub_envblk_t
+-read_envblk_file (grub_file_t file)
+-{
+-  grub_off_t offset = 0;
+-  char *buf;
+-  grub_size_t size = grub_file_size (file);
+-  grub_envblk_t envblk;
+-
+-  buf = grub_malloc (size);
+-  if (! buf)
+-    return 0;
+-
+-  while (size > 0)
+-    {
+-      grub_ssize_t ret;
+-
+-      ret = grub_file_read (file, buf + offset, size);
+-      if (ret <= 0)
+-        {
+-          grub_free (buf);
+-          return 0;
+-        }
+-
+-      size -= ret;
+-      offset += ret;
+-    }
+-
+-  envblk = grub_envblk_open (buf, offset);
+-  if (! envblk)
+-    {
+-      grub_free (buf);
+-      grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
+-      return 0;
+-    }
+-
+-  return envblk;
+-}
+-
+-struct grub_env_whitelist
+-{
+-  grub_size_t len;
+-  char **list;
+-};
+-typedef struct grub_env_whitelist grub_env_whitelist_t;
+-
+-static int
+-test_whitelist_membership (const char* name,
+-                           const grub_env_whitelist_t* whitelist)
+-{
+-  grub_size_t i;
+-
+-  for (i = 0; i < whitelist->len; i++)
+-    if (grub_strcmp (name, whitelist->list[i]) == 0)
+-      return 1;  /* found it */
+-
+-  return 0;  /* not found */
+-}
+-
+-/* Helper for grub_cmd_load_env.  */
+-static int
+-set_var (const char *name, const char *value, void *whitelist)
+-{
+-  if (! whitelist)
+-    {
+-      grub_env_set (name, value);
+-      return 0;
+-    }
+-
+-  if (test_whitelist_membership (name,
+-                               (const grub_env_whitelist_t *) whitelist))
+-    grub_env_set (name, value);
+-
+-  return 0;
+-}
+-
+ static grub_err_t
+ grub_cmd_load_env (grub_extcmd_context_t ctxt, int argc, char **args)
+ {
+diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c
+index 2c5363da7f5..9faf2be0f64 100644
+--- a/grub-core/commands/menuentry.c
++++ b/grub-core/commands/menuentry.c
+@@ -78,7 +78,7 @@ grub_normal_add_menu_entry (int argc, const char **args,
+                           char **classes, const char *id,
+                           const char *users, const char *hotkey,
+                           const char *prefix, const char *sourcecode,
+-                          int submenu)
++                          int submenu, int *index, struct bls_entry *bls)
+ {
+   int menu_hotkey = 0;
+   char **menu_args = NULL;
+@@ -149,9 +149,12 @@ grub_normal_add_menu_entry (int argc, const char **args,
+   if (! menu_title)
+     goto fail;
++  grub_dprintf ("menu", "id:\"%s\"\n", id);
++  grub_dprintf ("menu", "title:\"%s\"\n", menu_title);
+   menu_id = grub_strdup (id ? : menu_title);
+   if (! menu_id)
+     goto fail;
++  grub_dprintf ("menu", "menu_id:\"%s\"\n", menu_id);
+   /* Save argc, args to pass as parameters to block arg later. */
+   menu_args = grub_malloc (sizeof (char*) * (argc + 1));
+@@ -170,8 +173,12 @@ grub_normal_add_menu_entry (int argc, const char **args,
+   }
+   /* Add the menu entry at the end of the list.  */
++  int ind=0;
+   while (*last)
+-    last = &(*last)->next;
++    {
++      ind++;
++      last = &(*last)->next;
++    }
+   *last = grub_zalloc (sizeof (**last));
+   if (! *last)
+@@ -188,8 +195,11 @@ grub_normal_add_menu_entry (int argc, const char **args,
+   (*last)->args = menu_args;
+   (*last)->sourcecode = menu_sourcecode;
+   (*last)->submenu = submenu;
++  (*last)->bls = bls;
+   menu->size++;
++  if (index)
++    *index = ind;
+   return GRUB_ERR_NONE;
+  fail:
+@@ -286,7 +296,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
+                                      users,
+                                      ctxt->state[2].arg, 0,
+                                      ctxt->state[3].arg,
+-                                     ctxt->extcmd->cmd->name[0] == 's');
++                                     ctxt->extcmd->cmd->name[0] == 's',
++                                     NULL, NULL);
+   src = args[argc - 1];
+   args[argc - 1] = NULL;
+@@ -303,7 +314,8 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args)
+                                 ctxt->state[0].args, ctxt->state[4].arg,
+                                 users,
+                                 ctxt->state[2].arg, prefix, src + 1,
+-                                ctxt->extcmd->cmd->name[0] == 's');
++                                ctxt->extcmd->cmd->name[0] == 's', NULL,
++                                NULL);
+   src[len - 1] = ch;
+   args[argc - 1] = src;
+diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c
+index 9ef98481f70..a326b192c89 100644
+--- a/grub-core/normal/main.c
++++ b/grub-core/normal/main.c
+@@ -20,6 +20,7 @@
+ #include <grub/kernel.h>
+ #include <grub/normal.h>
+ #include <grub/dl.h>
++#include <grub/menu.h>
+ #include <grub/misc.h>
+ #include <grub/file.h>
+ #include <grub/mm.h>
+@@ -70,6 +71,11 @@ grub_normal_free_menu (grub_menu_t menu)
+         grub_free (entry->args);
+       }
++      if (entry->bls)
++      {
++        entry->bls->visible = 0;
++      }
++
+       grub_free ((void *) entry->id);
+       grub_free ((void *) entry->users);
+       grub_free ((void *) entry->title);
+diff --git a/grub-core/commands/loadenv.h b/grub-core/commands/loadenv.h
+new file mode 100644
+index 00000000000..952f46121bd
+--- /dev/null
++++ b/grub-core/commands/loadenv.h
+@@ -0,0 +1,93 @@
++/* loadenv.c - command to load/save environment variable.  */
++/*
++ *  GRUB  --  GRand Unified Bootloader
++ *  Copyright (C) 2008,2009,2010  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/>.
++ */
++
++static grub_envblk_t UNUSED
++read_envblk_file (grub_file_t file)
++{
++  grub_off_t offset = 0;
++  char *buf;
++  grub_size_t size = grub_file_size (file);
++  grub_envblk_t envblk;
++
++  buf = grub_malloc (size);
++  if (! buf)
++    return 0;
++
++  while (size > 0)
++    {
++      grub_ssize_t ret;
++
++      ret = grub_file_read (file, buf + offset, size);
++      if (ret <= 0)
++        {
++          grub_free (buf);
++          return 0;
++        }
++
++      size -= ret;
++      offset += ret;
++    }
++
++  envblk = grub_envblk_open (buf, offset);
++  if (! envblk)
++    {
++      grub_free (buf);
++      grub_error (GRUB_ERR_BAD_FILE_TYPE, "invalid environment block");
++      return 0;
++    }
++
++  return envblk;
++}
++
++struct grub_env_whitelist
++{
++  grub_size_t len;
++  char **list;
++};
++typedef struct grub_env_whitelist grub_env_whitelist_t;
++
++static int UNUSED
++test_whitelist_membership (const char* name,
++                           const grub_env_whitelist_t* whitelist)
++{
++  grub_size_t i;
++
++  for (i = 0; i < whitelist->len; i++)
++    if (grub_strcmp (name, whitelist->list[i]) == 0)
++      return 1;  /* found it */
++
++  return 0;  /* not found */
++}
++
++/* Helper for grub_cmd_load_env.  */
++static int UNUSED
++set_var (const char *name, const char *value, void *whitelist)
++{
++  if (! whitelist)
++    {
++      grub_env_set (name, value);
++      return 0;
++    }
++
++  if (test_whitelist_membership (name,
++                               (const grub_env_whitelist_t *) whitelist))
++    grub_env_set (name, value);
++
++  return 0;
++}
+diff --git a/include/grub/compiler.h b/include/grub/compiler.h
+index c9e1d7a73dc..9859ff4cc79 100644
+--- a/include/grub/compiler.h
++++ b/include/grub/compiler.h
+@@ -48,4 +48,6 @@
+ #  define WARN_UNUSED_RESULT
+ #endif
++#define UNUSED __attribute__((__unused__))
++
+ #endif /* ! GRUB_COMPILER_HEADER */
+diff --git a/include/grub/menu.h b/include/grub/menu.h
+index ee2b5e91045..0acdc2aa6bf 100644
+--- a/include/grub/menu.h
++++ b/include/grub/menu.h
+@@ -20,6 +20,16 @@
+ #ifndef GRUB_MENU_HEADER
+ #define GRUB_MENU_HEADER 1
++struct bls_entry
++{
++  struct bls_entry *next;
++  struct bls_entry *prev;
++  struct keyval **keyvals;
++  int nkeyvals;
++  char *filename;
++  int visible;
++};
++
+ struct grub_menu_entry_class
+ {
+   char *name;
+@@ -60,6 +70,9 @@ struct grub_menu_entry
+   /* The next element.  */
+   struct grub_menu_entry *next;
++
++  /* BLS used to populate the entry */
++  struct bls_entry *bls;
+ };
+ typedef struct grub_menu_entry *grub_menu_entry_t;
+diff --git a/include/grub/normal.h b/include/grub/normal.h
+index 218cbabccaf..8839ad85a19 100644
+--- a/include/grub/normal.h
++++ b/include/grub/normal.h
+@@ -145,7 +145,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes,
+                           const char *id,
+                           const char *users, const char *hotkey,
+                           const char *prefix, const char *sourcecode,
+-                          int submenu);
++                          int submenu, int *index, struct bls_entry *bls);
+ grub_err_t
+ grub_normal_set_password (const char *user, const char *password);
index 21ed2267e2188a794cd659a435698fc2c0932db1..c9a66b1711f83d6b147592039455514dfc37cb68 100644 (file)
@@ -47,7 +47,7 @@ Summary(pl.UTF-8):    GRUB2 - bootloader dla x86 i ppc
 Summary(pt_BR.UTF-8):  Gerenciador de inicializaĆ§Ć£o GRUB2
 Name:          grub2
 Version:       2.04
-Release:       0.1
+Release:       1
 License:       GPL v2
 Group:         Base
 Source0:       ftp://ftp.gnu.org/gnu/grub/grub-%{version}.tar.xz
@@ -295,7 +295,7 @@ Motyw starfield dla GRUB-a.
 %patch11 -p1
 %patch12 -p0
 %patch13 -p1
-#%patch14 -p1
+%patch14 -p1
 
 # we don't have C.utf-8 and need an UTF-8 locale for build
 sed -i -e 's/LC_ALL=C.UTF-8/LC_ALL=en_US.utf-8/g' po/Makefile* po/Rules*
This page took 0.181539 seconds and 4 git commands to generate.