1
0
mirror of https://github.com/systemd/systemd synced 2025-09-30 09:14:46 +02:00

Compare commits

..

No commits in common. "27897cecff47b26f26dcbe269eefbc8b88d126e4" and "e3f87b07bc485b2a6ff3d7b97f2c4c996836f4ec" have entirely different histories.

32 changed files with 395 additions and 475 deletions

View File

@ -410,21 +410,7 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>TransmitQueues=</varname></term> <term><varname>TxQueueLength=</varname></term>
<listitem>
<para>Specifies the device's number of transmit queues. An integer in the range 1…4096.
When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>ReceiveQueues=</varname></term>
<listitem>
<para>Specifies the device's number of receive queues. An integer in the range 1…4096.
When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>TransmitQueueLength=</varname></term>
<listitem> <listitem>
<para>Specifies the transmit queue length of the device in number of packets. An unsigned integer <para>Specifies the transmit queue length of the device in number of packets. An unsigned integer
in the range 0…4294967294. When unset, the kernel's default will be used.</para> in the range 0…4294967294. When unset, the kernel's default will be used.</para>

View File

@ -215,6 +215,20 @@
integer in the range 0…4294967294. Defaults to unset.</para> integer in the range 0…4294967294. Defaults to unset.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>TransmitQueues=</varname></term>
<listitem>
<para>Specifies the devices's number of transmit queues. An integer in the range 1…4096.
When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>ReceiveQueues=</varname></term>
<listitem>
<para>Specifies the devices's number of receive queues. An integer in the range 1…4096.
When unset, the kernel's default will be used.</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>RequiredForOnline=</varname></term> <term><varname>RequiredForOnline=</varname></term>
<listitem> <listitem>

View File

