#include "loader-features.h"
#include "measure.h"
#include "pe.h"
+#include "random-seed.h"
#include "shim.h"
#include "util.h"
};
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;
BOOLEAN force_menu;
UINTN console_mode;
enum console_mode_change_type console_mode_change;
+ RandomSeedMode random_seed_mode;
} Config;
static VOID cursor_left(UINTN *cursor, UINTN *first) {
Print(L"editor: %s\n", yes_no(config->editor));
Print(L"auto-entries: %s\n", yes_no(config->auto_entries));
Print(L"auto-firmware: %s\n", yes_no(config->auto_firmware));
+
+ switch (config->random_seed_mode) {
+ case RANDOM_SEED_OFF:
+ Print(L"random-seed-mode: off\n");
+ break;
+ case RANDOM_SEED_WITH_SYSTEM_TOKEN:
+ Print(L"random-seed-node: with-system-token\n");
+ break;
+ case RANDOM_SEED_ALWAYS:
+ Print(L"random-seed-node: always\n");
+ break;
+ default:
+ ;
+ }
+
Print(L"\n");
Print(L"config entry count: %d\n", config->entry_count);
BOOLEAN exit = FALSE;
BOOLEAN run = TRUE;
BOOLEAN wait = FALSE;
- BOOLEAN cleared_screen = FALSE;
graphics_mode(FALSE);
uefi_call_wrapper(ST->ConIn->Reset, 2, ST->ConIn, FALSE);
if (config->console_mode_change != CONSOLE_MODE_KEEP) {
err = console_set_mode(&config->console_mode, config->console_mode_change);
- if (!EFI_ERROR(err))
- cleared_screen = TRUE;
- }
-
- if (!cleared_screen)
+ if (EFI_ERROR(err)) {
+ uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
+ Print(L"Error switching console mode to %ld: %r.\r", (UINT64)config->console_mode, err);
+ }
+ } else
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
- if (config->console_mode_change != CONSOLE_MODE_KEEP && EFI_ERROR(err))
- Print(L"Error switching console mode to %ld: %r.\r", (UINT64)config->console_mode, err);
-
err = uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x_max, &y_max);
if (EFI_ERROR(err)) {
x_max = 80;
if (EFI_ERROR(parse_boolean(value, &on)))
continue;
+
config->editor = on;
+ continue;
}
if (strcmpa((CHAR8 *)"auto-entries", key) == 0) {
if (EFI_ERROR(parse_boolean(value, &on)))
continue;
+
config->auto_entries = on;
+ continue;
}
if (strcmpa((CHAR8 *)"auto-firmware", key) == 0) {
if (EFI_ERROR(parse_boolean(value, &on)))
continue;
+
config->auto_firmware = on;
+ continue;
}
if (strcmpa((CHAR8 *)"console-mode", key) == 0) {
continue;
}
+
+ if (strcmpa((CHAR8*) "random-seed-mode", key) == 0) {
+ if (strcmpa((CHAR8*) "off", value) == 0)
+ config->random_seed_mode = RANDOM_SEED_OFF;
+ else if (strcmpa((CHAR8*) "with-system-token", value) == 0)
+ config->random_seed_mode = RANDOM_SEED_WITH_SYSTEM_TOKEN;
+ else if (strcmpa((CHAR8*) "always", value) == 0)
+ config->random_seed_mode = RANDOM_SEED_ALWAYS;
+ else {
+ BOOLEAN on;
+
+ if (EFI_ERROR(parse_boolean(value, &on)))
+ continue;
+
+ config->random_seed_mode = on ? RANDOM_SEED_ALWAYS : RANDOM_SEED_OFF;
+ }
+ }
}
}
static VOID config_entry_add_from_file(
Config *config,
EFI_HANDLE *device,
+ EFI_FILE *root_dir,
CHAR16 *path,
CHAR16 *file,
CHAR8 *content,
CHAR8 *line;
UINTN pos = 0;
CHAR8 *key, *value;
- UINTN len;
+ EFI_STATUS err;
+ EFI_FILE_HANDLE handle;
_cleanup_freepool_ CHAR16 *initrd = NULL;
entry = AllocatePool(sizeof(ConfigEntry));
return;
}
+ /* check existence */
+ err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &handle, entry->loader, EFI_FILE_MODE_READ, 0ULL);
+ if (EFI_ERROR(err)) {
+ config_entry_free(entry);
+ return;
+ }
+ uefi_call_wrapper(handle->Close, 1, handle);
+
/* add initrd= to options */
if (entry->type == LOADER_LINUX && initrd) {
if (entry->options) {
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);
.editor = TRUE,
.auto_entries = TRUE,
.auto_firmware = TRUE,
+ .random_seed_mode = RANDOM_SEED_WITH_SYSTEM_TOKEN,
};
err = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content, NULL);
err = file_read(entries_dir, f->FileName, 0, 0, &content, NULL);
if (!EFI_ERROR(err))
- config_entry_add_from_file(config, device, L"\\loader\\entries", f->FileName, content, loaded_image_path);
+ config_entry_add_from_file(config, device, root_dir, L"\\loader\\entries", f->FileName, content, loaded_image_path);
}
uefi_call_wrapper(entries_dir->Close, 1, entries_dir);
}
CHAR16 *id,
CHAR16 key,
CHAR16 *title,
- CHAR16 *loader) {
+ CHAR16 *loader,
+ CHAR16 *version) {
ConfigEntry *entry;
*entry = (ConfigEntry) {
.type = type,
.title = StrDuplicate(title),
+ .version = StrDuplicate(version),
.device = device,
.loader = StrDuplicate(loader),
.id = StrDuplicate(id),
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;
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))
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);
/* 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;
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;
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);
}
EFI_LOADER_FEATURE_ENTRY_ONESHOT |
EFI_LOADER_FEATURE_BOOT_COUNTING |
EFI_LOADER_FEATURE_XBOOTLDR |
+ EFI_LOADER_FEATURE_RANDOM_SEED |
0;
_cleanup_freepool_ CHAR16 *infostr = NULL, *typestr = NULL;
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
if (EFI_ERROR(err)) {
- Print(L"Error getting a LoadedImageProtocol handle: %r ", err);
+ Print(L"Error getting a LoadedImageProtocol handle: %r", err);
uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
return err;
}
UINT64 key;
err = console_key_read(&key, FALSE);
+
+ if (err == EFI_NOT_READY) {
+ uefi_call_wrapper(BS->Stall, 1, 100 * 1000);
+ err = console_key_read(&key, FALSE);
+ }
+
if (!EFI_ERROR(err)) {
INT16 idx;
config_entry_bump_counters(entry, root_dir);
- /* export the selected boot entry to the system */
- efivar_set(L"LoaderEntrySelected", entry->id, FALSE);
+ /* Export the selected boot entry to the system */
+ (VOID) efivar_set(L"LoaderEntrySelected", entry->id, FALSE);
+
+ /* Optionally, read a random seed off the ESP and pass it to the OS */
+ (VOID) process_random_seed(root_dir, config.random_seed_mode);
uefi_call_wrapper(BS->SetWatchdogTimer, 4, 5 * 60, 0x10000, 0, NULL);
err = image_start(image, &config, entry);