On Sun, Jul 27, 2025 at 01:54:36AM +0000, Alec Brown wrote: > 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. > > The Unified Kernel Image Specification: > https://uapi-group.org/specifications/specs/unified_kernel_image/ > > Signed-off-by: Alec Brown <alec.r.br...@oracle.com> > --- > docs/grub.texi | 33 +++ > grub-core/commands/blsuki.c | 453 +++++++++++++++++++++++++++++++++--- > include/grub/menu.h | 2 + > 3 files changed, 450 insertions(+), 38 deletions(-) > > diff --git a/docs/grub.texi b/docs/grub.texi > index 1186f274f..5d9217057 100644 > --- a/docs/grub.texi > +++ b/docs/grub.texi > @@ -6495,6 +6495,7 @@ you forget a command, you can run the command > @command{help} > * tpm2_dump_pcr:: Dump TPM2 PCRs > * 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 > @@ -8247,6 +8248,38 @@ Unset the environment variable @var{envvar}. > @end deffn > > > +@node uki > +@subsection uki > + > +@deffn Command uki [@option{-p|--path} dir] [@option{-f|--enable-fallback}] > [@option{-d|--show-default}] [@option{-n|--show-non-default}] > [@option{-e|--entry} file] > +Load Unified Kernel Image (UKI) entries into the GRUB menu. Boot entries > +generated from @command{uki} won't interfere with entries from > @file{grub.cfg} appearing in the > +GRUB menu. Also, entries generated from @command{uki} exists only in memory > and don't > +update @file{grub.cfg}. > + > +By default, the UKI entries are stored in the @file{/EFI/Linux} directory in > the EFI
"entries"? I think you mean UKI "files"? The GRUB generates "UKI entires" from "UKI files". I think this should be fixed in the doc snippet. > +system partition. If UKI entries are stored elsewhere, the @option{--path} > option can be > +used to check a different directory instead of the default location. If no > UKI > +entries are found while using the @option{--path} option, the > @option{--enable-fallback} option > +can be used to check for entries in the default location. > + > +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. > + > +For more information on UKI, see: > @uref{https://uapi-group.org/specifications/specs/unified_kernel_image/, The > Unified Kernel Image Specification} > +@end deffn > + > @ignore > @node vbeinfo > @subsection vbeinfo > diff --git a/grub-core/commands/blsuki.c b/grub-core/commands/blsuki.c > index 76615e9bc..86a72cd0b 100644 > --- a/grub-core/commands/blsuki.c > +++ b/grub-core/commands/blsuki.c > @@ -32,6 +32,12 @@ > #include <grub/lib/envblk.h> > #include <filevercmp.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,10 +48,19 @@ > GRUB_MOD_LICENSE ("GPLv3+"); > > #define GRUB_BLS_CONFIG_PATH "/loader/entries/" > +#define GRUB_UKI_CONFIG_PATH "/EFI/Linux" > > #define BLS_EXT_LEN (sizeof (".conf") - 1) > +#define UKI_EXT_LEN (sizeof (".efi") - 1) > > #define BLSUKI_KEYVALS_MAX 10000 > +#define UKI_SECTION_SIZE_MAX 10000 I think these MAX values require some comments. Where do they come from? Why not 20000 or 25000? This should be explained. > +enum blsuki_cmd_type > + { > + BLSUKI_BLS_CMD, > + BLSUKI_UKI_CMD, > + }; > > static const struct grub_arg_option bls_opt[] = > { > @@ -57,6 +72,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; > @@ -67,6 +94,7 @@ struct read_entry_info > { > const char *devid; > const char *dirname; > + enum blsuki_cmd_type cmd_type; > grub_file_t file; > }; > > @@ -78,7 +106,7 @@ struct find_entry_info > grub_fs_t fs; > }; > > -static grub_blsuki_entry_t *entries; > +static grub_blsuki_entry_t *entries = NULL; > > #define FOR_BLSUKI_ENTRIES(var) FOR_LIST_ELEMENTS (var, entries) > > @@ -183,7 +211,7 @@ blsuki_add_keyval (grub_blsuki_entry_t *entry, char *key, > char *val) > * Find the value of the key named by keyname. If there are allowed to be > * more than one, pass a pointer set to -1 to the last parameter 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. > + * them in sorted order. > */ > static char * > blsuki_get_val (grub_blsuki_entry_t *entry, const char *keyname, int *last) > @@ -312,20 +340,213 @@ bls_parse_keyvals (grub_file_t f, grub_blsuki_entry_t > *entry) > return err; > } > > +/* > + * This function searches for the .cmdline, .osrel, and .linux sections of a > + * UKI. We only need to store the data for the .cmdline and .osrel sections, > + * but we also need to verify that the .linux section exists. > + */ > +#ifdef GRUB_MACHINE_EFI > +static grub_err_t > +uki_parse_keyvals (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 finish; > + } > + if (dos->msdos_magic != GRUB_PE32_MAGIC) > + { > + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "plain image kernel is not > supported"); > + goto finish; > + } > + > + 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 finish; > + } > + 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 finish; > + } > + if (pe->optional_header.magic != GRUB_PE32_NATIVE_MAGIC) > + { > + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "non-native image not > supported"); > + goto finish; > + } > + > + 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; These two assignments seem redundant to me... > + section = grub_zalloc (sizeof (*section)); > + if (section == NULL) > + { > + err = grub_errno; > + goto finish; > + } > + > + if (grub_file_seek (f, section_offset) == (grub_off_t) -1 || > + grub_file_read (f, section, sizeof (*section)) != sizeof > (*section)) > + { > + err = grub_error (GRUB_ERR_FILE_READ_ERROR, "failed to read section > header"); > + goto finish; > + } > + > + key = grub_strndup (section->name, 8); > + if (key == NULL) > + { > + err = grub_errno; > + goto finish; > + } > + > + 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; > + } > + > + if (section->raw_data_size > UKI_SECTION_SIZE_MAX) > + { > + err = grub_error (GRUB_ERR_BAD_NUMBER, "UKI section size is > larger than expected"); > + goto finish; > + } > + > + val = grub_zalloc (section->raw_data_size); > + if (val == NULL) > + { > + err = grub_errno; > + goto finish; > + } > + > + if (grub_file_seek (f, section->raw_data_offset) == (grub_off_t) > -1 || > + 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 finish; > + } > + > + err = blsuki_add_keyval (entry, key, val); > + if (err != GRUB_ERR_NONE) > + goto finish; > + > + break; > + } > + } > + > + section_offset += sizeof (*section); > + grub_free (section); > + grub_free (val); > + grub_free (key); > + section = NULL; > + val = NULL; > + key = NULL; > + } > + > + if (has_linux == false) > + err = grub_error (GRUB_ERR_NO_KERNEL, "UKI is missing the '.linux' > section"); > + > + finish: > + grub_free (dos); > + grub_free (pe); > + grub_free (section); > + grub_free (val); > + grub_free (key); > + return err; > +} > +#endif > + > +/* > + * This function obtains the keyval pairs when the .osrel data is input into > + * the osrel_ptr parameter and returns the keyval pair. Since we are using > + * grub_strtok_r(), the osrel_ptr will be updated to the following line of > + * osrel. This function returns NULL when it reaches the end of osrel. > + */ > +static char * > +uki_read_osrel (char **osrel_ptr, char **val_ret) > +{ > + char *key, *val; > + grub_size_t val_size; > + > + for (;;) > + { > + key = grub_strtok_r (NULL, "\n\r", osrel_ptr); > + if (key == NULL) > + return NULL; > + > + /* Remove leading white space */ > + while (*key == ' ' || *key == '\t') > + key++; > + > + /* Skip commented lines */ > + if (*key == '#') > + continue; > + > + /* Split key/value */ > + key = grub_strtok_r (key, "=", &val); > + if (key == NULL || *val == '\0') > + continue; > + > + /* Remove quotes from value */ > + val_size = grub_strlen (val); > + if (*val == '\"' && val[val_size - 1] == '\"') Does it matter if somebody puts quotes into middle of the string? What about single quotes? > + { > + val[val_size - 1] = '\0'; > + val++; > + } > + > + *val_ret = val; > + break; > + } > + > + return key; > +} > + > /* > * If a file hasn't already been opened, this function opens a BLS config > file > - * and initializes entry data before parsing keyvals and adding the entry to > - * the list of BLS entries. > + * or UKI and initializes entry data before parsing keyvals and adding the > entry > + * to the list of BLS or UKI entries. > */ > static int > blsuki_read_entry (const char *filename, > const struct grub_dirhook_info *dirhook_info __attribute__ > ((__unused__)), > void *data) > { > - grub_size_t path_len = 0, filename_len; > - grub_err_t err; > + grub_size_t path_len = 0, ext_len = 0, filename_len; > + 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; > > @@ -333,17 +554,29 @@ blsuki_read_entry (const char *filename, > > filename_len = grub_strlen (filename); > > + if (info->cmd_type == BLSUKI_BLS_CMD) > + { > + ext = ".conf"; > + ext_len = BLS_EXT_LEN; > + file_type = GRUB_FILE_TYPE_CONFIG; > + } > + else if (info->cmd_type == BLSUKI_UKI_CMD) > + { > + ext = ".efi"; > + ext_len = UKI_EXT_LEN; > + file_type = GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE; Should not we fail here immediately on non-UEFI platforms? Or probably it should be disabled in that case... > + } > + > if (info->file != NULL) > f = info->file; > else > { > - if (filename_len < BLS_EXT_LEN || > - grub_strcmp (filename + filename_len - BLS_EXT_LEN, ".conf") != 0) > + if (filename_len < ext_len || > + grub_strcmp (filename + filename_len - 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; > @@ -380,7 +613,26 @@ blsuki_read_entry (const char *filename, > goto finish; > } > > - err = bls_parse_keyvals (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_parse_keyvals (f, entry); > +#ifdef GRUB_MACHINE_EFI > + else if (info->cmd_type == BLSUKI_UKI_CMD) > + err = uki_parse_keyvals (f, entry); > +#endif > > if (err == GRUB_ERR_NONE) > blsuki_add_entry (entry); > @@ -396,7 +648,7 @@ blsuki_read_entry (const char *filename, > > /* > * This function returns a list of values that had the same key in the BLS > - * config file. The number of entries in this list is returned by the len > + * config file or UKI. The number of entries in this list is returned by the > len > * parameter. > */ > static char ** > @@ -786,6 +1038,63 @@ bls_create_entry (grub_blsuki_entry_t *entry) > grub_free (src); > } > > +/* > + * This function puts together the section data recieved from the UKI and > + * generates a new entry un the GRUB boot menu. s/un/in/ > + */ > +static void > +uki_create_entry (grub_blsuki_entry_t *entry) > +{ > + const char **argv = NULL; > + char *id = entry->filename; > + char *title = NULL; > + char *options = NULL; > + char *osrel, *osrel_line; > + char *key = NULL; > + char *value = NULL; > + char *src = NULL; > + > + /* > + * Although .osrel is listed as optional in the UKI specification, the > .osrel > + * section is needed to generate the GRUB menu entry title. > + */ > + 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; > + } > + > + osrel_line = osrel; > + while ((key = uki_read_osrel (&osrel_line, &value))) (key = uki_read_osrel (&osrel_line, &value)) != NULL > + { > + if (grub_strcmp ("PRETTY_NAME", key) == 0) > + { > + title = value; > + break; > + } > + } > + > + options = blsuki_get_val (entry, ".cmdline", NULL); > + > + argv = grub_zalloc (2 * sizeof (char *)); > + if (argv == NULL) > + goto finish; > + argv[0] = title; > + > + src = grub_xasprintf ("chainloader (%s)%s/%s%s%s\n", > + entry->devid, entry->dirname, > + entry->filename, options ? " " : "", options ? options > : ""); (options != NULL) ? " " : "", (options != NULL) ? options : "" > + > + grub_normal_add_menu_entry (1, argv, NULL, id, NULL, NULL, NULL, src, 0, > entry); > + > + finish: > + grub_free (argv); > + grub_free (src); > + grub_free (options); > + grub_free (osrel); > +} > + > /* > * This function fills a find_entry_info struct passed in by the info > parameter. > * If the dirname or devid parameters are set to NULL, the dirname and devid > @@ -795,7 +1104,7 @@ bls_create_entry (grub_blsuki_entry_t *entry) > * device. > */ > 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, enum blsuki_cmd_type cmd_type) > { > grub_device_t dev; > grub_fs_t fs; > @@ -805,10 +1114,23 @@ 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; Please add empty line here and/or... grub_efi_loaded_image_t *image = grub_efi_get_loaded_image (grub_efi_image_handle); > + image = grub_efi_get_loaded_image (grub_efi_image_handle); > + if (image == NULL) > + return grub_error (GRUB_ERR_BAD_DEVICE, N_("unable to find boot > device")); > + 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"); > @@ -847,15 +1169,16 @@ blsuki_set_find_entry_info (struct find_entry_info > *info, const char *dirname, c > } > > /* > - * This function searches for BLS config files based on the data in the info > - * parameter. If the fallback option is enabled, the default location will be > - * checked for BLS config files if the first attempt fails. > + * This function searches for BLS config files and UKIs based on the data in > the > + * info parameter. If the fallback option is enabled, the default location > will > + * be checked for BLS config files or UKIs if the first attempt fails. > */ > 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, enum > blsuki_cmd_type 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; > @@ -872,6 +1195,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); > @@ -884,19 +1208,25 @@ 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 > + * "/EFI/Linux" on the EFI system partition. > */ > if (entries == NULL && fallback == false && enable_fallback == true) > { > - default_size = sizeof (GRUB_BOOT_DEVICE) + sizeof > (GRUB_BLS_CONFIG_PATH) - 2; > + 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; > + > + default_size = sizeof (GRUB_BOOT_DEVICE) + sizeof (cmd_dir) - 2; Oops... ... + strlen (cmd_dir) - 1; > default_dir = grub_malloc (default_size); > if (default_dir == NULL) > 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 = true; > @@ -911,15 +1241,17 @@ 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, enum blsuki_cmd_type > cmd_type) > { > - grub_size_t len; > + grub_size_t len, ext_len = 0; > 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, > @@ -928,12 +1260,24 @@ 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"; > + ext_len = BLS_EXT_LEN; > + } > + else if (cmd_type == BLSUKI_UKI_CMD) > + { > + ext = ".efi"; > + ext_len = UKI_EXT_LEN; Missing EFI ifdefery... In general it seems to me you are not consistent with it. I think more code should be disabled for nun-UEFI case. > + } > + > len = grub_strlen (path); > - if (len >= BLS_EXT_LEN && grub_strcmp (path + len - BLS_EXT_LEN, > ".conf") == 0) > + if (len >= ext_len && grub_strcmp (path + len - ext_len, ext) == 0) > { > rei.file = grub_file_open (path, GRUB_FILE_TYPE_CONFIG); > if (rei.file == NULL) > @@ -962,19 +1306,24 @@ blsuki_load_entries (char *path, bool enable_fallback) > > if (dir == NULL) > { > - dir_size = sizeof (GRUB_BOOT_DEVICE) + sizeof (GRUB_BLS_CONFIG_PATH) - > 2; > + 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; > + > + dir_size = sizeof (GRUB_BOOT_DEVICE) + sizeof (cmd_dir) - 2; Again... ... + strlen (cmd_dir) - 1; > default_dir = grub_malloc (dir_size); > if (default_dir == NULL) > 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); > @@ -1012,11 +1361,11 @@ blsuki_is_default_entry (const char *def_entry, > grub_blsuki_entry_t *entry, int > } Daniel _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel