A Unified Kernel Image is a single UEFI PE file that combines a UEFI boot stub,
a Linux kernel image, an initrd, and further resources. The uki command will
locate where the uki file is and create a GRUB menu entry to load it.
Signed-off-by: Alec Brown <alec.r.br...@oracle.com>
---
 docs/grub.texi              |  26 +++
 grub-core/commands/blsuki.c | 438 +++++++++++++++++++++++++++++++++---
 include/grub/menu.h         |   2 +
 3 files changed, 440 insertions(+), 26 deletions(-)

diff --git a/docs/grub.texi b/docs/grub.texi
index ea7a13953..df206dad3 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -6491,6 +6491,7 @@ you forget a command, you can run the command 
@command{help}
 * tpm2_key_protector_clear::    Clear the TPM2 key protector
 * true::                        Do nothing, successfully
 * trust::                       Add public key to list of trusted keys
+* uki::                         Load Unified Kernel Image menu entries
 * unset::                       Unset an environment variable
 @comment * vbeinfo::                     List available video modes
 * verify_detached::             Verify detached digital signature
@@ -8166,6 +8167,31 @@ Unset the environment variable @var{envvar}.
 @end deffn
 
 
+@node uki
+@subsection uki
+
+@deffn Command uki [@option{--path} dir] [@option{--show-default}] 
[@option{--show-non-default}] [@option{--entry} file]
+Load Unified Kernel Image entries into the GRUB menu.
+
+The @option{--path} option overrides the default path to the directory 
containing
+the UKI entries. If this option isn't used, the default location is
+/EFI/Linux in the EFI system partition.
+
+The @option{--show-default} option allows the default boot entry to be added 
to the
+GRUB menu from the UKI entries.
+
+The @option{--show-non-default} option allows non-default boot entries to be 
added to
+the GRUB menu from the UKI entries.
+
+The @option{--entry} option allows specific boot entries to be added to the 
GRUB menu
+from the UKI entries.
+
+The @option{--entry}, @option{--show-default}, and @option{--show-non-default} 
options
+are used to filter which UKI entries are added to the GRUB menu. If none are
+used, all entries in the default location or the location specified by 
@option{--path}
+will be added to the GRUB menu.
+@end deffn
+
 @ignore
 @node vbeinfo
 @subsection vbeinfo
diff --git a/grub-core/commands/blsuki.c b/grub-core/commands/blsuki.c
index 7b7b3e0e4..77f59b530 100644
--- a/grub-core/commands/blsuki.c
+++ b/grub-core/commands/blsuki.c
@@ -32,6 +32,12 @@
 #include <grub/lib/envblk.h>
 #include <grub/lib/vercmp.h>
 
+#ifdef GRUB_MACHINE_EFI
+#include <grub/efi/efi.h>
+#include <grub/efi/disk.h>
+#include <grub/efi/pe32.h>
+#endif
+
 #ifdef GRUB_MACHINE_EMU
 #include <grub/emu/misc.h>
 #define GRUB_BOOT_DEVICE "/boot"
@@ -42,6 +48,13 @@
 GRUB_MOD_LICENSE ("GPLv3+");
 
 #define GRUB_BLS_CONFIG_PATH "/loader/entries/"
+#define GRUB_UKI_CONFIG_PATH "/EFI/Linux"
+
+enum
+  {
+    BLSUKI_BLS_CMD     = 1,
+    BLSUKI_UKI_CMD     = 2,
+  };
 
 static const struct grub_arg_option bls_opt[] =
   {
@@ -53,6 +66,18 @@ static const struct grub_arg_option bls_opt[] =
     {0, 0, 0, 0, 0, 0}
   };
 
+#ifdef GRUB_MACHINE_EFI
+static const struct grub_arg_option uki_opt[] =
+  {
+    {"path", 'p', 0, N_("Specify path to find UKI entries."), N_("DIR"), 
ARG_TYPE_PATHNAME},
+    {"enable-fallback", 'f', 0, "Fallback to the default BLS path if --path 
fails to find UKI entries.", 0, ARG_TYPE_NONE},
+    {"show-default", 'd', 0, N_("Allow the default UKI entry to be added to 
the GRUB menu."), 0, ARG_TYPE_NONE},
+    {"show-non-default", 'n', 0, N_("Allow the non-default UKI entries to be 
added to the GRUB menu."), 0, ARG_TYPE_NONE},
+    {"entry", 'e', 0, N_("Allow specificUKII entries to be added to the GRUB 
menu."), N_("FILE"), ARG_TYPE_FILE},
+    {0, 0, 0, 0, 0, 0}
+  };
+#endif
+
 struct keyval
 {
   const char *key;
@@ -291,10 +316,211 @@ bls_read_entry (grub_file_t f, grub_blsuki_entry_t 
*entry)
   return err;
 }
 
+#ifdef GRUB_MACHINE_EFI
+static grub_err_t
+uki_read_entry (grub_file_t f, grub_blsuki_entry_t *entry)
+{
+  struct grub_msdos_image_header *dos = NULL;
+  struct grub_pe_image_header *pe = NULL;
+  grub_off_t section_offset = 0;
+  struct grub_pe32_section_table *section = NULL;
+  struct grub_pe32_coff_header *coff_header = NULL;
+  char *val = NULL;
+  char *key = NULL;
+  const char *target[] = {".cmdline", ".osrel", ".linux", NULL};
+  bool has_linux = false;
+  grub_err_t err = GRUB_ERR_NONE;
+
+  dos = grub_zalloc (sizeof (*dos));
+  if (dos == NULL)
+    return grub_errno;
+  if (grub_file_read (f, dos, sizeof (*dos)) < (grub_ssize_t) sizeof (*dos))
+    {
+      err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read UKI image 
header");
+      goto fail;
+    }
+  if (dos->msdos_magic != GRUB_PE32_MAGIC)
+    {
+      err = grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("plain image kernel not 
supported"));
+      goto fail;
+    }
+
+  grub_dprintf ("blsuki", "PE/COFF header @ %08x\n", 
dos->pe_image_header_offset);
+  pe = grub_zalloc (sizeof (*pe));
+  if (pe == NULL)
+    {
+      err = grub_errno;
+      goto fail;
+    }
+  if (grub_file_seek (f, dos->pe_image_header_offset) == (grub_off_t) -1
+      || grub_file_read (f, pe, sizeof (*pe)) != sizeof (*pe))
+    {
+      err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read COFF image 
header");
+      goto fail;
+    }
+  if (pe->optional_header.magic != GRUB_PE32_NATIVE_MAGIC)
+    {
+      err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "non-native image not 
supported");
+      goto fail;
+    }
+
+  coff_header = &(pe->coff_header);
+  section_offset = dos->pe_image_header_offset + sizeof (*pe);
+
+  for (int i = 0; i < coff_header->num_sections; i++)
+    {
+      key = NULL;
+      val = NULL;
+      section = grub_zalloc (sizeof (*section));
+      if (section == NULL)
+       {
+         err = grub_errno;
+         goto fail;
+       }
+
+      grub_file_seek (f, section_offset);
+      if (grub_file_read (f, section, sizeof (*section)) != sizeof (*section))
+       {
+         err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read section 
header");
+         goto fail;
+       }
+
+      key = grub_strndup (section->name, 8);
+      if (key == NULL)
+       {
+         err = grub_errno;
+         goto fail;
+       }
+
+      for (int j = 0; target[j] != NULL; j++)
+       {
+         if (grub_strcmp (key, target[j]) == 0)
+           {
+             /*
+              * We don't need to read the contents of the .linux PE section, 
but we
+              * should verify that the section exists.
+              */
+             if (grub_strcmp (key, ".linux") == 0)
+               {
+                 has_linux = true;
+                 break;
+               }
+
+             val = grub_zalloc (section->raw_data_size);
+             if (val == NULL)
+               {
+                 err = grub_errno;
+                 goto fail;
+               }
+
+             grub_file_seek (f, section->raw_data_offset);
+             if (grub_file_read (f, val, section->raw_data_size) != 
(grub_ssize_t) section->raw_data_size)
+               {
+                 err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read 
section");
+                 goto fail;
+               }
+
+             err = blsuki_add_keyval (entry, key, val);
+             if (err != GRUB_ERR_NONE)
+               goto fail;
+
+             break;
+           }
+       }
+
+      section_offset += sizeof (*section);
+      grub_free (section);
+      grub_free (val);
+      grub_free (key);
+    }
+
+  if (has_linux == false)
+    err = grub_error (GRUB_ERR_NO_KERNEL, "UKI is missing the '.linux' 
section");
+
+  grub_free (dos);
+  grub_free (pe);
+  return err;
+
+ fail:
+  grub_free (dos);
+  grub_free (pe);
+  grub_free (section);
+  grub_free (val);
+  grub_free (key);
+  return err;
+}
+#endif
+
+static char *
+uki_read_osrel (char *content, grub_off_t *pos, char **key_ret, char **val_ret)
+{
+  char *line;
+  char *value;
+  grub_size_t linelen;
+
+ skip:
+  line = content + *pos;
+  if (*line == '\0')
+    return NULL;
+
+  linelen = 0;
+  while (line[linelen] != '\0' && line[linelen] != '\n' && line[linelen] != 
'\r')
+    linelen++;
+
+  /* Move pos to the next line */
+  *pos += linelen;
+  if (content[*pos] != '\0')
+    (*pos)++;
+
+  /* Skip empty line */
+  if (linelen == 0)
+    goto skip;
+
+  line[linelen] = '\0';
+
+  /* Remove leading white space */
+  while (linelen > 0 && (*line == ' ' || *line == '\t'))
+    {
+      line++;
+      linelen--;
+    }
+
+  /* Remove trailing whitespace */
+  while (linelen > 0 && (line[linelen - 1] == ' ' || line[linelen - 1] == 
'\t'))
+    linelen--;
+  line[linelen] = '\0';
+
+  if (*line == '#')
+    goto skip;
+
+  /* Split key/value */
+  value = line;
+  while (*value != '\0' && *value != '=')
+    value++;
+  if (*value == '\0')
+    goto skip;
+  *value = '\0';
+  value++;
+  while (*value != '\0' && *value == '=')
+    value++;
+
+  /* Remove quotes from value */
+  if (*value == '\"' && line[linelen - 1] == '\"')
+    {
+      value++;
+      line[linelen - 1] = '\0';
+    }
+
+  *key_ret = line;
+  *val_ret = value;
+  return line;
+}
+
 struct read_entry_info
 {
   const char *devid;
   const char *dirname;
+  int cmd_type;
   grub_file_t file;
 };
 
@@ -304,9 +530,11 @@ blsuki_read_entry (const char *filename,
                   void *data)
 {
   grub_size_t m = 0, n, ext_len = 5;
-  grub_err_t err;
+  grub_err_t err = GRUB_ERR_NONE;
   char *p = NULL;
+  const char *ext = NULL;
   grub_file_t f = NULL;
+  enum grub_file_type file_type = 0;
   grub_blsuki_entry_t *entry;
   struct read_entry_info *info = (struct read_entry_info *) data;
 
@@ -314,6 +542,18 @@ blsuki_read_entry (const char *filename,
 
   n = grub_strlen (filename);
 
+  if (info->cmd_type == BLSUKI_BLS_CMD)
+    {
+      ext = ".conf";
+      file_type = GRUB_FILE_TYPE_CONFIG;
+    }
+  else if (info->cmd_type == BLSUKI_UKI_CMD)
+    {
+      ext = ".efi";
+      file_type = GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE;
+    }
+  ext_len = grub_strlen (ext);
+
   if (info->file != NULL)
     {
       f = info->file;
@@ -323,15 +563,14 @@ blsuki_read_entry (const char *filename,
       if (filename[0] == '.')
        return 0;
 
-      if (n <= 5)
+      if (n <= ext_len)
        return 0;
 
-      if (grub_strcmp (filename + n - ext_len, ".conf") != 0)
+      if (grub_strcmp (filename + n - ext_len, ext) != 0)
        return 0;
 
       p = grub_xasprintf ("(%s)%s/%s", info->devid, info->dirname, filename);
-
-      f = grub_file_open (p, GRUB_FILE_TYPE_CONFIG);
+      f = grub_file_open (p, file_type);
       grub_free (p);
       if (f == NULL)
        goto finish;
@@ -368,7 +607,26 @@ blsuki_read_entry (const char *filename,
       goto finish;
     }
 
-  err = bls_read_entry (f, entry);
+  entry->dirname = grub_strdup (info->dirname);
+  if (entry->dirname == NULL)
+    {
+      grub_free (entry);
+      goto finish;
+    }
+
+  entry->devid = grub_strdup (info->devid);
+  if (entry->devid == NULL)
+    {
+      grub_free (entry);
+      goto finish;
+    }
+
+  if (info->cmd_type == BLSUKI_BLS_CMD)
+    err = bls_read_entry (f, entry);
+#ifdef GRUB_MACHINE_EFI
+  else if (info->cmd_type == BLSUKI_UKI_CMD)
+    err = uki_read_entry (f, entry);
+#endif
 
   if (err == GRUB_ERR_NONE)
     blsuki_add_entry (entry);
@@ -820,6 +1078,71 @@ bls_create_entry (grub_blsuki_entry_t *entry)
   grub_free (src);
 }
 
+static void
+uki_create_entry (grub_blsuki_entry_t *entry)
+{
+  int argc = 0;
+  const char **argv = NULL;
+  char *id = entry->filename;
+  char *title = NULL;
+  char *options = NULL;
+  char *osrel = NULL;
+  char *line;
+  char *key = NULL;
+  char *value = NULL;
+  char *src = NULL;
+  grub_size_t size = 0;
+  grub_off_t pos = 0;
+
+  options = blsuki_get_val (entry, ".cmdline", NULL);
+  if (options == NULL)
+    {
+      grub_dprintf ("blsuki", "Skipping file %s with no '.cmdline' key.\n", 
entry->filename);
+      goto finish;
+    }
+  osrel = blsuki_get_val (entry, ".osrel", NULL);
+  if (osrel == NULL)
+    {
+      grub_dprintf ("blsuki", "Skipping file %s with no '.osrel' key.\n", 
entry->filename);
+      goto finish;
+    }
+
+  line = osrel;
+  while ((line = uki_read_osrel (osrel, &pos, &key, &value)))
+    {
+      if (grub_strcmp ("PRETTY_NAME", key) == 0)
+       {
+         title = value;
+         break;
+       }
+    }
+
+  argc += 1;
+  if (grub_mul (argc + 1, sizeof (char *), &size))
+    {
+      grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected creating argv 
list");
+      goto finish;
+    }
+  argv = grub_malloc (size);
+  if (argv == NULL)
+    goto finish;
+  argv[0] = title;
+  argv[argc] = NULL;
+
+  src = grub_xasprintf ("chainloader (%s)%s/%s%s%s\n",
+                       entry->devid, entry->dirname,
+                       entry->filename, options ? " " : "", options ? options 
: "");
+
+
+  grub_normal_add_menu_entry (argc, argv, NULL, id, NULL, NULL, NULL, src, 0, 
entry);
+
+ finish:
+  grub_free (argv);
+  grub_free (src);
+  grub_free (options);
+  grub_free (osrel);
+}
+
 struct find_entry_info
 {
   const char *dirname;
@@ -829,7 +1152,7 @@ struct find_entry_info
 };
 
 static grub_err_t
-blsuki_set_find_entry_info (struct find_entry_info *info, const char *dirname, 
const char *devid)
+blsuki_set_find_entry_info (struct find_entry_info *info, const char *dirname, 
const char *devid, int cmd_type)
 {
   grub_device_t dev;
   grub_fs_t fs;
@@ -839,10 +1162,21 @@ blsuki_set_find_entry_info (struct find_entry_info 
*info, const char *dirname, c
 
   if (devid == NULL)
     {
+      if (cmd_type == BLSUKI_BLS_CMD)
+       {
 #ifdef GRUB_MACHINE_EMU
-      devid = "host";
+         devid = "host";
 #else
-      devid = grub_env_get ("root");
+         devid = grub_env_get ("root");
+#endif
+       }
+#ifdef GRUB_MACHINE_EFI
+      else if (cmd_type == BLSUKI_UKI_CMD)
+       {
+         grub_efi_loaded_image_t *image;
+         image = grub_efi_get_loaded_image (grub_efi_image_handle);
+         devid = grub_efidisk_get_device_name (image->device_handle);
+       }
 #endif
       if (devid == NULL)
        return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't 
set"), "root");
@@ -882,10 +1216,11 @@ blsuki_set_find_entry_info (struct find_entry_info 
*info, const char *dirname, c
 
 /* info: the filesystem object the file is on. */
 static grub_err_t
-blsuki_find_entry (struct find_entry_info *info, bool enable_fallback)
+blsuki_find_entry (struct find_entry_info *info, bool enable_fallback, int 
cmd_type)
 {
   struct read_entry_info read_entry_info;
   char *default_dir = NULL;
+  const char *cmd_dir = NULL;
   char *tmp;
   grub_size_t default_size;
   grub_fs_t dir_fs = NULL;
@@ -901,6 +1236,7 @@ blsuki_find_entry (struct find_entry_info *info, bool 
enable_fallback)
   dir_dev = info->dev;
   dir_fs = info->fs;
   read_entry_info.devid = info->devid;
+  read_entry_info.cmd_type = cmd_type;
 
   r = dir_fs->fs_dir (dir_dev, read_entry_info.dirname, blsuki_read_entry,
                      &read_entry_info);
@@ -913,11 +1249,17 @@ blsuki_find_entry (struct find_entry_info *info, bool 
enable_fallback)
   /*
    * If we aren't able to find BLS entries in the directory given by 
info->dirname,
    * we can fallback to the default location "/boot/loader/entries/" and see 
if we
-   * can find the files there.
+   * can find the files there. If we can't find UKI entries, fallback to
+   * "/boot/efi/EFI/Linux".
    */
   if (entries == NULL && fallback == 0 && enable_fallback == true)
     {
-      if (grub_add (grub_strlen (GRUB_BOOT_DEVICE), grub_strlen 
(GRUB_BLS_CONFIG_PATH), &default_size))
+      if (cmd_type == BLSUKI_BLS_CMD)
+       cmd_dir = GRUB_BLS_CONFIG_PATH;
+      else if (cmd_type == BLSUKI_UKI_CMD)
+       cmd_dir = GRUB_UKI_CONFIG_PATH;
+
+      if (grub_add (grub_strlen (GRUB_BOOT_DEVICE), grub_strlen (cmd_dir), 
&default_size))
        return grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected 
calculating default directory buffer size");
 
       default_dir = grub_malloc (default_size);
@@ -925,9 +1267,9 @@ blsuki_find_entry (struct find_entry_info *info, bool 
enable_fallback)
        return grub_errno;
 
       tmp = blsuki_update_boot_device (default_dir);
-      tmp = grub_stpcpy (tmp, GRUB_BLS_CONFIG_PATH);
+      tmp = grub_stpcpy (tmp, cmd_dir);
 
-      blsuki_set_find_entry_info (info, default_dir, NULL);
+      blsuki_set_find_entry_info (info, default_dir, NULL, cmd_type);
       grub_dprintf ("blsuki", "Entries weren't found in %s, fallback to %s\n",
                    read_entry_info.dirname, info->dirname);
       fallback = 1;
@@ -939,15 +1281,18 @@ blsuki_find_entry (struct find_entry_info *info, bool 
enable_fallback)
 }
 
 static grub_err_t
-blsuki_load_entries (char *path, bool enable_fallback)
+blsuki_load_entries (char *path, bool enable_fallback, int cmd_type)
 {
   grub_size_t len;
+  grub_size_t ext_len;
   static grub_err_t r;
   const char *devid = NULL;
   char *dir = NULL;
   char *default_dir = NULL;
   char *tmp;
+  const char *cmd_dir = NULL;
   grub_size_t dir_size;
+  const char *ext = NULL;
   struct find_entry_info info = {
       .dev = NULL,
       .fs = NULL,
@@ -956,12 +1301,19 @@ blsuki_load_entries (char *path, bool enable_fallback)
   struct read_entry_info rei = {
       .devid = NULL,
       .dirname = NULL,
+      .cmd_type = cmd_type,
   };
 
   if (path != NULL)
     {
+      if (cmd_type == BLSUKI_BLS_CMD)
+       ext = ".conf";
+      else if (cmd_type == BLSUKI_UKI_CMD)
+       ext = ".efi";
+
       len = grub_strlen (path);
-      if (grub_strcmp (path + len - 5, ".conf") == 0)
+      ext_len = grub_strlen (ext);
+      if (grub_strcmp (path + len - ext_len, ext) == 0)
        {
          rei.file = grub_file_open (path, GRUB_FILE_TYPE_CONFIG);
          if (rei.file == NULL)
@@ -990,7 +1342,12 @@ blsuki_load_entries (char *path, bool enable_fallback)
 
   if (dir == NULL)
     {
-      if (grub_add (grub_strlen (GRUB_BOOT_DEVICE), grub_strlen 
(GRUB_BLS_CONFIG_PATH), &dir_size))
+      if (cmd_type == BLSUKI_BLS_CMD)
+       cmd_dir = GRUB_BLS_CONFIG_PATH;
+      else if (cmd_type == BLSUKI_UKI_CMD)
+       cmd_dir = GRUB_UKI_CONFIG_PATH;
+
+      if (grub_add (grub_strlen (GRUB_BOOT_DEVICE), grub_strlen (cmd_dir), 
&dir_size))
        return grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow detected 
calculating default directory buffer size");
 
       default_dir = grub_malloc (dir_size);
@@ -998,13 +1355,13 @@ blsuki_load_entries (char *path, bool enable_fallback)
        return grub_errno;
 
       tmp = blsuki_update_boot_device (default_dir);
-      tmp = grub_stpcpy (tmp, GRUB_BLS_CONFIG_PATH);
+      tmp = grub_stpcpy (tmp, cmd_dir);
       dir = default_dir;
     }
 
-  r = blsuki_set_find_entry_info (&info, dir, devid);
+  r = blsuki_set_find_entry_info (&info, dir, devid, cmd_type);
   if (r == GRUB_ERR_NONE)
-    r = blsuki_find_entry (&info, enable_fallback);
+    r = blsuki_find_entry (&info, enable_fallback, cmd_type);
 
   if (info.dev != NULL)
     grub_device_close (info.dev);
@@ -1044,7 +1401,7 @@ blsuki_is_default_entry (const char *def_entry, 
grub_blsuki_entry_t *entry, int
 }
 
 static grub_err_t
-blsuki_create_entries (bool show_default, bool show_non_default, char 
*entry_id)
+blsuki_create_entries (bool show_default, bool show_non_default, char 
*entry_id, int cmd_type)
 {
   const char *def_entry = NULL;
   grub_blsuki_entry_t *entry = NULL;
@@ -1063,7 +1420,10 @@ blsuki_create_entries (bool show_default, bool 
show_non_default, char *entry_id)
          (show_non_default == true && blsuki_is_default_entry (def_entry, 
entry, idx) == false) ||
          (entry_id != NULL && grub_strcmp (entry_id, entry->filename) == 0))
        {
-         bls_create_entry (entry);
+         if (cmd_type == BLSUKI_BLS_CMD)
+           bls_create_entry (entry);
+         else if (cmd_type == BLSUKI_UKI_CMD)
+           uki_create_entry (entry);
          entry->visible = 1;
        }
       idx++;
@@ -1073,8 +1433,7 @@ blsuki_create_entries (bool show_default, bool 
show_non_default, char *entry_id)
 }
 
 static grub_err_t
-grub_cmd_blscfg (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)),
-                char **args __attribute__ ((unused)))
+blsuki_cmd (grub_extcmd_context_t ctxt, int cmd_type)
 {
   grub_err_t err;
   struct grub_arg_list *state = ctxt->state;
@@ -1084,6 +1443,7 @@ grub_cmd_blscfg (grub_extcmd_context_t ctxt, int argc 
__attribute__ ((unused)),
   bool show_default = false;
   bool show_non_default = false;
   bool all = true;
+  entries = NULL;
 
   if (state[0].set)
     path = state[0].arg;
@@ -1110,24 +1470,50 @@ grub_cmd_blscfg (grub_extcmd_context_t ctxt, int argc 
__attribute__ ((unused)),
       show_non_default = true;
     }
 
-  err = blsuki_load_entries (path, enable_fallback);
+  err = blsuki_load_entries (path, enable_fallback, cmd_type);
   if (err != GRUB_ERR_NONE)
     return err;
 
-  return blsuki_create_entries (show_default, show_non_default, entry_id);
+  return blsuki_create_entries (show_default, show_non_default, entry_id, 
cmd_type);
+}
+
+static grub_err_t
+grub_cmd_blscfg (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)),
+                char **args __attribute__ ((unused)))
+{
+  return blsuki_cmd (ctxt, BLSUKI_BLS_CMD);
 }
 
 static grub_extcmd_t bls_cmd;
 
+#ifdef GRUB_MACHINE_EFI
+static grub_err_t
+grub_cmd_uki (grub_extcmd_context_t ctxt, int argc __attribute__ ((unused)),
+                char **args __attribute__ ((unused)))
+{
+  return blsuki_cmd (ctxt, BLSUKI_UKI_CMD);
+}
+
+static grub_extcmd_t uki_cmd;
+#endif
+
 GRUB_MOD_INIT(blsuki)
 {
   bls_cmd = grub_register_extcmd ("blscfg", grub_cmd_blscfg, 0,
                                  N_("[-p|--path] [-f|--enable-fallback] DIR 
[-d|--show-default] [-n|--show-non-default] [-e|--entry] FILE"),
                                  N_("Import Boot Loader Specification 
snippets."),
                                  bls_opt);
+#ifdef GRUB_MACHINE_EFI
+  uki_cmd = grub_register_extcmd ("uki", grub_cmd_uki, 0,
+                                 N_("[-p|--path] DIR [-f|--enable-fallback] 
[-d|--show-default] [-n|--show-non-default] [-e|--entry] FILE"),
+                                 N_("Import Unified Kernel Images"), uki_opt);
+#endif
 }
 
 GRUB_MOD_FINI(blsuki)
 {
   grub_unregister_extcmd (bls_cmd);
+#ifdef GRUB_MACHINE_EFI
+  grub_unregister_extcmd (uki_cmd);
+#endif
 }
diff --git a/include/grub/menu.h b/include/grub/menu.h
index c25a0d16d..907373625 100644
--- a/include/grub/menu.h
+++ b/include/grub/menu.h
@@ -28,6 +28,8 @@ struct grub_blsuki_entry
   grub_size_t keyvals_size;
   int nkeyvals;
   char *filename;
+  char *dirname;
+  char *devid;
   int visible;
 };
 typedef struct grub_blsuki_entry grub_blsuki_entry_t;
-- 
2.27.0


_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to