@ -13,7 +13,6 @@
#include "measure.h" #include "measure.h"
#include "pe.h" #include "pe.h"
#include "random-seed.h" #include "random-seed.h"
#include "secure-boot.h"
#include "shim.h" #include "shim.h"
#include "util.h" #include "util.h"
@ -24,6 +23,8 @@
/* magic string to find in the binary image */ /* magic string to find in the binary image */
static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " GIT_VERSION " ####"; static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-boot " GIT_VERSION " ####";
static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
enum loader_type { enum loader_type {
LOADER_UNDEFINED, LOADER_UNDEFINED,
LOADER_EFI, LOADER_EFI,
@ -118,17 +119,17 @@ static BOOLEAN line_edit(
while (!exit) { while (!exit) {
EFI_STATUS err; EFI_STATUS err;
UINT64 key; UINT64 key;
UINTN j; UINTN i;
j = len - first; i = len - first;
if (j >= x_max-1) if (i >= x_max-1)
j = x_max-1; i = x_max-1;
CopyMem(print, line + first, j * sizeof(CHAR16)); CopyMem(print, line + first, i * sizeof(CHAR16));
while (clear > 0 && j < x_max-1) { while (clear > 0 && i < x_max-1) {
clear--; clear--;
print[j++] = ' '; print[i++] = ' ';
} }
print[j] = '\0'; print[i] = '\0';
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_pos); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_pos);
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print); uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, print);
@ -212,14 +213,12 @@ static BOOLEAN line_edit(
case KEYPRESS(EFI_ALT_PRESSED, 0, 'd'): case KEYPRESS(EFI_ALT_PRESSED, 0, 'd'):
/* kill-word */ /* kill-word */
clear = 0; clear = 0;
for (i = first + cursor; i < len && line[i] == ' '; i++)
UINTN k;
for (k = first + cursor; k < len && line[k] == ' '; k++)
clear++; clear++;
for (; k < len && line[k] != ' '; k++) for (; i < len && line[i] != ' '; i++)
clear++; clear++;
for (UINTN i = first + cursor; i + clear < len; i++) for (i = first + cursor; i + clear < len; i++)
line[i] = line[i + clear]; line[i] = line[i + clear];
len -= clear; len -= clear;
line[len] = '\0'; line[len] = '\0';
@ -244,7 +243,7 @@ static BOOLEAN line_edit(
} }
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, cursor, y_pos);
for (UINTN i = first + cursor; i + clear < len; i++) for (i = first + cursor; i + clear < len; i++)
line[i] = line[i + clear]; line[i] = line[i + clear];
len -= clear; len -= clear;
line[len] = '\0'; line[len] = '\0';
@ -257,7 +256,7 @@ static BOOLEAN line_edit(
continue; continue;
if (first + cursor == len) if (first + cursor == len)
continue; continue;
for (UINTN i = first + cursor; i < len; i++) for (i = first + cursor; i < len; i++)
line[i] = line[i+1]; line[i] = line[i+1];
clear = 1; clear = 1;
len--; len--;
@ -286,7 +285,7 @@ static BOOLEAN line_edit(
continue; continue;
if (first == 0 && cursor == 0) if (first == 0 && cursor == 0)
continue; continue;
for (UINTN i = first + cursor-1; i < len; i++) for (i = first + cursor-1; i < len; i++)
line[i] = line[i+1]; line[i] = line[i+1];
clear = 1; clear = 1;
len--; len--;
@ -314,7 +313,7 @@ static BOOLEAN line_edit(
case KEYPRESS(0, 0, 0x80) ... KEYPRESS(0, 0, 0xffff): case KEYPRESS(0, 0, 0x80) ... KEYPRESS(0, 0, 0xffff):
if (len+1 == size) if (len+1 == size)
continue; continue;
for (UINTN i = len; i > first + cursor; i--) for (i = len; i > first + cursor; i--)
line[i] = line[i-1]; line[i] = line[i-1];
line[first + cursor] = KEYCHAR(key); line[first + cursor] = KEYCHAR(key);
len++; len++;
@ -332,23 +331,25 @@ static BOOLEAN line_edit(
} }
static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) { static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) {
UINTN i;
if (key == 0) if (key == 0)
return -1; return -1;
/* select entry by number key */ /* select entry by number key */
if (key >= '1' && key <= '9') { if (key >= '1' && key <= '9') {
UINTN i = key - '0'; i = key - '0';
if (i > config->entry_count) if (i > config->entry_count)
i = config->entry_count; i = config->entry_count;
return i-1; return i-1;
} }
/* find matching key in config entries */ /* find matching key in config entries */
for (UINTN i = start; i < config->entry_count; i++) for (i = start; i < config->entry_count; i++)
if (config->entries[i]->key == key) if (config->entries[i]->key == key)
return i; return i;
for (UINTN i = 0; i < start; i++) for (i = 0; i < start; i++)
if (config->entries[i]->key == key) if (config->entries[i]->key == key)
return i; return i;
@ -356,11 +357,11 @@ static UINTN entry_lookup_key(Config *config, UINTN start, CHAR16 key) {
} }
static VOID print_status(Config *config, CHAR16 *loaded_image_path) { static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
UINT64 key, indvar; UINT64 key;
UINTN timeout; UINTN i;
BOOLEAN modevar; _cleanup_freepool_ CHAR8 *bootvar = NULL, *modevar = NULL, *indvar = NULL;
_cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL; _cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL;
UINTN x, y; UINTN x, y, size;
uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK); uefi_call_wrapper(ST->ConOut->SetAttribute, 2, ST->ConOut, EFI_LIGHTGRAY|EFI_BACKGROUND_BLACK);
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut); uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
@ -375,16 +376,17 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
if (uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x, &y) == EFI_SUCCESS) if (uefi_call_wrapper(ST->ConOut->QueryMode, 4, ST->ConOut, ST->ConOut->Mode->Mode, &x, &y) == EFI_SUCCESS)
Print(L"console size: %d x %d\n", x, y); Print(L"console size: %d x %d\n", x, y);
Print(L"SecureBoot: %s\n", yes_no(secure_boot_enabled())); if (efivar_get_raw(&global_guid, L"SecureBoot", &bootvar, &size) == EFI_SUCCESS)
Print(L"SecureBoot: %s\n", yes_no(*bootvar > 0));
if (efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"SetupMode", &modevar) == EFI_SUCCESS) if (efivar_get_raw(&global_guid, L"SetupMode", &modevar, &size) == EFI_SUCCESS)
Print(L"SetupMode: %s\n", modevar ? L"setup" : L"user"); Print(L"SetupMode: %s\n", *modevar > 0 ? L"setup" : L"user");
if (shim_loaded()) if (shim_loaded())
Print(L"Shim: present\n"); Print(L"Shim: present\n");
if (efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndicationsSupported", &indvar) == EFI_SUCCESS) if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &indvar, &size) == EFI_SUCCESS)
Print(L"OsIndicationsSupported: %d\n", indvar); Print(L"OsIndicationsSupported: %d\n", (UINT64)*indvar);
Print(L"\n--- press key ---\n\n"); Print(L"\n--- press key ---\n\n");
console_key_read(&key, TRUE); console_key_read(&key, TRUE);
@ -421,20 +423,20 @@ static VOID print_status(Config *config, CHAR16 *loaded_image_path) {
Print(L"entry EFI var idx: %d\n", config->idx_default_efivar); Print(L"entry EFI var idx: %d\n", config->idx_default_efivar);
Print(L"\n"); Print(L"\n");
if (efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeout", &timeout) == EFI_SUCCESS) if (efivar_get_int(L"LoaderConfigTimeout", &i) == EFI_SUCCESS)
Print(L"LoaderConfigTimeout: %u\n", timeout); Print(L"LoaderConfigTimeout: %u\n", i);
if (config->entry_oneshot) if (config->entry_oneshot)
Print(L"LoaderEntryOneShot: %s\n", config->entry_oneshot); Print(L"LoaderEntryOneShot: %s\n", config->entry_oneshot);
if (efivar_get(LOADER_GUID, L"LoaderDevicePartUUID", &partstr) == EFI_SUCCESS) if (efivar_get(L"LoaderDevicePartUUID", &partstr) == EFI_SUCCESS)
Print(L"LoaderDevicePartUUID: %s\n", partstr); Print(L"LoaderDevicePartUUID: %s\n", partstr);
if (efivar_get(LOADER_GUID, L"LoaderEntryDefault", &defaultstr) == EFI_SUCCESS) if (efivar_get(L"LoaderEntryDefault", &defaultstr) == EFI_SUCCESS)
Print(L"LoaderEntryDefault: %s\n", defaultstr); Print(L"LoaderEntryDefault: %s\n", defaultstr);
Print(L"\n--- press key ---\n\n"); Print(L"\n--- press key ---\n\n");
console_key_read(&key, TRUE); console_key_read(&key, TRUE);
for (UINTN i = 0; i < config->entry_count; i++) { for (i = 0; i < config->entry_count; i++) {
ConfigEntry *entry; ConfigEntry *entry;
if (key == KEYPRESS(0, SCAN_ESC, 0) || key == KEYPRESS(0, 0, 'q')) if (key == KEYPRESS(0, SCAN_ESC, 0) || key == KEYPRESS(0, 0, 'q'))
@ -501,6 +503,7 @@ static BOOLEAN menu_run(
UINTN idx_last; UINTN idx_last;
BOOLEAN refresh; BOOLEAN refresh;
BOOLEAN highlight; BOOLEAN highlight;
UINTN i;
UINTN line_width; UINTN line_width;
CHAR16 **lines; CHAR16 **lines;
UINTN x_start; UINTN x_start;
@ -561,7 +564,7 @@ static BOOLEAN menu_run(
/* length of the longest entry */ /* length of the longest entry */
line_width = 5; line_width = 5;
for (UINTN i = 0; i < config->entry_count; i++) { for (i = 0; i < config->entry_count; i++) {
UINTN entry_len; UINTN entry_len;
entry_len = StrLen(config->entries[i]->title_show); entry_len = StrLen(config->entries[i]->title_show);
@ -580,14 +583,14 @@ static BOOLEAN menu_run(
/* menu entries title lines */ /* menu entries title lines */
lines = AllocatePool(sizeof(CHAR16 *) * config->entry_count); lines = AllocatePool(sizeof(CHAR16 *) * config->entry_count);
for (UINTN i = 0; i < config->entry_count; i++) { for (i = 0; i < config->entry_count; i++) {
UINTN j; UINTN j, k;
lines[i] = AllocatePool(((x_max+1) * sizeof(CHAR16))); lines[i] = AllocatePool(((x_max+1) * sizeof(CHAR16)));
for (j = 0; j < x_start; j++) for (j = 0; j < x_start; j++)
lines[i][j] = ' '; lines[i][j] = ' ';
for (UINTN k = 0; config->entries[i]->title_show[k] != '\0' && j < x_max; j++, k++) for (k = 0; config->entries[i]->title_show[k] != '\0' && j < x_max; j++, k++)
lines[i][j] = config->entries[i]->title_show[k]; lines[i][j] = config->entries[i]->title_show[k];
for (; j < x_max; j++) for (; j < x_max; j++)
@ -597,15 +600,15 @@ static BOOLEAN menu_run(
status = NULL; status = NULL;
clearline = AllocatePool((x_max+1) * sizeof(CHAR16)); clearline = AllocatePool((x_max+1) * sizeof(CHAR16));
for (UINTN i = 0; i < x_max; i++) for (i = 0; i < x_max; i++)
clearline[i] = ' '; clearline[i] = ' ';
clearline[x_max] = 0; clearline[i] = 0;
while (!exit) { while (!exit) {
UINT64 key; UINT64 key;
if (refresh) { if (refresh) {
for (UINTN i = 0; i < config->entry_count; i++) { for (i = 0; i < config->entry_count; i++) {
if (i < idx_first || i > idx_last) if (i < idx_first || i > idx_last)
continue; continue;
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + i - idx_first); uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, y_start + i - idx_first);
@ -761,16 +764,12 @@ static BOOLEAN menu_run(
case KEYPRESS(0, 0, 'd'): case KEYPRESS(0, 0, 'd'):
if (config->idx_default_efivar != (INTN)idx_highlight) { if (config->idx_default_efivar != (INTN)idx_highlight) {
/* store the selected entry in a persistent EFI variable */ /* store the selected entry in a persistent EFI variable */
efivar_set( efivar_set(L"LoaderEntryDefault", config->entries[idx_highlight]->id, TRUE);
LOADER_GUID,
L"LoaderEntryDefault",
config->entries[idx_highlight]->id,
TRUE);
config->idx_default_efivar = idx_highlight; config->idx_default_efivar = idx_highlight;
status = StrDuplicate(L"Default boot entry selected."); status = StrDuplicate(L"Default boot entry selected.");
} else { } else {
/* clear the default entry EFI variable */ /* clear the default entry EFI variable */
efivar_set(LOADER_GUID, L"LoaderEntryDefault", NULL, TRUE); efivar_set(L"LoaderEntryDefault", NULL, TRUE);
config->idx_default_efivar = -1; config->idx_default_efivar = -1;
status = StrDuplicate(L"Default boot entry cleared."); status = StrDuplicate(L"Default boot entry cleared.");
} }
@ -781,15 +780,14 @@ static BOOLEAN menu_run(
case KEYPRESS(0, 0, 'T'): case KEYPRESS(0, 0, 'T'):
if (config->timeout_sec_efivar > 0) { if (config->timeout_sec_efivar > 0) {
config->timeout_sec_efivar--; config->timeout_sec_efivar--;
efivar_set_uint_string( efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE);
LOADER_GUID, L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE);
if (config->timeout_sec_efivar > 0) if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar); status = PoolPrint(L"Menu timeout set to %d sec.", config->timeout_sec_efivar);
else else
status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu."); status = StrDuplicate(L"Menu disabled. Hold down key at bootup to show menu.");
} else if (config->timeout_sec_efivar <= 0){ } else if (config->timeout_sec_efivar <= 0){
config->timeout_sec_efivar = -1; config->timeout_sec_efivar = -1;
efivar_set(LOADER_GUID, L"LoaderConfigTimeout", NULL, TRUE); efivar_set(L"LoaderConfigTimeout", NULL, TRUE);
if (config->timeout_sec_config > 0) if (config->timeout_sec_config > 0)
status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.", status = PoolPrint(L"Menu timeout of %d sec is defined by configuration file.",
config->timeout_sec_config); config->timeout_sec_config);
@ -803,7 +801,7 @@ static BOOLEAN menu_run(
if (config->timeout_sec_efivar == -1 && config->timeout_sec_config == 0) if (config->timeout_sec_efivar == -1 && config->timeout_sec_config == 0)
config->timeout_sec_efivar++; config->timeout_sec_efivar++;
config->timeout_sec_efivar++; config->timeout_sec_efivar++;
efivar_set_uint_string(LOADER_GUID, L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE); efivar_set_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE);
if (config->timeout_sec_efivar > 0) if (config->timeout_sec_efivar > 0)
status = PoolPrint(L"Menu timeout set to %d sec.", status = PoolPrint(L"Menu timeout set to %d sec.",
config->timeout_sec_efivar); config->timeout_sec_efivar);
@ -865,7 +863,7 @@ static BOOLEAN menu_run(
*chosen_entry = config->entries[idx_highlight]; *chosen_entry = config->entries[idx_highlight];
for (UINTN i = 0; i < config->entry_count; i++) for (i = 0; i < config->entry_count; i++)
FreePool(lines[i]); FreePool(lines[i]);
FreePool(lines); FreePool(lines);
FreePool(clearline); FreePool(clearline);
@ -1295,7 +1293,7 @@ static VOID config_entry_bump_counters(
/* Let's tell the OS that we renamed this file, so that it knows what to rename to the counter-less name on /* Let's tell the OS that we renamed this file, so that it knows what to rename to the counter-less name on
* success */ * success */
new_path = PoolPrint(L"%s\\%s", entry->path, entry->next_name); new_path = PoolPrint(L"%s\\%s", entry->path, entry->next_name);
efivar_set(LOADER_GUID, L"LoaderBootCountPath", new_path, FALSE); efivar_set(L"LoaderBootCountPath", new_path, FALSE);
/* If the file we just renamed is the loader path, then let's update that. */ /* If the file we just renamed is the loader path, then let's update that. */
if (StrCmp(entry->loader, old_path) == 0) { if (StrCmp(entry->loader, old_path) == 0) {
@ -1460,17 +1458,17 @@ static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) {
if (!EFI_ERROR(err)) if (!EFI_ERROR(err))
config_defaults_load_from_file(config, content); config_defaults_load_from_file(config, content);
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeout", &sec); err = efivar_get_int(L"LoaderConfigTimeout", &sec);
if (!EFI_ERROR(err)) { if (!EFI_ERROR(err)) {
config->timeout_sec_efivar = sec > INTN_MAX ? INTN_MAX : sec; config->timeout_sec_efivar = sec > INTN_MAX ? INTN_MAX : sec;
config->timeout_sec = sec; config->timeout_sec = sec;
} else } else
config->timeout_sec_efivar = -1; config->timeout_sec_efivar = -1;
err = efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeoutOneShot", &sec); err = efivar_get_int(L"LoaderConfigTimeoutOneShot", &sec);
if (!EFI_ERROR(err)) { if (!EFI_ERROR(err)) {
/* Unset variable now, after all it's "one shot". */ /* Unset variable now, after all it's "one shot". */
(void) efivar_set(LOADER_GUID, L"LoaderConfigTimeoutOneShot", NULL, TRUE); (void) efivar_set(L"LoaderConfigTimeoutOneShot", NULL, TRUE);
config->timeout_sec = sec; config->timeout_sec = sec;
config->force_menu = TRUE; /* force the menu when this is set */ config->force_menu = TRUE; /* force the menu when this is set */
@ -1493,6 +1491,7 @@ static VOID config_load_entries(
UINTN bufsize; UINTN bufsize;
EFI_FILE_INFO *f; EFI_FILE_INFO *f;
_cleanup_freepool_ CHAR8 *content = NULL; _cleanup_freepool_ CHAR8 *content = NULL;
UINTN len;
bufsize = sizeof(buf); bufsize = sizeof(buf);
err = uefi_call_wrapper(entries_dir->Read, 3, entries_dir, &bufsize, buf); err = uefi_call_wrapper(entries_dir->Read, 3, entries_dir, &bufsize, buf);
@ -1505,9 +1504,12 @@ static VOID config_load_entries(
if (f->Attribute & EFI_FILE_DIRECTORY) if (f->Attribute & EFI_FILE_DIRECTORY)
continue; continue;
if (!endswith_no_case(f->FileName, L".conf")) len = StrLen(f->FileName);
if (len < 6)
continue; continue;
if (startswith(f->FileName, L"auto-")) if (StriCmp(f->FileName + len - 5, L".conf") != 0)
continue;
if (StrnCmp(f->FileName, L"auto-", 5) == 0)
continue; continue;
err = file_read(entries_dir, f->FileName, 0, 0, &content, NULL); err = file_read(entries_dir, f->FileName, 0, 0, &content, NULL);
@ -1551,11 +1553,14 @@ static INTN config_entry_compare(ConfigEntry *a, ConfigEntry *b) {
} }
static VOID config_sort_entries(Config *config) { static VOID config_sort_entries(Config *config) {
for (UINTN i = 1; i < config->entry_count; i++) { UINTN i;
for (i = 1; i < config->entry_count; i++) {
BOOLEAN more; BOOLEAN more;
UINTN k;
more = FALSE; more = FALSE;
for (UINTN k = 0; k < config->entry_count - i; k++) { for (k = 0; k < config->entry_count - i; k++) {
ConfigEntry *entry; ConfigEntry *entry;
if (config_entry_compare(config->entries[k], config->entries[k+1]) <= 0) if (config_entry_compare(config->entries[k], config->entries[k+1]) <= 0)
@ -1572,7 +1577,9 @@ static VOID config_sort_entries(Config *config) {
} }
static INTN config_entry_find(Config *config, CHAR16 *id) { static INTN config_entry_find(Config *config, CHAR16 *id) {
for (UINTN i = 0; i < config->entry_count; i++) UINTN i;
for (i = 0; i < config->entry_count; i++)
if (StrCmp(config->entries[i]->id, id) == 0) if (StrCmp(config->entries[i]->id, id) == 0)
return (INTN) i; return (INTN) i;
@ -1588,11 +1595,11 @@ static VOID config_default_entry_select(Config *config) {
* The EFI variable to specify a boot entry for the next, and only the * The EFI variable to specify a boot entry for the next, and only the
* next reboot. The variable is always cleared directly after it is read. * next reboot. The variable is always cleared directly after it is read.
*/ */
err = efivar_get(LOADER_GUID, L"LoaderEntryOneShot", &entry_oneshot); err = efivar_get(L"LoaderEntryOneShot", &entry_oneshot);
if (!EFI_ERROR(err)) { if (!EFI_ERROR(err)) {
config->entry_oneshot = StrDuplicate(entry_oneshot); config->entry_oneshot = StrDuplicate(entry_oneshot);
efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, TRUE); efivar_set(L"LoaderEntryOneShot", NULL, TRUE);
i = config_entry_find(config, entry_oneshot); i = config_entry_find(config, entry_oneshot);
if (i >= 0) { if (i >= 0) {
@ -1607,7 +1614,7 @@ static VOID config_default_entry_select(Config *config) {
* the 'd' key in the loader selection menu, the entry is marked with * the 'd' key in the loader selection menu, the entry is marked with
* an '*'. * an '*'.
*/ */
err = efivar_get(LOADER_GUID, L"LoaderEntryDefault", &entry_default); err = efivar_get(L"LoaderEntryDefault", &entry_default);
if (!EFI_ERROR(err)) { if (!EFI_ERROR(err)) {
i = config_entry_find(config, entry_default); i = config_entry_find(config, entry_default);
@ -1653,12 +1660,13 @@ static VOID config_default_entry_select(Config *config) {
static BOOLEAN find_nonunique(ConfigEntry **entries, UINTN entry_count) { static BOOLEAN find_nonunique(ConfigEntry **entries, UINTN entry_count) {
BOOLEAN non_unique = FALSE; BOOLEAN non_unique = FALSE;
UINTN i, k;
for (UINTN i = 0; i < entry_count; i++) for (i = 0; i < entry_count; i++)
entries[i]->non_unique = FALSE; entries[i]->non_unique = FALSE;
for (UINTN i = 0; i < entry_count; i++) for (i = 0; i < entry_count; i++)
for (UINTN k = 0; k < entry_count; k++) { for (k = 0; k < entry_count; k++) {
if (i == k) if (i == k)
continue; continue;
if (StrCmp(entries[i]->title_show, entries[k]->title_show) != 0) if (StrCmp(entries[i]->title_show, entries[k]->title_show) != 0)
@ -1672,8 +1680,10 @@ static BOOLEAN find_nonunique(ConfigEntry **entries, UINTN entry_count) {
/* generate a unique title, avoiding non-distinguishable menu entries */ /* generate a unique title, avoiding non-distinguishable menu entries */
static VOID config_title_generate(Config *config) { static VOID config_title_generate(Config *config) {
UINTN i;
/* set title */ /* set title */
for (UINTN i = 0; i < config->entry_count; i++) { for (i = 0; i < config->entry_count; i++) {
CHAR16 *title; CHAR16 *title;
FreePool(config->entries[i]->title_show); FreePool(config->entries[i]->title_show);
@ -1687,7 +1697,7 @@ static VOID config_title_generate(Config *config) {
return; return;
/* add version to non-unique titles */ /* add version to non-unique titles */
for (UINTN i = 0; i < config->entry_count; i++) { for (i = 0; i < config->entry_count; i++) {
CHAR16 *s; CHAR16 *s;
if (!config->entries[i]->non_unique) if (!config->entries[i]->non_unique)
@ -1704,7 +1714,7 @@ static VOID config_title_generate(Config *config) {
return; return;
/* add machine-id to non-unique titles */ /* add machine-id to non-unique titles */
for (UINTN i = 0; i < config->entry_count; i++) { for (i = 0; i < config->entry_count; i++) {
CHAR16 *s; CHAR16 *s;
_cleanup_freepool_ CHAR16 *m = NULL; _cleanup_freepool_ CHAR16 *m = NULL;
@ -1724,7 +1734,7 @@ static VOID config_title_generate(Config *config) {
return; return;
/* add file name to non-unique titles */ /* add file name to non-unique titles */
for (UINTN i = 0; i < config->entry_count; i++) { for (i = 0; i < config->entry_count; i++) {
CHAR16 *s; CHAR16 *s;
if (!config->entries[i]->non_unique) if (!config->entries[i]->non_unique)
@ -1816,10 +1826,14 @@ static BOOLEAN config_entry_add_loader_auto(
/* look for systemd-boot magic string */ /* look for systemd-boot magic string */
err = file_read(root_dir, loader, 0, 100*1024, &content, &len); err = file_read(root_dir, loader, 0, 100*1024, &content, &len);
if (!EFI_ERROR(err)) if (!EFI_ERROR(err)) {
for (CHAR8 *start = content; start <= content + len - sizeof(magic) - 1; start++) CHAR8 *start = content;
CHAR8 *last = content + len - sizeof(magic) - 1;
for (; start <= last; start++)
if (start[0] == magic[0] && CompareMem(start, magic, sizeof(magic) - 1) == 0) if (start[0] == magic[0] && CompareMem(start, magic, sizeof(magic) - 1) == 0)
return FALSE; return FALSE;
}
} }
/* check existence */ /* check existence */
@ -1848,7 +1862,9 @@ static VOID config_entry_add_osx(Config *config) {
err = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &handle_count, &handles); err = LibLocateHandle(ByProtocol, &FileSystemProtocol, NULL, &handle_count, &handles);
if (!EFI_ERROR(err)) { if (!EFI_ERROR(err)) {
for (UINTN i = 0; i < handle_count; i++) { UINTN i;
for (i = 0; i < handle_count; i++) {
EFI_FILE *root; EFI_FILE *root;
BOOLEAN found; BOOLEAN found;
@ -1890,6 +1906,7 @@ static VOID config_entry_add_linux(
UINTN szs[ELEMENTSOF(sections)-1] = {}; UINTN szs[ELEMENTSOF(sections)-1] = {};
UINTN addrs[ELEMENTSOF(sections)-1] = {}; UINTN addrs[ELEMENTSOF(sections)-1] = {};
CHAR8 *content = NULL; CHAR8 *content = NULL;
UINTN len;
CHAR8 *line; CHAR8 *line;
UINTN pos = 0; UINTN pos = 0;
CHAR8 *key, *value; CHAR8 *key, *value;
@ -1909,9 +1926,12 @@ static VOID config_entry_add_linux(
continue; continue;
if (f->Attribute & EFI_FILE_DIRECTORY) if (f->Attribute & EFI_FILE_DIRECTORY)
continue; continue;
if (!endswith_no_case(f->FileName, L".efi")) len = StrLen(f->FileName);
if (len < 5)
continue; continue;
if (startswith(f->FileName, L"auto-")) if (StriCmp(f->FileName + len - 4, L".efi") != 0)
continue;
if (StrnCmp(f->FileName, L"auto-", 5) == 0)
continue; continue;
/* look for .osrel and .cmdline sections in the .efi binary */ /* look for .osrel and .cmdline sections in the .efi binary */
@ -2000,8 +2020,10 @@ static VOID config_entry_add_linux(
uefi_call_wrapper(linux_dir->Close, 1, linux_dir); uefi_call_wrapper(linux_dir->Close, 1, linux_dir);
} }
#define XBOOTLDR_GUID \ /* Note that this is in GUID format, i.e. the first 32bit, and the following pair of 16bit are byteswapped. */
&(const EFI_GUID) { 0xbc13c2ff, 0x59e6, 0x4262, { 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72 } } static const UINT8 xbootldr_guid[16] = {
0xff, 0xc2, 0x13, 0xbc, 0xe6, 0x59, 0x62, 0x42, 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72
};
static EFI_DEVICE_PATH *path_parent(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node) { static EFI_DEVICE_PATH *path_parent(EFI_DEVICE_PATH *path, EFI_DEVICE_PATH *node) {
EFI_DEVICE_PATH *parent; EFI_DEVICE_PATH *parent;
@ -2019,7 +2041,7 @@ static VOID config_load_xbootldr(
Config *config, Config *config,
EFI_HANDLE *device) { EFI_HANDLE *device) {
EFI_DEVICE_PATH *partition_path, *disk_path, *copy; EFI_DEVICE_PATH *partition_path, *node, *disk_path, *copy;
UINT32 found_partition_number = (UINT32) -1; UINT32 found_partition_number = (UINT32) -1;
UINT64 found_partition_start = (UINT64) -1; UINT64 found_partition_start = (UINT64) -1;
UINT64 found_partition_size = (UINT64) -1; UINT64 found_partition_size = (UINT64) -1;
@ -2032,10 +2054,11 @@ static VOID config_load_xbootldr(
if (!partition_path) if (!partition_path)
return; return;
for (EFI_DEVICE_PATH *node = partition_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) { for (node = partition_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) {
EFI_HANDLE disk_handle; EFI_HANDLE disk_handle;
EFI_BLOCK_IO *block_io; EFI_BLOCK_IO *block_io;
EFI_DEVICE_PATH *p; EFI_DEVICE_PATH *p;
UINTN nr;
/* First, Let's look for the SCSI/SATA/USB/… device path node, i.e. one above the media /* First, Let's look for the SCSI/SATA/USB/… device path node, i.e. one above the media
* devices */ * devices */
@ -2062,7 +2085,7 @@ static VOID config_load_xbootldr(
continue; continue;
/* Try both copies of the GPT header, in case one is corrupted */ /* Try both copies of the GPT header, in case one is corrupted */
for (UINTN nr = 0; nr < 2; nr++) { for (nr = 0; nr < 2; nr++) {
_cleanup_freepool_ EFI_PARTITION_ENTRY* entries = NULL; _cleanup_freepool_ EFI_PARTITION_ENTRY* entries = NULL;
union { union {
EFI_PARTITION_TABLE_HEADER gpt_header; EFI_PARTITION_TABLE_HEADER gpt_header;
@ -2070,7 +2093,7 @@ static VOID config_load_xbootldr(
} gpt_header_buffer; } gpt_header_buffer;
const EFI_PARTITION_TABLE_HEADER *h = &gpt_header_buffer.gpt_header; const EFI_PARTITION_TABLE_HEADER *h = &gpt_header_buffer.gpt_header;
UINT64 where; UINT64 where;
UINTN sz; UINTN i, sz;
UINT32 c; UINT32 c;
if (nr == 0) if (nr == 0)
@ -2140,12 +2163,12 @@ static VOID config_load_xbootldr(
if (c != h->PartitionEntryArrayCRC32) if (c != h->PartitionEntryArrayCRC32)
continue; continue;
for (UINTN i = 0; i < h->NumberOfPartitionEntries; i++) { for (i = 0; i < h->NumberOfPartitionEntries; i++) {
EFI_PARTITION_ENTRY *entry; EFI_PARTITION_ENTRY *entry;
entry = (EFI_PARTITION_ENTRY*) ((UINT8*) entries + h->SizeOfPartitionEntry * i); entry = (EFI_PARTITION_ENTRY*) ((UINT8*) entries + h->SizeOfPartitionEntry * i);
if (CompareMem(&entry->PartitionTypeGUID, XBOOTLDR_GUID, 16) == 0) { if (CompareMem(&entry->PartitionTypeGUID, xbootldr_guid, 16) == 0) {
UINT64 end; UINT64 end;
/* Let's use memcpy(), in case the structs are not aligned (they really should be though) */ /* Let's use memcpy(), in case the structs are not aligned (they really should be though) */
@ -2174,7 +2197,7 @@ found:
copy = DuplicateDevicePath(partition_path); copy = DuplicateDevicePath(partition_path);
/* Patch in the data we found */ /* Patch in the data we found */
for (EFI_DEVICE_PATH *node = copy; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) { for (node = copy; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) {
HARDDRIVE_DEVICE_PATH *hd; HARDDRIVE_DEVICE_PATH *hd;
if (DevicePathType(node) != MEDIA_DEVICE_PATH) if (DevicePathType(node) != MEDIA_DEVICE_PATH)
@ -2259,7 +2282,7 @@ static EFI_STATUS image_start(
#endif #endif
} }
efivar_set_time_usec(LOADER_GUID, L"LoaderTimeExecUSec", 0); efivar_set_time_usec(L"LoaderTimeExecUSec", 0);
err = uefi_call_wrapper(BS->StartImage, 3, image, NULL, NULL); err = uefi_call_wrapper(BS->StartImage, 3, image, NULL, NULL);
out_unload: out_unload:
uefi_call_wrapper(BS->UnloadImage, 1, image); uefi_call_wrapper(BS->UnloadImage, 1, image);
@ -2267,16 +2290,18 @@ out_unload:
} }
static EFI_STATUS reboot_into_firmware(VOID) { static EFI_STATUS reboot_into_firmware(VOID) {
UINT64 old, new; _cleanup_freepool_ CHAR8 *b = NULL;
UINTN size;
UINT64 osind;
EFI_STATUS err; EFI_STATUS err;
new = EFI_OS_INDICATIONS_BOOT_TO_FW_UI; osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
err = efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", &old); err = efivar_get_raw(&global_guid, L"OsIndications", &b, &size);
if (!EFI_ERROR(err)) if (!EFI_ERROR(err))
new |= old; osind |= (UINT64)*b;
err = efivar_set_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", new, TRUE); err = efivar_set_raw(&global_guid, L"OsIndications", &osind, sizeof(UINT64), TRUE);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
@ -2287,7 +2312,9 @@ static EFI_STATUS reboot_into_firmware(VOID) {
} }
static VOID config_free(Config *config) { static VOID config_free(Config *config) {
for (UINTN i = 0; i < config->entry_count; i++) UINTN i;
for (i = 0; i < config->entry_count; i++)
config_entry_free(config->entries[i]); config_entry_free(config->entries[i]);
FreePool(config->entries); FreePool(config->entries);
FreePool(config->entry_default_pattern); FreePool(config->entry_default_pattern);
@ -2297,15 +2324,15 @@ static VOID config_free(Config *config) {
static VOID config_write_entries_to_variable(Config *config) { static VOID config_write_entries_to_variable(Config *config) {
_cleanup_freepool_ CHAR16 *buffer = NULL; _cleanup_freepool_ CHAR16 *buffer = NULL;
UINTN sz = 0; UINTN i, sz = 0;
CHAR16 *p; CHAR16 *p;
for (UINTN i = 0; i < config->entry_count; i++) for (i = 0; i < config->entry_count; i++)
sz += StrLen(config->entries[i]->id) + 1; sz += StrLen(config->entries[i]->id) + 1;
p = buffer = AllocatePool(sz * sizeof(CHAR16)); p = buffer = AllocatePool(sz * sizeof(CHAR16));
for (UINTN i = 0; i < config->entry_count; i++) { for (i = 0; i < config->entry_count; i++) {
UINTN l; UINTN l;
l = StrLen(config->entries[i]->id) + 1; l = StrLen(config->entries[i]->id) + 1;
@ -2315,7 +2342,7 @@ static VOID config_write_entries_to_variable(Config *config) {
} }
/* Store the full list of discovered entries. */ /* Store the full list of discovered entries. */
(void) efivar_set_raw(LOADER_GUID, L"LoaderEntries", buffer, (UINT8*) p - (UINT8*) buffer, FALSE); (void) efivar_set_raw(&loader_guid, L"LoaderEntries", buffer, (UINT8*) p - (UINT8*) buffer, FALSE);
} }
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
@ -2330,7 +2357,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
0; 0;
_cleanup_freepool_ CHAR16 *infostr = NULL, *typestr = NULL; _cleanup_freepool_ CHAR16 *infostr = NULL, *typestr = NULL;
UINT64 osind = 0; CHAR8 *b;
UINTN size;
EFI_LOADED_IMAGE *loaded_image; EFI_LOADED_IMAGE *loaded_image;
EFI_FILE *root_dir; EFI_FILE *root_dir;
CHAR16 *loaded_image_path; CHAR16 *loaded_image_path;
@ -2342,16 +2370,16 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
InitializeLib(image, sys_table); InitializeLib(image, sys_table);
init_usec = time_usec(); init_usec = time_usec();
efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec); efivar_set_time_usec(L"LoaderTimeInitUSec", init_usec);
efivar_set(LOADER_GUID, L"LoaderInfo", L"systemd-boot " GIT_VERSION, FALSE); efivar_set(L"LoaderInfo", L"systemd-boot " GIT_VERSION, FALSE);
infostr = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); infostr = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", infostr, FALSE); efivar_set(L"LoaderFirmwareInfo", infostr, FALSE);
typestr = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); typestr = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
efivar_set(LOADER_GUID, L"LoaderFirmwareType", typestr, FALSE); efivar_set(L"LoaderFirmwareType", typestr, FALSE);
(void) efivar_set_uint64_le(LOADER_GUID, L"LoaderFeatures", loader_features, FALSE); (void) efivar_set_raw(&loader_guid, L"LoaderFeatures", &loader_features, sizeof(loader_features), FALSE);
err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image, err = uefi_call_wrapper(BS->OpenProtocol, 6, image, &LoadedImageProtocol, (VOID **)&loaded_image,
image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
@ -2363,7 +2391,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
/* export the device path this image is started from */ /* export the device path this image is started from */
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, FALSE); efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
root_dir = LibOpenRoot(loaded_image->DeviceHandle); root_dir = LibOpenRoot(loaded_image->DeviceHandle);
if (!root_dir) { if (!root_dir) {
@ -2383,7 +2411,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
/* the filesystem path to this image, to prevent adding ourselves to the menu */ /* the filesystem path to this image, to prevent adding ourselves to the menu */
loaded_image_path = DevicePathToStr(loaded_image->FilePath); loaded_image_path = DevicePathToStr(loaded_image->FilePath);
efivar_set(LOADER_GUID, L"LoaderImageIdentifier", loaded_image_path, FALSE); efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE);
config_load_defaults(&config, root_dir); config_load_defaults(&config, root_dir);
@ -2408,12 +2436,15 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
L"auto-efi-default", '\0', L"EFI Default Loader", L"\\EFI\\Boot\\boot" EFI_MACHINE_TYPE_NAME ".efi"); L"auto-efi-default", '\0', L"EFI Default Loader", L"\\EFI\\Boot\\boot" EFI_MACHINE_TYPE_NAME ".efi");
config_entry_add_osx(&config); config_entry_add_osx(&config);
if (config.auto_firmware && efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndicationsSupported", &osind) == EFI_SUCCESS) { if (config.auto_firmware && efivar_get_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) {
UINT64 osind = (UINT64)*b;
if (osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) if (osind & EFI_OS_INDICATIONS_BOOT_TO_FW_UI)
config_entry_add_call(&config, config_entry_add_call(&config,
L"auto-reboot-to-firmware-setup", L"auto-reboot-to-firmware-setup",
L"Reboot Into Firmware Interface", L"Reboot Into Firmware Interface",
reboot_into_firmware); reboot_into_firmware);
FreePool(b);
} }
if (config.entry_count == 0) { if (config.entry_count == 0) {
@ -2466,7 +2497,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
entry = config.entries[config.idx_default]; entry = config.entries[config.idx_default];
if (menu) { if (menu) {
efivar_set_time_usec(LOADER_GUID, L"LoaderTimeMenuUSec", 0); efivar_set_time_usec(L"LoaderTimeMenuUSec", 0);
uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x10000, 0, NULL); uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0x10000, 0, NULL);
if (!menu_run(&config, &entry, loaded_image_path)) if (!menu_run(&config, &entry, loaded_image_path))
break; break;
@ -2481,7 +2512,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
config_entry_bump_counters(entry, root_dir); config_entry_bump_counters(entry, root_dir);
/* Export the selected boot entry to the system */ /* Export the selected boot entry to the system */
(VOID) efivar_set(LOADER_GUID, L"LoaderEntrySelected", entry->id, FALSE); (VOID) efivar_set(L"LoaderEntrySelected", entry->id, FALSE);
/* Optionally, read a random seed off the ESP and pass it to the OS */ /* Optionally, read a random seed off the ESP and pass it to the OS */
(VOID) process_random_seed(root_dir, config.random_seed_mode); (VOID) process_random_seed(root_dir, config.random_seed_mode);

View File

@ -9,8 +9,8 @@
#define SYSTEM_FONT_WIDTH 8 #define SYSTEM_FONT_WIDTH 8
#define SYSTEM_FONT_HEIGHT 19 #define SYSTEM_FONT_HEIGHT 19
#define EFI_SIMPLE_TEXT_INPUT_EX_GUID \ #define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
&(EFI_GUID) { 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } } { 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
@ -67,6 +67,7 @@ typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL {
} EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL; } EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL;
EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) { EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
EFI_GUID EfiSimpleTextInputExProtocolGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx; static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
static BOOLEAN checked; static BOOLEAN checked;
UINTN index; UINTN index;
@ -74,7 +75,7 @@ EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
EFI_STATUS err; EFI_STATUS err;
if (!checked) { if (!checked) {
err = LibLocateProtocol(EFI_SIMPLE_TEXT_INPUT_EX_GUID, (VOID **)&TextInputEx); err = LibLocateProtocol(&EfiSimpleTextInputExProtocolGuid, (VOID **)&TextInputEx);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
TextInputEx = NULL; TextInputEx = NULL;

View File

@ -128,8 +128,9 @@ UINT32 crc32_exclude_offset(
const UINT8 *p = buf; const UINT8 *p = buf;
UINT32 crc = seed; UINT32 crc = seed;
UINTN i;
for (UINTN i = 0; i < len; i++) { for (i = 0; i < len; i++) {
UINT8 x = *p++; UINT8 x = *p++;
if (i >= exclude_off && i < exclude_off + exclude_len) if (i >= exclude_off && i < exclude_off + exclude_len)

View File

@ -13,9 +13,10 @@ EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[static 37]) {
device_path = DevicePathFromHandle(handle); device_path = DevicePathFromHandle(handle);
if (device_path) { if (device_path) {
_cleanup_freepool_ EFI_DEVICE_PATH *paths = NULL; _cleanup_freepool_ EFI_DEVICE_PATH *paths = NULL;
EFI_DEVICE_PATH *path;
paths = UnpackDevicePath(device_path); paths = UnpackDevicePath(device_path);
for (EFI_DEVICE_PATH *path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) { for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) {
HARDDRIVE_DEVICE_PATH *drive; HARDDRIVE_DEVICE_PATH *drive;
if (DevicePathType(path) != MEDIA_DEVICE_PATH) if (DevicePathType(path) != MEDIA_DEVICE_PATH)

View File

@ -10,10 +10,9 @@
#include "graphics.h" #include "graphics.h"
#include "util.h" #include "util.h"
#define EFI_CONSOLE_CONTROL_GUID \
&(EFI_GUID) { 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } }
EFI_STATUS graphics_mode(BOOLEAN on) { EFI_STATUS graphics_mode(BOOLEAN on) {
#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
{ 0xf42f7782, 0x12e, 0x4c12, { 0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } };
struct _EFI_CONSOLE_CONTROL_PROTOCOL; struct _EFI_CONSOLE_CONTROL_PROTOCOL;
@ -46,6 +45,7 @@ EFI_STATUS graphics_mode(BOOLEAN on) {
EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn;
} EFI_CONSOLE_CONTROL_PROTOCOL; } EFI_CONSOLE_CONTROL_PROTOCOL;
EFI_GUID ConsoleControlProtocolGuid = EFI_CONSOLE_CONTROL_PROTOCOL_GUID;
EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL; EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl = NULL;
EFI_CONSOLE_CONTROL_SCREEN_MODE new; EFI_CONSOLE_CONTROL_SCREEN_MODE new;
EFI_CONSOLE_CONTROL_SCREEN_MODE current; EFI_CONSOLE_CONTROL_SCREEN_MODE current;
@ -53,7 +53,7 @@ EFI_STATUS graphics_mode(BOOLEAN on) {
BOOLEAN stdin_locked; BOOLEAN stdin_locked;
EFI_STATUS err; EFI_STATUS err;
err = LibLocateProtocol(EFI_CONSOLE_CONTROL_GUID, (VOID **)&ConsoleControl); err = LibLocateProtocol(&ConsoleControlProtocolGuid, (VOID **)&ConsoleControl);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
/* console control protocol is nonstandard and might not exist. */ /* console control protocol is nonstandard and might not exist. */
return err == EFI_NOT_FOUND ? EFI_SUCCESS : err; return err == EFI_NOT_FOUND ? EFI_SUCCESS : err;

View File

@ -4,11 +4,9 @@
#include <efi.h> #include <efi.h>
#include <efilib.h> #include <efilib.h>
#include "measure.h" #include "measure.h"
#define EFI_TCG_GUID \ #define EFI_TCG_PROTOCOL_GUID { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd} }
&(EFI_GUID) { 0xf541796d, 0xa62e, 0x4954, { 0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd } }
typedef struct _TCG_VERSION { typedef struct _TCG_VERSION {
UINT8 Major; UINT8 Major;
@ -102,8 +100,7 @@ typedef struct _EFI_TCG {
EFI_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent; EFI_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent;
} EFI_TCG; } EFI_TCG;
#define EFI_TCG2_GUID \ #define EFI_TCG2_PROTOCOL_GUID {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }}
&(EFI_GUID) { 0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f } }
typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL; typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL;
@ -241,6 +238,7 @@ static EFI_STATUS tpm2_measure_to_pcr_and_event_log(const EFI_TCG2 *tcg, UINT32
} }
static EFI_TCG * tcg1_interface_check(void) { static EFI_TCG * tcg1_interface_check(void) {
EFI_GUID tpm_guid = EFI_TCG_PROTOCOL_GUID;
EFI_STATUS status; EFI_STATUS status;
EFI_TCG *tcg; EFI_TCG *tcg;
TCG_BOOT_SERVICE_CAPABILITY capability; TCG_BOOT_SERVICE_CAPABILITY capability;
@ -248,7 +246,7 @@ static EFI_TCG * tcg1_interface_check(void) {
EFI_PHYSICAL_ADDRESS event_log_location; EFI_PHYSICAL_ADDRESS event_log_location;
EFI_PHYSICAL_ADDRESS event_log_last_entry; EFI_PHYSICAL_ADDRESS event_log_last_entry;
status = LibLocateProtocol(EFI_TCG_GUID, (void **) &tcg); status = LibLocateProtocol(&tpm_guid, (void **) &tcg);
if (EFI_ERROR(status)) if (EFI_ERROR(status))
return NULL; return NULL;
@ -269,11 +267,12 @@ static EFI_TCG * tcg1_interface_check(void) {
} }
static EFI_TCG2 * tcg2_interface_check(void) { static EFI_TCG2 * tcg2_interface_check(void) {
EFI_GUID tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
EFI_STATUS status; EFI_STATUS status;
EFI_TCG2 *tcg; EFI_TCG2 *tcg;
EFI_TCG2_BOOT_SERVICE_CAPABILITY capability; EFI_TCG2_BOOT_SERVICE_CAPABILITY capability;
status = LibLocateProtocol(EFI_TCG2_GUID, (void **) &tcg); status = LibLocateProtocol(&tpm2_guid, (void **) &tcg);
if (EFI_ERROR(status)) if (EFI_ERROR(status))
return NULL; return NULL;

View File

@ -21,7 +21,6 @@ common_sources = '''
graphics.c graphics.c
measure.c measure.c
pe.c pe.c
secure-boot.c
util.c util.c
'''.split() '''.split()
@ -134,8 +133,8 @@ endif
if have_gnu_efi if have_gnu_efi
compile_args = ['-Wall', compile_args = ['-Wall',
'-Wextra', '-Wextra',
'-std=gnu99', '-std=gnu90',
'-nostdlib', '-nostdinc',
'-fpic', '-fpic',
'-fshort-wchar', '-fshort-wchar',
'-ffreestanding', '-ffreestanding',

View File

@ -62,6 +62,7 @@ struct PeSectionHeader {
EFI_STATUS pe_memory_locate_sections(CHAR8 *base, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) { EFI_STATUS pe_memory_locate_sections(CHAR8 *base, CHAR8 **sections, UINTN *addrs, UINTN *offsets, UINTN *sizes) {
struct DosFileHeader *dos; struct DosFileHeader *dos;
struct PeHeader *pe; struct PeHeader *pe;
UINTN i;
UINTN offset; UINTN offset;
dos = (struct DosFileHeader *)base; dos = (struct DosFileHeader *)base;
@ -84,11 +85,12 @@ EFI_STATUS pe_memory_locate_sections(CHAR8 *base, CHAR8 **sections, UINTN *addrs
offset = dos->ExeHeader + sizeof(*pe) + pe->FileHeader.SizeOfOptionalHeader; offset = dos->ExeHeader + sizeof(*pe) + pe->FileHeader.SizeOfOptionalHeader;
for (UINTN i = 0; i < pe->FileHeader.NumberOfSections; i++) { for (i = 0; i < pe->FileHeader.NumberOfSections; i++) {
struct PeSectionHeader *sect; struct PeSectionHeader *sect;
UINTN j;
sect = (struct PeSectionHeader *)&base[offset]; sect = (struct PeSectionHeader *)&base[offset];
for (UINTN j = 0; sections[j]; j++) { for (j = 0; sections[j]; j++) {
if (CompareMem(sect->Name, sections[j], strlena(sections[j])) != 0) if (CompareMem(sect->Name, sections[j], strlena(sections[j])) != 0)
continue; continue;

View File

@ -5,14 +5,14 @@
#include "missing_efi.h" #include "missing_efi.h"
#include "random-seed.h" #include "random-seed.h"
#include "secure-boot.h"
#include "sha256.h" #include "sha256.h"
#include "util.h" #include "util.h"
#include "shim.h"
#define RANDOM_MAX_SIZE_MIN (32U) #define RANDOM_MAX_SIZE_MIN (32U)
#define RANDOM_MAX_SIZE_MAX (32U*1024U) #define RANDOM_MAX_SIZE_MAX (32U*1024U)
#define EFI_RNG_GUID &(EFI_GUID) EFI_RNG_PROTOCOL_GUID static const EFI_GUID rng_protocol_guid = EFI_RNG_PROTOCOL_GUID;
/* SHA256 gives us 256/8=32 bytes */ /* SHA256 gives us 256/8=32 bytes */
#define HASH_VALUE_SIZE 32 #define HASH_VALUE_SIZE 32
@ -24,7 +24,7 @@ static EFI_STATUS acquire_rng(UINTN size, VOID **ret) {
/* Try to acquire the specified number of bytes from the UEFI RNG */ /* Try to acquire the specified number of bytes from the UEFI RNG */
err = LibLocateProtocol(EFI_RNG_GUID, (VOID**) &rng); err = LibLocateProtocol((EFI_GUID*) &rng_protocol_guid, (VOID**) &rng);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
if (!rng) if (!rng)
@ -86,6 +86,7 @@ static EFI_STATUS hash_many(
VOID **ret) { VOID **ret) {
_cleanup_freepool_ VOID *output = NULL; _cleanup_freepool_ VOID *output = NULL;
UINTN i;
/* Hashes the specified parameters in counter mode, generating n hash values, with the counter in the /* Hashes the specified parameters in counter mode, generating n hash values, with the counter in the
* range counter_startcounter_start+n-1. */ * range counter_startcounter_start+n-1. */
@ -94,7 +95,7 @@ static EFI_STATUS hash_many(
if (!output) if (!output)
return log_oom(); return log_oom();
for (UINTN i = 0; i < n; i++) for (i = 0; i < n; i++)
hash_once(old_seed, rng, size, hash_once(old_seed, rng, size,
system_token, system_token_size, system_token, system_token_size,
counter_start + i, counter_start + i,
@ -146,7 +147,7 @@ static EFI_STATUS acquire_system_token(VOID **ret, UINTN *ret_size) {
EFI_STATUS err; EFI_STATUS err;
UINTN size; UINTN size;
err = efivar_get_raw(LOADER_GUID, L"LoaderSystemToken", &data, &size); err = efivar_get_raw(&loader_guid, L"LoaderSystemToken", &data, &size);
if (EFI_ERROR(err)) { if (EFI_ERROR(err)) {
if (err != EFI_NOT_FOUND) if (err != EFI_NOT_FOUND)
Print(L"Failed to read LoaderSystemToken EFI variable: %r", err); Print(L"Failed to read LoaderSystemToken EFI variable: %r", err);
@ -200,7 +201,9 @@ static VOID validate_sha256(void) {
0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1 }}, 0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1 }},
}; };
for (UINTN i = 0; i < ELEMENTSOF(array); i++) { UINTN i;
for (i = 0; i < ELEMENTSOF(array); i++) {
struct sha256_ctx hash; struct sha256_ctx hash;
uint8_t result[HASH_VALUE_SIZE]; uint8_t result[HASH_VALUE_SIZE];
@ -315,7 +318,7 @@ EFI_STATUS process_random_seed(EFI_FILE *root_dir, RandomSeedMode mode) {
} }
/* We are good to go */ /* We are good to go */
err = efivar_set_raw(LOADER_GUID, L"LoaderRandomSeed", for_kernel, size, FALSE); err = efivar_set_raw(&loader_guid, L"LoaderRandomSeed", for_kernel, size, FALSE);
if (EFI_ERROR(err)) { if (EFI_ERROR(err)) {
Print(L"Failed to write random seed to EFI variable: %r\n", err); Print(L"Failed to write random seed to EFI variable: %r\n", err);
return err; return err;

View File

@ -1,13 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "secure-boot.h"
#include "util.h"
BOOLEAN secure_boot_enabled(void) {
BOOLEAN secure;
EFI_STATUS err;
err = efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"SecureBoot", &secure);
return !EFI_ERROR(err) && secure;
}

View File

@ -1,6 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <efi.h>
BOOLEAN secure_boot_enabled(void);

View File

@ -94,7 +94,7 @@ void sha256_init_ctx(struct sha256_ctx *ctx) {
void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) { void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
/* Take yet unprocessed bytes into account. */ /* Take yet unprocessed bytes into account. */
UINT32 bytes = ctx->buflen; UINT32 bytes = ctx->buflen;
UINTN pad; UINTN pad, i;
/* Now count remaining bytes. */ /* Now count remaining bytes. */
ctx->total64 += bytes; ctx->total64 += bytes;
@ -111,7 +111,7 @@ void *sha256_finish_ctx(struct sha256_ctx *ctx, void *resbuf) {
sha256_process_block (ctx->buffer, bytes + pad + 8, ctx); sha256_process_block (ctx->buffer, bytes + pad + 8, ctx);
/* Put result from CTX in first 32 bytes following RESBUF. */ /* Put result from CTX in first 32 bytes following RESBUF. */
for (UINTN i = 0; i < 8; ++i) for (i = 0; i < 8; ++i)
((UINT32 *) resbuf)[i] = SWAP (ctx->H[i]); ((UINT32 *) resbuf)[i] = SWAP (ctx->H[i]);
return resbuf; return resbuf;
@ -214,6 +214,7 @@ static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ct
UINT32 f_save = f; UINT32 f_save = f;
UINT32 g_save = g; UINT32 g_save = g;
UINT32 h_save = h; UINT32 h_save = h;
UINTN t;
/* Operators defined in FIPS 180-2:4.1.2. */ /* Operators defined in FIPS 180-2:4.1.2. */
#define Ch(x, y, z) ((x & y) ^ (~x & z)) #define Ch(x, y, z) ((x & y) ^ (~x & z))
@ -228,15 +229,15 @@ static void sha256_process_block(const void *buffer, UINTN len, struct sha256_ct
#define CYCLIC(w, s) ((w >> s) | (w << (32 - s))) #define CYCLIC(w, s) ((w >> s) | (w << (32 - s)))
/* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */
for (UINTN t = 0; t < 16; ++t) { for (t = 0; t < 16; ++t) {
W[t] = SWAP (*words); W[t] = SWAP (*words);
++words; ++words;
} }
for (UINTN t = 16; t < 64; ++t) for (t = 16; t < 64; ++t)
W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16]; W[t] = R1 (W[t - 2]) + W[t - 7] + R0 (W[t - 15]) + W[t - 16];
/* The actual computation according to FIPS 180-2:6.2.2 step 3. */ /* The actual computation according to FIPS 180-2:6.2.2 step 3. */
for (UINTN t = 0; t < 64; ++t) { for (t = 0; t < 64; ++t) {
UINT32 T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t]; UINT32 T1 = h + S1 (e) + Ch (e, f, g) + K[t] + W[t];
UINT32 T2 = S0 (a) + Maj (a, b, c); UINT32 T2 = S0 (a) + Maj (a, b, c);
h = g; h = g;

View File

@ -30,18 +30,17 @@ struct ShimLock {
EFI_STATUS __sysv_abi__ (*read_header) (VOID *data, UINT32 datasize, VOID *context); EFI_STATUS __sysv_abi__ (*read_header) (VOID *data, UINT32 datasize, VOID *context);
}; };
#define SIMPLE_FS_GUID &(EFI_GUID) SIMPLE_FILE_SYSTEM_PROTOCOL static const EFI_GUID simple_fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL;
#define SECURITY_PROTOCOL_GUID \ static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
&(EFI_GUID) { 0xa46423e3, 0x4617, 0x49f1, { 0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } }
#define SECURITY_PROTOCOL2_GUID \ static const EFI_GUID security_protocol_guid = { 0xa46423e3, 0x4617, 0x49f1, {0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } };
&(EFI_GUID) { 0x94ab2f58, 0x1438, 0x4ef1, { 0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } } static const EFI_GUID security2_protocol_guid = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } };
#define SHIM_LOCK_GUID \ static const EFI_GUID shim_lock_guid = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} };
&(EFI_GUID) { 0x605dab50, 0xe046, 0x4300, { 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23 } }
BOOLEAN shim_loaded(void) { BOOLEAN shim_loaded(void) {
struct ShimLock *shim_lock; struct ShimLock *shim_lock;
return uefi_call_wrapper(BS->LocateProtocol, 3, SHIM_LOCK_GUID, NULL, (VOID**) &shim_lock) == EFI_SUCCESS; return uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS;
} }
static BOOLEAN shim_validate(VOID *data, UINT32 size) { static BOOLEAN shim_validate(VOID *data, UINT32 size) {
@ -50,7 +49,7 @@ static BOOLEAN shim_validate(VOID *data, UINT32 size) {
if (!data) if (!data)
return FALSE; return FALSE;
if (uefi_call_wrapper(BS->LocateProtocol, 3, SHIM_LOCK_GUID, NULL, (VOID**) &shim_lock) != EFI_SUCCESS) if (uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) != EFI_SUCCESS)
return FALSE; return FALSE;
if (!shim_lock) if (!shim_lock)
@ -59,6 +58,16 @@ static BOOLEAN shim_validate(VOID *data, UINT32 size) {
return shim_lock->shim_verify(data, size) == EFI_SUCCESS; return shim_lock->shim_verify(data, size) == EFI_SUCCESS;
} }
BOOLEAN secure_boot_enabled(void) {
_cleanup_freepool_ CHAR8 *b = NULL;
UINTN size;
if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS)
return *b > 0;
return FALSE;
}
/* /*
* See the UEFI Platform Initialization manual (Vol2: DXE) for this * See the UEFI Platform Initialization manual (Vol2: DXE) for this
*/ */
@ -148,7 +157,7 @@ static EFIAPI EFI_STATUS security_policy_authentication (const EFI_SECURITY_PROT
dev_path = DuplicateDevicePath((EFI_DEVICE_PATH*) device_path_const); dev_path = DuplicateDevicePath((EFI_DEVICE_PATH*) device_path_const);
status = uefi_call_wrapper(BS->LocateDevicePath, 3, SIMPLE_FS_GUID, &dev_path, &h); status = uefi_call_wrapper(BS->LocateDevicePath, 3, (EFI_GUID*) &simple_fs_guid, &dev_path, &h);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
return status; return status;
@ -182,9 +191,9 @@ EFI_STATUS security_policy_install(void) {
* to fail, since SECURITY2 was introduced in PI 1.2.1. * to fail, since SECURITY2 was introduced in PI 1.2.1.
* Use security2_protocol == NULL as indicator. * Use security2_protocol == NULL as indicator.
*/ */
uefi_call_wrapper(BS->LocateProtocol, 3, SECURITY_PROTOCOL2_GUID, NULL, (VOID**) &security2_protocol); uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security2_protocol_guid, NULL, (VOID**) &security2_protocol);
status = uefi_call_wrapper(BS->LocateProtocol, 3, SECURITY_PROTOCOL_GUID, NULL, (VOID**) &security_protocol); status = uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security_protocol_guid, NULL, (VOID**) &security_protocol);
/* This one is mandatory, so there's a serious problem */ /* This one is mandatory, so there's a serious problem */
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
return status; return status;

View File

@ -13,4 +13,6 @@
BOOLEAN shim_loaded(void); BOOLEAN shim_loaded(void);
BOOLEAN secure_boot_enabled(void);
EFI_STATUS security_policy_install(void); EFI_STATUS security_policy_install(void);

View File

@ -151,18 +151,22 @@ static EFI_STATUS bmp_to_blt(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf,
struct bmp_dib *dib, struct bmp_map *map, struct bmp_dib *dib, struct bmp_map *map,
UINT8 *pixmap) { UINT8 *pixmap) {
UINT8 *in; UINT8 *in;
UINTN y;
/* transform and copy pixels */ /* transform and copy pixels */
in = pixmap; in = pixmap;
for (UINTN y = 0; y < dib->y; y++) { for (y = 0; y < dib->y; y++) {
EFI_GRAPHICS_OUTPUT_BLT_PIXEL *out; EFI_GRAPHICS_OUTPUT_BLT_PIXEL *out;
UINTN row_size; UINTN row_size;
UINTN x;
out = &buf[(dib->y - y - 1) * dib->x]; out = &buf[(dib->y - y - 1) * dib->x];
for (UINTN x = 0; x < dib->x; x++, in++, out++) { for (x = 0; x < dib->x; x++, in++, out++) {
switch (dib->depth) { switch (dib->depth) {
case 1: { case 1: {
for (UINTN i = 0; i < 8 && x < dib->x; i++) { UINTN i;
for (i = 0; i < 8 && x < dib->x; i++) {
out->Red = map[((*in) >> (7 - i)) & 1].red; out->Red = map[((*in) >> (7 - i)) & 1].red;
out->Green = map[((*in) >> (7 - i)) & 1].green; out->Green = map[((*in) >> (7 - i)) & 1].green;
out->Blue = map[((*in) >> (7 - i)) & 1].blue; out->Blue = map[((*in) >> (7 - i)) & 1].blue;

View File

@ -8,15 +8,19 @@
#include "linux.h" #include "linux.h"
#include "measure.h" #include "measure.h"
#include "pe.h" #include "pe.h"
#include "secure-boot.h"
#include "splash.h" #include "splash.h"
#include "util.h" #include "util.h"
/* magic string to find in the binary image */ /* magic string to find in the binary image */
static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####"; static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " GIT_VERSION " ####";
static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE;
EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) { EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
EFI_LOADED_IMAGE *loaded_image; EFI_LOADED_IMAGE *loaded_image;
_cleanup_freepool_ CHAR8 *b = NULL;
UINTN size;
BOOLEAN secure = FALSE;
CHAR8 *sections[] = { CHAR8 *sections[] = {
(CHAR8 *)".cmdline", (CHAR8 *)".cmdline",
(CHAR8 *)".linux", (CHAR8 *)".linux",
@ -42,6 +46,10 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
return err; return err;
} }
if (efivar_get_raw(&global_guid, L"SecureBoot", &b, &size) == EFI_SUCCESS)
if (*b > 0)
secure = TRUE;
err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs); err = pe_memory_locate_sections(loaded_image->ImageBase, sections, addrs, offs, szs);
if (EFI_ERROR(err)) { if (EFI_ERROR(err)) {
Print(L"Unable to locate embedded .linux section: %r ", err); Print(L"Unable to locate embedded .linux section: %r ", err);
@ -50,20 +58,20 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
} }
if (szs[0] > 0) if (szs[0] > 0)
cmdline = (CHAR8 *)(loaded_image->ImageBase) + addrs[0]; cmdline = (CHAR8 *)(loaded_image->ImageBase + addrs[0]);
cmdline_len = szs[0]; cmdline_len = szs[0];
/* if we are not in secure boot mode, or none was provided, accept a custom command line and replace the built-in one */ /* if we are not in secure boot mode, or none was provided, accept a custom command line and replace the built-in one */
if ((!secure_boot_enabled() || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 && if ((!secure || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions > 0x1F) {
*(CHAR16 *) loaded_image->LoadOptions > 0x1F) {
CHAR16 *options; CHAR16 *options;
CHAR8 *line; CHAR8 *line;
UINTN i;
options = (CHAR16 *)loaded_image->LoadOptions; options = (CHAR16 *)loaded_image->LoadOptions;
cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8); cmdline_len = (loaded_image->LoadOptionsSize / sizeof(CHAR16)) * sizeof(CHAR8);
line = AllocatePool(cmdline_len); line = AllocatePool(cmdline_len);
for (UINTN i = 0; i < cmdline_len; i++) for (i = 0; i < cmdline_len; i++)
line[i] = options[i]; line[i] = options[i];
cmdline = line; cmdline = line;
@ -80,37 +88,37 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
} }
/* Export the device path this image is started from, if it's not set yet */ /* Export the device path this image is started from, if it's not set yet */
if (efivar_get_raw(LOADER_GUID, L"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS) if (efivar_get_raw(&loader_guid, L"LoaderDevicePartUUID", NULL, NULL) != EFI_SUCCESS)
if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS) if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, FALSE); efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
/* if LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from UEFI */ /* if LoaderImageIdentifier is not set, assume the image with this stub was loaded directly from UEFI */
if (efivar_get_raw(LOADER_GUID, L"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS) { if (efivar_get_raw(&loader_guid, L"LoaderImageIdentifier", NULL, NULL) != EFI_SUCCESS) {
_cleanup_freepool_ CHAR16 *s; _cleanup_freepool_ CHAR16 *s;
s = DevicePathToStr(loaded_image->FilePath); s = DevicePathToStr(loaded_image->FilePath);
efivar_set(LOADER_GUID, L"LoaderImageIdentifier", s, FALSE); efivar_set(L"LoaderImageIdentifier", s, FALSE);
} }
/* if LoaderFirmwareInfo is not set, let's set it */ /* if LoaderFirmwareInfo is not set, let's set it */
if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) { if (efivar_get_raw(&loader_guid, L"LoaderFirmwareInfo", NULL, NULL) != EFI_SUCCESS) {
_cleanup_freepool_ CHAR16 *s; _cleanup_freepool_ CHAR16 *s;
s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff); s = PoolPrint(L"%s %d.%02d", ST->FirmwareVendor, ST->FirmwareRevision >> 16, ST->FirmwareRevision & 0xffff);
efivar_set(LOADER_GUID, L"LoaderFirmwareInfo", s, FALSE); efivar_set(L"LoaderFirmwareInfo", s, FALSE);
} }
/* ditto for LoaderFirmwareType */ /* ditto for LoaderFirmwareType */
if (efivar_get_raw(LOADER_GUID, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) { if (efivar_get_raw(&loader_guid, L"LoaderFirmwareType", NULL, NULL) != EFI_SUCCESS) {
_cleanup_freepool_ CHAR16 *s; _cleanup_freepool_ CHAR16 *s;
s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff); s = PoolPrint(L"UEFI %d.%02d", ST->Hdr.Revision >> 16, ST->Hdr.Revision & 0xffff);
efivar_set(LOADER_GUID, L"LoaderFirmwareType", s, FALSE); efivar_set(L"LoaderFirmwareType", s, FALSE);
} }
/* add StubInfo */ /* add StubInfo */
if (efivar_get_raw(LOADER_GUID, L"StubInfo", NULL, NULL) != EFI_SUCCESS) if (efivar_get_raw(&loader_guid, L"StubInfo", NULL, NULL) != EFI_SUCCESS)
efivar_set(LOADER_GUID, L"StubInfo", L"systemd-stub " GIT_VERSION, FALSE); efivar_set(L"StubInfo", L"systemd-stub " GIT_VERSION, FALSE);
if (szs[3] > 0) if (szs[3] > 0)
graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL); graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL);

View File

@ -5,6 +5,13 @@
#include "util.h" #include "util.h"
/*
* Allocated random UUID, intended to be shared across tools that implement
* the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
* associated EFI variables.
*/
const EFI_GUID loader_guid = { 0x4a67b082, 0x0a4c, 0x41cf, {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f} };
#ifdef __x86_64__ #ifdef __x86_64__
UINT64 ticks_read(VOID) { UINT64 ticks_read(VOID) {
UINT64 a, d; UINT64 a, d;
@ -85,51 +92,24 @@ EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID
return uefi_call_wrapper(RT->SetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, flags, size, (VOID*) buf); return uefi_call_wrapper(RT->SetVariable, 5, (CHAR16*) name, (EFI_GUID *)vendor, flags, size, (VOID*) buf);
} }
EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent) { EFI_STATUS efivar_set(const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent) {
return efivar_set_raw( return efivar_set_raw(&loader_guid, name, value, value ? (StrLen(value)+1) * sizeof(CHAR16) : 0, persistent);
vendor, name, value, value ? (StrLen(value) + 1) * sizeof(CHAR16) : 0, persistent);
} }
EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, CHAR16 *name, UINTN i, BOOLEAN persistent) { EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) {
CHAR16 str[32]; CHAR16 str[32];
SPrint(str, 32, L"%u", i); SPrint(str, 32, L"%u", i);
return efivar_set(vendor, name, str, persistent); return efivar_set(name, str, persistent);
} }
EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *name, UINT32 value, BOOLEAN persistent) { EFI_STATUS efivar_get(const CHAR16 *name, CHAR16 **value) {
UINT8 buf[4];
buf[0] = (UINT8)(value >> 0U & 0xFF);
buf[1] = (UINT8)(value >> 8U & 0xFF);
buf[2] = (UINT8)(value >> 16U & 0xFF);
buf[3] = (UINT8)(value >> 24U & 0xFF);
return efivar_set_raw(vendor, name, buf, sizeof(buf), persistent);
}
EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, CHAR16 *name, UINT64 value, BOOLEAN persistent) {
UINT8 buf[8];
buf[0] = (UINT8)(value >> 0U & 0xFF);
buf[1] = (UINT8)(value >> 8U & 0xFF);
buf[2] = (UINT8)(value >> 16U & 0xFF);
buf[3] = (UINT8)(value >> 24U & 0xFF);
buf[4] = (UINT8)(value >> 32U & 0xFF);
buf[5] = (UINT8)(value >> 40U & 0xFF);
buf[6] = (UINT8)(value >> 48U & 0xFF);
buf[7] = (UINT8)(value >> 56U & 0xFF);
return efivar_set_raw(vendor, name, buf, sizeof(buf), persistent);
}
EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value) {
_cleanup_freepool_ CHAR8 *buf = NULL; _cleanup_freepool_ CHAR8 *buf = NULL;
EFI_STATUS err; EFI_STATUS err;
CHAR16 *val; CHAR16 *val;
UINTN size; UINTN size;
err = efivar_get_raw(vendor, name, &buf, &size); err = efivar_get_raw(&loader_guid, name, &buf, &size);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
@ -158,52 +138,17 @@ EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value
return EFI_SUCCESS; return EFI_SUCCESS;
} }
EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN *i) { EFI_STATUS efivar_get_int(const CHAR16 *name, UINTN *i) {
_cleanup_freepool_ CHAR16 *val = NULL; _cleanup_freepool_ CHAR16 *val = NULL;
EFI_STATUS err; EFI_STATUS err;
err = efivar_get(vendor, name, &val); err = efivar_get(name, &val);
if (!EFI_ERROR(err) && i) if (!EFI_ERROR(err) && i)
*i = Atoi(val); *i = Atoi(val);
return err; return err;
} }
EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 *ret) {
_cleanup_freepool_ CHAR8 *buf = NULL;
UINTN size;
EFI_STATUS err;
err = efivar_get_raw(vendor, name, &buf, &size);
if (!EFI_ERROR(err) && ret) {
if (size != sizeof(UINT32))
return EFI_BUFFER_TOO_SMALL;
*ret = (UINT32) buf[0] << 0U | (UINT32) buf[1] << 8U | (UINT32) buf[2] << 16U |
(UINT32) buf[3] << 24U;
}
return err;
}
EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 *ret) {
_cleanup_freepool_ CHAR8 *buf = NULL;
UINTN size;
EFI_STATUS err;
err = efivar_get_raw(vendor, name, &buf, &size);
if (!EFI_ERROR(err) && ret) {
if (size != sizeof(UINT64))
return EFI_BUFFER_TOO_SMALL;
*ret = (UINT64) buf[0] << 0U | (UINT64) buf[1] << 8U | (UINT64) buf[2] << 16U |
(UINT64) buf[3] << 24U | (UINT64) buf[4] << 32U | (UINT64) buf[5] << 40U |
(UINT64) buf[6] << 48U | (UINT64) buf[7] << 56U;
}
return err;
}
EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size) { EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size) {
_cleanup_freepool_ CHAR8 *buf = NULL; _cleanup_freepool_ CHAR8 *buf = NULL;
UINTN l; UINTN l;
@ -227,19 +172,7 @@ EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **bu
return err; return err;
} }
EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOOLEAN *ret) { VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) {
_cleanup_freepool_ CHAR8 *b = NULL;
UINTN size;
EFI_STATUS err;
err = efivar_get_raw(vendor, name, &b, &size);
if (!EFI_ERROR(err))
*ret = *b > 0;
return err;
}
VOID efivar_set_time_usec(const EFI_GUID *vendor, CHAR16 *name, UINT64 usec) {
CHAR16 str[32]; CHAR16 str[32];
if (usec == 0) if (usec == 0)
@ -248,12 +181,13 @@ VOID efivar_set_time_usec(const EFI_GUID *vendor, CHAR16 *name, UINT64 usec) {
return; return;
SPrint(str, 32, L"%ld", usec); SPrint(str, 32, L"%ld", usec);
efivar_set(vendor, name, str, FALSE); efivar_set(name, str, FALSE);
} }
static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) { static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) {
CHAR16 unichar; CHAR16 unichar;
UINTN len; UINTN len;
UINTN i;
if (!(stra[0] & 0x80)) if (!(stra[0] & 0x80))
len = 1; len = 1;
@ -291,7 +225,7 @@ static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) {
break; break;
} }
for (UINTN i = 1; i < len; i++) { for (i = 1; i < len; i++) {
if ((stra[i] & 0xc0) != 0x80) if ((stra[i] & 0xc0) != 0x80)
return -1; return -1;
unichar <<= 6; unichar <<= 6;
@ -375,62 +309,6 @@ CHAR8 *strchra(CHAR8 *s, CHAR8 c) {
return NULL; return NULL;
} }
const CHAR16 *startswith(const CHAR16 *s, const CHAR16 *prefix) {
UINTN l;
l = StrLen(prefix);
if (StrnCmp(s, prefix, l) == 0)
return s + l;
return NULL;
}
const CHAR16 *endswith(const CHAR16 *s, const CHAR16 *postfix) {
UINTN sl, pl;
sl = StrLen(s);
pl = StrLen(postfix);
if (pl == 0)
return s + sl;
if (sl < pl)
return NULL;
if (StrnCmp(s + sl - pl, postfix, pl) != 0)
return NULL;
return s + sl - pl;
}
const CHAR16 *startswith_no_case(const CHAR16 *s, const CHAR16 *prefix) {
UINTN l;
l = StrLen(prefix);
if (StriCmp(s, prefix) == 0)
return s + l;
return NULL;
}
const CHAR16 *endswith_no_case(const CHAR16 *s, const CHAR16 *postfix) {
UINTN sl, pl;
sl = StrLen(s);
pl = StrLen(postfix);
if (pl == 0)
return s + sl;
if (sl < pl)
return NULL;
if (StriCmp(s + sl - pl, postfix) != 0)
return NULL;
return s + sl - pl;
}
EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **ret, UINTN *ret_size) { EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **ret, UINTN *ret_size) {
_cleanup_(FileHandleClosep) EFI_FILE_HANDLE handle = NULL; _cleanup_(FileHandleClosep) EFI_FILE_HANDLE handle = NULL;
_cleanup_freepool_ CHAR8 *buf = NULL; _cleanup_freepool_ CHAR8 *buf = NULL;

View File

@ -21,30 +21,19 @@ UINT64 ticks_read(void);
UINT64 ticks_freq(void); UINT64 ticks_freq(void);
UINT64 time_usec(void); UINT64 time_usec(void);
EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent); EFI_STATUS efivar_set(const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent);
EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, BOOLEAN persistent); EFI_STATUS efivar_set_raw(const EFI_GUID *vendor, const CHAR16 *name, const VOID *buf, UINTN size, BOOLEAN persistent);
EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, CHAR16 *name, UINTN i, BOOLEAN persistent); EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent);
EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *NAME, UINT32 value, BOOLEAN persistent); VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec);
EFI_STATUS efivar_set_uint64_le(const EFI_GUID *vendor, CHAR16 *name, UINT64 value, BOOLEAN persistent);
VOID efivar_set_time_usec(const EFI_GUID *vendor, CHAR16 *name, UINT64 usec);
EFI_STATUS efivar_get(const EFI_GUID *vendor, const CHAR16 *name, CHAR16 **value); EFI_STATUS efivar_get(const CHAR16 *name, CHAR16 **value);
EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size); EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **buffer, UINTN *size);
EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN *i); EFI_STATUS efivar_get_int(const CHAR16 *name, UINTN *i);
EFI_STATUS efivar_get_uint32_le(const EFI_GUID *vendor, const CHAR16 *name, UINT32 *ret);
EFI_STATUS efivar_get_uint64_le(const EFI_GUID *vendor, const CHAR16 *name, UINT64 *ret);
EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOOLEAN *ret);
CHAR8 *strchra(CHAR8 *s, CHAR8 c); CHAR8 *strchra(CHAR8 *s, CHAR8 c);
CHAR16 *stra_to_path(CHAR8 *stra); CHAR16 *stra_to_path(CHAR8 *stra);
CHAR16 *stra_to_str(CHAR8 *stra); CHAR16 *stra_to_str(CHAR8 *stra);
const CHAR16 *startswith(const CHAR16 *s, const CHAR16 *prefix);
const CHAR16 *endswith(const CHAR16 *s, const CHAR16 *postfix);
const CHAR16 *startswith_no_case(const CHAR16 *s, const CHAR16 *prefix);
const CHAR16 *endswith_no_case(const CHAR16 *s, const CHAR16 *postfix);
EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size); EFI_STATUS file_read(EFI_FILE_HANDLE dir, const CHAR16 *name, UINTN off, UINTN size, CHAR8 **content, UINTN *content_size);
static inline void FreePoolp(void *p) { static inline void FreePoolp(void *p) {
@ -66,14 +55,7 @@ static inline void FileHandleClosep(EFI_FILE_HANDLE *handle) {
uefi_call_wrapper((*handle)->Close, 1, *handle); uefi_call_wrapper((*handle)->Close, 1, *handle);
} }
/* extern const EFI_GUID loader_guid;
* Allocated random UUID, intended to be shared across tools that implement
* the (ESP)\loader\entries\<vendor>-<revision>.conf convention and the
* associated EFI variables.
*/
#define LOADER_GUID \
&(const EFI_GUID) { 0x4a67b082, 0x0a4c, 0x41cf, { 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } }
#define EFI_GLOBAL_GUID &(const EFI_GUID) EFI_GLOBAL_VARIABLE
#define UINTN_MAX (~(UINTN)0) #define UINTN_MAX (~(UINTN)0)
#define INTN_MAX ((INTN)(UINTN_MAX>>1)) #define INTN_MAX ((INTN)(UINTN_MAX>>1))

View File

@ -57,25 +57,15 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
return 0; return 0;
} }
int rtnl_set_link_properties( int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac,
sd_netlink **rtnl, uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments) {
int ifindex,
const char *alias,
const struct ether_addr *mac,
uint32_t txqueues,
uint32_t rxqueues,
uint32_t txqueuelen,
uint32_t mtu,
uint32_t gso_max_size,
size_t gso_max_segments) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL; _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *message = NULL;
int r; int r;
assert(rtnl); assert(rtnl);
assert(ifindex > 0); assert(ifindex > 0);
if (!alias && !mac && txqueues == 0 && rxqueues == 0 && txqueuelen == UINT32_MAX && mtu == 0 && if (!alias && !mac && txqueuelen == UINT32_MAX && mtu == 0 && gso_max_size == 0 && gso_max_segments == 0)
gso_max_size == 0 && gso_max_segments == 0)
return 0; return 0;
if (!*rtnl) { if (!*rtnl) {
@ -100,18 +90,6 @@ int rtnl_set_link_properties(
return r; return r;
} }
if (txqueues > 0) {
r = sd_netlink_message_append_u32(message, IFLA_NUM_TX_QUEUES, txqueues);
if (r < 0)
return r;
}
if (rxqueues > 0) {
r = sd_netlink_message_append_u32(message, IFLA_NUM_RX_QUEUES, rxqueues);
if (r < 0)
return r;
}
if (txqueuelen < UINT32_MAX) { if (txqueuelen < UINT32_MAX) {
r = sd_netlink_message_append_u32(message, IFLA_TXQLEN, txqueuelen); r = sd_netlink_message_append_u32(message, IFLA_TXQLEN, txqueuelen);
if (r < 0) if (r < 0)

View File

@ -70,17 +70,8 @@ static inline bool rtnl_message_type_is_mdb(uint16_t type) {
} }
int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name); int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name);
int rtnl_set_link_properties( int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac,
sd_netlink **rtnl, uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments);
int ifindex,
const char *alias,
const struct ether_addr *mac,
uint32_t txqueues,
uint32_t rxqueues,
uint32_t txqueuelen,
uint32_t mtu,
uint32_t gso_max_size,
size_t gso_max_segments);
int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret); int rtnl_get_link_alternative_names(sd_netlink **rtnl, int ifindex, char ***ret);
int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names); int rtnl_set_link_alternative_names(sd_netlink **rtnl, int ifindex, char * const *alternative_names);
int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char * const *alternative_names); int rtnl_set_link_alternative_names_by_ifname(sd_netlink **rtnl, const char *ifname, char * const *alternative_names);

View File

@ -1871,8 +1871,8 @@ static int method_do_shutdown_or_sleep(
bool with_flags, bool with_flags,
sd_bus_error *error) { sd_bus_error *error) {
uint64_t flags; int interactive = false, r;
int r; uint64_t flags = 0;
assert(m); assert(m);
assert(message); assert(message);
@ -1880,25 +1880,19 @@ static int method_do_shutdown_or_sleep(
assert(w >= 0); assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX); assert(w <= _INHIBIT_WHAT_MAX);
if (with_flags) { if (with_flags)
/* New style method: with flags parameter (and interactive bool in the bus message header) */
r = sd_bus_message_read(message, "t", &flags); r = sd_bus_message_read(message, "t", &flags);
if (r < 0) else
return r;
if ((flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC) != 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags parameter");
} else {
/* Old style method: no flags parameter, but interactive bool passed as boolean in
* payload. Let's convert this argument to the new-style flags parameter for our internal
* use. */
int interactive;
r = sd_bus_message_read(message, "b", &interactive); r = sd_bus_message_read(message, "b", &interactive);
if (r < 0)
return r;
flags = interactive ? SD_LOGIND_INTERACTIVE : 0; if (r < 0)
} return r;
if (with_flags && (flags & ~SD_LOGIND_SHUTDOWN_AND_SLEEP_FLAGS_PUBLIC))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid flags parameter");
SET_FLAG(flags, SD_LOGIND_INTERACTIVE, interactive);
/* Don't allow multiple jobs being executed at the same time */ /* Don't allow multiple jobs being executed at the same time */
if (m->action_what > 0) if (m->action_what > 0)

View File

@ -1479,6 +1479,61 @@ static int link_set_group(Link *link) {
return 0; return 0;
} }
static int link_tx_rx_queues_hadler(sd_netlink *rtnl, sd_netlink_message *m, Link *link) {
int r;
assert(link);
if (IN_SET(link->state, LINK_STATE_FAILED, LINK_STATE_LINGER))
return 1;
r = sd_netlink_message_get_errno(m);
if (r < 0)
log_link_message_warning_errno(link, m, r, "Could not set transmit / receive queues for the interface");
return 1;
}
static int link_set_tx_rx_queues(Link *link) {
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
int r;
assert(link);
assert(link->network);
assert(link->manager);
assert(link->manager->rtnl);
if (link->network->txqueues == 0 && link->network->rxqueues == 0)
return 0;
log_link_debug(link, "Setting transmit / receive queues");
r = sd_rtnl_message_new_link(link->manager->rtnl, &req, RTM_SETLINK, link->ifindex);
if (r < 0)
return log_link_error_errno(link, r, "Could not allocate RTM_SETLINK message: %m");
if (link->network->txqueues > 0) {
r = sd_netlink_message_append_u32(req, IFLA_NUM_TX_QUEUES, link->network->txqueues);
if (r < 0)
return log_link_error_errno(link, r, "Could not set link transmit queues: %m");
}
if (link->network->rxqueues > 0) {
r = sd_netlink_message_append_u32(req, IFLA_NUM_RX_QUEUES, link->network->rxqueues);
if (r < 0)
return log_link_error_errno(link, r, "Could not set link receive queues: %m");
}
r = netlink_call_async(link->manager->rtnl, NULL, req, link_tx_rx_queues_hadler,
link_netlink_destroy_callback, link);
if (r < 0)
return log_link_error_errno(link, r, "Could not send rtnetlink message: %m");
link_ref(link);
return 0;
}
static int link_handle_bound_to_list(Link *link) { static int link_handle_bound_to_list(Link *link) {
Link *l; Link *l;
int r; int r;
@ -2056,6 +2111,10 @@ int link_configure(Link *link) {
if (r < 0) if (r < 0)
return r; return r;
r = link_set_tx_rx_queues(link);
if (r < 0)
return r;
r = ipv4ll_configure(link); r = ipv4ll_configure(link);
if (r < 0) if (r < 0)
return r; return r;

View File

@ -60,6 +60,8 @@ Match.Architecture, config_parse_net_condition,
Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac) Link.MACAddress, config_parse_hwaddr, 0, offsetof(Network, mac)
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(Network, mtu) Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(Network, mtu)
Link.Group, config_parse_uint32, 0, offsetof(Network, group) Link.Group, config_parse_uint32, 0, offsetof(Network, group)
Link.TransmitQueues, config_parse_rx_tx_queues, 0, offsetof(Network, txqueues)
Link.ReceiveQueues, config_parse_rx_tx_queues, 0, offsetof(Network, rxqueues)
Link.ARP, config_parse_tristate, 0, offsetof(Network, arp) Link.ARP, config_parse_tristate, 0, offsetof(Network, arp)
Link.Multicast, config_parse_tristate, 0, offsetof(Network, multicast) Link.Multicast, config_parse_tristate, 0, offsetof(Network, multicast)
Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast) Link.AllMulticast, config_parse_tristate, 0, offsetof(Network, allmulticast)

View File

@ -1198,6 +1198,40 @@ int config_parse_required_for_online(
return 0; return 0;
} }
int config_parse_rx_tx_queues(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
uint32_t k, *v = data;
int r;
if (isempty(rvalue)) {
*v = 0;
return 0;
}
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s.", lvalue, rvalue);
return 0;
}
if (k == 0 || k > 4096) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid %s=, ignoring assignment: %s.", lvalue, rvalue);
return 0;
}
*v = k;
return 0;
}
DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration, DEFINE_CONFIG_PARSE_ENUM(config_parse_keep_configuration, keep_configuration, KeepConfiguration,
"Failed to parse KeepConfiguration= setting"); "Failed to parse KeepConfiguration= setting");

View File

@ -95,6 +95,8 @@ struct Network {
struct ether_addr *mac; struct ether_addr *mac;
uint32_t mtu; uint32_t mtu;
uint32_t group; uint32_t group;
uint32_t txqueues;
uint32_t rxqueues;
int arp; int arp;
int multicast; int multicast;
int allmulticast; int allmulticast;
@ -342,6 +344,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_ntp);
CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online); CONFIG_PARSER_PROTOTYPE(config_parse_required_for_online);
CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration); CONFIG_PARSER_PROTOTYPE(config_parse_keep_configuration);
CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode); CONFIG_PARSER_PROTOTYPE(config_parse_ipv6_link_local_address_gen_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_rx_tx_queues);
CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy); CONFIG_PARSER_PROTOTYPE(config_parse_activation_policy);
const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length); const struct ConfigPerfItem* network_network_gperf_lookup(const char *key, GPERF_LEN_TYPE length);

View File

@ -41,9 +41,7 @@ Link.Name, config_parse_ifname, 0,
Link.AlternativeName, config_parse_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(link_config, alternative_names) Link.AlternativeName, config_parse_ifnames, IFNAME_VALID_ALTERNATIVE, offsetof(link_config, alternative_names)
Link.AlternativeNamesPolicy, config_parse_alternative_names_policy, 0, offsetof(link_config, alternative_names_policy) Link.AlternativeNamesPolicy, config_parse_alternative_names_policy, 0, offsetof(link_config, alternative_names_policy)
Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias) Link.Alias, config_parse_ifalias, 0, offsetof(link_config, alias)
Link.TransmitQueues, config_parse_rx_tx_queues, 0, offsetof(link_config, txqueues) Link.TxQueueLength, config_parse_txqueuelen, 0, offsetof(link_config, txqueuelen)
Link.ReceiveQueues, config_parse_rx_tx_queues, 0, offsetof(link_config, rxqueues)
Link.TransmitQueueLength, config_parse_txqueuelen, 0, offsetof(link_config, txqueuelen)
Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu) Link.MTUBytes, config_parse_mtu, AF_UNSPEC, offsetof(link_config, mtu)
Link.BitsPerSecond, config_parse_si_uint64, 0, offsetof(link_config, speed) Link.BitsPerSecond, config_parse_si_uint64, 0, offsetof(link_config, speed)
Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex) Link.Duplex, config_parse_duplex, 0, offsetof(link_config, duplex)

View File

@ -427,15 +427,11 @@ static int link_config_apply_rtnl_settings(sd_netlink **rtnl, const link_config
} else } else
mac = config->mac; mac = config->mac;
r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac, config->txqueuelen, config->mtu,
config->txqueues, config->rxqueues, config->txqueuelen, config->gso_max_size, config->gso_max_segments);
config->mtu, config->gso_max_size, config->gso_max_segments);
if (r < 0) if (r < 0)
log_device_warning_errno(device, r, log_device_warning_errno(device, r, "Could not set Alias=, MACAddress=, TxQueueLength=, MTU=, "
"Could not set Alias=, MACAddress=, " "GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, ignoring: %m");
"TransmitQueues=, ReceiveQueues=, TransmitQueueLength=, MTU=, "
"GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, "
"ignoring: %m");
return 0; return 0;
} }
@ -708,40 +704,6 @@ int config_parse_ifalias(
return 0; return 0;
} }
int config_parse_rx_tx_queues(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
uint32_t k, *v = data;
int r;
if (isempty(rvalue)) {
*v = 0;
return 0;
}
r = safe_atou32(rvalue, &k);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse %s=, ignoring assignment: %s.", lvalue, rvalue);
return 0;
}
if (k == 0 || k > 4096) {
log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid %s=, ignoring assignment: %s.", lvalue, rvalue);
return 0;
}
*v = k;
return 0;
}
int config_parse_txqueuelen( int config_parse_txqueuelen(
const char *unit, const char *unit,
const char *filename, const char *filename,

View File

@ -46,8 +46,6 @@ struct link_config {
char *name; char *name;
char **alternative_names; char **alternative_names;
char *alias; char *alias;
uint32_t txqueues;
uint32_t rxqueues;
uint32_t txqueuelen; uint32_t txqueuelen;
uint32_t mtu; uint32_t mtu;
uint32_t gso_max_segments; uint32_t gso_max_segments;
@ -93,7 +91,6 @@ MACAddressPolicy mac_address_policy_from_string(const char *p) _pure_;
const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length); const struct ConfigPerfItem* link_config_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
CONFIG_PARSER_PROTOTYPE(config_parse_ifalias); CONFIG_PARSER_PROTOTYPE(config_parse_ifalias);
CONFIG_PARSER_PROTOTYPE(config_parse_rx_tx_queues);
CONFIG_PARSER_PROTOTYPE(config_parse_txqueuelen); CONFIG_PARSER_PROTOTYPE(config_parse_txqueuelen);
CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy); CONFIG_PARSER_PROTOTYPE(config_parse_mac_address_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_name_policy); CONFIG_PARSER_PROTOTYPE(config_parse_name_policy);

View File

@ -20,9 +20,7 @@ Name=
AlternativeNamesPolicy= AlternativeNamesPolicy=
AlternativeName= AlternativeName=
Alias= Alias=
TransmitQueues= TxQueueLength=
ReceiveQueues=
TransmitQueueLength=
MTUBytes= MTUBytes=
BitsPerSecond= BitsPerSecond=
Duplex= Duplex=

View File

@ -40,6 +40,8 @@ Multicast=
MACAddress= MACAddress=
Group= Group=
Promiscuous= Promiscuous=
TransmitQueues=
ReceiveQueues=
[SR-IOV] [SR-IOV]
VirtualFunction= VirtualFunction=
MACSpoofCheck= MACSpoofCheck=