Merge pull request #13953 from SpencerMichaels/systemd-boot-efistub-id-fix
boot: Fix default/oneshot selection for EFISTUB entries
This commit is contained in:
commit
41ab3b7a85
|
@ -32,7 +32,7 @@ enum loader_type {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
CHAR16 *id; /* The identifier for this entry (note that this id is not necessarily unique though!) */
|
||||
CHAR16 *id; /* The unique identifier for this entry */
|
||||
CHAR16 *title_show;
|
||||
CHAR16 *title;
|
||||
CHAR16 *version;
|
||||
|
@ -1310,7 +1310,6 @@ static VOID config_entry_add_from_file(
|
|||
CHAR8 *line;
|
||||
UINTN pos = 0;
|
||||
CHAR8 *key, *value;
|
||||
UINTN len;
|
||||
EFI_STATUS err;
|
||||
EFI_FILE_HANDLE handle;
|
||||
_cleanup_freepool_ CHAR16 *initrd = NULL;
|
||||
|
@ -1431,10 +1430,6 @@ static VOID config_entry_add_from_file(
|
|||
|
||||
entry->device = device;
|
||||
entry->id = StrDuplicate(file);
|
||||
len = StrLen(entry->id);
|
||||
/* remove ".conf" */
|
||||
if (len > 5)
|
||||
entry->id[len - 5] = '\0';
|
||||
StrLwr(entry->id);
|
||||
|
||||
config_add_entry(config, entry);
|
||||
|
@ -1775,7 +1770,8 @@ static ConfigEntry *config_entry_add_loader(
|
|||
CHAR16 *id,
|
||||
CHAR16 key,
|
||||
CHAR16 *title,
|
||||
CHAR16 *loader) {
|
||||
CHAR16 *loader,
|
||||
CHAR16 *version) {
|
||||
|
||||
ConfigEntry *entry;
|
||||
|
||||
|
@ -1783,6 +1779,7 @@ static ConfigEntry *config_entry_add_loader(
|
|||
*entry = (ConfigEntry) {
|
||||
.type = type,
|
||||
.title = StrDuplicate(title),
|
||||
.version = StrDuplicate(version),
|
||||
.device = device,
|
||||
.loader = StrDuplicate(loader),
|
||||
.id = StrDuplicate(id),
|
||||
|
@ -1840,7 +1837,7 @@ static BOOLEAN config_entry_add_loader_auto(
|
|||
return FALSE;
|
||||
uefi_call_wrapper(handle->Close, 1, handle);
|
||||
|
||||
entry = config_entry_add_loader(config, device, LOADER_UNDEFINED, id, key, title, loader);
|
||||
entry = config_entry_add_loader(config, device, LOADER_UNDEFINED, id, key, title, loader, NULL);
|
||||
if (!entry)
|
||||
return FALSE;
|
||||
|
||||
|
@ -1908,10 +1905,12 @@ static VOID config_entry_add_linux(
|
|||
CHAR8 *line;
|
||||
UINTN pos = 0;
|
||||
CHAR8 *key, *value;
|
||||
CHAR16 *os_name_pretty = NULL;
|
||||
CHAR16 *os_name = NULL;
|
||||
CHAR16 *os_id = NULL;
|
||||
CHAR16 *os_version = NULL;
|
||||
CHAR16 *os_build = NULL;
|
||||
CHAR16 *os_version_id = NULL;
|
||||
CHAR16 *os_build_id = NULL;
|
||||
|
||||
err = uefi_call_wrapper(linux_dir->Read, 3, linux_dir, &bufsize, buf);
|
||||
if (bufsize == 0 || EFI_ERROR(err))
|
||||
|
@ -1927,6 +1926,8 @@ static VOID config_entry_add_linux(
|
|||
continue;
|
||||
if (StriCmp(f->FileName + len - 4, L".efi") != 0)
|
||||
continue;
|
||||
if (StrnCmp(f->FileName, L"auto-", 5) == 0)
|
||||
continue;
|
||||
|
||||
/* look for .osrel and .cmdline sections in the .efi binary */
|
||||
err = pe_file_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
|
||||
|
@ -1940,6 +1941,12 @@ static VOID config_entry_add_linux(
|
|||
/* read properties from the embedded os-release file */
|
||||
while ((line = line_get_key_value(content, (CHAR8 *)"=", &pos, &key, &value))) {
|
||||
if (strcmpa((CHAR8 *)"PRETTY_NAME", key) == 0) {
|
||||
FreePool(os_name_pretty);
|
||||
os_name_pretty = stra_to_str(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmpa((CHAR8 *)"NAME", key) == 0) {
|
||||
FreePool(os_name);
|
||||
os_name = stra_to_str(value);
|
||||
continue;
|
||||
|
@ -1957,20 +1964,27 @@ static VOID config_entry_add_linux(
|
|||
continue;
|
||||
}
|
||||
|
||||
if (strcmpa((CHAR8 *)"VERSION_ID", key) == 0) {
|
||||
FreePool(os_version_id);
|
||||
os_version_id = stra_to_str(value);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmpa((CHAR8 *)"BUILD_ID", key) == 0) {
|
||||
FreePool(os_build);
|
||||
os_build = stra_to_str(value);
|
||||
FreePool(os_build_id);
|
||||
os_build_id = stra_to_str(value);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (os_name && os_id && (os_version || os_build)) {
|
||||
_cleanup_freepool_ CHAR16 *conf = NULL, *path = NULL;
|
||||
if ((os_name_pretty || os_name) && os_id && (os_version || os_version_id || os_build_id)) {
|
||||
_cleanup_freepool_ CHAR16 *path = NULL;
|
||||
|
||||
conf = PoolPrint(L"%s-%s", os_id, os_version ? : os_build);
|
||||
path = PoolPrint(L"\\EFI\\Linux\\%s", f->FileName);
|
||||
|
||||
entry = config_entry_add_loader(config, device, LOADER_LINUX, conf, 'l', os_name, path);
|
||||
entry = config_entry_add_loader(config, device, LOADER_LINUX, f->FileName, 'l',
|
||||
os_name_pretty ? : (os_name ? : os_id), path,
|
||||
os_version ? : (os_version_id ? : os_build_id));
|
||||
|
||||
FreePool(content);
|
||||
content = NULL;
|
||||
|
@ -1989,10 +2003,12 @@ static VOID config_entry_add_linux(
|
|||
config_entry_parse_tries(entry, L"\\EFI\\Linux", f->FileName, L".efi");
|
||||
}
|
||||
|
||||
FreePool(os_name_pretty);
|
||||
FreePool(os_name);
|
||||
FreePool(os_id);
|
||||
FreePool(os_version);
|
||||
FreePool(os_build);
|
||||
FreePool(os_version_id);
|
||||
FreePool(os_build_id);
|
||||
FreePool(content);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ static void boot_entry_free(BootEntry *entry) {
|
|||
assert(entry);
|
||||
|
||||
free(entry->id);
|
||||
free(entry->id_old);
|
||||
free(entry->path);
|
||||
free(entry->root);
|
||||
free(entry->title);
|
||||
|
@ -73,12 +74,13 @@ static int boot_entry_load(
|
|||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry file suffix: %s", path);
|
||||
|
||||
b = basename(path);
|
||||
tmp.id = strndup(b, c - b);
|
||||
if (!tmp.id)
|
||||
tmp.id = strdup(b);
|
||||
tmp.id_old = strndup(b, c - b);
|
||||
if (!tmp.id || !tmp.id_old)
|
||||
return log_oom();
|
||||
|
||||
if (!efi_loader_entry_name_valid(tmp.id))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry filename: %s", path);
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid loader entry: %s", tmp.id);
|
||||
|
||||
tmp.path = strdup(path);
|
||||
if (!tmp.path)
|
||||
|
@ -289,6 +291,7 @@ static int boot_entry_load_unified(
|
|||
};
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
const char *k;
|
||||
char *b;
|
||||
int r;
|
||||
|
||||
assert(root);
|
||||
|
@ -314,8 +317,10 @@ static int boot_entry_load_unified(
|
|||
if (!os_pretty_name || !os_id || !(version_id || build_id))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Missing fields in os-release data from unified kernel image %s, refusing.", path);
|
||||
|
||||
tmp.id = strjoin(os_id, "-", version_id ?: build_id);
|
||||
if (!tmp.id)
|
||||
b = basename(path);
|
||||
tmp.id = strdup(b);
|
||||
tmp.id_old = strjoin(os_id, "-", version_id ?: build_id);
|
||||
if (!tmp.id || !tmp.id_old)
|
||||
return log_oom();
|
||||
|
||||
if (!efi_loader_entry_name_valid(tmp.id))
|
||||
|
|
|
@ -21,6 +21,7 @@ typedef enum BootEntryType {
|
|||
typedef struct BootEntry {
|
||||
BootEntryType type;
|
||||
char *id; /* This is the file basename without extension */
|
||||
char *id_old; /* Old-style ID, for deduplication purposes. */
|
||||
char *path; /* This is the full path to the drop-in file */
|
||||
char *root; /* The root path in which the drop-in was found, i.e. to which 'kernel', 'efi' and 'initrd' are relative */
|
||||
char *title;
|
||||
|
@ -54,9 +55,12 @@ typedef struct BootConfig {
|
|||
static inline bool boot_config_has_entry(BootConfig *config, const char *id) {
|
||||
size_t j;
|
||||
|
||||
for (j = 0; j < config->n_entries; j++)
|
||||
if (streq(config->entries[j].id, id))
|
||||
for (j = 0; j < config->n_entries; j++) {
|
||||
const char* entry_id_old = config->entries[j].id_old;
|
||||
if (streq(config->entries[j].id, id) ||
|
||||
(entry_id_old && streq(entry_id_old, id)))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue