1
0
mirror of https://github.com/systemd/systemd synced 2025-09-29 16:54:46 +02:00

Compare commits

...

17 Commits

Author SHA1 Message Date
Yu Watanabe
27897cecff
Merge pull request #18319 from yuwata/udev-move-tx-rx-queues
network,udev: move TransmitQueues=/ReceiveQueues= from .network to .link
2021-02-03 18:18:57 +09:00
Lennart Poettering
3ecafb1f5b logind: simplify flags handling a bit
Let's split out the two codepaths a bit, and emphasize which ones it the
new-style and which the old-style codepath, and let's clearly convert
the params of the old-stye into the new style for further processing, so
that the old style path is brief and isolated.

No change in behaviour.

Follow-up for: 8885fed4e3a52cf1bf105e42043203c485ed9d92
2021-02-03 17:22:59 +09:00
Yu Watanabe
89d2da287b
Merge pull request #18423 from DaanDeMeyer/sd-boot-no-include
More sd-boot cleanups
2021-02-03 15:04:26 +09:00
Yu Watanabe
face9fcc16 network,udev: move TransmitQueues=/ReceiveQueues= from .network to .link
As the settings are mostly hardware setup, and merely see from network
layer.

See also discussions in
https://github.com/systemd/systemd/pull/18170#issuecomment-758807497
https://github.com/orgs/systemd/teams/systemd/discussions/1
2021-02-03 14:44:51 +09:00
Yu Watanabe
1f8dc96c06 udev: rename TxQueueLength= -> TransmitQueueLength=
As we usually (unfortunately not always though) do not use abbreviations.

Tx may be standard abbreviation, but we already have e.g.
TransmitChecksumOffload=. So, let's use Transmit instead of Tx.

Follow-up for ef4a91a7e8d8337a9d65177b09eb7580b25b8f5d.
2021-02-03 14:43:49 +09:00
Daan De Meyer
cb347d263d boot: Add startswith() and endswith() functions with no_case variants
Adapted from string-util
2021-02-02 22:53:31 +00:00
Daan De Meyer
fffd5e8ee3 boot: Drop unnecessary braces 2021-02-02 21:15:24 +00:00
Daan De Meyer
d47b7c5720 boot: Fix void pointer arithmetic warning 2021-02-02 21:15:24 +00:00
Daan De Meyer
c8af7dab21 boot: Replace raw efivar gets with typed variants 2021-02-02 21:15:21 +00:00
Daan De Meyer
987d0a1250 boot: Add efivar_get/set_uint64_le() functions
These are implemented as bit-shifting functions that allow reading
and writing UEFI variables stored as little endian 64-bit unsigned
values.
2021-02-02 21:03:58 +00:00
Daan De Meyer
a7308a266b boot: Rename efivar_get/set_int() to efivar_get/set_uint_string()
Let's clearly indicate that these are used to set/get uints that
are stored as strings.
2021-02-02 21:03:47 +00:00
Daan De Meyer
258f0970f9 boot: Tighten scope of variables used in loops 2021-02-02 21:03:35 +00:00
Daan De Meyer
2a7c16753b boot: Add efivar_get_boolean_u8() 2021-02-02 21:03:33 +00:00
Daan De Meyer
5e1f0e6fca boot: Make all efivar util functions take the guid as an argument
Let's make these functions a little more generic so we can have
them work on more than one GUID. More specifically, this allows
using them with the global guid which will be used a bit more to
extend the secure boot support.
2021-01-31 21:46:05 +00:00
Daan De Meyer
7d2ebb6f85 boot: Turn all guid constants into C99 compound initializers
Avoids having to use the address operator all the time and
avoids having to cast or do other unintuitive stuff.
2021-01-31 21:46:05 +00:00
Daan De Meyer
5021222842 boot: Enable C99
Instead of using -nostdinc, we use -nostdlib. This is necessary
to allow moving to C99 as efibind.h includes stdint.h when C99
is enabled. It isn't necessarily problematic to use some standard
library headers as long as they don't contain functions defined in
libc or another system library (or in other words, header only
headers are fine to use in sd-boot).
2021-01-31 21:46:05 +00:00
Daan De Meyer
ce0f078f4d boot: Move Secure Boot logic to new file 2021-01-31 21:46:05 +00:00
32 changed files with 475 additions and 395 deletions

View File

