summaryrefslogtreecommitdiff
path: root/src/boot/efi
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot/efi')
-rw-r--r--src/boot/efi/boot.c108
-rw-r--r--src/boot/efi/console.c12
-rw-r--r--src/boot/efi/console.h2
-rw-r--r--src/boot/efi/disk.c49
-rw-r--r--src/boot/efi/disk.h19
-rw-r--r--src/boot/efi/graphics.c7
-rw-r--r--src/boot/efi/graphics.h2
-rw-r--r--src/boot/efi/linux.c4
-rw-r--r--src/boot/efi/linux.h2
-rw-r--r--src/boot/efi/measure.c335
-rw-r--r--src/boot/efi/measure.h21
-rw-r--r--src/boot/efi/pefile.c4
-rw-r--r--src/boot/efi/pefile.h2
-rw-r--r--src/boot/efi/splash.c8
-rw-r--r--src/boot/efi/splash.h2
-rw-r--r--src/boot/efi/stub.c27
-rw-r--r--src/boot/efi/util.c2
-rw-r--r--src/boot/efi/util.h2
18 files changed, 516 insertions, 92 deletions
diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c
index 827c11844c..30c1ead1aa 100644
--- a/src/boot/efi/boot.c
+++ b/src/boot/efi/boot.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -18,11 +16,13 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "console.h"
+#include "disk.h"
#include "graphics.h"
-#include "pefile.h"
#include "linux.h"
+#include "pefile.h"
+#include "util.h"
+#include "measure.h"
#ifndef EFI_OS_INDICATIONS_BOOT_TO_FW_UI
#define EFI_OS_INDICATIONS_BOOT_TO_FW_UI 0x0000000000000001ULL
@@ -69,16 +69,14 @@ typedef struct {
BOOLEAN no_editor;
} Config;
-static VOID cursor_left(UINTN *cursor, UINTN *first)
-{
+static VOID cursor_left(UINTN *cursor, UINTN *first) {
if ((*cursor) > 0)
(*cursor)--;
else if ((*first) > 0)
(*first)--;
}
-static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len)
-{
+static VOID cursor_right(UINTN *cursor, UINTN *first, UINTN x_max, UINTN len) {
if ((*cursor)+1 < x_max)
(*cursor)++;
else if ((*first) + (*cursor) < len)
@@ -855,13 +853,11 @@ static VOID config_entry_free(ConfigEntry *entry) {
FreePool(entry->options);
}
-static BOOLEAN is_digit(CHAR16 c)
-{
+static BOOLEAN is_digit(CHAR16 c) {
return (c >= '0') && (c <= '9');
}
-static UINTN c_order(CHAR16 c)
-{
+static UINTN c_order(CHAR16 c) {
if (c == '\0')
return 0;
if (is_digit(c))
@@ -872,8 +868,7 @@ static UINTN c_order(CHAR16 c)
return c + 0x10000;
}
-static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2)
-{
+static INTN str_verscmp(CHAR16 *s1, CHAR16 *s2) {
CHAR16 *os1 = s1;
CHAR16 *os2 = s2;
@@ -1139,13 +1134,11 @@ static VOID config_entry_add_from_file(Config *config, EFI_HANDLE *device, CHAR1
config_add_entry(config, entry);
}
-static VOID config_load(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir, CHAR16 *loaded_image_path) {
- EFI_FILE_HANDLE entries_dir;
- EFI_STATUS err;
+static VOID config_load_defaults(Config *config, EFI_FILE *root_dir) {
CHAR8 *content = NULL;
UINTN sec;
UINTN len;
- UINTN i;
+ EFI_STATUS err;
len = file_read(root_dir, L"\\loader\\loader.conf", 0, 0, &content);
if (len > 0)
@@ -1158,6 +1151,11 @@ static VOID config_load(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir,
config->timeout_sec = sec;
} else
config->timeout_sec_efivar = -1;
+}
+
+static VOID config_load_entries(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir, CHAR16 *loaded_image_path) {
+ EFI_FILE_HANDLE entries_dir;
+ EFI_STATUS err;
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &entries_dir, L"\\loader\\entries", EFI_FILE_MODE_READ, 0ULL);
if (!EFI_ERROR(err)) {
@@ -1194,8 +1192,11 @@ static VOID config_load(Config *config, EFI_HANDLE *device, EFI_FILE *root_dir,
}
uefi_call_wrapper(entries_dir->Close, 1, entries_dir);
}
+}
+
+static VOID config_sort_entries(Config *config) {
+ UINTN i;
- /* sort entries after version number */
for (i = 1; i < config->entry_count; i++) {
BOOLEAN more;
UINTN k;
@@ -1495,6 +1496,7 @@ static VOID config_entry_add_osx(Config *config) {
static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_image, EFI_FILE *root_dir) {
EFI_FILE_HANDLE linux_dir;
EFI_STATUS err;
+ ConfigEntry *entry;
err = uefi_call_wrapper(root_dir->Open, 5, root_dir, &linux_dir, L"\\EFI\\Linux", EFI_FILE_MODE_READ, 0ULL);
if (!EFI_ERROR(err)) {
@@ -1504,6 +1506,7 @@ static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_ima
EFI_FILE_INFO *f;
CHAR8 *sections[] = {
(UINT8 *)".osrel",
+ (UINT8 *)".cmdline",
NULL
};
UINTN offs[ELEMENTSOF(sections)-1] = {};
@@ -1535,7 +1538,7 @@ static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_ima
if (StriCmp(f->FileName + len - 4, L".efi") != 0)
continue;
- /* look for an .osrel section in the .efi binary */
+ /* look for .osrel and .cmdline sections in the .efi binary */
err = pefile_locate_sections(linux_dir, f->FileName, sections, addrs, offs, szs);
if (EFI_ERROR(err))
continue;
@@ -1575,10 +1578,21 @@ static VOID config_entry_add_linux( Config *config, EFI_LOADED_IMAGE *loaded_ima
if (os_name && os_id && (os_version || os_build)) {
CHAR16 *conf;
CHAR16 *path;
+ CHAR16 *cmdline;
conf = PoolPrint(L"%s-%s", os_id, os_version ? : os_build);
path = PoolPrint(L"\\EFI\\Linux\\%s", f->FileName);
- config_entry_add_loader(config, loaded_image->DeviceHandle, LOADER_LINUX, conf, 'l', os_name, path);
+ entry = config_entry_add_loader(config, loaded_image->DeviceHandle, LOADER_LINUX, conf, 'l', os_name, path);
+
+ FreePool(content);
+ /* read the embedded cmdline file */
+ len = file_read(linux_dir, f->FileName, offs[1], szs[1] - 1 , &content);
+ if (len > 0) {
+ cmdline = stra_to_str(content);
+ entry->options = cmdline;
+ cmdline = NULL;
+ }
+ FreePool(cmdline);
FreePool(conf);
FreePool(path);
}
@@ -1631,6 +1645,18 @@ static EFI_STATUS image_start(EFI_HANDLE parent_image, const Config *config, con
}
loaded_image->LoadOptions = options;
loaded_image->LoadOptionsSize = (StrLen(loaded_image->LoadOptions)+1) * sizeof(CHAR16);
+
+#ifdef SD_BOOT_LOG_TPM
+ /* Try to log any options to the TPM, escpecially to catch manually edited options */
+ err = tpm_log_event(SD_TPM_PCR,
+ (EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions,
+ loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
+ if (EFI_ERROR(err)) {
+ Print(L"Unable to add image options measurement: %r", err);
+ uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+ return err;
+ }
+#endif
}
efivar_set_time_usec(L"LoaderTimeExecUSec", 0);
@@ -1683,11 +1709,11 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
EFI_LOADED_IMAGE *loaded_image;
EFI_FILE *root_dir;
CHAR16 *loaded_image_path;
- EFI_DEVICE_PATH *device_path;
EFI_STATUS err;
Config config;
UINT64 init_usec;
BOOLEAN menu = FALSE;
+ CHAR16 uuid[37];
InitializeLib(image, sys_table);
init_usec = time_usec();
@@ -1709,29 +1735,8 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
}
/* export the device path this image is started from */
- device_path = DevicePathFromHandle(loaded_image->DeviceHandle);
- if (device_path) {
- EFI_DEVICE_PATH *path, *paths;
-
- paths = UnpackDevicePath(device_path);
- for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) {
- HARDDRIVE_DEVICE_PATH *drive;
- CHAR16 uuid[37];
-
- if (DevicePathType(path) != MEDIA_DEVICE_PATH)
- continue;
- if (DevicePathSubType(path) != MEDIA_HARDDRIVE_DP)
- continue;
- drive = (HARDDRIVE_DEVICE_PATH *)path;
- if (drive->SignatureType != SIGNATURE_TYPE_GUID)
- continue;
-
- GuidToString(uuid, (EFI_GUID *)&drive->Signature);
- efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
- break;
- }
- FreePool(paths);
- }
+ if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
+ efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
root_dir = LibOpenRoot(loaded_image->DeviceHandle);
if (!root_dir) {
@@ -1745,12 +1750,19 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
loaded_image_path = DevicePathToStr(loaded_image->FilePath);
efivar_set(L"LoaderImageIdentifier", loaded_image_path, FALSE);
- /* scan "\loader\entries\*.conf" files */
ZeroMem(&config, sizeof(Config));
- config_load(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
+ config_load_defaults(&config, root_dir);
- /* if we find some well-known loaders, add them to the end of the list */
+ /* scan /EFI/Linux/ directory */
config_entry_add_linux(&config, loaded_image, root_dir);
+
+ /* scan /loader/entries/\*.conf files */
+ config_load_entries(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
+
+ /* sort entries after version number */
+ config_sort_entries(&config);
+
+ /* if we find some well-known loaders, add them to the end of the list */
config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
L"auto-windows", 'w', L"Windows Boot Manager", L"\\EFI\\Microsoft\\Boot\\bootmgfw.efi");
config_entry_add_loader_auto(&config, loaded_image->DeviceHandle, root_dir, loaded_image_path,
diff --git a/src/boot/efi/console.c b/src/boot/efi/console.c
index 66aa88f32e..2b797c9a5f 100644
--- a/src/boot/efi/console.c
+++ b/src/boot/efi/console.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -18,8 +16,8 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "console.h"
+#include "util.h"
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
{ 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
@@ -95,12 +93,8 @@ EFI_STATUS console_key_read(UINT64 *key, BOOLEAN wait) {
}
/* wait until key is pressed */
- if (wait) {
- if (TextInputEx)
- uefi_call_wrapper(BS->WaitForEvent, 3, 1, &TextInputEx->WaitForKeyEx, &index);
- else
- uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
- }
+ if (wait)
+ uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
if (TextInputEx) {
EFI_KEY_DATA keydata;
diff --git a/src/boot/efi/console.h b/src/boot/efi/console.h
index 5c7808a067..3fe0ce5ec4 100644
--- a/src/boot/efi/console.h
+++ b/src/boot/efi/console.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
diff --git a/src/boot/efi/disk.c b/src/boot/efi/disk.c
new file mode 100644
index 0000000000..3e3b5b224a
--- /dev/null
+++ b/src/boot/efi/disk.c
@@ -0,0 +1,49 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
+ */
+
+#include <efi.h>
+#include <efilib.h>
+
+#include "util.h"
+
+EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]) {
+ EFI_DEVICE_PATH *device_path;
+ EFI_STATUS r = EFI_NOT_FOUND;
+
+ /* export the device path this image is started from */
+ device_path = DevicePathFromHandle(handle);
+ if (device_path) {
+ EFI_DEVICE_PATH *path, *paths;
+
+ paths = UnpackDevicePath(device_path);
+ for (path = paths; !IsDevicePathEnd(path); path = NextDevicePathNode(path)) {
+ HARDDRIVE_DEVICE_PATH *drive;
+
+ if (DevicePathType(path) != MEDIA_DEVICE_PATH)
+ continue;
+ if (DevicePathSubType(path) != MEDIA_HARDDRIVE_DP)
+ continue;
+ drive = (HARDDRIVE_DEVICE_PATH *)path;
+ if (drive->SignatureType != SIGNATURE_TYPE_GUID)
+ continue;
+
+ GuidToString(uuid, (EFI_GUID *)&drive->Signature);
+ r = EFI_SUCCESS;
+ break;
+ }
+ FreePool(paths);
+ }
+
+ return r;
+}
diff --git a/src/boot/efi/disk.h b/src/boot/efi/disk.h
new file mode 100644
index 0000000000..af91a9c674
--- /dev/null
+++ b/src/boot/efi/disk.h
@@ -0,0 +1,19 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * Copyright (C) 2015 Kay Sievers <kay@vrfy.org>
+ */
+
+#ifndef __SDBOOT_DISK_H
+#define __SDBOOT_DISK_H
+
+EFI_STATUS disk_get_part_uuid(EFI_HANDLE *handle, CHAR16 uuid[37]);
+#endif
diff --git a/src/boot/efi/graphics.c b/src/boot/efi/graphics.c
index 2e9c11f5a0..4854baf874 100644
--- a/src/boot/efi/graphics.c
+++ b/src/boot/efi/graphics.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -20,8 +18,8 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "graphics.h"
+#include "util.h"
EFI_STATUS graphics_mode(BOOLEAN on) {
#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \
@@ -67,10 +65,9 @@ EFI_STATUS graphics_mode(BOOLEAN on) {
EFI_STATUS err;
err = LibLocateProtocol(&ConsoleControlProtocolGuid, (VOID **)&ConsoleControl);
- if (EFI_ERROR(err)) {
+ if (EFI_ERROR(err))
/* console control protocol is nonstandard and might not exist. */
return err == EFI_NOT_FOUND ? EFI_SUCCESS : err;
- }
/* check current mode */
err = uefi_call_wrapper(ConsoleControl->GetMode, 4, ConsoleControl, &current, &uga_exists, &stdin_locked);
diff --git a/src/boot/efi/graphics.h b/src/boot/efi/graphics.h
index 3ee4972798..cf48e647e7 100644
--- a/src/boot/efi/graphics.h
+++ b/src/boot/efi/graphics.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
diff --git a/src/boot/efi/linux.c b/src/boot/efi/linux.c
index 809c69310e..0dc99a6c53 100644
--- a/src/boot/efi/linux.c
+++ b/src/boot/efi/linux.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -17,8 +15,8 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "linux.h"
+#include "util.h"
#define SETUP_MAGIC 0x53726448 /* "HdrS" */
struct SetupHeader {
diff --git a/src/boot/efi/linux.h b/src/boot/efi/linux.h
index aff69a9778..d9e6ed7955 100644
--- a/src/boot/efi/linux.h
+++ b/src/boot/efi/linux.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c
new file mode 100644
index 0000000000..4ac11a9bb0
--- /dev/null
+++ b/src/boot/efi/measure.c
@@ -0,0 +1,335 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ */
+
+#ifdef SD_BOOT_LOG_TPM
+
+#include <efi.h>
+#include <efilib.h>
+#include "measure.h"
+
+#define EFI_TCG_PROTOCOL_GUID { 0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd} }
+
+typedef struct _TCG_VERSION {
+ UINT8 Major;
+ UINT8 Minor;
+ UINT8 RevMajor;
+ UINT8 RevMinor;
+} TCG_VERSION;
+
+typedef struct _TCG_BOOT_SERVICE_CAPABILITY {
+ UINT8 Size;
+ struct _TCG_VERSION StructureVersion;
+ struct _TCG_VERSION ProtocolSpecVersion;
+ UINT8 HashAlgorithmBitmap;
+ BOOLEAN TPMPresentFlag;
+ BOOLEAN TPMDeactivatedFlag;
+} TCG_BOOT_SERVICE_CAPABILITY;
+
+typedef UINT32 TCG_ALGORITHM_ID;
+#define TCG_ALG_SHA 0x00000004 // The SHA1 algorithm
+
+#define SHA1_DIGEST_SIZE 20
+
+typedef struct _TCG_DIGEST {
+ UINT8 Digest[SHA1_DIGEST_SIZE];
+} TCG_DIGEST;
+
+#define EV_IPL 13
+
+typedef struct _TCG_PCR_EVENT {
+ UINT32 PCRIndex;
+ UINT32 EventType;
+ struct _TCG_DIGEST digest;
+ UINT32 EventSize;
+ UINT8 Event[1];
+} TCG_PCR_EVENT;
+
+INTERFACE_DECL(_EFI_TCG);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG_STATUS_CHECK) (IN struct _EFI_TCG * This,
+ OUT struct _TCG_BOOT_SERVICE_CAPABILITY * ProtocolCapability,
+ OUT UINT32 * TCGFeatureFlags,
+ OUT EFI_PHYSICAL_ADDRESS * EventLogLocation,
+ OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG_HASH_ALL) (IN struct _EFI_TCG * This,
+ IN UINT8 * HashData,
+ IN UINT64 HashDataLen,
+ IN TCG_ALGORITHM_ID AlgorithmId,
+ IN OUT UINT64 * HashedDataLen, IN OUT UINT8 ** HashedDataResult);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG_LOG_EVENT) (IN struct _EFI_TCG * This,
+ IN struct _TCG_PCR_EVENT * TCGLogData,
+ IN OUT UINT32 * EventNumber, IN UINT32 Flags);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG_PASS_THROUGH_TO_TPM) (IN struct _EFI_TCG * This,
+ IN UINT32 TpmInputParameterBlockSize,
+ IN UINT8 * TpmInputParameterBlock,
+ IN UINT32 TpmOutputParameterBlockSize,
+ IN UINT8 * TpmOutputParameterBlock);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG_HASH_LOG_EXTEND_EVENT) (IN struct _EFI_TCG * This,
+ IN EFI_PHYSICAL_ADDRESS HashData,
+ IN UINT64 HashDataLen,
+ IN TCG_ALGORITHM_ID AlgorithmId,
+ IN struct _TCG_PCR_EVENT * TCGLogData,
+ IN OUT UINT32 * EventNumber,
+ OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry);
+
+typedef struct _EFI_TCG {
+ EFI_TCG_STATUS_CHECK StatusCheck;
+ EFI_TCG_HASH_ALL HashAll;
+ EFI_TCG_LOG_EVENT LogEvent;
+ EFI_TCG_PASS_THROUGH_TO_TPM PassThroughToTPM;
+ EFI_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent;
+} EFI_TCG;
+
+#define EFI_TCG2_PROTOCOL_GUID {0x607f766c, 0x7455, 0x42be, { 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }}
+
+typedef struct tdEFI_TCG2_PROTOCOL EFI_TCG2_PROTOCOL;
+
+typedef struct tdEFI_TCG2_VERSION {
+ UINT8 Major;
+ UINT8 Minor;
+} EFI_TCG2_VERSION;
+
+typedef UINT32 EFI_TCG2_EVENT_LOG_BITMAP;
+typedef UINT32 EFI_TCG2_EVENT_LOG_FORMAT;
+typedef UINT32 EFI_TCG2_EVENT_ALGORITHM_BITMAP;
+
+#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x00000001
+#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002
+
+typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY {
+ UINT8 Size;
+ EFI_TCG2_VERSION StructureVersion;
+ EFI_TCG2_VERSION ProtocolVersion;
+ EFI_TCG2_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap;
+ EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs;
+ BOOLEAN TPMPresentFlag;
+ UINT16 MaxCommandSize;
+ UINT16 MaxResponseSize;
+ UINT32 ManufacturerID;
+ UINT32 NumberOfPCRBanks;
+ EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks;
+} EFI_TCG2_BOOT_SERVICE_CAPABILITY;
+
+#define EFI_TCG2_EVENT_HEADER_VERSION 1
+
+typedef struct {
+ UINT32 HeaderSize;
+ UINT16 HeaderVersion;
+ UINT32 PCRIndex;
+ UINT32 EventType;
+} EFI_TCG2_EVENT_HEADER;
+
+typedef struct tdEFI_TCG2_EVENT {
+ UINT32 Size;
+ EFI_TCG2_EVENT_HEADER Header;
+ UINT8 Event[1];
+} EFI_TCG2_EVENT;
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_CAPABILITY) (IN EFI_TCG2_PROTOCOL * This,
+ IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY * ProtocolCapability);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_EVENT_LOG) (IN EFI_TCG2_PROTOCOL * This,
+ IN EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat,
+ OUT EFI_PHYSICAL_ADDRESS * EventLogLocation,
+ OUT EFI_PHYSICAL_ADDRESS * EventLogLastEntry,
+ OUT BOOLEAN * EventLogTruncated);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG2_HASH_LOG_EXTEND_EVENT) (IN EFI_TCG2_PROTOCOL * This,
+ IN UINT64 Flags,
+ IN EFI_PHYSICAL_ADDRESS DataToHash,
+ IN UINT64 DataToHashLen, IN EFI_TCG2_EVENT * EfiTcgEvent);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG2_SUBMIT_COMMAND) (IN EFI_TCG2_PROTOCOL * This,
+ IN UINT32 InputParameterBlockSize,
+ IN UINT8 * InputParameterBlock,
+ IN UINT32 OutputParameterBlockSize, IN UINT8 * OutputParameterBlock);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This, OUT UINT32 * ActivePcrBanks);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG2_SET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This, IN UINT32 ActivePcrBanks);
+
+typedef EFI_STATUS(EFIAPI * EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS) (IN EFI_TCG2_PROTOCOL * This,
+ OUT UINT32 * OperationPresent, OUT UINT32 * Response);
+
+typedef struct tdEFI_TCG2_PROTOCOL {
+ EFI_TCG2_GET_CAPABILITY GetCapability;
+ EFI_TCG2_GET_EVENT_LOG GetEventLog;
+ EFI_TCG2_HASH_LOG_EXTEND_EVENT HashLogExtendEvent;
+ EFI_TCG2_SUBMIT_COMMAND SubmitCommand;
+ EFI_TCG2_GET_ACTIVE_PCR_BANKS GetActivePcrBanks;
+ EFI_TCG2_SET_ACTIVE_PCR_BANKS SetActivePcrBanks;
+ EFI_TCG2_GET_RESULT_OF_SET_ACTIVE_PCR_BANKS GetResultOfSetActivePcrBanks;
+} EFI_TCG2;
+
+
+static EFI_STATUS tpm1_measure_to_pcr_and_event_log(const EFI_TCG *tcg, UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer,
+ UINTN buffer_size, const CHAR16 *description) {
+ EFI_STATUS status;
+ TCG_PCR_EVENT *tcg_event;
+ UINT32 event_number;
+ EFI_PHYSICAL_ADDRESS event_log_last;
+ UINTN desc_len;
+
+ desc_len = (StrLen(description) + 1) * sizeof(CHAR16);
+
+ tcg_event = AllocateZeroPool(desc_len + sizeof(TCG_PCR_EVENT));
+
+ if (tcg_event == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ tcg_event->EventSize = desc_len;
+ CopyMem((VOID *) & tcg_event->Event[0], (VOID *) description, desc_len);
+
+ tcg_event->PCRIndex = pcrindex;
+ tcg_event->EventType = EV_IPL;
+
+ event_number = 1;
+ status = uefi_call_wrapper(tcg->HashLogExtendEvent, 7,
+ tcg, buffer, buffer_size, TCG_ALG_SHA, tcg_event, &event_number, &event_log_last);
+
+ if (EFI_ERROR(status))
+ return status;
+
+ uefi_call_wrapper(BS->FreePool, 1, tcg_event);
+
+ return EFI_SUCCESS;
+}
+
+/*
+ * According to TCG EFI Protocol Specification for TPM 2.0 family,
+ * all events generated after the invocation of EFI_TCG2_GET_EVENT_LOG
+ * shall be stored in an instance of an EFI_CONFIGURATION_TABLE aka
+ * EFI TCG 2.0 final events table. Hence, it is necessary to trigger the
+ * internal switch through calling get_event_log() in order to allow
+ * to retrieve the logs from OS runtime.
+ */
+static EFI_STATUS trigger_tcg2_final_events_table(const EFI_TCG2 *tcg)
+{
+ return uefi_call_wrapper(tcg->GetEventLog, 5, tcg,
+ EFI_TCG2_EVENT_LOG_FORMAT_TCG_2, NULL,
+ NULL, NULL);
+}
+
+static EFI_STATUS tpm2_measure_to_pcr_and_event_log(const EFI_TCG2 *tcg, UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer,
+ UINT64 buffer_size, const CHAR16 *description) {
+ EFI_STATUS status;
+ EFI_TCG2_EVENT *tcg_event;
+ UINTN desc_len;
+ static BOOLEAN triggered = FALSE;
+
+ if (triggered == FALSE) {
+ status = trigger_tcg2_final_events_table(tcg);
+ if (EFI_ERROR(status))
+ return status;
+
+ triggered = TRUE;
+ }
+
+ desc_len = StrLen(description) * sizeof(CHAR16);
+
+ tcg_event = AllocateZeroPool(sizeof(*tcg_event) - sizeof(tcg_event->Event) + desc_len + 1);
+
+ if (tcg_event == NULL)
+ return EFI_OUT_OF_RESOURCES;
+
+ tcg_event->Size = sizeof(EFI_TCG2_EVENT) - sizeof(tcg_event->Event) + desc_len + 1;
+ tcg_event->Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER);
+ tcg_event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
+ tcg_event->Header.PCRIndex = pcrindex;
+ tcg_event->Header.EventType = EV_IPL;
+
+ CopyMem((VOID *) tcg_event->Event, (VOID *) description, desc_len);
+
+ status = uefi_call_wrapper(tcg->HashLogExtendEvent, 5, tcg, 0, buffer, buffer_size, tcg_event);
+
+ uefi_call_wrapper(BS->FreePool, 1, tcg_event);
+
+ if (EFI_ERROR(status))
+ return status;
+
+ return EFI_SUCCESS;
+}
+
+static EFI_TCG * tcg1_interface_check(void) {
+ EFI_GUID tpm_guid = EFI_TCG_PROTOCOL_GUID;
+ EFI_STATUS status;
+ EFI_TCG *tcg;
+ TCG_BOOT_SERVICE_CAPABILITY capability;
+ UINT32 features;
+ EFI_PHYSICAL_ADDRESS event_log_location;
+ EFI_PHYSICAL_ADDRESS event_log_last_entry;
+
+ status = LibLocateProtocol(&tpm_guid, (void **) &tcg);
+
+ if (EFI_ERROR(status))
+ return NULL;
+
+ capability.Size = (UINT8) sizeof(capability);
+ status = uefi_call_wrapper(tcg->StatusCheck, 5, tcg, &capability, &features, &event_log_location, &event_log_last_entry);
+
+ if (EFI_ERROR(status))
+ return NULL;
+
+ if (capability.TPMDeactivatedFlag)
+ return NULL;
+
+ if (!capability.TPMPresentFlag)
+ return NULL;
+
+ return tcg;
+}
+
+static EFI_TCG2 * tcg2_interface_check(void) {
+ EFI_GUID tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
+ EFI_STATUS status;
+ EFI_TCG2 *tcg;
+ EFI_TCG2_BOOT_SERVICE_CAPABILITY capability;
+
+ status = LibLocateProtocol(&tpm2_guid, (void **) &tcg);
+
+ if (EFI_ERROR(status))
+ return NULL;
+
+ capability.Size = (UINT8) sizeof(capability);
+ status = uefi_call_wrapper(tcg->GetCapability, 2, tcg, &capability);
+
+ if (EFI_ERROR(status))
+ return NULL;
+
+ if (!capability.TPMPresentFlag)
+ return NULL;
+
+ return tcg;
+}
+
+EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description) {
+ EFI_TCG *tpm1;
+ EFI_TCG2 *tpm2;
+
+ tpm2 = tcg2_interface_check();
+ if (tpm2)
+ return tpm2_measure_to_pcr_and_event_log(tpm2, pcrindex, buffer, buffer_size, description);
+
+ tpm1 = tcg1_interface_check();
+ if (tpm1)
+ return tpm1_measure_to_pcr_and_event_log(tpm1, pcrindex, buffer, buffer_size, description);
+
+ /* No active TPM found, so don't return an error */
+ return EFI_SUCCESS;
+}
+
+#endif
diff --git a/src/boot/efi/measure.h b/src/boot/efi/measure.h
new file mode 100644
index 0000000000..a2cfe817d0
--- /dev/null
+++ b/src/boot/efi/measure.h
@@ -0,0 +1,21 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ */
+#ifndef __SDBOOT_MEASURE_H
+#define __SDBOOT_MEASURE_H
+
+#ifndef SD_TPM_PCR
+#define SD_TPM_PCR 8
+#endif
+
+EFI_STATUS tpm_log_event(UINT32 pcrindex, const EFI_PHYSICAL_ADDRESS buffer, UINTN buffer_size, const CHAR16 *description);
+#endif
diff --git a/src/boot/efi/pefile.c b/src/boot/efi/pefile.c
index e6fedbc929..77fff77b69 100644
--- a/src/boot/efi/pefile.c
+++ b/src/boot/efi/pefile.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -17,8 +15,8 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "pefile.h"
+#include "util.h"
struct DosFileHeader {
UINT8 Magic[2];
diff --git a/src/boot/efi/pefile.h b/src/boot/efi/pefile.h
index ca2f9a2508..2e445ede17 100644
--- a/src/boot/efi/pefile.h
+++ b/src/boot/efi/pefile.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
diff --git a/src/boot/efi/splash.c b/src/boot/efi/splash.c
index 470ea3e2cc..c0ef7f64fe 100644
--- a/src/boot/efi/splash.c
+++ b/src/boot/efi/splash.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
@@ -18,9 +16,9 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
#include "graphics.h"
#include "splash.h"
+#include "util.h"
struct bmp_file {
CHAR8 signature[2];
@@ -283,9 +281,9 @@ EFI_STATUS graphics_splash(UINT8 *content, UINTN len, const EFI_GRAPHICS_OUTPUT_
if (EFI_ERROR(err))
goto err;
- if(dib->x < GraphicsOutput->Mode->Info->HorizontalResolution)
+ if (dib->x < GraphicsOutput->Mode->Info->HorizontalResolution)
x_pos = (GraphicsOutput->Mode->Info->HorizontalResolution - dib->x) / 2;
- if(dib->y < GraphicsOutput->Mode->Info->VerticalResolution)
+ if (dib->y < GraphicsOutput->Mode->Info->VerticalResolution)
y_pos = (GraphicsOutput->Mode->Info->VerticalResolution - dib->y) / 2;
uefi_call_wrapper(GraphicsOutput->Blt, 10, GraphicsOutput,
diff --git a/src/boot/efi/splash.h b/src/boot/efi/splash.h
index 0183e79b16..09b543fb47 100644
--- a/src/boot/efi/splash.h
+++ b/src/boot/efi/splash.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c
index 0b1bc491ed..1e250f34f4 100644
--- a/src/boot/efi/stub.c
+++ b/src/boot/efi/stub.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
@@ -16,11 +14,13 @@
#include <efi.h>
#include <efilib.h>
-#include "util.h"
-#include "pefile.h"
+#include "disk.h"
#include "graphics.h"
-#include "splash.h"
#include "linux.h"
+#include "pefile.h"
+#include "splash.h"
+#include "util.h"
+#include "measure.h"
/* magic string to find in the binary image */
static const char __attribute__((used)) magic[] = "#### LoaderInfo: systemd-stub " VERSION " ####";
@@ -46,6 +46,7 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
UINTN szs[ELEMENTSOF(sections)-1] = {};
CHAR8 *cmdline = NULL;
UINTN cmdline_len;
+ CHAR16 uuid[37];
EFI_STATUS err;
InitializeLib(image, sys_table);
@@ -97,8 +98,24 @@ EFI_STATUS efi_main(EFI_HANDLE image, EFI_SYSTEM_TABLE *sys_table) {
for (i = 0; i < cmdline_len; i++)
line[i] = options[i];
cmdline = line;
+
+#ifdef SD_BOOT_LOG_TPM
+ /* Try to log any options to the TPM, escpecially manually edited options */
+ err = tpm_log_event(SD_TPM_PCR,
+ (EFI_PHYSICAL_ADDRESS) loaded_image->LoadOptions,
+ loaded_image->LoadOptionsSize, loaded_image->LoadOptions);
+ if (EFI_ERROR(err)) {
+ Print(L"Unable to add image options measurement: %r", err);
+ uefi_call_wrapper(BS->Stall, 1, 3 * 1000 * 1000);
+ return err;
+ }
+#endif
}
+ /* export the device path this image is started from */
+ if (disk_get_part_uuid(loaded_image->DeviceHandle, uuid) == EFI_SUCCESS)
+ efivar_set(L"LoaderDevicePartUUID", uuid, FALSE);
+
if (szs[3] > 0)
graphics_splash((UINT8 *)((UINTN)loaded_image->ImageBase + addrs[3]), szs[3], NULL);
diff --git a/src/boot/efi/util.c b/src/boot/efi/util.c
index 5e374edacf..98c5be74ce 100644
--- a/src/boot/efi/util.c
+++ b/src/boot/efi/util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
diff --git a/src/boot/efi/util.h b/src/boot/efi/util.h
index 4727a34d1f..e673cdf9a0 100644
--- a/src/boot/efi/util.h
+++ b/src/boot/efi/util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by