@ -410,7 +410,21 @@
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><varname>TxQueueLength=</varname></term> <term><varname>TransmitQueues=</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,20 +215,6 @@
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,6 +13,7 @@
#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"
@ -23,8 +24,6 @@
/* 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,
@ -119,17 +118,17 @@ static BOOLEAN line_edit(
while (!exit) { while (!exit) {
EFI_STATUS err; EFI_STATUS err;
UINT64 key; UINT64 key;
UINTN i; UINTN j;
i = len - first; j = len - first;
if (i >= x_max-1) if (j >= x_max-1)
i = x_max-1; j = x_max-1;
CopyMem(print, line + first, i * sizeof(CHAR16)); CopyMem(print, line + first, j * sizeof(CHAR16));
while (clear > 0 && i < x_max-1) { while (clear > 0 && j < x_max-1) {
clear--; clear--;
print[i++] = ' '; print[j++] = ' ';
} }
print[i] = '\0'; print[j] = '\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);
@ -213,12 +212,14 @@ 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 (; i < len && line[i] != ' '; i++) for (; k < len && line[k] != ' '; k++)
clear++; clear++;
for (i = first + cursor; i + clear < len; i++) for (UINTN 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';
@ -243,7 +244,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 (i = first + cursor; i + clear < len; i++) for (UINTN 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';
@ -256,7 +257,7 @@ static BOOLEAN line_edit(
continue; continue;
if (first + cursor == len) if (first + cursor == len)
continue; continue;
for (i = first + cursor; i < len; i++) for (UINTN i = first + cursor; i < len; i++)
line[i] = line[i+1]; line[i] = line[i+1];
clear = 1; clear = 1;
len--; len--;
@ -285,7 +286,7 @@ static BOOLEAN line_edit(
continue; continue;
if (first == 0 && cursor == 0) if (first == 0 && cursor == 0)
continue; continue;
for (i = first + cursor-1; i < len; i++) for (UINTN i = first + cursor-1; i < len; i++)
line[i] = line[i+1]; line[i] = line[i+1];
clear = 1; clear = 1;
len--; len--;
@ -313,7 +314,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 (i = len; i > first + cursor; i--) for (UINTN 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++;
@ -331,25 +332,23 @@ 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') {
i = key - '0'; UINTN 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 (i = start; i < config->entry_count; i++) for (UINTN i = start; i < config->entry_count; i++)
if (config->entries[i]->key == key) if (config->entries[i]->key == key)
return i; return i;
for (i = 0; i < start; i++) for (UINTN i = 0; i < start; i++)
if (config->entries[i]->key == key) if (config->entries[i]->key == key)
return i; return i;
@ -357,11 +356,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; UINT64 key, indvar;
UINTN i; UINTN timeout;
_cleanup_freepool_ CHAR8 *bootvar = NULL, *modevar = NULL, *indvar = NULL; BOOLEAN modevar;
_cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL; _cleanup_freepool_ CHAR16 *partstr = NULL, *defaultstr = NULL;
UINTN x, y, size; UINTN x, y;
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);
@ -376,17 +375,16 @@ 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);
if (efivar_get_raw(&global_guid, L"SecureBoot", &bootvar, &size) == EFI_SUCCESS) Print(L"SecureBoot: %s\n", yes_no(secure_boot_enabled()));
Print(L"SecureBoot: %s\n", yes_no(*bootvar > 0));
if (efivar_get_raw(&global_guid, L"SetupMode", &modevar, &size) == EFI_SUCCESS) if (efivar_get_boolean_u8(EFI_GLOBAL_GUID, L"SetupMode", &modevar) == EFI_SUCCESS)
Print(L"SetupMode: %s\n", *modevar > 0 ? L"setup" : L"user"); Print(L"SetupMode: %s\n", modevar ? L"setup" : L"user");
if (shim_loaded()) if (shim_loaded())
Print(L"Shim: present\n"); Print(L"Shim: present\n");
if (efivar_get_raw(&global_guid, L"OsIndicationsSupported", &indvar, &size) == EFI_SUCCESS) if (efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndicationsSupported", &indvar) == EFI_SUCCESS)
Print(L"OsIndicationsSupported: %d\n", (UINT64)*indvar); Print(L"OsIndicationsSupported: %d\n", 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);
@ -423,20 +421,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_int(L"LoaderConfigTimeout", &i) == EFI_SUCCESS) if (efivar_get_uint_string(LOADER_GUID, L"LoaderConfigTimeout", &timeout) == EFI_SUCCESS)
Print(L"LoaderConfigTimeout: %u\n", i); Print(L"LoaderConfigTimeout: %u\n", timeout);
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(L"LoaderDevicePartUUID", &partstr) == EFI_SUCCESS) if (efivar_get(LOADER_GUID, L"LoaderDevicePartUUID", &partstr) == EFI_SUCCESS)
Print(L"LoaderDevicePartUUID: %s\n", partstr); Print(L"LoaderDevicePartUUID: %s\n", partstr);
if (efivar_get(L"LoaderEntryDefault", &defaultstr) == EFI_SUCCESS) if (efivar_get(LOADER_GUID, 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 (i = 0; i < config->entry_count; i++) { for (UINTN 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'))
@ -503,7 +501,6 @@ 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;
@ -564,7 +561,7 @@ static BOOLEAN menu_run(
/* length of the longest entry */ /* length of the longest entry */
line_width = 5; line_width = 5;
for (i = 0; i < config->entry_count; i++) { for (UINTN 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);
@ -583,14 +580,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 (i = 0; i < config->entry_count; i++) { for (UINTN i = 0; i < config->entry_count; i++) {
UINTN j, k; UINTN j;
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 (k = 0; config->entries[i]->title_show[k] != '\0' && j < x_max; j++, k++) for (UINTN 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++)
@ -600,15 +597,15 @@ static BOOLEAN menu_run(
status = NULL; status = NULL;
clearline = AllocatePool((x_max+1) * sizeof(CHAR16)); clearline = AllocatePool((x_max+1) * sizeof(CHAR16));
for (i = 0; i < x_max; i++) for (UINTN i = 0; i < x_max; i++)
clearline[i] = ' '; clearline[i] = ' ';
clearline[i] = 0; clearline[x_max] = 0;
while (!exit) { while (!exit) {
UINT64 key; UINT64 key;
if (refresh) { if (refresh) {
for (i = 0; i < config->entry_count; i++) { for (UINTN 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);
@ -764,12 +761,16 @@ 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(L"LoaderEntryDefault", config->entries[idx_highlight]->id, TRUE); efivar_set(
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(L"LoaderEntryDefault", NULL, TRUE); efivar_set(LOADER_GUID, 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.");
} }
@ -780,14 +781,15 @@ 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_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE); efivar_set_uint_string(
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(L"LoaderConfigTimeout", NULL, TRUE); efivar_set(LOADER_GUID, 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);
@ -801,7 +803,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_int(L"LoaderConfigTimeout", config->timeout_sec_efivar, TRUE); efivar_set_uint_string(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.", status = PoolPrint(L"Menu timeout set to %d sec.",
config->timeout_sec_efivar); config->timeout_sec_efivar);
@ -863,7 +865,7 @@ static BOOLEAN menu_run(
*chosen_entry = config->entries[idx_highlight]; *chosen_entry = config->entries[idx_highlight];
for (i = 0; i < config->entry_count; i++) for (UINTN i = 0; i < config->entry_count; i++)
FreePool(lines[i]); FreePool(lines[i]);
FreePool(lines); FreePool(lines);
FreePool(clearline); FreePool(clearline);
@ -1293,7 +1295,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(L"LoaderBootCountPath", new_path, FALSE); efivar_set(LOADER_GUID, 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) {
@ -1458,17 +1460,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_int(L"LoaderConfigTimeout", &sec); err = efivar_get_uint_string(LOADER_GUID, 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_int(L"LoaderConfigTimeoutOneShot", &sec); err = efivar_get_uint_string(LOADER_GUID, 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(L"LoaderConfigTimeoutOneShot", NULL, TRUE); (void) efivar_set(LOADER_GUID, 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 */
@ -1491,7 +1493,6 @@ 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);
@ -1504,12 +1505,9 @@ static VOID config_load_entries(
if (f->Attribute & EFI_FILE_DIRECTORY) if (f->Attribute & EFI_FILE_DIRECTORY)
continue; continue;
len = StrLen(f->FileName); if (!endswith_no_case(f->FileName, L".conf"))
if (len < 6)
continue; continue;
if (StriCmp(f->FileName + len - 5, L".conf") != 0) if (startswith(f->FileName, L"auto-"))
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);
@ -1553,14 +1551,11 @@ static INTN config_entry_compare(ConfigEntry *a, ConfigEntry *b) {
} }
static VOID config_sort_entries(Config *config) { static VOID config_sort_entries(Config *config) {
UINTN i; for (UINTN i = 1; i < config->entry_count; i++) {
for (i = 1; i < config->entry_count; i++) {
BOOLEAN more; BOOLEAN more;
UINTN k;
more = FALSE; more = FALSE;
for (k = 0; k < config->entry_count - i; k++) { for (UINTN 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)
@ -1577,9 +1572,7 @@ 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) {
UINTN i; for (UINTN i = 0; i < config->entry_count; 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;
@ -1595,11 +1588,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(L"LoaderEntryOneShot", &entry_oneshot); err = efivar_get(LOADER_GUID, 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(L"LoaderEntryOneShot", NULL, TRUE); efivar_set(LOADER_GUID, L"LoaderEntryOneShot", NULL, TRUE);
i = config_entry_find(config, entry_oneshot); i = config_entry_find(config, entry_oneshot);
if (i >= 0) { if (i >= 0) {
@ -1614,7 +1607,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(L"LoaderEntryDefault", &entry_default); err = efivar_get(LOADER_GUID, 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);
@ -1660,13 +1653,12 @@ 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 (i = 0; i < entry_count; i++) for (UINTN i = 0; i < entry_count; i++)
entries[i]->non_unique = FALSE; entries[i]->non_unique = FALSE;
for (i = 0; i < entry_count; i++) for (UINTN i = 0; i < entry_count; i++)
for (k = 0; k < entry_count; k++) { for (UINTN 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)
@ -1680,10 +1672,8 @@ 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 (i = 0; i < config->entry_count; i++) { for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *title; CHAR16 *title;
FreePool(config->entries[i]->title_show); FreePool(config->entries[i]->title_show);
@ -1697,7 +1687,7 @@ static VOID config_title_generate(Config *config) {
return; return;
/* add version to non-unique titles */ /* add version to non-unique titles */
for (i = 0; i < config->entry_count; i++) { for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *s; CHAR16 *s;
if (!config->entries[i]->non_unique) if (!config->entries[i]->non_unique)
@ -1714,7 +1704,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 (i = 0; i < config->entry_count; i++) { for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *s; CHAR16 *s;
_cleanup_freepool_ CHAR16 *m = NULL; _cleanup_freepool_ CHAR16 *m = NULL;
@ -1734,7 +1724,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 (i = 0; i < config->entry_count; i++) { for (UINTN i = 0; i < config->entry_count; i++) {
CHAR16 *s; CHAR16 *s;
if (!config->entries[i]->non_unique) if (!config->entries[i]->non_unique)
@ -1826,14 +1816,10 @@ 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))
CHAR8 *start = content; for (CHAR8 *start = content; start <= content + len - sizeof(magic) - 1; start++)
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 */
@ -1862,9 +1848,7 @@ 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)) {
UINTN i; for (UINTN i = 0; i < handle_count; i++) {
for (i = 0; i < handle_count; i++) {
EFI_FILE *root; EFI_FILE *root;
BOOLEAN found; BOOLEAN found;
@ -1906,7 +1890,6 @@ 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;
@ -1926,12 +1909,9 @@ static VOID config_entry_add_linux(
continue; continue;
if (f->Attribute & EFI_FILE_DIRECTORY) if (f->Attribute & EFI_FILE_DIRECTORY)
continue; continue;
len = StrLen(f->FileName); if (!endswith_no_case(f->FileName, L".efi"))
if (len < 5)
continue; continue;
if (StriCmp(f->FileName + len - 4, L".efi") != 0) if (startswith(f->FileName, L"auto-"))
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 */
@ -2020,10 +2000,8 @@ static VOID config_entry_add_linux(
uefi_call_wrapper(linux_dir->Close, 1, linux_dir); uefi_call_wrapper(linux_dir->Close, 1, linux_dir);
} }
/* Note that this is in GUID format, i.e. the first 32bit, and the following pair of 16bit are byteswapped. */ #define XBOOTLDR_GUID \
static const UINT8 xbootldr_guid[16] = { &(const EFI_GUID) { 0xbc13c2ff, 0x59e6, 0x4262, { 0xa3, 0x52, 0xb2, 0x75, 0xfd, 0x6f, 0x71, 0x72 } }
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;
@ -2041,7 +2019,7 @@ static VOID config_load_xbootldr(
Config *config, Config *config,
EFI_HANDLE *device) { EFI_HANDLE *device) {
EFI_DEVICE_PATH *partition_path, *node, *disk_path, *copy; EFI_DEVICE_PATH *partition_path, *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;
@ -2054,11 +2032,10 @@ static VOID config_load_xbootldr(
if (!partition_path) if (!partition_path)
return; return;
for (node = partition_path; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) { for (EFI_DEVICE_PATH *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 */
@ -2085,7 +2062,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 (nr = 0; nr < 2; nr++) { for (UINTN 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;
@ -2093,7 +2070,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 i, sz; UINTN sz;
UINT32 c; UINT32 c;
if (nr == 0) if (nr == 0)
@ -2163,12 +2140,12 @@ static VOID config_load_xbootldr(
if (c != h->PartitionEntryArrayCRC32) if (c != h->PartitionEntryArrayCRC32)
continue; continue;
for (i = 0; i < h->NumberOfPartitionEntries; i++) { for (UINTN 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) */
@ -2197,7 +2174,7 @@ found:
copy = DuplicateDevicePath(partition_path); copy = DuplicateDevicePath(partition_path);
/* Patch in the data we found */ /* Patch in the data we found */
for (node = copy; !IsDevicePathEnd(node); node = NextDevicePathNode(node)) { for (EFI_DEVICE_PATH *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)
@ -2282,7 +2259,7 @@ static EFI_STATUS image_start(
#endif #endif
} }
efivar_set_time_usec(L"LoaderTimeExecUSec", 0); efivar_set_time_usec(LOADER_GUID, 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);
@ -2290,18 +2267,16 @@ out_unload:
} }
static EFI_STATUS reboot_into_firmware(VOID) { static EFI_STATUS reboot_into_firmware(VOID) {
_cleanup_freepool_ CHAR8 *b = NULL; UINT64 old, new;
UINTN size;
UINT64 osind;
EFI_STATUS err; EFI_STATUS err;
osind = EFI_OS_INDICATIONS_BOOT_TO_FW_UI; new = EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
err = efivar_get_raw(&global_guid, L"OsIndications", &b, &size); err = efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", &old);
if (!EFI_ERROR(err)) if (!EFI_ERROR(err))
osind |= (UINT64)*b; new |= old;
err = efivar_set_raw(&global_guid, L"OsIndications", &osind, sizeof(UINT64), TRUE); err = efivar_set_uint64_le(EFI_GLOBAL_GUID, L"OsIndications", new, TRUE);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
@ -2312,9 +2287,7 @@ static EFI_STATUS reboot_into_firmware(VOID) {
} }
static VOID config_free(Config *config) { static VOID config_free(Config *config) {
UINTN i; for (UINTN i = 0; i < config->entry_count; 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);
@ -2324,15 +2297,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 i, sz = 0; UINTN sz = 0;
CHAR16 *p; CHAR16 *p;
for (i = 0; i < config->entry_count; i++) for (UINTN 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 (i = 0; i < config->entry_count; i++) { for (UINTN 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;
@ -2342,7 +2315,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) {
@ -2357,8 +2330,7 @@ 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;
CHAR8 *b; UINT64 osind = 0;
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;
@ -2370,16 +2342,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(L"LoaderTimeInitUSec", init_usec); efivar_set_time_usec(LOADER_GUID, L"LoaderTimeInitUSec", init_usec);
efivar_set(L"LoaderInfo", L"systemd-boot " GIT_VERSION, FALSE); efivar_set(LOADER_GUID, 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(L"LoaderFirmwareInfo", infostr, FALSE); efivar_set(LOADER_GUID, 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(L"LoaderFirmwareType", typestr, FALSE); efivar_set(LOADER_GUID, L"LoaderFirmwareType", typestr, FALSE);
(void) efivar_set_raw(&loader_guid, L"LoaderFeatures", &loader_features, sizeof(loader_features), FALSE); (void) efivar_set_uint64_le(LOADER_GUID, L"LoaderFeatures", 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);
@ -2391,7 +2363,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(L"LoaderDevicePartUUID", uuid, FALSE); efivar_set(LOADER_GUID, L"LoaderDevicePartUUID", uuid, FALSE);
root_dir = LibOpenRoot(loaded_image->DeviceHandle); root_dir = LibOpenRoot(loaded_image->DeviceHandle);
if (!root_dir) { if (!root_dir) {
@ -2411,7 +2383,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(L"LoaderImageIdentifier", loaded_image_path, FALSE); efivar_set(LOADER_GUID, L"LoaderImageIdentifier", loaded_image_path, FALSE);
config_load_defaults(&config, root_dir); config_load_defaults(&config, root_dir);
@ -2436,15 +2408,12 @@ 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_raw(&global_guid, L"OsIndicationsSupported", &b, &size) == EFI_SUCCESS) { if (config.auto_firmware && efivar_get_uint64_le(EFI_GLOBAL_GUID, L"OsIndicationsSupported", &osind) == 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) {
@ -2497,7 +2466,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(L"LoaderTimeMenuUSec", 0); efivar_set_time_usec(LOADER_GUID, 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;
@ -2512,7 +2481,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(L"LoaderEntrySelected", entry->id, FALSE); (VOID) efivar_set(LOADER_GUID, 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_PROTOCOL_GUID \ #define EFI_SIMPLE_TEXT_INPUT_EX_GUID \
{ 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } } &(EFI_GUID) { 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,7 +67,6 @@ 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;
@ -75,7 +74,7 @@ EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
EFI_STATUS err; EFI_STATUS err;
if (!checked) { if (!checked) {
err = LibLocateProtocol(&EfiSimpleTextInputExProtocolGuid, (VOID **)&TextInputEx); err = LibLocateProtocol(EFI_SIMPLE_TEXT_INPUT_EX_GUID, (VOID **)&TextInputEx);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
TextInputEx = NULL; TextInputEx = NULL;

View File

@ -128,9 +128,8 @@ UINT32 crc32_exclude_offset(
const UINT8 *p = buf; const UINT8 *p = buf;
UINT32 crc = seed; UINT32 crc = seed;
UINTN i;
for (i = 0; i < len; i++) { for (UINTN 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,10 +13,9 @@ 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 (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) { for (EFI_DEVICE_PATH *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,9 +10,10 @@
#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;
@ -45,7 +46,6 @@ 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(&ConsoleControlProtocolGuid, (VOID **)&ConsoleControl); err = LibLocateProtocol(EFI_CONSOLE_CONTROL_GUID, (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,9 +4,11 @@
#include <efi.h> #include <efi.h>
#include <efilib.h> #include <efilib.h>
#include "measure.h" #include "measure.h"
#define EFI_TCG_PROTOCOL_GUID { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd} } #define EFI_TCG_GUID \
&(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;
@ -100,7 +102,8 @@ 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_PROTOCOL_GUID {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }} #define EFI_TCG2_GUID \
&(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;
@ -238,7 +241,6 @@ 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;
@ -246,7 +248,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(&tpm_guid, (void **) &tcg); status = LibLocateProtocol(EFI_TCG_GUID, (void **) &tcg);
if (EFI_ERROR(status)) if (EFI_ERROR(status))
return NULL; return NULL;
@ -267,12 +269,11 @@ 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(&tpm2_guid, (void **) &tcg); status = LibLocateProtocol(EFI_TCG2_GUID, (void **) &tcg);
if (EFI_ERROR(status)) if (EFI_ERROR(status))
return NULL; return NULL;

View File

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

View File

@ -62,7 +62,6 @@ 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;
@ -85,12 +84,11 @@ 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 (i = 0; i < pe->FileHeader.NumberOfSections; i++) { for (UINTN 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 (j = 0; sections[j]; j++) { for (UINTN 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)
static const EFI_GUID rng_protocol_guid = EFI_RNG_PROTOCOL_GUID; #define EFI_RNG_GUID &(EFI_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_GUID*) &rng_protocol_guid, (VOID**) &rng); err = LibLocateProtocol(EFI_RNG_GUID, (VOID**) &rng);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
if (!rng) if (!rng)
@ -86,7 +86,6 @@ 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. */
@ -95,7 +94,7 @@ static EFI_STATUS hash_many(
if (!output) if (!output)
return log_oom(); return log_oom();
for (i = 0; i < n; i++) for (UINTN 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,
@ -147,7 +146,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);
@ -201,9 +200,7 @@ static VOID validate_sha256(void) {
0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1 }}, 0xaf, 0xac, 0x45, 0x03, 0x7a, 0xfe, 0xe9, 0xd1 }},
}; };
UINTN i; for (UINTN i = 0; i < ELEMENTSOF(array); 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];
@ -318,7 +315,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

@ -0,0 +1,13 @@
/* 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

@ -0,0 +1,6 @@
/* 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, i; UINTN pad;
/* 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 (i = 0; i < 8; ++i) for (UINTN i = 0; i < 8; ++i)
((UINT32 *) resbuf)[i] = SWAP (ctx->H[i]); ((UINT32 *) resbuf)[i] = SWAP (ctx->H[i]);
return resbuf; return resbuf;
@ -214,7 +214,6 @@ 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))
@ -229,15 +228,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 (t = 0; t < 16; ++t) { for (UINTN t = 0; t < 16; ++t) {
W[t] = SWAP (*words); W[t] = SWAP (*words);
++words; ++words;
} }
for (t = 16; t < 64; ++t) for (UINTN 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 (t = 0; t < 64; ++t) { for (UINTN 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,17 +30,18 @@ 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);
}; };
static const EFI_GUID simple_fs_guid = SIMPLE_FILE_SYSTEM_PROTOCOL; #define SIMPLE_FS_GUID &(EFI_GUID) SIMPLE_FILE_SYSTEM_PROTOCOL
static const EFI_GUID global_guid = EFI_GLOBAL_VARIABLE; #define SECURITY_PROTOCOL_GUID \
&(EFI_GUID) { 0xa46423e3, 0x4617, 0x49f1, { 0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } }
static const EFI_GUID security_protocol_guid = { 0xa46423e3, 0x4617, 0x49f1, {0xb9, 0xff, 0xd1, 0xbf, 0xa9, 0x11, 0x58, 0x39 } }; #define SECURITY_PROTOCOL2_GUID \
static const EFI_GUID security2_protocol_guid = { 0x94ab2f58, 0x1438, 0x4ef1, {0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }; &(EFI_GUID) { 0x94ab2f58, 0x1438, 0x4ef1, { 0x91, 0x52, 0x18, 0x94, 0x1a, 0x3a, 0x0e, 0x68 } }
static const EFI_GUID shim_lock_guid = { 0x605dab50, 0xe046, 0x4300, {0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23} }; #define SHIM_LOCK_GUID \
&(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, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) == EFI_SUCCESS; return uefi_call_wrapper(BS->LocateProtocol, 3, 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) {
@ -49,7 +50,7 @@ static BOOLEAN shim_validate(VOID *data, UINT32 size) {
if (!data) if (!data)
return FALSE; return FALSE;
if (uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &shim_lock_guid, NULL, (VOID**) &shim_lock) != EFI_SUCCESS) if (uefi_call_wrapper(BS->LocateProtocol, 3, SHIM_LOCK_GUID, NULL, (VOID**) &shim_lock) != EFI_SUCCESS)
return FALSE; return FALSE;
if (!shim_lock) if (!shim_lock)
@ -58,16 +59,6 @@ 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
*/ */
@ -157,7 +148,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, (EFI_GUID*) &simple_fs_guid, &dev_path, &h); status = uefi_call_wrapper(BS->LocateDevicePath, 3, SIMPLE_FS_GUID, &dev_path, &h);
if (status != EFI_SUCCESS) if (status != EFI_SUCCESS)
return status; return status;
@ -191,9 +182,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, (EFI_GUID*) &security2_protocol_guid, NULL, (VOID**) &security2_protocol); uefi_call_wrapper(BS->LocateProtocol, 3, SECURITY_PROTOCOL2_GUID, NULL, (VOID**) &security2_protocol);
status = uefi_call_wrapper(BS->LocateProtocol, 3, (EFI_GUID*) &security_protocol_guid, NULL, (VOID**) &security_protocol); status = uefi_call_wrapper(BS->LocateProtocol, 3, 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,6 +13,4 @@
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,22 +151,18 @@ 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 (y = 0; y < dib->y; y++) { for (UINTN 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 (x = 0; x < dib->x; x++, in++, out++) { for (UINTN x = 0; x < dib->x; x++, in++, out++) {
switch (dib->depth) { switch (dib->depth) {
case 1: { case 1: {
UINTN i; for (UINTN i = 0; i < 8 && x < dib->x; 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,19 +8,15 @@
#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",
@ -46,10 +42,6 @@ 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);
@ -58,20 +50,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 || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 && *(CHAR16 *)loaded_image->LoadOptions > 0x1F) { if ((!secure_boot_enabled() || cmdline_len == 0) && loaded_image->LoadOptionsSize > 0 &&
*(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 (i = 0; i < cmdline_len; i++) for (UINTN i = 0; i < cmdline_len; i++)
line[i] = options[i]; line[i] = options[i];
cmdline = line; cmdline = line;
@ -88,37 +80,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(L"LoaderDevicePartUUID", uuid, FALSE); efivar_set(LOADER_GUID, 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(L"LoaderImageIdentifier", s, FALSE); efivar_set(LOADER_GUID, 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(L"LoaderFirmwareInfo", s, FALSE); efivar_set(LOADER_GUID, 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(L"LoaderFirmwareType", s, FALSE); efivar_set(LOADER_GUID, 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(L"StubInfo", L"systemd-stub " GIT_VERSION, FALSE); efivar_set(LOADER_GUID, 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,13 +5,6 @@
#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;
@ -92,24 +85,51 @@ 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 CHAR16 *name, const CHAR16 *value, BOOLEAN persistent) { EFI_STATUS efivar_set(const EFI_GUID *vendor, const CHAR16 *name, const CHAR16 *value, BOOLEAN persistent) {
return efivar_set_raw(&loader_guid, name, value, value ? (StrLen(value)+1) * sizeof(CHAR16) : 0, persistent); return efivar_set_raw(
vendor, name, value, value ? (StrLen(value) + 1) * sizeof(CHAR16) : 0, persistent);
} }
EFI_STATUS efivar_set_int(CHAR16 *name, UINTN i, BOOLEAN persistent) { EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, 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(name, str, persistent); return efivar_set(vendor, name, str, persistent);
} }
EFI_STATUS efivar_get(const CHAR16 *name, CHAR16 **value) { EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *name, UINT32 value, BOOLEAN persistent) {
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(&loader_guid, name, &buf, &size); err = efivar_get_raw(vendor, name, &buf, &size);
if (EFI_ERROR(err)) if (EFI_ERROR(err))
return err; return err;
@ -138,17 +158,52 @@ EFI_STATUS efivar_get(const CHAR16 *name, CHAR16 **value) {
return EFI_SUCCESS; return EFI_SUCCESS;
} }
EFI_STATUS efivar_get_int(const CHAR16 *name, UINTN *i) { EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, const CHAR16 *name, UINTN *i) {
_cleanup_freepool_ CHAR16 *val = NULL; _cleanup_freepool_ CHAR16 *val = NULL;
EFI_STATUS err; EFI_STATUS err;
err = efivar_get(name, &val); err = efivar_get(vendor, 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;
@ -172,7 +227,19 @@ EFI_STATUS efivar_get_raw(const EFI_GUID *vendor, const CHAR16 *name, CHAR8 **bu
return err; return err;
} }
VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) { EFI_STATUS efivar_get_boolean_u8(const EFI_GUID *vendor, const CHAR16 *name, BOOLEAN *ret) {
_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)
@ -181,13 +248,12 @@ VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec) {
return; return;
SPrint(str, 32, L"%ld", usec); SPrint(str, 32, L"%ld", usec);
efivar_set(name, str, FALSE); efivar_set(vendor, 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;
@ -225,7 +291,7 @@ static INTN utf8_to_16(CHAR8 *stra, CHAR16 *c) {
break; break;
} }
for (i = 1; i < len; i++) { for (UINTN i = 1; i < len; i++) {
if ((stra[i] & 0xc0) != 0x80) if ((stra[i] & 0xc0) != 0x80)
return -1; return -1;
unichar <<= 6; unichar <<= 6;
@ -309,6 +375,62 @@ 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,19 +21,30 @@ 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 CHAR16 *name, const CHAR16 *value, BOOLEAN persistent); EFI_STATUS efivar_set(const EFI_GUID *vendor, 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_int(CHAR16 *name, UINTN i, BOOLEAN persistent); EFI_STATUS efivar_set_uint_string(const EFI_GUID *vendor, CHAR16 *name, UINTN i, BOOLEAN persistent);
VOID efivar_set_time_usec(CHAR16 *name, UINT64 usec); EFI_STATUS efivar_set_uint32_le(const EFI_GUID *vendor, CHAR16 *NAME, UINT32 value, BOOLEAN persistent);
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 CHAR16 *name, CHAR16 **value); EFI_STATUS efivar_get(const EFI_GUID *vendor, 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_int(const CHAR16 *name, UINTN *i); EFI_STATUS efivar_get_uint_string(const EFI_GUID *vendor, 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) {
@ -55,7 +66,14 @@ 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,15 +57,25 @@ int rtnl_set_link_name(sd_netlink **rtnl, int ifindex, const char *name) {
return 0; return 0;
} }
int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, int rtnl_set_link_properties(
uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments) { sd_netlink **rtnl,
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 && txqueuelen == UINT32_MAX && mtu == 0 && gso_max_size == 0 && gso_max_segments == 0) if (!alias && !mac && txqueues == 0 && rxqueues == 0 && txqueuelen == UINT32_MAX && mtu == 0 &&
gso_max_size == 0 && gso_max_segments == 0)
return 0; return 0;
if (!*rtnl) { if (!*rtnl) {
@ -90,6 +100,18 @@ int rtnl_set_link_properties(sd_netlink **rtnl, int ifindex, const char *alias,
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,8 +70,17 @@ 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(sd_netlink **rtnl, int ifindex, const char *alias, const struct ether_addr *mac, int rtnl_set_link_properties(
uint32_t txqueuelen, uint32_t mtu, uint32_t gso_max_size, size_t gso_max_segments); sd_netlink **rtnl,
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) {
int interactive = false, r; uint64_t flags;
uint64_t flags = 0; int r;
assert(m); assert(m);
assert(message); assert(message);
@ -1880,19 +1880,25 @@ 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);
else if (r < 0)
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;
if (r < 0) flags = interactive ? SD_LOGIND_INTERACTIVE : 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,61 +1479,6 @@ 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;
@ -2111,10 +2056,6 @@ 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,8 +60,6 @@ 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,40 +1198,6 @@ 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,8 +95,6 @@ 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;
@ -344,7 +342,6 @@ 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,7 +41,9 @@ 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.TxQueueLength, config_parse_txqueuelen, 0, offsetof(link_config, txqueuelen) Link.TransmitQueues, config_parse_rx_tx_queues, 0, offsetof(link_config, txqueues)
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,11 +427,15 @@ 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, config->txqueuelen, config->mtu, r = rtnl_set_link_properties(rtnl, ifindex, config->alias, mac,
config->gso_max_size, config->gso_max_segments); config->txqueues, config->rxqueues, config->txqueuelen,
config->mtu, config->gso_max_size, config->gso_max_segments);
if (r < 0) if (r < 0)
log_device_warning_errno(device, r, "Could not set Alias=, MACAddress=, TxQueueLength=, MTU=, " log_device_warning_errno(device, r,
"GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, ignoring: %m"); "Could not set Alias=, MACAddress=, "
"TransmitQueues=, ReceiveQueues=, TransmitQueueLength=, MTU=, "
"GenericSegmentOffloadMaxBytes= or GenericSegmentOffloadMaxSegments=, "
"ignoring: %m");
return 0; return 0;
} }
@ -704,6 +708,40 @@ 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,6 +46,8 @@ 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;
@ -91,6 +93,7 @@ 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,7 +20,9 @@ Name=
AlternativeNamesPolicy= AlternativeNamesPolicy=
AlternativeName= AlternativeName=
Alias= Alias=
TxQueueLength= TransmitQueues=
ReceiveQueues=
TransmitQueueLength=
MTUBytes= MTUBytes=
BitsPerSecond= BitsPerSecond=
Duplex= Duplex=

View File

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