All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot
@ 2021-10-22 11:24 Masahisa Kojima
  2021-10-22 11:24 ` [PATCH 1/2] efi_loader: add missing const qualifier Masahisa Kojima
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Masahisa Kojima @ 2021-10-22 11:24 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass, Masahisa Kojima

This patch series adds the selftest for the EFI_TCG2_PROTOCOL and
Measured Boot flow.
This selftest is verified on qemu with swtpm.

This covers most of the functionalities, but there are some
limitations and TODO items.

[Limitation]
- tcg2 selftest must run at the beginning of the efi_selftest because
  some measurement occurs in efi_tcg2_register() and boottime->image_load().
  Need to configure the efi_selftest with "setenv efi_selftest tcg2; bootefi selftest"
- Skip ExitBootService measurement test
   - EFI application can not read PCR after calling ExitBootService
- Skip EventLog Validation
   - Measured Boot measures U-Boot version, so EventLog varies every build having
     different commit hash.
- Skip PCR[0] validation
   - PCR[0] include U-Boot version measurement, this value varies every build
     having different commit hash.
- Skip PCR[7] validation
   - Secure Boot Variables can not be updated through efi_selftest.
- The initial PCR value of PCR[17 - 22] is all 0xff, I'm not sure
  it is expected or not.

[TODO]
- GPT measurement test
- Secure Boot Variable test
- Eventlog validation

Masahisa Kojima (2):
  efi_loader: add missing const qualifier
  efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot

 include/efi_api.h                             |   2 +-
 lib/efi_loader/efi_boottime.c                 |   5 +-
 lib/efi_selftest/Makefile                     |  10 +
 .../efi_selftest_miniapp_measuredboot.c       |  93 ++
 lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
 5 files changed, 910 insertions(+), 4 deletions(-)
 create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/2] efi_loader: add missing const qualifier
  2021-10-22 11:24 [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot Masahisa Kojima
@ 2021-10-22 11:24 ` Masahisa Kojima
  2021-10-23  8:40   ` Heinrich Schuchardt
  2021-10-22 11:24 ` [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot Masahisa Kojima
  2021-10-24 19:54 ` [PATCH 0/2] " Simon Glass
  2 siblings, 1 reply; 16+ messages in thread
From: Masahisa Kojima @ 2021-10-22 11:24 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass,
	Masahisa Kojima, Alexander Graf

This commit fixes the following compilation warning
of boottime->install_configuration_table() function.

---
lib/efi_selftest/efi_selftest_tcg2.c:475:46:
warning: passing argument 1 of ‘boottime->install_configuration_table’
discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
  ret = boottime->install_configuration_table(&smbios_guid, dmi);
---

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
 include/efi_api.h             | 2 +-
 lib/efi_loader/efi_boottime.c | 5 +++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/include/efi_api.h b/include/efi_api.h
index c8f959bb72..0accad08c8 100644
--- a/include/efi_api.h
+++ b/include/efi_api.h
@@ -120,7 +120,7 @@ struct efi_boot_services {
 			struct efi_device_path **device_path,
 			efi_handle_t *device);
 	efi_status_t (EFIAPI *install_configuration_table)(
-			efi_guid_t *guid, void *table);
+			const efi_guid_t *guid, void *table);
 
 	efi_status_t (EFIAPI *load_image)(bool boot_policiy,
 			efi_handle_t parent_image,
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index bf5661e1ee..1823990d9b 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -1692,8 +1692,9 @@ out:
  *
  * Return: status code
  */
-static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
-							       void *table)
+static efi_status_t
+EFIAPI efi_install_configuration_table_ext(const efi_guid_t *guid,
+					   void *table)
 {
 	EFI_ENTRY("%pUl, %p", guid, table);
 	return EFI_EXIT(efi_install_configuration_table(guid, table));
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-10-22 11:24 [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot Masahisa Kojima
  2021-10-22 11:24 ` [PATCH 1/2] efi_loader: add missing const qualifier Masahisa Kojima
@ 2021-10-22 11:24 ` Masahisa Kojima
  2021-10-23  9:42   ` Heinrich Schuchardt
  2021-10-24 19:54 ` [PATCH 0/2] " Simon Glass
  2 siblings, 1 reply; 16+ messages in thread
From: Masahisa Kojima @ 2021-10-22 11:24 UTC (permalink / raw)
  To: u-boot
  Cc: Heinrich Schuchardt, Ilias Apalodimas, Simon Glass,
	Masahisa Kojima, Alexander Graf

This commit adds the missing EFI_TCG2_PROTOCOL selftest
and Measured Boot selftest in lib/efi_selftest.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
 lib/efi_selftest/Makefile                     |  10 +
 .../efi_selftest_miniapp_measuredboot.c       |  93 ++
 lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
 3 files changed, 906 insertions(+), 1 deletion(-)
 create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c

diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
index 9ff6e1760c..09950ee028 100644
--- a/lib/efi_selftest/Makefile
+++ b/lib/efi_selftest/Makefile
@@ -14,6 +14,8 @@ CFLAGS_efi_selftest_miniapp_exception.o := $(CFLAGS_EFI) -Os -ffreestanding
 CFLAGS_REMOVE_efi_selftest_miniapp_exception.o := $(CFLAGS_NON_EFI)
 CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
 CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI)
+CFLAGS_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_EFI) -Os -ffreestanding
+CFLAGS_REMOVE_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_NON_EFI)
 CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
 CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI)
 CFLAGS_initrddump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
@@ -78,9 +80,11 @@ obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o
 targets += \
 efi_miniapp_file_image_exception.h \
 efi_miniapp_file_image_exit.h \
+efi_miniapp_file_image_measuredboot.h \
 efi_miniapp_file_image_return.h \
 efi_selftest_miniapp_exception.efi \
 efi_selftest_miniapp_exit.efi \
+efi_selftest_miniapp_measuredboot.efi \
 efi_selftest_miniapp_return.efi
 
 ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
@@ -99,6 +103,10 @@ $(obj)/efi_miniapp_file_image_exit.h: $(obj)/efi_selftest_miniapp_exit.efi
 	$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exit.efi > \
 	$(obj)/efi_miniapp_file_image_exit.h
 
+$(obj)/efi_miniapp_file_image_measuredboot.h: $(obj)/efi_selftest_miniapp_measuredboot.efi
+	$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_measuredboot.efi > \
+	$(obj)/efi_miniapp_file_image_measuredboot.h
+
 $(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi
 	$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
 	$(obj)/efi_miniapp_file_image_return.h
@@ -112,3 +120,5 @@ $(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h
 $(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
 
 $(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
+
+$(obj)/efi_selftest_tcg2.o: $(obj)/efi_miniapp_file_image_measuredboot.h
diff --git a/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
new file mode 100644
index 0000000000..926713c1c2
--- /dev/null
+++ b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * efi_selftest_miniapp_measuredboot
+ *
+ * Copyright (c) 2018 Heinrich Schuchardt
+ * Copyright (c) 2021 Masahisa Kojima
+ *
+ * This EFI application is run by the StartImage selftest.
+ * It uses the Exit boot service to return and used for
+ * Measured Boot selftest.
+ */
+
+#include <common.h>
+#include <efi_selftest.h>
+
+static efi_guid_t loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+
+/**
+ * check_loaded_image_protocol() - check image_base/image_size
+ *
+ * Try to open the loaded image protocol. Check that this function is located
+ * between image_base and image_base + image_size.
+ *
+ * @image_handle:	handle of the loaded image
+ * @systable:		system table
+ * @return:		status code
+ */
+static efi_status_t EFIAPI check_loaded_image_protocol
+		(efi_handle_t image_handle, struct efi_system_table *systable)
+{
+	struct efi_simple_text_output_protocol *cout = systable->con_out;
+	struct efi_boot_services *boottime = systable->boottime;
+	struct efi_loaded_image *loaded_image_protocol;
+	efi_status_t ret;
+
+	/*
+	 * Open the loaded image protocol.
+	 */
+	ret = boottime->open_protocol
+				(image_handle, &loaded_image_protocol_guid,
+				 (void **)&loaded_image_protocol, NULL,
+				  NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+	if (ret != EFI_SUCCESS) {
+		cout->output_string(cout,
+				    L"Could not open loaded image protocol");
+		return ret;
+	}
+	if ((void *)check_loaded_image_protocol <
+	    loaded_image_protocol->image_base ||
+	    (void *)check_loaded_image_protocol >=
+	    loaded_image_protocol->image_base +
+	    loaded_image_protocol->image_size) {
+		cout->output_string(cout,
+				    L"Incorrect image_base or image_size\n");
+		return EFI_NOT_FOUND;
+	}
+	return EFI_SUCCESS;
+}
+
+/**
+ * Entry point of the EFI application.
+ *
+ * @handle:	handle of the loaded image
+ * @systable:	system table
+ * @return:	status code
+ */
+efi_status_t EFIAPI efi_main(efi_handle_t handle,
+			     struct efi_system_table *systable)
+{
+	struct efi_simple_text_output_protocol *con_out = systable->con_out;
+	efi_status_t ret;
+	u16 text[] = EFI_ST_SUCCESS_STR;
+
+	con_out->output_string(con_out, L"EFI application calling Exit\n");
+
+	if (check_loaded_image_protocol(handle, systable) != EFI_SUCCESS) {
+		con_out->output_string(con_out,
+				       L"Loaded image protocol missing\n");
+		ret = EFI_NOT_FOUND;
+		goto out;
+	}
+
+	/* This return value is expected by the calling test */
+	ret = EFI_UNSUPPORTED;
+out:
+	systable->boottime->exit(handle, ret, sizeof(text), text);
+
+	/*
+	 * This statement should not be reached.
+	 * To enable testing use a different return value.
+	 */
+	return EFI_SUCCESS;
+}
diff --git a/lib/efi_selftest/efi_selftest_tcg2.c b/lib/efi_selftest/efi_selftest_tcg2.c
index 1399309cec..50de735f5e 100644
--- a/lib/efi_selftest/efi_selftest_tcg2.c
+++ b/lib/efi_selftest/efi_selftest_tcg2.c
@@ -9,10 +9,495 @@
 
 #include <efi_selftest.h>
 #include <efi_tcg2.h>
+/* Include containing the miniapp.efi application */
+#include "efi_miniapp_file_image_measuredboot.h"
+
+#include <linux/unaligned/access_ok.h>
+#include <mapmem.h>
+#include <smbios.h>
+#include <tables_csum.h>
 
 static struct efi_boot_services *boottime;
 static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
 
+/* Block size of compressed disk image */
+#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
+
+static efi_handle_t image_handle;
+/* Decompressed file image */
+static u8 *image;
+
+/* One 8 byte block of the compressed disk image */
+struct line {
+	size_t addr;
+	char *line;
+};
+
+/* Compressed file image */
+struct compressed_file_image {
+	size_t length;
+	struct line lines[];
+};
+
+static struct compressed_file_image img = EFI_ST_DISK_IMG;
+
+static struct efi_tcg2_event *efi_tcg2_event;
+
+static struct efi_runtime_services *runtime;
+#define BOOT_NAME_1000 u"Boot1000"
+#define BOOT_NAME_1001 u"Boot1001"
+#define BOOT_NAME_1002 u"Boot1002"
+
+#define DEFAULT_ATTR (EFI_VARIABLE_NON_VOLATILE | \
+		      EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+		      EFI_VARIABLE_RUNTIME_ACCESS)
+
+/* "efidebug boot add -b 1000 test1000 virtio 0:1 /EFI/debian/grubaa64.efi" */
+static const u8 boot_1000[] = {
+0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
+0x74, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
+0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
+0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
+0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
+0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
+0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
+0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
+0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
+0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
+0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
+0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
+0xff, 0x04, 0x00 };
+
+/* "efidebug boot add -b 1001 test1001 virtio 0:1 /EFI/debian/grubaa64.efi" */
+static const u8 boot_1001[] = {
+0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
+0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
+0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
+0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
+0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
+0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
+0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
+0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
+0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
+0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
+0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
+0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
+0xff, 0x04, 0x00 };
+
+/* "efidebug boot add -b 1002 test1002 virtio 0:1 /EFI/debian/grubaa64.efi" */
+static const u8 boot_1002[] = {
+0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
+0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
+0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
+0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
+0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
+0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
+0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
+0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
+0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
+0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
+0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
+0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
+0xff, 0x04, 0x00};
+
+/* "efidebug boot order 1002 1000 1001" */
+static u8 boot_order[] = {0x02, 0x10, 0x00, 0x10, 0x01, 0x10};
+
+static void *orig_smbios_table;
+static u64 dmi_addr = U32_MAX;
+#define SMBIOS_ENTRY_HEADER_SIZE 0x20
+/* smbios table for the measurement test */
+static u8 smbios_table_test[] = {
+0x5f, 0x53, 0x4d, 0x5f, 0x2c, 0x1f, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x5f, 0x44, 0x4d, 0x49, 0x5f, 0xe4, 0x5c, 0x01,
+0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+0x01, 0x02, 0x00, 0x00, 0x03, 0x00, 0x80, 0x08, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x15, 0x0a, 0xff, 0xff, 0x55, 0x2d, 0x42, 0x6f,
+0x6f, 0x74, 0x00, 0x32, 0x30, 0x32, 0x31, 0x2e, 0x31, 0x30, 0x2d, 0x72,
+0x63, 0x34, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x35, 0x2d, 0x67, 0x37, 0x32,
+0x37, 0x63, 0x33, 0x66, 0x33, 0x32, 0x35, 0x39, 0x2d, 0x64, 0x69, 0x72,
+0x74, 0x79, 0x00, 0x31, 0x30, 0x2f, 0x30, 0x31, 0x2f, 0x32, 0x30, 0x32,
+0x31, 0x00, 0x00, 0x01, 0x1b, 0x01, 0x00, 0x01, 0x02, 0x00, 0x03, 0x31,
+0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
+0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
+0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+0x37, 0x38, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x00, 0x01, 0x02, 0x00, 0x04,
+0x03, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
+0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
+0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
+0x33, 0x33, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00,
+0x00, 0x03, 0x15, 0x03, 0x00, 0x01, 0x03, 0x00, 0x02, 0x03, 0x03, 0x03,
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6e,
+0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
+0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00,
+0x00, 0x04, 0x30, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x01, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x03, 0x04,
+0x04, 0x04, 0x08, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01,
+0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33,
+0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
+0x33, 0x33, 0x00, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x00,
+0x00, 0x20, 0x0b, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7f, 0x04, 0x06, 0x00, 0x00, 0x00
+};
+
+#define TPM2_CMD_BUF_SIZE 64
+/* TPM command is big endian */
+#define __MSB(x) ((x) >> 8)
+#define __LSB(x) ((x) & 0xFF)
+#define tpm_u16(x) __MSB(x), __LSB(x)
+#define tpm_u32(x) tpm_u16((x) >> 16), tpm_u16((x) & 0xFFFF)
+#define TPM2_PCR_READ_HEADER_SIZE 30
+
+static u8 *pcrs;
+static u8 expected_pcrs[EFI_TCG2_MAX_PCR_INDEX + 1][TPM2_SHA256_DIGEST_SIZE] = {
+	{0x91, 0x21, 0x37, 0xc7, 0x1a, 0x49, 0x19, 0xc8,
+	 0xf1, 0xfb, 0xa9, 0x84, 0x5c, 0x65, 0xa9, 0xdd,
+	 0x7b, 0xb9, 0xfe, 0xa1, 0xcd, 0x64, 0x49, 0xdd,
+	 0xed, 0xe2, 0x65, 0x82, 0xc5, 0x3e, 0xf4, 0xc4},
+
+	{0xf5, 0x79, 0xf3, 0x20, 0x62, 0x6e, 0x8b, 0x58,
+	 0x62, 0xa3, 0x4e, 0x2f, 0xb7, 0x10, 0xac, 0x34,
+	 0x4e, 0x68, 0x94, 0x37, 0x87, 0x29, 0xc4, 0xbe,
+	 0xa3, 0xc4, 0xd9, 0x14, 0x2b, 0x66, 0x79, 0x9b},
+
+	{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
+	 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
+	 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
+	 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
+
+	{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
+	 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
+	 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
+	 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
+
+	{0xbe, 0xea, 0xdc, 0xe0, 0x44, 0x5b, 0x5f, 0x14,
+	 0xef, 0x24, 0x5d, 0x13, 0x15, 0xfe, 0x41, 0x86,
+	 0xc2, 0xd5, 0xdc, 0x0d, 0x04, 0x2f, 0xd4, 0x04,
+	 0x0d, 0x02, 0x62, 0xc0, 0x34, 0x80, 0xee, 0xd5},
+
+	{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
+	 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
+	 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
+	 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
+
+	{0x8d, 0x28, 0xde, 0x72, 0x22, 0x3e, 0x88, 0x1a,
+	 0x37, 0xfa, 0x47, 0x12, 0x68, 0x45, 0xdf, 0x71,
+	 0x50, 0x8f, 0xab, 0x59, 0x50, 0x7b, 0x52, 0x32,
+	 0xa6, 0xaa, 0x03, 0x3d, 0x4e, 0x22, 0x89, 0xd7},
+
+	{0x96, 0x74, 0xae, 0xcd, 0x3f, 0x40, 0xb4, 0xa9,
+	 0x36, 0xae, 0x19, 0xc8, 0x84, 0x8a, 0xb9, 0x5a,
+	 0x87, 0x99, 0xd8, 0x89, 0x7f, 0xfc, 0x40, 0x48,
+	 0x05, 0x99, 0x65, 0x2e, 0x55, 0xd4, 0x93, 0x32},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+
+	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+
+	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+};
+
+struct boot_variable {
+	u16 name[16];
+	u8 *buf;
+	efi_uintn_t size;
+	u32 attr;
+	const u8 *test_data;
+	efi_uintn_t test_data_size;
+};
+
+static struct boot_variable boot_variable_test[] = {
+	{u"BootOrder",		NULL, 0, DEFAULT_ATTR, boot_order, sizeof(boot_order)},
+	{BOOT_NAME_1000,	NULL, 0, DEFAULT_ATTR, boot_1000, sizeof(boot_1000)},
+	{BOOT_NAME_1001,	NULL, 0, DEFAULT_ATTR, boot_1001, sizeof(boot_1001)},
+	{BOOT_NAME_1002,	NULL, 0, DEFAULT_ATTR, boot_1002, sizeof(boot_1002)},
+};
+
+/*
+ * Decompress the disk image.
+ *
+ * @image	decompressed disk image
+ * @return	status code
+ */
+static efi_status_t decompress(u8 **image)
+{
+	u8 *buf;
+	size_t i;
+	size_t addr;
+	size_t len;
+	efi_status_t ret;
+
+	ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
+				      (void **)&buf);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Out of memory\n");
+		return ret;
+	}
+	boottime->set_mem(buf, img.length, 0);
+
+	for (i = 0; ; ++i) {
+		if (!img.lines[i].line)
+			break;
+		addr = img.lines[i].addr;
+		len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
+		if (addr + len > img.length)
+			len = img.length - addr;
+		boottime->copy_mem(buf + addr, img.lines[i].line, len);
+	}
+	*image = buf;
+	return ret;
+}
+
+/*
+ * Configure dummy boot variables.
+ *
+ * @return	status code
+ */
+static efi_status_t setup_boot_variable(void)
+{
+	efi_status_t ret;
+	u32 i;
+	efi_uintn_t size;
+	u8 dummy;
+
+	for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
+		size = 1;
+		ret = runtime->get_variable(boot_variable_test[i].name,
+					    &efi_global_variable_guid,
+					    &boot_variable_test[i].attr,
+					    &size,
+					    &dummy);
+		if (ret == EFI_BUFFER_TOO_SMALL) {
+			/* Variable exists, save the current vaiable */
+			boot_variable_test[i].size = size;
+			ret = boottime->allocate_pool(EFI_LOADER_DATA,
+						      boot_variable_test[i].size,
+						      (void **)&boot_variable_test[i].buf);
+			if (ret != EFI_SUCCESS) {
+				efi_st_error("fail to allocate buffer for boot variable\n");
+				return ret;
+			}
+			ret = runtime->get_variable(boot_variable_test[i].name,
+						    &efi_global_variable_guid,
+						    &boot_variable_test[i].attr,
+						    &boot_variable_test[i].size,
+						    boot_variable_test[i].buf);
+			if (ret != EFI_SUCCESS) {
+				efi_st_error("fail to get current boot variable\n");
+				return ret;
+			}
+		}
+
+		/* set boot variable for the measurement test */
+		ret = runtime->set_variable(boot_variable_test[i].name,
+					    &efi_global_variable_guid,
+					    boot_variable_test[i].attr,
+					    boot_variable_test[i].test_data_size,
+					    boot_variable_test[i].test_data);
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("### fail to set test boot variable(%d)n", i);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Restore original boot variables.
+ *
+ * @return	status code
+ */
+efi_status_t restore_boot_variable(void)
+{
+	int i;
+	efi_status_t ret;
+
+	for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
+		if (boot_variable_test[i].buf) {
+			ret = runtime->set_variable(boot_variable_test[i].name,
+						    &efi_global_variable_guid,
+						    boot_variable_test[i].attr,
+						    boot_variable_test[i].size,
+						    boot_variable_test[i].buf);
+			if (ret != EFI_SUCCESS) {
+				efi_st_error("### fail to restore boot variable\n");
+				return ret;
+			}
+			ret = boottime->free_pool(boot_variable_test[i].buf);
+			if (ret != EFI_SUCCESS) {
+				efi_st_error("Failed to free boot variable\n");
+				return ret;
+			}
+		} else {
+			/* delete the variable used only for testing */
+			ret = runtime->set_variable(boot_variable_test[i].name,
+						    &efi_global_variable_guid,
+						    0, 0, NULL);
+			if (ret != EFI_SUCCESS) {
+				efi_st_error("### fail to delete boot variable\n");
+				return ret;
+			}
+		}
+	}
+
+	return EFI_SUCCESS;
+}
+
+/**
+ * Find smbios table
+ *
+ * @systable	system table
+ * @return	status code
+ */
+static void *find_smbios_table(const struct efi_system_table *systable)
+{
+	u32 i;
+
+	for (i = 0; i < systable->nr_tables; i++) {
+		if (!guidcmp(&smbios_guid, &systable->tables[i].guid))
+			return systable->tables[i].table;
+	}
+
+	return NULL;
+}
+
+/**
+ * Prepare the dummy SMBIOS table
+ *
+ * @systable	system table
+ * @return	status code
+ */
+efi_status_t setup_smbios_table(const struct efi_system_table *systable)
+{
+	struct smbios_entry *se;
+	efi_status_t ret;
+	/* Map within the low 32 bits, to allow for 32bit SMBIOS tables */
+	void *dmi;
+	char *istart;
+	int isize;
+
+	if (sizeof(smbios_table_test) > EFI_PAGE_SIZE)
+		return EFI_OUT_OF_RESOURCES;
+
+	orig_smbios_table = find_smbios_table(systable);
+
+	/* Reserve 4kiB page for SMBIOS */
+	ret = boottime->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
+				 EFI_RUNTIME_SERVICES_DATA, 1, &dmi_addr);
+
+	if (ret != EFI_SUCCESS) {
+		/* Could not find space in lowmem, use highmem instead */
+		ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
+					 EFI_RUNTIME_SERVICES_DATA, 1,
+					 &dmi_addr);
+
+		if (ret != EFI_SUCCESS)
+			return ret;
+	}
+
+	dmi = (void *)(uintptr_t)dmi_addr;
+	se = dmi;
+	boottime->copy_mem(se, smbios_table_test, sizeof(smbios_table_test));
+
+	/* update smbios table start address */
+	se->struct_table_address = (uintptr_t)((u8 *)dmi + SMBIOS_ENTRY_HEADER_SIZE);
+
+	/* calculate checksums */
+	istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
+	isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
+	se->intermediate_checksum = table_compute_checksum(istart, isize);
+	se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
+
+	/* Install SMBIOS information as configuration table */
+	ret = boottime->install_configuration_table(&smbios_guid, dmi);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Cannot install SMBIOS table\n");
+		boottime->free_pages(dmi_addr, 1);
+	}
+
+	return ret;
+}
+
 /**
  * efi_st_tcg2_setup() - setup test
  *
@@ -23,7 +508,171 @@ static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
 static int efi_st_tcg2_setup(const efi_handle_t img_handle,
 			     const struct efi_system_table *systable)
 {
+	efi_status_t ret;
+	struct uefi_image_load_event image_load_event;
+
+	image_handle = img_handle;
 	boottime = systable->boottime;
+	runtime = systable->runtime;
+
+	/* Load the application image into memory */
+	decompress(&image);
+
+	ret = boottime->allocate_pool(EFI_LOADER_DATA,
+				      sizeof(struct efi_tcg2_event) +
+				      sizeof(struct uefi_image_load_event),
+				      (void **)&efi_tcg2_event);
+	if (!efi_tcg2_event)
+		return EFI_ST_FAILURE;
+
+	efi_tcg2_event->size = sizeof(struct efi_tcg2_event) +
+			       sizeof(struct uefi_image_load_event);
+	efi_tcg2_event->header.header_size = sizeof(struct efi_tcg2_event_header);
+	efi_tcg2_event->header.header_version = 1;
+	efi_tcg2_event->header.pcr_index = 6;
+	efi_tcg2_event->header.event_type = EV_EFI_RUNTIME_SERVICES_DRIVER;
+	image_load_event.image_location_in_memory = 0x12345678;
+	image_load_event.image_length_in_memory = 0x300000;
+	image_load_event.image_link_time_address = 0x87654321;
+	image_load_event.length_of_device_path = 0;
+	boottime->copy_mem(efi_tcg2_event->event, &image_load_event,
+			   sizeof(struct uefi_image_load_event));
+
+	ret = setup_boot_variable();
+	if (ret != EFI_SUCCESS)
+		return EFI_ST_FAILURE;
+
+	ret = setup_smbios_table(systable);
+	if (ret != EFI_SUCCESS)
+		return EFI_ST_FAILURE;
+
+	ret = boottime->allocate_pool(EFI_LOADER_DATA,
+				      (EFI_TCG2_MAX_PCR_INDEX + 1) *
+				      TPM2_SHA256_DIGEST_SIZE,
+				      (void **)&pcrs);
+	if (!pcrs)
+		return EFI_ST_FAILURE;
+
+	boottime->set_mem(pcrs, (EFI_TCG2_MAX_PCR_INDEX + 1) * TPM2_SHA256_DIGEST_SIZE, 0);
+
+	return EFI_ST_SUCCESS;
+}
+
+/**
+ * Get manufacturer_id through submit_command API
+ *
+ * @tcg2		tcg2 protocol
+ * @manufacturer_id	pointer to the manufacturer_id
+ * @return		status code
+ */
+static efi_status_t get_manufacturer_id(struct efi_tcg2_protocol *tcg2, u32 *manufacturer_id)
+{
+	efi_status_t ret;
+	u8 cmd[TPM2_CMD_BUF_SIZE] = {
+		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
+		tpm_u32(22),				/* Length */
+		tpm_u32(TPM2_CC_GET_CAPABILITY),	/* Command code */
+
+		tpm_u32(TPM2_CAP_TPM_PROPERTIES),	/* Capability */
+		tpm_u32(TPM2_PT_MANUFACTURER),		/* Property */
+		tpm_u32(1),			/* Property count */
+	};
+	u8 resp[TPM2_CMD_BUF_SIZE];
+	unsigned int value_off;
+
+	ret = tcg2->submit_command(tcg2, 22, cmd,
+				   TPM2_CMD_BUF_SIZE, resp);
+	if (ret != EFI_SUCCESS)
+		return ret;
+
+	/*
+	 * In the response buffer, the properties are located after the:
+	 * tag (u16), response size (u32), response code (u32),
+	 * YES/NO flag (u8), TPM_CAP (u32).
+	 * The value is located after count (u32), property (u32).
+	 */
+	value_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
+			 sizeof(u8) + sizeof(u32) + sizeof(u32) + sizeof(u32);
+	*manufacturer_id = get_unaligned_be32(&resp[value_off]);
+
+	return ret;
+}
+
+/**
+ * Read the PCR from the TPM device
+ *
+ * @tcg2	tcg2 protocol
+ * @idx		pcr index to read
+ * @return	status code
+ */
+static efi_status_t read_pcr(struct efi_tcg2_protocol *tcg2, u32 idx)
+{
+	efi_status_t ret;
+	u8 idx_array_sz = 3; /* support 24 PCRs */
+	u32 cmd_len = 17 + idx_array_sz;
+	u8 cmd[TPM2_CMD_BUF_SIZE] = {
+		tpm_u16(TPM2_ST_NO_SESSIONS),	/* TAG */
+		tpm_u32(cmd_len),		/* Length */
+		tpm_u32(TPM2_CC_PCR_READ),	/* Command code */
+		/* TPML_PCR_SELECTION */
+		tpm_u32(1),			/* Number of selections */
+		tpm_u16(TPM2_ALG_SHA256),	/* Algorithm of the hash */
+		idx_array_sz,			/* Array size for selection */
+		/* bitmap(idx),			   Selected PCR bitmap */
+	};
+	u8 resp[TPM2_CMD_BUF_SIZE];
+	u32 pcr_sel_idx = idx / 8;
+	u8 pcr_sel_bit = BIT(idx % 8);
+	u8 *dst;
+
+	cmd[17 + pcr_sel_idx] = pcr_sel_bit;
+	ret = tcg2->submit_command(tcg2, cmd_len, cmd,
+				   TPM2_CMD_BUF_SIZE, resp);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("tcg2->submit_command fail to read PCR\n");
+		return ret;
+	}
+
+	dst = pcrs + (idx * TPM2_SHA256_DIGEST_SIZE);
+	boottime->copy_mem(dst, &resp[TPM2_PCR_READ_HEADER_SIZE],
+			   TPM2_SHA256_DIGEST_SIZE);
+
+	return ret;
+}
+
+/**
+ * Compare the expected and actual pcrs
+ *
+ * @return	status code
+ */
+static int validate_pcrs(void)
+{
+	u32 i;
+	u8 *expected = (u8 *)expected_pcrs;
+	u8 *result = pcrs;
+
+	/*
+	 *  - Skip PCR[0] validation. PCR[0] contains U-Boot version measurement
+	 *    it contains the commit hash, so the measurement varies every build
+	 *    with different commit hash.
+	 *  - Skip PCR[7] validation. PCR[7] contains UEFI Secure Boot variables
+	 *    measurement. These variables can not be updated through efi_selftest and
+	 *    it varies depending on the platform.
+	 */
+	for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {
+		result = pcrs + (TPM2_SHA256_DIGEST_SIZE * i);
+		if (i == 0 || i == 7) {
+			expected += TPM2_SHA256_DIGEST_SIZE;
+			result += TPM2_SHA256_DIGEST_SIZE;
+			continue; /* skip validation */
+		}
+		if (memcmp(expected, result, TPM2_SHA256_DIGEST_SIZE)) {
+			efi_st_printf("PCR[%d] is not the expected value\n", i);
+			return EFI_ST_FAILURE;
+		}
+		expected += TPM2_SHA256_DIGEST_SIZE;
+		result += TPM2_SHA256_DIGEST_SIZE;
+	}
 
 	return EFI_ST_SUCCESS;
 }
@@ -31,7 +680,8 @@ static int efi_st_tcg2_setup(const efi_handle_t img_handle,
 /**
  * efi_st_tcg2_execute() - execute test
  *
- * Call the GetCapability service of the EFI_TCG2_PROTOCOL.
+ * Call EFI_TCG2_PROTOCOL services and check the
+ * Measured Boot behavior.
  *
  * Return:	status code
  */
@@ -40,12 +690,22 @@ static int efi_st_tcg2_execute(void)
 	struct efi_tcg2_protocol *tcg2;
 	struct efi_tcg2_boot_service_capability capability;
 	efi_status_t ret;
+	u32 active_pcr_banks;
+	u64 eventlog, eventlog_last_entry;
+	bool eventlog_truncated;
+	efi_handle_t handle;
+	efi_uintn_t exit_data_size = 0;
+	u16 *exit_data = NULL;
+	u32 i;
+	u32 manufacturer_id;
 
 	ret = boottime->locate_protocol(&guid_tcg2, NULL, (void **)&tcg2);
 	if (ret != EFI_SUCCESS) {
 		efi_st_error("TCG2 protocol is not available.\n");
 		return EFI_ST_FAILURE;
 	}
+
+	/* EFI_TCG2_PROTOCOL.GetCapability test */
 	capability.size = sizeof(struct efi_tcg2_boot_service_capability) - 1;
 	ret = tcg2->get_capability(tcg2, &capability);
 	if (ret != EFI_BUFFER_TOO_SMALL) {
@@ -64,12 +724,154 @@ static int efi_st_tcg2_execute(void)
 	}
 	efi_st_printf("TPM supports 0x%.8x event logs\n",
 		      capability.supported_event_logs);
+
+	/* EFI_TCG2_PROTOCOL.GetActivePcrBanks test */
+	ret = tcg2->get_active_pcr_banks(tcg2, &active_pcr_banks);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("tcg2->get_active_pcr_banks failed\n");
+		return EFI_ST_FAILURE;
+	}
+	if (active_pcr_banks != capability.active_pcr_banks) {
+		efi_st_error("tcg2->get_active_pcr_banks return wrong value\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* EFI_TCG2_PROTOCOL.HashLogExtendEvent test */
+	ret = tcg2->hash_log_extend_event(tcg2, EFI_TCG2_EXTEND_ONLY,
+					  (uintptr_t)image,
+					  img.length, efi_tcg2_event);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("tcg2->hash_log_extend_event(EXTEND_ONLY) failed\n");
+		return EFI_ST_FAILURE;
+	}
+
+	ret = tcg2->hash_log_extend_event(tcg2, PE_COFF_IMAGE, (uintptr_t)image,
+					  img.length, efi_tcg2_event);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("tcg2->hash_log_extend_event(PE_COFF_IMAGE) failed\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* EFI_TCG2_PROTOCOL.SubmitCommand test */
+	ret = get_manufacturer_id(tcg2, &manufacturer_id);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("get_manufacturer_id failed\n");
+		return EFI_ST_FAILURE;
+	}
+	if (capability.manufacturer_id != manufacturer_id) {
+		efi_st_error("tcg2->submit_command test failed\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* tcg2_measure_pe_image test */
+	ret = boottime->load_image(false, image_handle, NULL, image,
+				   img.length, &handle);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to load image\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* measure ready_to_boot event(boot variables, smbios table, etc.) */
+	/* TODO: add GPT measurement test */
+	ret = boottime->start_image(handle, &exit_data_size, &exit_data);
+	if (ret != EFI_UNSUPPORTED) {
+		efi_st_error("Wrong return value from application\n");
+		return EFI_ST_FAILURE;
+	}
+	ret = boottime->free_pool(exit_data);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("Failed to free exit data\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* validate PCR read from the TPM device */
+	for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {
+		ret = read_pcr(tcg2, i);
+		if (ret != EFI_SUCCESS) {
+			efi_st_error("read pcr error\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+	if (validate_pcrs()) {
+		efi_st_error("PCR validation failed\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/* EFI_TCG2_PROTOCOL.GetEventLog test */
+	ret = tcg2->get_eventlog(tcg2, TCG2_EVENT_LOG_FORMAT_TCG_2, &eventlog,
+				 &eventlog_last_entry, &eventlog_truncated);
+	if (ret != EFI_SUCCESS) {
+		efi_st_error("tcg2->get_eventlog failed\n");
+		return EFI_ST_FAILURE;
+	}
+	/* TODO: eventlog format check */
+
 	return EFI_ST_SUCCESS;
 }
 
+/*
+ * Tear down unit test.
+ *
+ * @return:	EFI_ST_SUCCESS for success
+ */
+static int efi_st_tcg2_teardown(void)
+{
+	efi_status_t r = EFI_ST_SUCCESS;
+
+	if (image) {
+		r = boottime->free_pool(image);
+		if (r != EFI_SUCCESS) {
+			efi_st_error("Failed to free image\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+	if (efi_tcg2_event) {
+		r = boottime->free_pool(efi_tcg2_event);
+		if (r != EFI_SUCCESS) {
+			efi_st_error("Failed to free efi_tcg2_event\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+	if (pcrs) {
+		r = boottime->free_pool(pcrs);
+		if (r != EFI_SUCCESS) {
+			efi_st_error("Failed to free pcr\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	r = restore_boot_variable();
+	if (r != EFI_SUCCESS) {
+		efi_st_error("Failed to restore boot variables\n");
+		return EFI_ST_FAILURE;
+	}
+
+	/*
+	 * Restore SMBIOS table
+	 * If orig_smbios_table is NULL, calling install_configuration_table()
+	 * removes dummy SMBIOS table form systab.
+	 */
+	r = boottime->install_configuration_table(&smbios_guid, orig_smbios_table);
+	if (r != EFI_SUCCESS) {
+		efi_st_error("Failed to restore SMBOIS table\n");
+		return EFI_ST_FAILURE;
+	}
+
+	if (dmi_addr) {
+		r = boottime->free_pages(dmi_addr, 1);
+		if (r != EFI_SUCCESS) {
+			efi_st_error("Failed to free dummy smbios table\n");
+			return EFI_ST_FAILURE;
+		}
+	}
+
+	return r;
+}
+
 EFI_UNIT_TEST(tcg2) = {
 	.name = "tcg2",
 	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
 	.execute = efi_st_tcg2_execute,
 	.setup = efi_st_tcg2_setup,
+	.teardown = efi_st_tcg2_teardown,
 };
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/2] efi_loader: add missing const qualifier
  2021-10-22 11:24 ` [PATCH 1/2] efi_loader: add missing const qualifier Masahisa Kojima
@ 2021-10-23  8:40   ` Heinrich Schuchardt
  2021-10-23 17:21     ` Ilias Apalodimas
  0 siblings, 1 reply; 16+ messages in thread
From: Heinrich Schuchardt @ 2021-10-23  8:40 UTC (permalink / raw)
  To: Masahisa Kojima, u-boot; +Cc: Ilias Apalodimas, Simon Glass, Alexander Graf

On 10/22/21 13:24, Masahisa Kojima wrote:
> This commit fixes the following compilation warning
> of boottime->install_configuration_table() function.
>
> ---
> lib/efi_selftest/efi_selftest_tcg2.c:475:46:
> warning: passing argument 1 of ‘boottime->install_configuration_table’
> discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
>    ret = boottime->install_configuration_table(&smbios_guid, dmi);
> ---
>
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>

The first --- separates the commit message from the rest of the patch:

$ scripts/checkpatch.pl 0001-efi_loader-add-missing-const-qualifier.patch
ERROR: Missing Signed-off-by: line by nominal patch author 'Masahisa
Kojima <masahisa.kojima@linaro.org>'

I will reformat the commit message when merging.

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

> ---
>   include/efi_api.h             | 2 +-
>   lib/efi_loader/efi_boottime.c | 5 +++--
>   2 files changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/include/efi_api.h b/include/efi_api.h
> index c8f959bb72..0accad08c8 100644
> --- a/include/efi_api.h
> +++ b/include/efi_api.h
> @@ -120,7 +120,7 @@ struct efi_boot_services {
>   			struct efi_device_path **device_path,
>   			efi_handle_t *device);
>   	efi_status_t (EFIAPI *install_configuration_table)(
> -			efi_guid_t *guid, void *table);
> +			const efi_guid_t *guid, void *table);
>
>   	efi_status_t (EFIAPI *load_image)(bool boot_policiy,
>   			efi_handle_t parent_image,
> diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
> index bf5661e1ee..1823990d9b 100644
> --- a/lib/efi_loader/efi_boottime.c
> +++ b/lib/efi_loader/efi_boottime.c
> @@ -1692,8 +1692,9 @@ out:
>    *
>    * Return: status code
>    */
> -static efi_status_t EFIAPI efi_install_configuration_table_ext(efi_guid_t *guid,
> -							       void *table)
> +static efi_status_t
> +EFIAPI efi_install_configuration_table_ext(const efi_guid_t *guid,
> +					   void *table)
>   {
>   	EFI_ENTRY("%pUl, %p", guid, table);
>   	return EFI_EXIT(efi_install_configuration_table(guid, table));
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-10-22 11:24 ` [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot Masahisa Kojima
@ 2021-10-23  9:42   ` Heinrich Schuchardt
  2021-10-25  7:59     ` Masahisa Kojima
  0 siblings, 1 reply; 16+ messages in thread
From: Heinrich Schuchardt @ 2021-10-23  9:42 UTC (permalink / raw)
  To: Masahisa Kojima; +Cc: Ilias Apalodimas, Simon Glass, Alexander Graf, u-boot



On 10/22/21 13:24, Masahisa Kojima wrote:
> This commit adds the missing EFI_TCG2_PROTOCOL selftest
> and Measured Boot selftest in lib/efi_selftest.
>
> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> ---
>   lib/efi_selftest/Makefile                     |  10 +
>   .../efi_selftest_miniapp_measuredboot.c       |  93 ++
>   lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
>   3 files changed, 906 insertions(+), 1 deletion(-)
>   create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>
> diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
> index 9ff6e1760c..09950ee028 100644
> --- a/lib/efi_selftest/Makefile
> +++ b/lib/efi_selftest/Makefile
> @@ -14,6 +14,8 @@ CFLAGS_efi_selftest_miniapp_exception.o := $(CFLAGS_EFI) -Os -ffreestanding
>   CFLAGS_REMOVE_efi_selftest_miniapp_exception.o := $(CFLAGS_NON_EFI)
>   CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
>   CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI)
> +CFLAGS_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_EFI) -Os -ffreestanding
> +CFLAGS_REMOVE_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_NON_EFI)
>   CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
>   CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI)
>   CFLAGS_initrddump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
> @@ -78,9 +80,11 @@ obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o
>   targets += \
>   efi_miniapp_file_image_exception.h \
>   efi_miniapp_file_image_exit.h \
> +efi_miniapp_file_image_measuredboot.h \
>   efi_miniapp_file_image_return.h \
>   efi_selftest_miniapp_exception.efi \
>   efi_selftest_miniapp_exit.efi \
> +efi_selftest_miniapp_measuredboot.efi \
>   efi_selftest_miniapp_return.efi
>
>   ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
> @@ -99,6 +103,10 @@ $(obj)/efi_miniapp_file_image_exit.h: $(obj)/efi_selftest_miniapp_exit.efi
>   	$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exit.efi > \
>   	$(obj)/efi_miniapp_file_image_exit.h
>
> +$(obj)/efi_miniapp_file_image_measuredboot.h: $(obj)/efi_selftest_miniapp_measuredboot.efi
> +	$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_measuredboot.efi > \
> +	$(obj)/efi_miniapp_file_image_measuredboot.h
> +
>   $(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi
>   	$(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
>   	$(obj)/efi_miniapp_file_image_return.h
> @@ -112,3 +120,5 @@ $(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h
>   $(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
>
>   $(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
> +
> +$(obj)/efi_selftest_tcg2.o: $(obj)/efi_miniapp_file_image_measuredboot.h
> diff --git a/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c

Thank you for going the extra mile and adding the test.

Which image is actually loaded seems to be irrelevant for the test. Can
we reuse an existing one, e.g. efi_miniapp_file_image_return.h?

I guess the PCR related to the loaded image is not checked as it will
depend on the build tools and date.

> new file mode 100644
> index 0000000000..926713c1c2
> --- /dev/null
> +++ b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
> @@ -0,0 +1,93 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * efi_selftest_miniapp_measuredboot
> + *
> + * Copyright (c) 2018 Heinrich Schuchardt
> + * Copyright (c) 2021 Masahisa Kojima
> + *
> + * This EFI application is run by the StartImage selftest.

This is incorrect due to copy and paste.

> + * It uses the Exit boot service to return and used for
> + * Measured Boot selftest.
> + */
> +
> +#include <common.h>
> +#include <efi_selftest.h>
> +
> +static efi_guid_t loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
> +
> +/**
> + * check_loaded_image_protocol() - check image_base/image_size
> + *
> + * Try to open the loaded image protocol. Check that this function is located
> + * between image_base and image_base + image_size.
> + *
> + * @image_handle:	handle of the loaded image
> + * @systable:		system table
> + * @return:		status code
> + */
> +static efi_status_t EFIAPI check_loaded_image_protocol
> +		(efi_handle_t image_handle, struct efi_system_table *systable)
> +{
> +	struct efi_simple_text_output_protocol *cout = systable->con_out;
> +	struct efi_boot_services *boottime = systable->boottime;
> +	struct efi_loaded_image *loaded_image_protocol;
> +	efi_status_t ret;
> +
> +	/*
> +	 * Open the loaded image protocol.
> +	 */
> +	ret = boottime->open_protocol
> +				(image_handle, &loaded_image_protocol_guid,
> +				 (void **)&loaded_image_protocol, NULL,
> +				  NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> +	if (ret != EFI_SUCCESS) {
> +		cout->output_string(cout,
> +				    L"Could not open loaded image protocol");
> +		return ret;
> +	}
> +	if ((void *)check_loaded_image_protocol <
> +	    loaded_image_protocol->image_base ||
> +	    (void *)check_loaded_image_protocol >=
> +	    loaded_image_protocol->image_base +
> +	    loaded_image_protocol->image_size) {
> +		cout->output_string(cout,
> +				    L"Incorrect image_base or image_size\n");
> +		return EFI_NOT_FOUND;
> +	}
> +	return EFI_SUCCESS;
> +}
> +
> +/**
> + * Entry point of the EFI application.
> + *
> + * @handle:	handle of the loaded image
> + * @systable:	system table
> + * @return:	status code
> + */
> +efi_status_t EFIAPI efi_main(efi_handle_t handle,
> +			     struct efi_system_table *systable)
> +{
> +	struct efi_simple_text_output_protocol *con_out = systable->con_out;
> +	efi_status_t ret;
> +	u16 text[] = EFI_ST_SUCCESS_STR;
> +
> +	con_out->output_string(con_out, L"EFI application calling Exit\n");
> +
> +	if (check_loaded_image_protocol(handle, systable) != EFI_SUCCESS) {
> +		con_out->output_string(con_out,
> +				       L"Loaded image protocol missing\n");
> +		ret = EFI_NOT_FOUND;
> +		goto out;
> +	}
> +
> +	/* This return value is expected by the calling test */
> +	ret = EFI_UNSUPPORTED;
> +out:
> +	systable->boottime->exit(handle, ret, sizeof(text), text);
> +
> +	/*
> +	 * This statement should not be reached.
> +	 * To enable testing use a different return value.
> +	 */
> +	return EFI_SUCCESS;
> +}
> diff --git a/lib/efi_selftest/efi_selftest_tcg2.c b/lib/efi_selftest/efi_selftest_tcg2.c
> index 1399309cec..50de735f5e 100644
> --- a/lib/efi_selftest/efi_selftest_tcg2.c
> +++ b/lib/efi_selftest/efi_selftest_tcg2.c
> @@ -9,10 +9,495 @@
>
>   #include <efi_selftest.h>
>   #include <efi_tcg2.h>
> +/* Include containing the miniapp.efi application */
> +#include "efi_miniapp_file_image_measuredboot.h"

efi_miniapp_file_image_return.h

> +
> +#include <linux/unaligned/access_ok.h>
> +#include <mapmem.h>
> +#include <smbios.h>
> +#include <tables_csum.h>
>
>   static struct efi_boot_services *boottime;
>   static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
>
> +/* Block size of compressed disk image */
> +#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
> +
> +static efi_handle_t image_handle;
> +/* Decompressed file image */
> +static u8 *image;
> +
> +/* One 8 byte block of the compressed disk image */
> +struct line {
> +	size_t addr;
> +	char *line;
> +};
> +
> +/* Compressed file image */
> +struct compressed_file_image {
> +	size_t length;
> +	struct line lines[];
> +};
> +
> +static struct compressed_file_image img = EFI_ST_DISK_IMG;
> +
> +static struct efi_tcg2_event *efi_tcg2_event;
> +
> +static struct efi_runtime_services *runtime;
> +#define BOOT_NAME_1000 u"Boot1000"
> +#define BOOT_NAME_1001 u"Boot1001"
> +#define BOOT_NAME_1002 u"Boot1002"
> +
> +#define DEFAULT_ATTR (EFI_VARIABLE_NON_VOLATILE | \
> +		      EFI_VARIABLE_BOOTSERVICE_ACCESS | \
> +		      EFI_VARIABLE_RUNTIME_ACCESS)
> +
> +/* "efidebug boot add -b 1000 test1000 virtio 0:1 /EFI/debian/grubaa64.efi" */
> +static const u8 boot_1000[] = {
> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
> +0x74, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
> +0xff, 0x04, 0x00 };
> +
> +/* "efidebug boot add -b 1001 test1001 virtio 0:1 /EFI/debian/grubaa64.efi" */
> +static const u8 boot_1001[] = {
> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
> +0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
> +0xff, 0x04, 0x00 };
> +
> +/* "efidebug boot add -b 1002 test1002 virtio 0:1 /EFI/debian/grubaa64.efi" */
> +static const u8 boot_1002[] = {
> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
> +0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
> +0xff, 0x04, 0x00};
> +
> +/* "efidebug boot order 1002 1000 1001" */
> +static u8 boot_order[] = {0x02, 0x10, 0x00, 0x10, 0x01, 0x10};
> +
> +static void *orig_smbios_table;
> +static u64 dmi_addr = U32_MAX;
> +#define SMBIOS_ENTRY_HEADER_SIZE 0x20
> +/* smbios table for the measurement test */
> +static u8 smbios_table_test[] = {
> +0x5f, 0x53, 0x4d, 0x5f, 0x2c, 0x1f, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00,
> +0x00, 0x00, 0x00, 0x00, 0x5f, 0x44, 0x4d, 0x49, 0x5f, 0xe4, 0x5c, 0x01,
> +0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
> +0x01, 0x02, 0x00, 0x00, 0x03, 0x00, 0x80, 0x08, 0x01, 0x00, 0x00, 0x00,
> +0x00, 0x00, 0x00, 0x0c, 0x15, 0x0a, 0xff, 0xff, 0x55, 0x2d, 0x42, 0x6f,
> +0x6f, 0x74, 0x00, 0x32, 0x30, 0x32, 0x31, 0x2e, 0x31, 0x30, 0x2d, 0x72,
> +0x63, 0x34, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x35, 0x2d, 0x67, 0x37, 0x32,
> +0x37, 0x63, 0x33, 0x66, 0x33, 0x32, 0x35, 0x39, 0x2d, 0x64, 0x69, 0x72,
> +0x74, 0x79, 0x00, 0x31, 0x30, 0x2f, 0x30, 0x31, 0x2f, 0x32, 0x30, 0x32,
> +0x31, 0x00, 0x00, 0x01, 0x1b, 0x01, 0x00, 0x01, 0x02, 0x00, 0x03, 0x31,
> +0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
> +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
> +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
> +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
> +0x37, 0x38, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x00, 0x01, 0x02, 0x00, 0x04,
> +0x03, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
> +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
> +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
> +0x33, 0x33, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00,
> +0x00, 0x03, 0x15, 0x03, 0x00, 0x01, 0x03, 0x00, 0x02, 0x03, 0x03, 0x03,
> +0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6e,
> +0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
> +0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00,
> +0x00, 0x04, 0x30, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00,
> +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
> +0x00, 0x01, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x03, 0x04,
> +0x04, 0x04, 0x08, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01,
> +0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33,
> +0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
> +0x33, 0x33, 0x00, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x00,
> +0x00, 0x20, 0x0b, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +0x00, 0x00, 0x7f, 0x04, 0x06, 0x00, 0x00, 0x00
> +};
> +
> +#define TPM2_CMD_BUF_SIZE 64
> +/* TPM command is big endian */
> +#define __MSB(x) ((x) >> 8)
> +#define __LSB(x) ((x) & 0xFF)
> +#define tpm_u16(x) __MSB(x), __LSB(x)
> +#define tpm_u32(x) tpm_u16((x) >> 16), tpm_u16((x) & 0xFFFF)
> +#define TPM2_PCR_READ_HEADER_SIZE 30
> +
> +static u8 *pcrs;
> +static u8 expected_pcrs[EFI_TCG2_MAX_PCR_INDEX + 1][TPM2_SHA256_DIGEST_SIZE] = {
> +	{0x91, 0x21, 0x37, 0xc7, 0x1a, 0x49, 0x19, 0xc8,
> +	 0xf1, 0xfb, 0xa9, 0x84, 0x5c, 0x65, 0xa9, 0xdd,
> +	 0x7b, 0xb9, 0xfe, 0xa1, 0xcd, 0x64, 0x49, 0xdd,
> +	 0xed, 0xe2, 0x65, 0x82, 0xc5, 0x3e, 0xf4, 0xc4},
> +
> +	{0xf5, 0x79, 0xf3, 0x20, 0x62, 0x6e, 0x8b, 0x58,
> +	 0x62, 0xa3, 0x4e, 0x2f, 0xb7, 0x10, 0xac, 0x34,
> +	 0x4e, 0x68, 0x94, 0x37, 0x87, 0x29, 0xc4, 0xbe,
> +	 0xa3, 0xc4, 0xd9, 0x14, 0x2b, 0x66, 0x79, 0x9b},
> +
> +	{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
> +	 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
> +	 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
> +	 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
> +
> +	{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
> +	 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
> +	 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
> +	 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
> +
> +	{0xbe, 0xea, 0xdc, 0xe0, 0x44, 0x5b, 0x5f, 0x14,
> +	 0xef, 0x24, 0x5d, 0x13, 0x15, 0xfe, 0x41, 0x86,
> +	 0xc2, 0xd5, 0xdc, 0x0d, 0x04, 0x2f, 0xd4, 0x04,
> +	 0x0d, 0x02, 0x62, 0xc0, 0x34, 0x80, 0xee, 0xd5},
> +
> +	{0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
> +	 0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
> +	 0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
> +	 0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
> +
> +	{0x8d, 0x28, 0xde, 0x72, 0x22, 0x3e, 0x88, 0x1a,
> +	 0x37, 0xfa, 0x47, 0x12, 0x68, 0x45, 0xdf, 0x71,
> +	 0x50, 0x8f, 0xab, 0x59, 0x50, 0x7b, 0x52, 0x32,
> +	 0xa6, 0xaa, 0x03, 0x3d, 0x4e, 0x22, 0x89, 0xd7},
> +
> +	{0x96, 0x74, 0xae, 0xcd, 0x3f, 0x40, 0xb4, 0xa9,
> +	 0x36, 0xae, 0x19, 0xc8, 0x84, 0x8a, 0xb9, 0x5a,
> +	 0x87, 0x99, 0xd8, 0x89, 0x7f, 0xfc, 0x40, 0x48,
> +	 0x05, 0x99, 0x65, 0x2e, 0x55, 0xd4, 0x93, 0x32},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +
> +	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> +
> +	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> +
> +	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> +
> +	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> +
> +	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> +
> +	{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +	 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> +
> +	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> +	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> +};
> +
> +struct boot_variable {
> +	u16 name[16];
> +	u8 *buf;
> +	efi_uintn_t size;
> +	u32 attr;
> +	const u8 *test_data;
> +	efi_uintn_t test_data_size;
> +};
> +
> +static struct boot_variable boot_variable_test[] = {
> +	{u"BootOrder",		NULL, 0, DEFAULT_ATTR, boot_order, sizeof(boot_order)},
> +	{BOOT_NAME_1000,	NULL, 0, DEFAULT_ATTR, boot_1000, sizeof(boot_1000)},
> +	{BOOT_NAME_1001,	NULL, 0, DEFAULT_ATTR, boot_1001, sizeof(boot_1001)},
> +	{BOOT_NAME_1002,	NULL, 0, DEFAULT_ATTR, boot_1002, sizeof(boot_1002)},
> +};
> +
> +/*
> + * Decompress the disk image.
> + *
> + * @image	decompressed disk image
> + * @return	status code
> + */
> +static efi_status_t decompress(u8 **image)
> +{
> +	u8 *buf;
> +	size_t i;
> +	size_t addr;
> +	size_t len;
> +	efi_status_t ret;
> +
> +	ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
> +				      (void **)&buf);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("Out of memory\n");
> +		return ret;
> +	}
> +	boottime->set_mem(buf, img.length, 0);
> +
> +	for (i = 0; ; ++i) {
> +		if (!img.lines[i].line)
> +			break;
> +		addr = img.lines[i].addr;
> +		len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
> +		if (addr + len > img.length)
> +			len = img.length - addr;
> +		boottime->copy_mem(buf + addr, img.lines[i].line, len);
> +	}
> +	*image = buf;
> +	return ret;
> +}
> +
> +/*
> + * Configure dummy boot variables.

/**
  * efi_status_t setup_boot_variable() - configure dummy boot variables
  *
  * Preexisting variable values are saved and will be restored by
  * calling restore_boot_variable().
  *

> + *
> + * @return	status code
> + */
> +static efi_status_t setup_boot_variable(void)
> +{
> +	efi_status_t ret;
> +	u32 i;
> +	efi_uintn_t size;
> +	u8 dummy;

This variable is superfluous.

> +
> +	for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
> +		size = 1;

Please, set size to 0.

> +		ret = runtime->get_variable(boot_variable_test[i].name,
> +					    &efi_global_variable_guid,
> +					    &boot_variable_test[i].attr,
> +					    &size,
> +					    &dummy);

Instead of dummy you can use NULL if size = 0.

> +		if (ret == EFI_BUFFER_TOO_SMALL) {
> +			/* Variable exists, save the current vaiable */

%s/vaiable/value/

> +			boot_variable_test[i].size = size;
> +			ret = boottime->allocate_pool(EFI_LOADER_DATA,
> +						      boot_variable_test[i].size,
> +						      (void **)&boot_variable_test[i].buf);
> +			if (ret != EFI_SUCCESS) {
> +				efi_st_error("fail to allocate buffer for boot variable\n");

In all other tests we use 'Failed to'

%s/fail/Failed/

> +				return ret;
> +			}
> +			ret = runtime->get_variable(boot_variable_test[i].name,
> +						    &efi_global_variable_guid,
> +						    &boot_variable_test[i].attr,
> +						    &boot_variable_test[i].size,
> +						    boot_variable_test[i].buf);
> +			if (ret != EFI_SUCCESS) {
> +				efi_st_error("fail to get current boot variable\n");

%s/fail/Failed/


> +				return ret;
> +			}
> +		}
> +
> +		/* set boot variable for the measurement test */
> +		ret = runtime->set_variable(boot_variable_test[i].name,
> +					    &efi_global_variable_guid,
> +					    boot_variable_test[i].attr,
> +					    boot_variable_test[i].test_data_size,
> +					    boot_variable_test[i].test_data);
> +		if (ret != EFI_SUCCESS) {
> +			efi_st_error("### fail to set test boot variable(%d)n", i);

%s/### fail/Failed/

> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +/*

/**
  * efi_status_t restore_boot_variable() - restore original values
  *
  * Restore the variable values saved in setup_boot_variable().
  *

> + * Restore original boot variables.
> + *
> + * @return	status code
> + */
> +efi_status_t restore_boot_variable(void)
> +{
> +	int i;
> +	efi_status_t ret;
> +
> +	for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
> +		if (boot_variable_test[i].buf) {
> +			ret = runtime->set_variable(boot_variable_test[i].name,
> +						    &efi_global_variable_guid,
> +						    boot_variable_test[i].attr,
> +						    boot_variable_test[i].size,
> +						    boot_variable_test[i].buf);
> +			if (ret != EFI_SUCCESS) {
> +				efi_st_error("### fail to restore boot variable\n");
> +				return ret;
> +			}
> +			ret = boottime->free_pool(boot_variable_test[i].buf);
> +			if (ret != EFI_SUCCESS) {
> +				efi_st_error("Failed to free boot variable\n");
> +				return ret;
> +			}
> +		} else {
> +			/* delete the variable used only for testing */
> +			ret = runtime->set_variable(boot_variable_test[i].name,
> +						    &efi_global_variable_guid,
> +						    0, 0, NULL);
> +			if (ret != EFI_SUCCESS) {
> +				efi_st_error("### fail to delete boot variable\n");

%s/### fail/Failed/

> +				return ret;
> +			}
> +		}
> +	}
> +
> +	return EFI_SUCCESS;
> +}
> +
> +/**
> + * Find smbios table
> + *
> + * @systable	system table
> + * @return	status code
> + */
> +static void *find_smbios_table(const struct efi_system_table *systable)
> +{
> +	u32 i;
> +
> +	for (i = 0; i < systable->nr_tables; i++) {
> +		if (!guidcmp(&smbios_guid, &systable->tables[i].guid))
> +			return systable->tables[i].table;
> +	}
> +
> +	return NULL;
> +}
> +
> +/**
> + * Prepare the dummy SMBIOS table
> + *
> + * @systable	system table
> + * @return	status code
> + */
> +efi_status_t setup_smbios_table(const struct efi_system_table *systable)
> +{
> +	struct smbios_entry *se;
> +	efi_status_t ret;
> +	/* Map within the low 32 bits, to allow for 32bit SMBIOS tables */
> +	void *dmi;
> +	char *istart;
> +	int isize;
> +
> +	if (sizeof(smbios_table_test) > EFI_PAGE_SIZE)
> +		return EFI_OUT_OF_RESOURCES;
> +
> +	orig_smbios_table = find_smbios_table(systable);
> +
> +	/* Reserve 4kiB page for SMBIOS */
> +	ret = boottime->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
> +				 EFI_RUNTIME_SERVICES_DATA, 1, &dmi_addr);
> +
> +	if (ret != EFI_SUCCESS) {
> +		/* Could not find space in lowmem, use highmem instead */
> +		ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> +					 EFI_RUNTIME_SERVICES_DATA, 1,
> +					 &dmi_addr);
> +
> +		if (ret != EFI_SUCCESS)
> +			return ret;
> +	}
> +
> +	dmi = (void *)(uintptr_t)dmi_addr;
> +	se = dmi;
> +	boottime->copy_mem(se, smbios_table_test, sizeof(smbios_table_test));
> +
> +	/* update smbios table start address */
> +	se->struct_table_address = (uintptr_t)((u8 *)dmi + SMBIOS_ENTRY_HEADER_SIZE);
> +
> +	/* calculate checksums */
> +	istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
> +	isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
> +	se->intermediate_checksum = table_compute_checksum(istart, isize);
> +	se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
> +
> +	/* Install SMBIOS information as configuration table */
> +	ret = boottime->install_configuration_table(&smbios_guid, dmi);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("Cannot install SMBIOS table\n");
> +		boottime->free_pages(dmi_addr, 1);
> +	}
> +
> +	return ret;
> +}
> +
>   /**
>    * efi_st_tcg2_setup() - setup test
>    *
> @@ -23,7 +508,171 @@ static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
>   static int efi_st_tcg2_setup(const efi_handle_t img_handle,
>   			     const struct efi_system_table *systable)
>   {
> +	efi_status_t ret;
> +	struct uefi_image_load_event image_load_event;
> +
> +	image_handle = img_handle;
>   	boottime = systable->boottime;
> +	runtime = systable->runtime;
> +
> +	/* Load the application image into memory */
> +	decompress(&image);
> +
> +	ret = boottime->allocate_pool(EFI_LOADER_DATA,
> +				      sizeof(struct efi_tcg2_event) +
> +				      sizeof(struct uefi_image_load_event),
> +				      (void **)&efi_tcg2_event);
> +	if (!efi_tcg2_event)
> +		return EFI_ST_FAILURE;
> +
> +	efi_tcg2_event->size = sizeof(struct efi_tcg2_event) +
> +			       sizeof(struct uefi_image_load_event);
> +	efi_tcg2_event->header.header_size = sizeof(struct efi_tcg2_event_header);
> +	efi_tcg2_event->header.header_version = 1;
> +	efi_tcg2_event->header.pcr_index = 6;
> +	efi_tcg2_event->header.event_type = EV_EFI_RUNTIME_SERVICES_DRIVER;
> +	image_load_event.image_location_in_memory = 0x12345678;
> +	image_load_event.image_length_in_memory = 0x300000;
> +	image_load_event.image_link_time_address = 0x87654321;
> +	image_load_event.length_of_device_path = 0;
> +	boottime->copy_mem(efi_tcg2_event->event, &image_load_event,
> +			   sizeof(struct uefi_image_load_event));
> +
> +	ret = setup_boot_variable();
> +	if (ret != EFI_SUCCESS)
> +		return EFI_ST_FAILURE;
> +
> +	ret = setup_smbios_table(systable);
> +	if (ret != EFI_SUCCESS)
> +		return EFI_ST_FAILURE;
> +
> +	ret = boottime->allocate_pool(EFI_LOADER_DATA,
> +				      (EFI_TCG2_MAX_PCR_INDEX + 1) *
> +				      TPM2_SHA256_DIGEST_SIZE,
> +				      (void **)&pcrs);
> +	if (!pcrs)
> +		return EFI_ST_FAILURE;
> +
> +	boottime->set_mem(pcrs, (EFI_TCG2_MAX_PCR_INDEX + 1) * TPM2_SHA256_DIGEST_SIZE, 0);
> +
> +	return EFI_ST_SUCCESS;
> +}
> +
> +/**
> + * Get manufacturer_id through submit_command API
> + *
> + * @tcg2		tcg2 protocol
> + * @manufacturer_id	pointer to the manufacturer_id
> + * @return		status code
> + */
> +static efi_status_t get_manufacturer_id(struct efi_tcg2_protocol *tcg2, u32 *manufacturer_id)
> +{
> +	efi_status_t ret;
> +	u8 cmd[TPM2_CMD_BUF_SIZE] = {
> +		tpm_u16(TPM2_ST_NO_SESSIONS),		/* TAG */
> +		tpm_u32(22),				/* Length */
> +		tpm_u32(TPM2_CC_GET_CAPABILITY),	/* Command code */
> +
> +		tpm_u32(TPM2_CAP_TPM_PROPERTIES),	/* Capability */
> +		tpm_u32(TPM2_PT_MANUFACTURER),		/* Property */
> +		tpm_u32(1),			/* Property count */
> +	};
> +	u8 resp[TPM2_CMD_BUF_SIZE];
> +	unsigned int value_off;
> +
> +	ret = tcg2->submit_command(tcg2, 22, cmd,
> +				   TPM2_CMD_BUF_SIZE, resp);
> +	if (ret != EFI_SUCCESS)
> +		return ret;
> +
> +	/*
> +	 * In the response buffer, the properties are located after the:
> +	 * tag (u16), response size (u32), response code (u32),
> +	 * YES/NO flag (u8), TPM_CAP (u32).
> +	 * The value is located after count (u32), property (u32).
> +	 */
> +	value_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
> +			 sizeof(u8) + sizeof(u32) + sizeof(u32) + sizeof(u32);
> +	*manufacturer_id = get_unaligned_be32(&resp[value_off]);
> +
> +	return ret;
> +}
> +
> +/**
> + * Read the PCR from the TPM device
> + *
> + * @tcg2	tcg2 protocol
> + * @idx		pcr index to read
> + * @return	status code
> + */
> +static efi_status_t read_pcr(struct efi_tcg2_protocol *tcg2, u32 idx)
> +{
> +	efi_status_t ret;
> +	u8 idx_array_sz = 3; /* support 24 PCRs */

This is a constant.

#define IDX_ARRAY_SZ 3

You can move it close to the TPM2_CMD_BUF_SIZE definition.

> +	u32 cmd_len = 17 + idx_array_sz;
> +	u8 cmd[TPM2_CMD_BUF_SIZE] = {
> +		tpm_u16(TPM2_ST_NO_SESSIONS),	/* TAG */
> +		tpm_u32(cmd_len),		/* Length */
> +		tpm_u32(TPM2_CC_PCR_READ),	/* Command code */
> +		/* TPML_PCR_SELECTION */
> +		tpm_u32(1),			/* Number of selections */
> +		tpm_u16(TPM2_ALG_SHA256),	/* Algorithm of the hash */
> +		idx_array_sz,			/* Array size for selection */
> +		/* bitmap(idx),			   Selected PCR bitmap */
> +	};
> +	u8 resp[TPM2_CMD_BUF_SIZE];
> +	u32 pcr_sel_idx = idx / 8;
> +	u8 pcr_sel_bit = BIT(idx % 8);
> +	u8 *dst;
> +
> +	cmd[17 + pcr_sel_idx] = pcr_sel_bit;
> +	ret = tcg2->submit_command(tcg2, cmd_len, cmd,
> +				   TPM2_CMD_BUF_SIZE, resp);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("tcg2->submit_command fail to read PCR\n");
> +		return ret;
> +	}
> +
> +	dst = pcrs + (idx * TPM2_SHA256_DIGEST_SIZE);
> +	boottime->copy_mem(dst, &resp[TPM2_PCR_READ_HEADER_SIZE],
> +			   TPM2_SHA256_DIGEST_SIZE);
> +
> +	return ret;
> +}
> +
> +/**
> + * Compare the expected and actual pcrs
> + *
> + * @return	status code
> + */
> +static int validate_pcrs(void)
> +{
> +	u32 i;
> +	u8 *expected = (u8 *)expected_pcrs;
> +	u8 *result = pcrs;

Making expected_pcrs and pcrs arrays with elements of size
TPM2_SHA256_DIGEST_SIZE can replace these pointers.

> +
> +	/*
> +	 *  - Skip PCR[0] validation. PCR[0] contains U-Boot version measurement
> +	 *    it contains the commit hash, so the measurement varies every build
> +	 *    with different commit hash.
> +	 *  - Skip PCR[7] validation. PCR[7] contains UEFI Secure Boot variables
> +	 *    measurement. These variables can not be updated through efi_selftest and
> +	 *    it varies depending on the platform.

%s/it varies/vary/

> +	 */
> +	for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {

for (i = 1; i < (EFI_TCG2_MAX_PCR_INDEX + 1); ++i) {
   if (i != 7)
	continue;
   if (memcmp(pcr[i], expected_pcr[i], PM2_SHA256_DIGEST_SIZE)) {
     if (memcmp(expected, result, TPM2_SHA256_DIGEST_SIZE)) {
       efi_st_printf("PCR[%d] is not the expected value\n", i);
       return EFI_ST_FAILURE;
     }
   }
}

> +		result = pcrs + (TPM2_SHA256_DIGEST_SIZE * i);
> +		if (i == 0 || i == 7) {
> +			expected += TPM2_SHA256_DIGEST_SIZE;
> +			result += TPM2_SHA256_DIGEST_SIZE;
> +			continue; /* skip validation */
> +		}
> +		if (memcmp(expected, result, TPM2_SHA256_DIGEST_SIZE)) {
> +			efi_st_printf("PCR[%d] is not the expected value\n", i);
> +			return EFI_ST_FAILURE;
> +		}
> +		expected += TPM2_SHA256_DIGEST_SIZE;
> +		result += TPM2_SHA256_DIGEST_SIZE;
> +	}
>
>   	return EFI_ST_SUCCESS;
>   }
> @@ -31,7 +680,8 @@ static int efi_st_tcg2_setup(const efi_handle_t img_handle,
>   /**
>    * efi_st_tcg2_execute() - execute test
>    *
> - * Call the GetCapability service of the EFI_TCG2_PROTOCOL.
> + * Call EFI_TCG2_PROTOCOL services and check the
> + * Measured Boot behavior.
>    *
>    * Return:	status code
>    */
> @@ -40,12 +690,22 @@ static int efi_st_tcg2_execute(void)
>   	struct efi_tcg2_protocol *tcg2;
>   	struct efi_tcg2_boot_service_capability capability;
>   	efi_status_t ret;
> +	u32 active_pcr_banks;
> +	u64 eventlog, eventlog_last_entry;
> +	bool eventlog_truncated;
> +	efi_handle_t handle;
> +	efi_uintn_t exit_data_size = 0;
> +	u16 *exit_data = NULL;
> +	u32 i;
> +	u32 manufacturer_id;
>
>   	ret = boottime->locate_protocol(&guid_tcg2, NULL, (void **)&tcg2);
>   	if (ret != EFI_SUCCESS) {
>   		efi_st_error("TCG2 protocol is not available.\n");
>   		return EFI_ST_FAILURE;
>   	}
> +
> +	/* EFI_TCG2_PROTOCOL.GetCapability test */
>   	capability.size = sizeof(struct efi_tcg2_boot_service_capability) - 1;
>   	ret = tcg2->get_capability(tcg2, &capability);
>   	if (ret != EFI_BUFFER_TOO_SMALL) {
> @@ -64,12 +724,154 @@ static int efi_st_tcg2_execute(void)
>   	}
>   	efi_st_printf("TPM supports 0x%.8x event logs\n",
>   		      capability.supported_event_logs);
> +
> +	/* EFI_TCG2_PROTOCOL.GetActivePcrBanks test */
> +	ret = tcg2->get_active_pcr_banks(tcg2, &active_pcr_banks);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("tcg2->get_active_pcr_banks failed\n");
> +		return EFI_ST_FAILURE;
> +	}
> +	if (active_pcr_banks != capability.active_pcr_banks) {
> +		efi_st_error("tcg2->get_active_pcr_banks return wrong value\n");
> +		return EFI_ST_FAILURE;
> +	}
> +
> +	/* EFI_TCG2_PROTOCOL.HashLogExtendEvent test */
> +	ret = tcg2->hash_log_extend_event(tcg2, EFI_TCG2_EXTEND_ONLY,
> +					  (uintptr_t)image,
> +					  img.length, efi_tcg2_event);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("tcg2->hash_log_extend_event(EXTEND_ONLY) failed\n");
> +		return EFI_ST_FAILURE;
> +	}
> +
> +	ret = tcg2->hash_log_extend_event(tcg2, PE_COFF_IMAGE, (uintptr_t)image,
> +					  img.length, efi_tcg2_event);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("tcg2->hash_log_extend_event(PE_COFF_IMAGE) failed\n");
> +		return EFI_ST_FAILURE;
> +	}
> +
> +	/* EFI_TCG2_PROTOCOL.SubmitCommand test */
> +	ret = get_manufacturer_id(tcg2, &manufacturer_id);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("get_manufacturer_id failed\n");
> +		return EFI_ST_FAILURE;
> +	}
> +	if (capability.manufacturer_id != manufacturer_id) {
> +		efi_st_error("tcg2->submit_command test failed\n");
> +		return EFI_ST_FAILURE;
> +	}
> +
> +	/* tcg2_measure_pe_image test */
> +	ret = boottime->load_image(false, image_handle, NULL, image,
> +				   img.length, &handle);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("Failed to load image\n");
> +		return EFI_ST_FAILURE;
> +	}
> +
> +	/* measure ready_to_boot event(boot variables, smbios table, etc.) */
> +	/* TODO: add GPT measurement test */

lib/efi_selftest/efi_selftest_block_device.c shows how to setup a memory
based block device.

> +	ret = boottime->start_image(handle, &exit_data_size, &exit_data);
> +	if (ret != EFI_UNSUPPORTED) {
> +		efi_st_error("Wrong return value from application\n");
> +		return EFI_ST_FAILURE;
> +	}
> +	ret = boottime->free_pool(exit_data);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("Failed to free exit data\n");
> +		return EFI_ST_FAILURE;
> +	}
> +
> +	/* validate PCR read from the TPM device */
> +	for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {
> +		ret = read_pcr(tcg2, i);
> +		if (ret != EFI_SUCCESS) {
> +			efi_st_error("read pcr error\n");
> +			return EFI_ST_FAILURE;
> +		}
> +	}
> +	if (validate_pcrs()) {
> +		efi_st_error("PCR validation failed\n");
> +		return EFI_ST_FAILURE;
> +	}
> +
> +	/* EFI_TCG2_PROTOCOL.GetEventLog test */
> +	ret = tcg2->get_eventlog(tcg2, TCG2_EVENT_LOG_FORMAT_TCG_2, &eventlog,
> +				 &eventlog_last_entry, &eventlog_truncated);
> +	if (ret != EFI_SUCCESS) {
> +		efi_st_error("tcg2->get_eventlog failed\n");
> +		return EFI_ST_FAILURE;
> +	}
> +	/* TODO: eventlog format check */
> +
>   	return EFI_ST_SUCCESS;
>   }
>
> +/*
> + * Tear down unit test.

/**
  * efi_st_tcg2_teardown() - tear down unit test
  *

Overall the design looks good to me.

Best regards

Heinrich

> + *
> + * @return:	EFI_ST_SUCCESS for success
> + */
> +static int efi_st_tcg2_teardown(void)
> +{
> +	efi_status_t r = EFI_ST_SUCCESS;
> +
> +	if (image) {
> +		r = boottime->free_pool(image);
> +		if (r != EFI_SUCCESS) {
> +			efi_st_error("Failed to free image\n");
> +			return EFI_ST_FAILURE;
> +		}
> +	}
> +	if (efi_tcg2_event) {
> +		r = boottime->free_pool(efi_tcg2_event);
> +		if (r != EFI_SUCCESS) {
> +			efi_st_error("Failed to free efi_tcg2_event\n");
> +			return EFI_ST_FAILURE;
> +		}
> +	}
> +	if (pcrs) {
> +		r = boottime->free_pool(pcrs);
> +		if (r != EFI_SUCCESS) {
> +			efi_st_error("Failed to free pcr\n");
> +			return EFI_ST_FAILURE;
> +		}
> +	}
> +
> +	r = restore_boot_variable();
> +	if (r != EFI_SUCCESS) {
> +		efi_st_error("Failed to restore boot variables\n");
> +		return EFI_ST_FAILURE;
> +	}
> +
> +	/*
> +	 * Restore SMBIOS table
> +	 * If orig_smbios_table is NULL, calling install_configuration_table()
> +	 * removes dummy SMBIOS table form systab.
> +	 */
> +	r = boottime->install_configuration_table(&smbios_guid, orig_smbios_table);
> +	if (r != EFI_SUCCESS) {
> +		efi_st_error("Failed to restore SMBOIS table\n");
> +		return EFI_ST_FAILURE;
> +	}
> +
> +	if (dmi_addr) {
> +		r = boottime->free_pages(dmi_addr, 1);
> +		if (r != EFI_SUCCESS) {
> +			efi_st_error("Failed to free dummy smbios table\n");
> +			return EFI_ST_FAILURE;
> +		}
> +	}
> +
> +	return r;
> +}
> +
>   EFI_UNIT_TEST(tcg2) = {
>   	.name = "tcg2",
>   	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
>   	.execute = efi_st_tcg2_execute,
>   	.setup = efi_st_tcg2_setup,
> +	.teardown = efi_st_tcg2_teardown,
>   };
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/2] efi_loader: add missing const qualifier
  2021-10-23  8:40   ` Heinrich Schuchardt
@ 2021-10-23 17:21     ` Ilias Apalodimas
  0 siblings, 0 replies; 16+ messages in thread
From: Ilias Apalodimas @ 2021-10-23 17:21 UTC (permalink / raw)
  To: Heinrich Schuchardt; +Cc: Masahisa Kojima, u-boot, Simon Glass, Alexander Graf

On Sat, 23 Oct 2021 at 11:40, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 10/22/21 13:24, Masahisa Kojima wrote:
> > This commit fixes the following compilation warning
> > of boottime->install_configuration_table() function.
> >
> > ---
> > lib/efi_selftest/efi_selftest_tcg2.c:475:46:
> > warning: passing argument 1 of ‘boottime->install_configuration_table’
> > discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
> >    ret = boottime->install_configuration_table(&smbios_guid, dmi);
> > ---
> >
> > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
>
> The first --- separates the commit message from the rest of the patch:
>
> $ scripts/checkpatch.pl 0001-efi_loader-add-missing-const-qualifier.patch
> ERROR: Missing Signed-off-by: line by nominal patch author 'Masahisa
> Kojima <masahisa.kojima@linaro.org>'
>
> I will reformat the commit message when merging.
>
> Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-10-22 11:24 [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot Masahisa Kojima
  2021-10-22 11:24 ` [PATCH 1/2] efi_loader: add missing const qualifier Masahisa Kojima
  2021-10-22 11:24 ` [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot Masahisa Kojima
@ 2021-10-24 19:54 ` Simon Glass
  2021-11-02  8:03   ` Masahisa Kojima
  2 siblings, 1 reply; 16+ messages in thread
From: Simon Glass @ 2021-10-24 19:54 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas

Hi Masahisa,

On Fri, 22 Oct 2021 at 05:23, Masahisa Kojima
<masahisa.kojima@linaro.org> wrote:
>
> This patch series adds the selftest for the EFI_TCG2_PROTOCOL and
> Measured Boot flow.
> This selftest is verified on qemu with swtpm.

Is this in CI? Where are the instructions for doing this?

I have expressed my preference for expanding the in-tree emulator to
handle this.

Regards,
Simon


>
> This covers most of the functionalities, but there are some
> limitations and TODO items.
>
> [Limitation]
> - tcg2 selftest must run at the beginning of the efi_selftest because
>   some measurement occurs in efi_tcg2_register() and boottime->image_load().
>   Need to configure the efi_selftest with "setenv efi_selftest tcg2; bootefi selftest"
> - Skip ExitBootService measurement test
>    - EFI application can not read PCR after calling ExitBootService
> - Skip EventLog Validation
>    - Measured Boot measures U-Boot version, so EventLog varies every build having
>      different commit hash.
> - Skip PCR[0] validation
>    - PCR[0] include U-Boot version measurement, this value varies every build
>      having different commit hash.
> - Skip PCR[7] validation
>    - Secure Boot Variables can not be updated through efi_selftest.
> - The initial PCR value of PCR[17 - 22] is all 0xff, I'm not sure
>   it is expected or not.
>
> [TODO]
> - GPT measurement test
> - Secure Boot Variable test
> - Eventlog validation
>
> Masahisa Kojima (2):
>   efi_loader: add missing const qualifier
>   efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
>
>  include/efi_api.h                             |   2 +-
>  lib/efi_loader/efi_boottime.c                 |   5 +-
>  lib/efi_selftest/Makefile                     |  10 +
>  .../efi_selftest_miniapp_measuredboot.c       |  93 ++
>  lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
>  5 files changed, 910 insertions(+), 4 deletions(-)
>  create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>
> --
> 2.17.1
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-10-23  9:42   ` Heinrich Schuchardt
@ 2021-10-25  7:59     ` Masahisa Kojima
  2021-10-25  9:43       ` Heinrich Schuchardt
  0 siblings, 1 reply; 16+ messages in thread
From: Masahisa Kojima @ 2021-10-25  7:59 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Ilias Apalodimas, Simon Glass, Alexander Graf, U-Boot Mailing List

On Sat, 23 Oct 2021 at 18:42, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
>
>
> On 10/22/21 13:24, Masahisa Kojima wrote:
> > This commit adds the missing EFI_TCG2_PROTOCOL selftest
> > and Measured Boot selftest in lib/efi_selftest.
> >
> > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> > ---
> >   lib/efi_selftest/Makefile                     |  10 +
> >   .../efi_selftest_miniapp_measuredboot.c       |  93 ++
> >   lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
> >   3 files changed, 906 insertions(+), 1 deletion(-)
> >   create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
> >
> > diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
> > index 9ff6e1760c..09950ee028 100644
> > --- a/lib/efi_selftest/Makefile
> > +++ b/lib/efi_selftest/Makefile
> > @@ -14,6 +14,8 @@ CFLAGS_efi_selftest_miniapp_exception.o := $(CFLAGS_EFI) -Os -ffreestanding
> >   CFLAGS_REMOVE_efi_selftest_miniapp_exception.o := $(CFLAGS_NON_EFI)
> >   CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
> >   CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI)
> > +CFLAGS_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_EFI) -Os -ffreestanding
> > +CFLAGS_REMOVE_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_NON_EFI)
> >   CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
> >   CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI)
> >   CFLAGS_initrddump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
> > @@ -78,9 +80,11 @@ obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o
> >   targets += \
> >   efi_miniapp_file_image_exception.h \
> >   efi_miniapp_file_image_exit.h \
> > +efi_miniapp_file_image_measuredboot.h \
> >   efi_miniapp_file_image_return.h \
> >   efi_selftest_miniapp_exception.efi \
> >   efi_selftest_miniapp_exit.efi \
> > +efi_selftest_miniapp_measuredboot.efi \
> >   efi_selftest_miniapp_return.efi
> >
> >   ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
> > @@ -99,6 +103,10 @@ $(obj)/efi_miniapp_file_image_exit.h: $(obj)/efi_selftest_miniapp_exit.efi
> >       $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exit.efi > \
> >       $(obj)/efi_miniapp_file_image_exit.h
> >
> > +$(obj)/efi_miniapp_file_image_measuredboot.h: $(obj)/efi_selftest_miniapp_measuredboot.efi
> > +     $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_measuredboot.efi > \
> > +     $(obj)/efi_miniapp_file_image_measuredboot.h
> > +
> >   $(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi
> >       $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
> >       $(obj)/efi_miniapp_file_image_return.h
> > @@ -112,3 +120,5 @@ $(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h
> >   $(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
> >
> >   $(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
> > +
> > +$(obj)/efi_selftest_tcg2.o: $(obj)/efi_miniapp_file_image_measuredboot.h
> > diff --git a/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>
> Thank you for going the extra mile and adding the test.
>
> Which image is actually loaded seems to be irrelevant for the test. Can
> we reuse an existing one, e.g. efi_miniapp_file_image_return.h?
>
> I guess the PCR related to the loaded image is not checked as it will
> depend on the build tools and date.

Sorry, I'm doing wrong.
Actually this selftest verifies the PE/COFF image measurement, so measuremt
will be different depending on the build tools and date.
 # In my build environment, timestamp is set to all zero.

To test the PE/COFF image measurement, I must prepare the
static PE/COFF image. I plan to add efi_miniapp_file_image_measuredboot.h
as a pre-compiled small static PE/COFF image for the measurement test,
instead of adding efi_selftest_miniapp_measuredboot.c or reusing existing one.

>
> > new file mode 100644
> > index 0000000000..926713c1c2
> > --- /dev/null
> > +++ b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
> > @@ -0,0 +1,93 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * efi_selftest_miniapp_measuredboot
> > + *
> > + * Copyright (c) 2018 Heinrich Schuchardt
> > + * Copyright (c) 2021 Masahisa Kojima
> > + *
> > + * This EFI application is run by the StartImage selftest.
>
> This is incorrect due to copy and paste.
>
> > + * It uses the Exit boot service to return and used for
> > + * Measured Boot selftest.
> > + */
> > +
> > +#include <common.h>
> > +#include <efi_selftest.h>
> > +
> > +static efi_guid_t loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
> > +
> > +/**
> > + * check_loaded_image_protocol() - check image_base/image_size
> > + *
> > + * Try to open the loaded image protocol. Check that this function is located
> > + * between image_base and image_base + image_size.
> > + *
> > + * @image_handle:    handle of the loaded image
> > + * @systable:                system table
> > + * @return:          status code
> > + */
> > +static efi_status_t EFIAPI check_loaded_image_protocol
> > +             (efi_handle_t image_handle, struct efi_system_table *systable)
> > +{
> > +     struct efi_simple_text_output_protocol *cout = systable->con_out;
> > +     struct efi_boot_services *boottime = systable->boottime;
> > +     struct efi_loaded_image *loaded_image_protocol;
> > +     efi_status_t ret;
> > +
> > +     /*
> > +      * Open the loaded image protocol.
> > +      */
> > +     ret = boottime->open_protocol
> > +                             (image_handle, &loaded_image_protocol_guid,
> > +                              (void **)&loaded_image_protocol, NULL,
> > +                               NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> > +     if (ret != EFI_SUCCESS) {
> > +             cout->output_string(cout,
> > +                                 L"Could not open loaded image protocol");
> > +             return ret;
> > +     }
> > +     if ((void *)check_loaded_image_protocol <
> > +         loaded_image_protocol->image_base ||
> > +         (void *)check_loaded_image_protocol >=
> > +         loaded_image_protocol->image_base +
> > +         loaded_image_protocol->image_size) {
> > +             cout->output_string(cout,
> > +                                 L"Incorrect image_base or image_size\n");
> > +             return EFI_NOT_FOUND;
> > +     }
> > +     return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + * Entry point of the EFI application.
> > + *
> > + * @handle:  handle of the loaded image
> > + * @systable:        system table
> > + * @return:  status code
> > + */
> > +efi_status_t EFIAPI efi_main(efi_handle_t handle,
> > +                          struct efi_system_table *systable)
> > +{
> > +     struct efi_simple_text_output_protocol *con_out = systable->con_out;
> > +     efi_status_t ret;
> > +     u16 text[] = EFI_ST_SUCCESS_STR;
> > +
> > +     con_out->output_string(con_out, L"EFI application calling Exit\n");
> > +
> > +     if (check_loaded_image_protocol(handle, systable) != EFI_SUCCESS) {
> > +             con_out->output_string(con_out,
> > +                                    L"Loaded image protocol missing\n");
> > +             ret = EFI_NOT_FOUND;
> > +             goto out;
> > +     }
> > +
> > +     /* This return value is expected by the calling test */
> > +     ret = EFI_UNSUPPORTED;
> > +out:
> > +     systable->boottime->exit(handle, ret, sizeof(text), text);
> > +
> > +     /*
> > +      * This statement should not be reached.
> > +      * To enable testing use a different return value.
> > +      */
> > +     return EFI_SUCCESS;
> > +}
> > diff --git a/lib/efi_selftest/efi_selftest_tcg2.c b/lib/efi_selftest/efi_selftest_tcg2.c
> > index 1399309cec..50de735f5e 100644
> > --- a/lib/efi_selftest/efi_selftest_tcg2.c
> > +++ b/lib/efi_selftest/efi_selftest_tcg2.c
> > @@ -9,10 +9,495 @@
> >
> >   #include <efi_selftest.h>
> >   #include <efi_tcg2.h>
> > +/* Include containing the miniapp.efi application */
> > +#include "efi_miniapp_file_image_measuredboot.h"
>
> efi_miniapp_file_image_return.h

As I said above, I will prepare static PE/COFF image only for the
measurement purpose.

>
> > +
> > +#include <linux/unaligned/access_ok.h>
> > +#include <mapmem.h>
> > +#include <smbios.h>
> > +#include <tables_csum.h>
> >
> >   static struct efi_boot_services *boottime;
> >   static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
> >
> > +/* Block size of compressed disk image */
> > +#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
> > +
> > +static efi_handle_t image_handle;
> > +/* Decompressed file image */
> > +static u8 *image;
> > +
> > +/* One 8 byte block of the compressed disk image */
> > +struct line {
> > +     size_t addr;
> > +     char *line;
> > +};
> > +
> > +/* Compressed file image */
> > +struct compressed_file_image {
> > +     size_t length;
> > +     struct line lines[];
> > +};
> > +
> > +static struct compressed_file_image img = EFI_ST_DISK_IMG;
> > +
> > +static struct efi_tcg2_event *efi_tcg2_event;
> > +
> > +static struct efi_runtime_services *runtime;
> > +#define BOOT_NAME_1000 u"Boot1000"
> > +#define BOOT_NAME_1001 u"Boot1001"
> > +#define BOOT_NAME_1002 u"Boot1002"
> > +
> > +#define DEFAULT_ATTR (EFI_VARIABLE_NON_VOLATILE | \
> > +                   EFI_VARIABLE_BOOTSERVICE_ACCESS | \
> > +                   EFI_VARIABLE_RUNTIME_ACCESS)
> > +
> > +/* "efidebug boot add -b 1000 test1000 virtio 0:1 /EFI/debian/grubaa64.efi" */
> > +static const u8 boot_1000[] = {
> > +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
> > +0x74, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
> > +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
> > +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
> > +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
> > +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> > +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
> > +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
> > +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
> > +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
> > +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
> > +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
> > +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
> > +0xff, 0x04, 0x00 };
> > +
> > +/* "efidebug boot add -b 1001 test1001 virtio 0:1 /EFI/debian/grubaa64.efi" */
> > +static const u8 boot_1001[] = {
> > +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
> > +0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
> > +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
> > +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
> > +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
> > +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> > +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
> > +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
> > +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
> > +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
> > +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
> > +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
> > +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
> > +0xff, 0x04, 0x00 };
> > +
> > +/* "efidebug boot add -b 1002 test1002 virtio 0:1 /EFI/debian/grubaa64.efi" */
> > +static const u8 boot_1002[] = {
> > +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
> > +0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
> > +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
> > +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
> > +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
> > +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
> > +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
> > +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
> > +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
> > +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
> > +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
> > +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
> > +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
> > +0xff, 0x04, 0x00};
> > +
> > +/* "efidebug boot order 1002 1000 1001" */
> > +static u8 boot_order[] = {0x02, 0x10, 0x00, 0x10, 0x01, 0x10};
> > +
> > +static void *orig_smbios_table;
> > +static u64 dmi_addr = U32_MAX;
> > +#define SMBIOS_ENTRY_HEADER_SIZE 0x20
> > +/* smbios table for the measurement test */
> > +static u8 smbios_table_test[] = {
> > +0x5f, 0x53, 0x4d, 0x5f, 0x2c, 0x1f, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00,
> > +0x00, 0x00, 0x00, 0x00, 0x5f, 0x44, 0x4d, 0x49, 0x5f, 0xe4, 0x5c, 0x01,
> > +0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
> > +0x01, 0x02, 0x00, 0x00, 0x03, 0x00, 0x80, 0x08, 0x01, 0x00, 0x00, 0x00,
> > +0x00, 0x00, 0x00, 0x0c, 0x15, 0x0a, 0xff, 0xff, 0x55, 0x2d, 0x42, 0x6f,
> > +0x6f, 0x74, 0x00, 0x32, 0x30, 0x32, 0x31, 0x2e, 0x31, 0x30, 0x2d, 0x72,
> > +0x63, 0x34, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x35, 0x2d, 0x67, 0x37, 0x32,
> > +0x37, 0x63, 0x33, 0x66, 0x33, 0x32, 0x35, 0x39, 0x2d, 0x64, 0x69, 0x72,
> > +0x74, 0x79, 0x00, 0x31, 0x30, 0x2f, 0x30, 0x31, 0x2f, 0x32, 0x30, 0x32,
> > +0x31, 0x00, 0x00, 0x01, 0x1b, 0x01, 0x00, 0x01, 0x02, 0x00, 0x03, 0x31,
> > +0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
> > +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
> > +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
> > +0x37, 0x38, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x00, 0x01, 0x02, 0x00, 0x04,
> > +0x03, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
> > +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
> > +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
> > +0x33, 0x33, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00,
> > +0x00, 0x03, 0x15, 0x03, 0x00, 0x01, 0x03, 0x00, 0x02, 0x03, 0x03, 0x03,
> > +0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6e,
> > +0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
> > +0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00,
> > +0x00, 0x04, 0x30, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00,
> > +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +0x00, 0x01, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x03, 0x04,
> > +0x04, 0x04, 0x08, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01,
> > +0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33,
> > +0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
> > +0x33, 0x33, 0x00, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x00,
> > +0x00, 0x20, 0x0b, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +0x00, 0x00, 0x7f, 0x04, 0x06, 0x00, 0x00, 0x00
> > +};
> > +
> > +#define TPM2_CMD_BUF_SIZE 64
> > +/* TPM command is big endian */
> > +#define __MSB(x) ((x) >> 8)
> > +#define __LSB(x) ((x) & 0xFF)
> > +#define tpm_u16(x) __MSB(x), __LSB(x)
> > +#define tpm_u32(x) tpm_u16((x) >> 16), tpm_u16((x) & 0xFFFF)
> > +#define TPM2_PCR_READ_HEADER_SIZE 30
> > +
> > +static u8 *pcrs;
> > +static u8 expected_pcrs[EFI_TCG2_MAX_PCR_INDEX + 1][TPM2_SHA256_DIGEST_SIZE] = {
> > +     {0x91, 0x21, 0x37, 0xc7, 0x1a, 0x49, 0x19, 0xc8,
> > +      0xf1, 0xfb, 0xa9, 0x84, 0x5c, 0x65, 0xa9, 0xdd,
> > +      0x7b, 0xb9, 0xfe, 0xa1, 0xcd, 0x64, 0x49, 0xdd,
> > +      0xed, 0xe2, 0x65, 0x82, 0xc5, 0x3e, 0xf4, 0xc4},
> > +
> > +     {0xf5, 0x79, 0xf3, 0x20, 0x62, 0x6e, 0x8b, 0x58,
> > +      0x62, 0xa3, 0x4e, 0x2f, 0xb7, 0x10, 0xac, 0x34,
> > +      0x4e, 0x68, 0x94, 0x37, 0x87, 0x29, 0xc4, 0xbe,
> > +      0xa3, 0xc4, 0xd9, 0x14, 0x2b, 0x66, 0x79, 0x9b},
> > +
> > +     {0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
> > +      0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
> > +      0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
> > +      0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
> > +
> > +     {0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
> > +      0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
> > +      0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
> > +      0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
> > +
> > +     {0xbe, 0xea, 0xdc, 0xe0, 0x44, 0x5b, 0x5f, 0x14,
> > +      0xef, 0x24, 0x5d, 0x13, 0x15, 0xfe, 0x41, 0x86,
> > +      0xc2, 0xd5, 0xdc, 0x0d, 0x04, 0x2f, 0xd4, 0x04,
> > +      0x0d, 0x02, 0x62, 0xc0, 0x34, 0x80, 0xee, 0xd5},
> > +
> > +     {0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
> > +      0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
> > +      0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
> > +      0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
> > +
> > +     {0x8d, 0x28, 0xde, 0x72, 0x22, 0x3e, 0x88, 0x1a,
> > +      0x37, 0xfa, 0x47, 0x12, 0x68, 0x45, 0xdf, 0x71,
> > +      0x50, 0x8f, 0xab, 0x59, 0x50, 0x7b, 0x52, 0x32,
> > +      0xa6, 0xaa, 0x03, 0x3d, 0x4e, 0x22, 0x89, 0xd7},
> > +
> > +     {0x96, 0x74, 0xae, 0xcd, 0x3f, 0x40, 0xb4, 0xa9,
> > +      0x36, 0xae, 0x19, 0xc8, 0x84, 0x8a, 0xb9, 0x5a,
> > +      0x87, 0x99, 0xd8, 0x89, 0x7f, 0xfc, 0x40, 0x48,
> > +      0x05, 0x99, 0x65, 0x2e, 0x55, 0xd4, 0x93, 0x32},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +
> > +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> > +
> > +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> > +
> > +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> > +
> > +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> > +
> > +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> > +
> > +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> > +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
> > +
> > +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
> > +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
> > +};
> > +
> > +struct boot_variable {
> > +     u16 name[16];
> > +     u8 *buf;
> > +     efi_uintn_t size;
> > +     u32 attr;
> > +     const u8 *test_data;
> > +     efi_uintn_t test_data_size;
> > +};
> > +
> > +static struct boot_variable boot_variable_test[] = {
> > +     {u"BootOrder",          NULL, 0, DEFAULT_ATTR, boot_order, sizeof(boot_order)},
> > +     {BOOT_NAME_1000,        NULL, 0, DEFAULT_ATTR, boot_1000, sizeof(boot_1000)},
> > +     {BOOT_NAME_1001,        NULL, 0, DEFAULT_ATTR, boot_1001, sizeof(boot_1001)},
> > +     {BOOT_NAME_1002,        NULL, 0, DEFAULT_ATTR, boot_1002, sizeof(boot_1002)},
> > +};
> > +
> > +/*
> > + * Decompress the disk image.
> > + *
> > + * @image    decompressed disk image
> > + * @return   status code
> > + */
> > +static efi_status_t decompress(u8 **image)
> > +{
> > +     u8 *buf;
> > +     size_t i;
> > +     size_t addr;
> > +     size_t len;
> > +     efi_status_t ret;
> > +
> > +     ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
> > +                                   (void **)&buf);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("Out of memory\n");
> > +             return ret;
> > +     }
> > +     boottime->set_mem(buf, img.length, 0);
> > +
> > +     for (i = 0; ; ++i) {
> > +             if (!img.lines[i].line)
> > +                     break;
> > +             addr = img.lines[i].addr;
> > +             len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
> > +             if (addr + len > img.length)
> > +                     len = img.length - addr;
> > +             boottime->copy_mem(buf + addr, img.lines[i].line, len);
> > +     }
> > +     *image = buf;
> > +     return ret;
> > +}
> > +
> > +/*
> > + * Configure dummy boot variables.
>
> /**
>   * efi_status_t setup_boot_variable() - configure dummy boot variables
>   *
>   * Preexisting variable values are saved and will be restored by
>   * calling restore_boot_variable().
>   *
>
> > + *
> > + * @return   status code
> > + */
> > +static efi_status_t setup_boot_variable(void)
> > +{
> > +     efi_status_t ret;
> > +     u32 i;
> > +     efi_uintn_t size;
> > +     u8 dummy;
>
> This variable is superfluous.
>
> > +
> > +     for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
> > +             size = 1;
>
> Please, set size to 0.
>
> > +             ret = runtime->get_variable(boot_variable_test[i].name,
> > +                                         &efi_global_variable_guid,
> > +                                         &boot_variable_test[i].attr,
> > +                                         &size,
> > +                                         &dummy);
>
> Instead of dummy you can use NULL if size = 0.
>
> > +             if (ret == EFI_BUFFER_TOO_SMALL) {
> > +                     /* Variable exists, save the current vaiable */
>
> %s/vaiable/value/
>
> > +                     boot_variable_test[i].size = size;
> > +                     ret = boottime->allocate_pool(EFI_LOADER_DATA,
> > +                                                   boot_variable_test[i].size,
> > +                                                   (void **)&boot_variable_test[i].buf);
> > +                     if (ret != EFI_SUCCESS) {
> > +                             efi_st_error("fail to allocate buffer for boot variable\n");
>
> In all other tests we use 'Failed to'
>
> %s/fail/Failed/
>
> > +                             return ret;
> > +                     }
> > +                     ret = runtime->get_variable(boot_variable_test[i].name,
> > +                                                 &efi_global_variable_guid,
> > +                                                 &boot_variable_test[i].attr,
> > +                                                 &boot_variable_test[i].size,
> > +                                                 boot_variable_test[i].buf);
> > +                     if (ret != EFI_SUCCESS) {
> > +                             efi_st_error("fail to get current boot variable\n");
>
> %s/fail/Failed/
>
>
> > +                             return ret;
> > +                     }
> > +             }
> > +
> > +             /* set boot variable for the measurement test */
> > +             ret = runtime->set_variable(boot_variable_test[i].name,
> > +                                         &efi_global_variable_guid,
> > +                                         boot_variable_test[i].attr,
> > +                                         boot_variable_test[i].test_data_size,
> > +                                         boot_variable_test[i].test_data);
> > +             if (ret != EFI_SUCCESS) {
> > +                     efi_st_error("### fail to set test boot variable(%d)n", i);
>
> %s/### fail/Failed/
>
> > +                     return ret;
> > +             }
> > +     }
> > +
> > +     return 0;
> > +}
> > +
> > +/*
>
> /**
>   * efi_status_t restore_boot_variable() - restore original values
>   *
>   * Restore the variable values saved in setup_boot_variable().
>   *
>
> > + * Restore original boot variables.
> > + *
> > + * @return   status code
> > + */
> > +efi_status_t restore_boot_variable(void)
> > +{
> > +     int i;
> > +     efi_status_t ret;
> > +
> > +     for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
> > +             if (boot_variable_test[i].buf) {
> > +                     ret = runtime->set_variable(boot_variable_test[i].name,
> > +                                                 &efi_global_variable_guid,
> > +                                                 boot_variable_test[i].attr,
> > +                                                 boot_variable_test[i].size,
> > +                                                 boot_variable_test[i].buf);
> > +                     if (ret != EFI_SUCCESS) {
> > +                             efi_st_error("### fail to restore boot variable\n");
> > +                             return ret;
> > +                     }
> > +                     ret = boottime->free_pool(boot_variable_test[i].buf);
> > +                     if (ret != EFI_SUCCESS) {
> > +                             efi_st_error("Failed to free boot variable\n");
> > +                             return ret;
> > +                     }
> > +             } else {
> > +                     /* delete the variable used only for testing */
> > +                     ret = runtime->set_variable(boot_variable_test[i].name,
> > +                                                 &efi_global_variable_guid,
> > +                                                 0, 0, NULL);
> > +                     if (ret != EFI_SUCCESS) {
> > +                             efi_st_error("### fail to delete boot variable\n");
>
> %s/### fail/Failed/
>
> > +                             return ret;
> > +                     }
> > +             }
> > +     }
> > +
> > +     return EFI_SUCCESS;
> > +}
> > +
> > +/**
> > + * Find smbios table
> > + *
> > + * @systable system table
> > + * @return   status code
> > + */
> > +static void *find_smbios_table(const struct efi_system_table *systable)
> > +{
> > +     u32 i;
> > +
> > +     for (i = 0; i < systable->nr_tables; i++) {
> > +             if (!guidcmp(&smbios_guid, &systable->tables[i].guid))
> > +                     return systable->tables[i].table;
> > +     }
> > +
> > +     return NULL;
> > +}
> > +
> > +/**
> > + * Prepare the dummy SMBIOS table
> > + *
> > + * @systable system table
> > + * @return   status code
> > + */
> > +efi_status_t setup_smbios_table(const struct efi_system_table *systable)
> > +{
> > +     struct smbios_entry *se;
> > +     efi_status_t ret;
> > +     /* Map within the low 32 bits, to allow for 32bit SMBIOS tables */
> > +     void *dmi;
> > +     char *istart;
> > +     int isize;
> > +
> > +     if (sizeof(smbios_table_test) > EFI_PAGE_SIZE)
> > +             return EFI_OUT_OF_RESOURCES;
> > +
> > +     orig_smbios_table = find_smbios_table(systable);
> > +
> > +     /* Reserve 4kiB page for SMBIOS */
> > +     ret = boottime->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
> > +                              EFI_RUNTIME_SERVICES_DATA, 1, &dmi_addr);
> > +
> > +     if (ret != EFI_SUCCESS) {
> > +             /* Could not find space in lowmem, use highmem instead */
> > +             ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
> > +                                      EFI_RUNTIME_SERVICES_DATA, 1,
> > +                                      &dmi_addr);
> > +
> > +             if (ret != EFI_SUCCESS)
> > +                     return ret;
> > +     }
> > +
> > +     dmi = (void *)(uintptr_t)dmi_addr;
> > +     se = dmi;
> > +     boottime->copy_mem(se, smbios_table_test, sizeof(smbios_table_test));
> > +
> > +     /* update smbios table start address */
> > +     se->struct_table_address = (uintptr_t)((u8 *)dmi + SMBIOS_ENTRY_HEADER_SIZE);
> > +
> > +     /* calculate checksums */
> > +     istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
> > +     isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
> > +     se->intermediate_checksum = table_compute_checksum(istart, isize);
> > +     se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
> > +
> > +     /* Install SMBIOS information as configuration table */
> > +     ret = boottime->install_configuration_table(&smbios_guid, dmi);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("Cannot install SMBIOS table\n");
> > +             boottime->free_pages(dmi_addr, 1);
> > +     }
> > +
> > +     return ret;
> > +}
> > +
> >   /**
> >    * efi_st_tcg2_setup() - setup test
> >    *
> > @@ -23,7 +508,171 @@ static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
> >   static int efi_st_tcg2_setup(const efi_handle_t img_handle,
> >                            const struct efi_system_table *systable)
> >   {
> > +     efi_status_t ret;
> > +     struct uefi_image_load_event image_load_event;
> > +
> > +     image_handle = img_handle;
> >       boottime = systable->boottime;
> > +     runtime = systable->runtime;
> > +
> > +     /* Load the application image into memory */
> > +     decompress(&image);
> > +
> > +     ret = boottime->allocate_pool(EFI_LOADER_DATA,
> > +                                   sizeof(struct efi_tcg2_event) +
> > +                                   sizeof(struct uefi_image_load_event),
> > +                                   (void **)&efi_tcg2_event);
> > +     if (!efi_tcg2_event)
> > +             return EFI_ST_FAILURE;
> > +
> > +     efi_tcg2_event->size = sizeof(struct efi_tcg2_event) +
> > +                            sizeof(struct uefi_image_load_event);
> > +     efi_tcg2_event->header.header_size = sizeof(struct efi_tcg2_event_header);
> > +     efi_tcg2_event->header.header_version = 1;
> > +     efi_tcg2_event->header.pcr_index = 6;
> > +     efi_tcg2_event->header.event_type = EV_EFI_RUNTIME_SERVICES_DRIVER;
> > +     image_load_event.image_location_in_memory = 0x12345678;
> > +     image_load_event.image_length_in_memory = 0x300000;
> > +     image_load_event.image_link_time_address = 0x87654321;
> > +     image_load_event.length_of_device_path = 0;
> > +     boottime->copy_mem(efi_tcg2_event->event, &image_load_event,
> > +                        sizeof(struct uefi_image_load_event));
> > +
> > +     ret = setup_boot_variable();
> > +     if (ret != EFI_SUCCESS)
> > +             return EFI_ST_FAILURE;
> > +
> > +     ret = setup_smbios_table(systable);
> > +     if (ret != EFI_SUCCESS)
> > +             return EFI_ST_FAILURE;
> > +
> > +     ret = boottime->allocate_pool(EFI_LOADER_DATA,
> > +                                   (EFI_TCG2_MAX_PCR_INDEX + 1) *
> > +                                   TPM2_SHA256_DIGEST_SIZE,
> > +                                   (void **)&pcrs);
> > +     if (!pcrs)
> > +             return EFI_ST_FAILURE;
> > +
> > +     boottime->set_mem(pcrs, (EFI_TCG2_MAX_PCR_INDEX + 1) * TPM2_SHA256_DIGEST_SIZE, 0);
> > +
> > +     return EFI_ST_SUCCESS;
> > +}
> > +
> > +/**
> > + * Get manufacturer_id through submit_command API
> > + *
> > + * @tcg2             tcg2 protocol
> > + * @manufacturer_id  pointer to the manufacturer_id
> > + * @return           status code
> > + */
> > +static efi_status_t get_manufacturer_id(struct efi_tcg2_protocol *tcg2, u32 *manufacturer_id)
> > +{
> > +     efi_status_t ret;
> > +     u8 cmd[TPM2_CMD_BUF_SIZE] = {
> > +             tpm_u16(TPM2_ST_NO_SESSIONS),           /* TAG */
> > +             tpm_u32(22),                            /* Length */
> > +             tpm_u32(TPM2_CC_GET_CAPABILITY),        /* Command code */
> > +
> > +             tpm_u32(TPM2_CAP_TPM_PROPERTIES),       /* Capability */
> > +             tpm_u32(TPM2_PT_MANUFACTURER),          /* Property */
> > +             tpm_u32(1),                     /* Property count */
> > +     };
> > +     u8 resp[TPM2_CMD_BUF_SIZE];
> > +     unsigned int value_off;
> > +
> > +     ret = tcg2->submit_command(tcg2, 22, cmd,
> > +                                TPM2_CMD_BUF_SIZE, resp);
> > +     if (ret != EFI_SUCCESS)
> > +             return ret;
> > +
> > +     /*
> > +      * In the response buffer, the properties are located after the:
> > +      * tag (u16), response size (u32), response code (u32),
> > +      * YES/NO flag (u8), TPM_CAP (u32).
> > +      * The value is located after count (u32), property (u32).
> > +      */
> > +     value_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
> > +                      sizeof(u8) + sizeof(u32) + sizeof(u32) + sizeof(u32);
> > +     *manufacturer_id = get_unaligned_be32(&resp[value_off]);
> > +
> > +     return ret;
> > +}
> > +
> > +/**
> > + * Read the PCR from the TPM device
> > + *
> > + * @tcg2     tcg2 protocol
> > + * @idx              pcr index to read
> > + * @return   status code
> > + */
> > +static efi_status_t read_pcr(struct efi_tcg2_protocol *tcg2, u32 idx)
> > +{
> > +     efi_status_t ret;
> > +     u8 idx_array_sz = 3; /* support 24 PCRs */
>
> This is a constant.
>
> #define IDX_ARRAY_SZ 3
>
> You can move it close to the TPM2_CMD_BUF_SIZE definition.
>
> > +     u32 cmd_len = 17 + idx_array_sz;
> > +     u8 cmd[TPM2_CMD_BUF_SIZE] = {
> > +             tpm_u16(TPM2_ST_NO_SESSIONS),   /* TAG */
> > +             tpm_u32(cmd_len),               /* Length */
> > +             tpm_u32(TPM2_CC_PCR_READ),      /* Command code */
> > +             /* TPML_PCR_SELECTION */
> > +             tpm_u32(1),                     /* Number of selections */
> > +             tpm_u16(TPM2_ALG_SHA256),       /* Algorithm of the hash */
> > +             idx_array_sz,                   /* Array size for selection */
> > +             /* bitmap(idx),                    Selected PCR bitmap */
> > +     };
> > +     u8 resp[TPM2_CMD_BUF_SIZE];
> > +     u32 pcr_sel_idx = idx / 8;
> > +     u8 pcr_sel_bit = BIT(idx % 8);
> > +     u8 *dst;
> > +
> > +     cmd[17 + pcr_sel_idx] = pcr_sel_bit;
> > +     ret = tcg2->submit_command(tcg2, cmd_len, cmd,
> > +                                TPM2_CMD_BUF_SIZE, resp);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("tcg2->submit_command fail to read PCR\n");
> > +             return ret;
> > +     }
> > +
> > +     dst = pcrs + (idx * TPM2_SHA256_DIGEST_SIZE);
> > +     boottime->copy_mem(dst, &resp[TPM2_PCR_READ_HEADER_SIZE],
> > +                        TPM2_SHA256_DIGEST_SIZE);
> > +
> > +     return ret;
> > +}
> > +
> > +/**
> > + * Compare the expected and actual pcrs
> > + *
> > + * @return   status code
> > + */
> > +static int validate_pcrs(void)
> > +{
> > +     u32 i;
> > +     u8 *expected = (u8 *)expected_pcrs;
> > +     u8 *result = pcrs;
>
> Making expected_pcrs and pcrs arrays with elements of size
> TPM2_SHA256_DIGEST_SIZE can replace these pointers.
>
> > +
> > +     /*
> > +      *  - Skip PCR[0] validation. PCR[0] contains U-Boot version measurement
> > +      *    it contains the commit hash, so the measurement varies every build
> > +      *    with different commit hash.
> > +      *  - Skip PCR[7] validation. PCR[7] contains UEFI Secure Boot variables
> > +      *    measurement. These variables can not be updated through efi_selftest and
> > +      *    it varies depending on the platform.
>
> %s/it varies/vary/
>
> > +      */
> > +     for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {
>
> for (i = 1; i < (EFI_TCG2_MAX_PCR_INDEX + 1); ++i) {
>    if (i != 7)
>         continue;
>    if (memcmp(pcr[i], expected_pcr[i], PM2_SHA256_DIGEST_SIZE)) {
>      if (memcmp(expected, result, TPM2_SHA256_DIGEST_SIZE)) {
>        efi_st_printf("PCR[%d] is not the expected value\n", i);
>        return EFI_ST_FAILURE;
>      }
>    }
> }
>
> > +             result = pcrs + (TPM2_SHA256_DIGEST_SIZE * i);
> > +             if (i == 0 || i == 7) {
> > +                     expected += TPM2_SHA256_DIGEST_SIZE;
> > +                     result += TPM2_SHA256_DIGEST_SIZE;
> > +                     continue; /* skip validation */
> > +             }
> > +             if (memcmp(expected, result, TPM2_SHA256_DIGEST_SIZE)) {
> > +                     efi_st_printf("PCR[%d] is not the expected value\n", i);
> > +                     return EFI_ST_FAILURE;
> > +             }
> > +             expected += TPM2_SHA256_DIGEST_SIZE;
> > +             result += TPM2_SHA256_DIGEST_SIZE;
> > +     }
> >
> >       return EFI_ST_SUCCESS;
> >   }
> > @@ -31,7 +680,8 @@ static int efi_st_tcg2_setup(const efi_handle_t img_handle,
> >   /**
> >    * efi_st_tcg2_execute() - execute test
> >    *
> > - * Call the GetCapability service of the EFI_TCG2_PROTOCOL.
> > + * Call EFI_TCG2_PROTOCOL services and check the
> > + * Measured Boot behavior.
> >    *
> >    * Return:  status code
> >    */
> > @@ -40,12 +690,22 @@ static int efi_st_tcg2_execute(void)
> >       struct efi_tcg2_protocol *tcg2;
> >       struct efi_tcg2_boot_service_capability capability;
> >       efi_status_t ret;
> > +     u32 active_pcr_banks;
> > +     u64 eventlog, eventlog_last_entry;
> > +     bool eventlog_truncated;
> > +     efi_handle_t handle;
> > +     efi_uintn_t exit_data_size = 0;
> > +     u16 *exit_data = NULL;
> > +     u32 i;
> > +     u32 manufacturer_id;
> >
> >       ret = boottime->locate_protocol(&guid_tcg2, NULL, (void **)&tcg2);
> >       if (ret != EFI_SUCCESS) {
> >               efi_st_error("TCG2 protocol is not available.\n");
> >               return EFI_ST_FAILURE;
> >       }
> > +
> > +     /* EFI_TCG2_PROTOCOL.GetCapability test */
> >       capability.size = sizeof(struct efi_tcg2_boot_service_capability) - 1;
> >       ret = tcg2->get_capability(tcg2, &capability);
> >       if (ret != EFI_BUFFER_TOO_SMALL) {
> > @@ -64,12 +724,154 @@ static int efi_st_tcg2_execute(void)
> >       }
> >       efi_st_printf("TPM supports 0x%.8x event logs\n",
> >                     capability.supported_event_logs);
> > +
> > +     /* EFI_TCG2_PROTOCOL.GetActivePcrBanks test */
> > +     ret = tcg2->get_active_pcr_banks(tcg2, &active_pcr_banks);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("tcg2->get_active_pcr_banks failed\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +     if (active_pcr_banks != capability.active_pcr_banks) {
> > +             efi_st_error("tcg2->get_active_pcr_banks return wrong value\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +
> > +     /* EFI_TCG2_PROTOCOL.HashLogExtendEvent test */
> > +     ret = tcg2->hash_log_extend_event(tcg2, EFI_TCG2_EXTEND_ONLY,
> > +                                       (uintptr_t)image,
> > +                                       img.length, efi_tcg2_event);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("tcg2->hash_log_extend_event(EXTEND_ONLY) failed\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +
> > +     ret = tcg2->hash_log_extend_event(tcg2, PE_COFF_IMAGE, (uintptr_t)image,
> > +                                       img.length, efi_tcg2_event);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("tcg2->hash_log_extend_event(PE_COFF_IMAGE) failed\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +
> > +     /* EFI_TCG2_PROTOCOL.SubmitCommand test */
> > +     ret = get_manufacturer_id(tcg2, &manufacturer_id);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("get_manufacturer_id failed\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +     if (capability.manufacturer_id != manufacturer_id) {
> > +             efi_st_error("tcg2->submit_command test failed\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +
> > +     /* tcg2_measure_pe_image test */
> > +     ret = boottime->load_image(false, image_handle, NULL, image,
> > +                                img.length, &handle);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("Failed to load image\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +
> > +     /* measure ready_to_boot event(boot variables, smbios table, etc.) */
> > +     /* TODO: add GPT measurement test */
>
> lib/efi_selftest/efi_selftest_block_device.c shows how to setup a memory
> based block device.

Thank you for the information.
I tried to copy efi_selftest_block_device but I encountered error.

To test GPT measurement, I need to add the device path node having
following type.
    dp->type == DEVICE_PATH_TYPE_MEDIA_DEVICE
    dp->sub_type == DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH
If I added this node in the device path,
boottime->connect_controller() returns EFI_NOT_FOUND
and I'm investigating how to use connect_controller.

For other comments, I will include fixes in the next version.

Thanks,
Masahisa Kojima

>
> > +     ret = boottime->start_image(handle, &exit_data_size, &exit_data);
> > +     if (ret != EFI_UNSUPPORTED) {
> > +             efi_st_error("Wrong return value from application\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +     ret = boottime->free_pool(exit_data);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("Failed to free exit data\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +
> > +     /* validate PCR read from the TPM device */
> > +     for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {
> > +             ret = read_pcr(tcg2, i);
> > +             if (ret != EFI_SUCCESS) {
> > +                     efi_st_error("read pcr error\n");
> > +                     return EFI_ST_FAILURE;
> > +             }
> > +     }
> > +     if (validate_pcrs()) {
> > +             efi_st_error("PCR validation failed\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +
> > +     /* EFI_TCG2_PROTOCOL.GetEventLog test */
> > +     ret = tcg2->get_eventlog(tcg2, TCG2_EVENT_LOG_FORMAT_TCG_2, &eventlog,
> > +                              &eventlog_last_entry, &eventlog_truncated);
> > +     if (ret != EFI_SUCCESS) {
> > +             efi_st_error("tcg2->get_eventlog failed\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +     /* TODO: eventlog format check */
> > +
> >       return EFI_ST_SUCCESS;
> >   }
> >
> > +/*
> > + * Tear down unit test.
>
> /**
>   * efi_st_tcg2_teardown() - tear down unit test
>   *
>
> Overall the design looks good to me.
>
> Best regards
>
> Heinrich
>
> > + *
> > + * @return:  EFI_ST_SUCCESS for success
> > + */
> > +static int efi_st_tcg2_teardown(void)
> > +{
> > +     efi_status_t r = EFI_ST_SUCCESS;
> > +
> > +     if (image) {
> > +             r = boottime->free_pool(image);
> > +             if (r != EFI_SUCCESS) {
> > +                     efi_st_error("Failed to free image\n");
> > +                     return EFI_ST_FAILURE;
> > +             }
> > +     }
> > +     if (efi_tcg2_event) {
> > +             r = boottime->free_pool(efi_tcg2_event);
> > +             if (r != EFI_SUCCESS) {
> > +                     efi_st_error("Failed to free efi_tcg2_event\n");
> > +                     return EFI_ST_FAILURE;
> > +             }
> > +     }
> > +     if (pcrs) {
> > +             r = boottime->free_pool(pcrs);
> > +             if (r != EFI_SUCCESS) {
> > +                     efi_st_error("Failed to free pcr\n");
> > +                     return EFI_ST_FAILURE;
> > +             }
> > +     }
> > +
> > +     r = restore_boot_variable();
> > +     if (r != EFI_SUCCESS) {
> > +             efi_st_error("Failed to restore boot variables\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +
> > +     /*
> > +      * Restore SMBIOS table
> > +      * If orig_smbios_table is NULL, calling install_configuration_table()
> > +      * removes dummy SMBIOS table form systab.
> > +      */
> > +     r = boottime->install_configuration_table(&smbios_guid, orig_smbios_table);
> > +     if (r != EFI_SUCCESS) {
> > +             efi_st_error("Failed to restore SMBOIS table\n");
> > +             return EFI_ST_FAILURE;
> > +     }
> > +
> > +     if (dmi_addr) {
> > +             r = boottime->free_pages(dmi_addr, 1);
> > +             if (r != EFI_SUCCESS) {
> > +                     efi_st_error("Failed to free dummy smbios table\n");
> > +                     return EFI_ST_FAILURE;
> > +             }
> > +     }
> > +
> > +     return r;
> > +}
> > +
> >   EFI_UNIT_TEST(tcg2) = {
> >       .name = "tcg2",
> >       .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
> >       .execute = efi_st_tcg2_execute,
> >       .setup = efi_st_tcg2_setup,
> > +     .teardown = efi_st_tcg2_teardown,
> >   };
> >

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-10-25  7:59     ` Masahisa Kojima
@ 2021-10-25  9:43       ` Heinrich Schuchardt
  2021-10-30  6:02         ` Ilias Apalodimas
  0 siblings, 1 reply; 16+ messages in thread
From: Heinrich Schuchardt @ 2021-10-25  9:43 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: Ilias Apalodimas, Simon Glass, Alexander Graf, U-Boot Mailing List



On 10/25/21 09:59, Masahisa Kojima wrote:
> On Sat, 23 Oct 2021 at 18:42, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>>
>>
>>
>> On 10/22/21 13:24, Masahisa Kojima wrote:
>>> This commit adds the missing EFI_TCG2_PROTOCOL selftest
>>> and Measured Boot selftest in lib/efi_selftest.
>>>
>>> Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
>>> ---
>>>    lib/efi_selftest/Makefile                     |  10 +
>>>    .../efi_selftest_miniapp_measuredboot.c       |  93 ++
>>>    lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
>>>    3 files changed, 906 insertions(+), 1 deletion(-)
>>>    create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>>>
>>> diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile
>>> index 9ff6e1760c..09950ee028 100644
>>> --- a/lib/efi_selftest/Makefile
>>> +++ b/lib/efi_selftest/Makefile
>>> @@ -14,6 +14,8 @@ CFLAGS_efi_selftest_miniapp_exception.o := $(CFLAGS_EFI) -Os -ffreestanding
>>>    CFLAGS_REMOVE_efi_selftest_miniapp_exception.o := $(CFLAGS_NON_EFI)
>>>    CFLAGS_efi_selftest_miniapp_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
>>>    CFLAGS_REMOVE_efi_selftest_miniapp_exit.o := $(CFLAGS_NON_EFI)
>>> +CFLAGS_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_EFI) -Os -ffreestanding
>>> +CFLAGS_REMOVE_efi_selftest_miniapp_measuredboot.o := $(CFLAGS_NON_EFI)
>>>    CFLAGS_efi_selftest_miniapp_return.o := $(CFLAGS_EFI) -Os -ffreestanding
>>>    CFLAGS_REMOVE_efi_selftest_miniapp_return.o := $(CFLAGS_NON_EFI)
>>>    CFLAGS_initrddump_exit.o := $(CFLAGS_EFI) -Os -ffreestanding
>>> @@ -78,9 +80,11 @@ obj-$(CONFIG_EFI_ESRT) += efi_selftest_esrt.o
>>>    targets += \
>>>    efi_miniapp_file_image_exception.h \
>>>    efi_miniapp_file_image_exit.h \
>>> +efi_miniapp_file_image_measuredboot.h \
>>>    efi_miniapp_file_image_return.h \
>>>    efi_selftest_miniapp_exception.efi \
>>>    efi_selftest_miniapp_exit.efi \
>>> +efi_selftest_miniapp_measuredboot.efi \
>>>    efi_selftest_miniapp_return.efi
>>>
>>>    ifeq ($(CONFIG_GENERATE_ACPI_TABLE),)
>>> @@ -99,6 +103,10 @@ $(obj)/efi_miniapp_file_image_exit.h: $(obj)/efi_selftest_miniapp_exit.efi
>>>        $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_exit.efi > \
>>>        $(obj)/efi_miniapp_file_image_exit.h
>>>
>>> +$(obj)/efi_miniapp_file_image_measuredboot.h: $(obj)/efi_selftest_miniapp_measuredboot.efi
>>> +     $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_measuredboot.efi > \
>>> +     $(obj)/efi_miniapp_file_image_measuredboot.h
>>> +
>>>    $(obj)/efi_miniapp_file_image_return.h: $(obj)/efi_selftest_miniapp_return.efi
>>>        $(obj)/../../tools/file2include $(obj)/efi_selftest_miniapp_return.efi > \
>>>        $(obj)/efi_miniapp_file_image_return.h
>>> @@ -112,3 +120,5 @@ $(obj)/efi_selftest_loadimage.o: $(obj)/efi_miniapp_file_image_exit.h
>>>    $(obj)/efi_selftest_startimage_exit.o: $(obj)/efi_miniapp_file_image_exit.h
>>>
>>>    $(obj)/efi_selftest_startimage_return.o: $(obj)/efi_miniapp_file_image_return.h
>>> +
>>> +$(obj)/efi_selftest_tcg2.o: $(obj)/efi_miniapp_file_image_measuredboot.h
>>> diff --git a/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>>
>> Thank you for going the extra mile and adding the test.
>>
>> Which image is actually loaded seems to be irrelevant for the test. Can
>> we reuse an existing one, e.g. efi_miniapp_file_image_return.h?
>>
>> I guess the PCR related to the loaded image is not checked as it will
>> depend on the build tools and date.
>
> Sorry, I'm doing wrong.
> Actually this selftest verifies the PE/COFF image measurement, so measuremt
> will be different depending on the build tools and date.
>   # In my build environment, timestamp is set to all zero.
>
> To test the PE/COFF image measurement, I must prepare the
> static PE/COFF image. I plan to add efi_miniapp_file_image_measuredboot.h
> as a pre-compiled small static PE/COFF image for the measurement test,
> instead of adding efi_selftest_miniapp_measuredboot.c or reusing existing one.

You will need one image per UEFI architecture (ia32, x64, arm, aa64,
riscv32, riscv64). You could present the image via the
EFI_LOAD_FILE2_PROTOCOL, see lib/efi_selftest/efi_selftest_load_file.c.

Here is how to detect the target architecture:

#if defined(__arm__)
#include efi_miniapp_tcg2_arm.h
#elif defined(__aarch64__)
#include efi_miniapp_tcg2_aarch64.h
#elif defined(__i386__)
#include efi_miniapp_tcg2_ia32.h
#elif defined(__x86_64__)
#include efi_miniapp_tcg2_x64.h
#elif defined(__riscv) && (__riscv_xlen == 32)
#include efi_miniapp_tcg2_riscv32.h
#elif defined(__riscv) && (__riscv_xlen == 64)
#include efi_miniapp_tcg2_riscv64.h
#endif

Best regards

Heinrich

>
>>
>>> new file mode 100644
>>> index 0000000000..926713c1c2
>>> --- /dev/null
>>> +++ b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>>> @@ -0,0 +1,93 @@
>>> +// SPDX-License-Identifier: GPL-2.0+
>>> +/*
>>> + * efi_selftest_miniapp_measuredboot
>>> + *
>>> + * Copyright (c) 2018 Heinrich Schuchardt
>>> + * Copyright (c) 2021 Masahisa Kojima
>>> + *
>>> + * This EFI application is run by the StartImage selftest.
>>
>> This is incorrect due to copy and paste.
>>
>>> + * It uses the Exit boot service to return and used for
>>> + * Measured Boot selftest.
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <efi_selftest.h>
>>> +
>>> +static efi_guid_t loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
>>> +
>>> +/**
>>> + * check_loaded_image_protocol() - check image_base/image_size
>>> + *
>>> + * Try to open the loaded image protocol. Check that this function is located
>>> + * between image_base and image_base + image_size.
>>> + *
>>> + * @image_handle:    handle of the loaded image
>>> + * @systable:                system table
>>> + * @return:          status code
>>> + */
>>> +static efi_status_t EFIAPI check_loaded_image_protocol
>>> +             (efi_handle_t image_handle, struct efi_system_table *systable)
>>> +{
>>> +     struct efi_simple_text_output_protocol *cout = systable->con_out;
>>> +     struct efi_boot_services *boottime = systable->boottime;
>>> +     struct efi_loaded_image *loaded_image_protocol;
>>> +     efi_status_t ret;
>>> +
>>> +     /*
>>> +      * Open the loaded image protocol.
>>> +      */
>>> +     ret = boottime->open_protocol
>>> +                             (image_handle, &loaded_image_protocol_guid,
>>> +                              (void **)&loaded_image_protocol, NULL,
>>> +                               NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             cout->output_string(cout,
>>> +                                 L"Could not open loaded image protocol");
>>> +             return ret;
>>> +     }
>>> +     if ((void *)check_loaded_image_protocol <
>>> +         loaded_image_protocol->image_base ||
>>> +         (void *)check_loaded_image_protocol >=
>>> +         loaded_image_protocol->image_base +
>>> +         loaded_image_protocol->image_size) {
>>> +             cout->output_string(cout,
>>> +                                 L"Incorrect image_base or image_size\n");
>>> +             return EFI_NOT_FOUND;
>>> +     }
>>> +     return EFI_SUCCESS;
>>> +}
>>> +
>>> +/**
>>> + * Entry point of the EFI application.
>>> + *
>>> + * @handle:  handle of the loaded image
>>> + * @systable:        system table
>>> + * @return:  status code
>>> + */
>>> +efi_status_t EFIAPI efi_main(efi_handle_t handle,
>>> +                          struct efi_system_table *systable)
>>> +{
>>> +     struct efi_simple_text_output_protocol *con_out = systable->con_out;
>>> +     efi_status_t ret;
>>> +     u16 text[] = EFI_ST_SUCCESS_STR;
>>> +
>>> +     con_out->output_string(con_out, L"EFI application calling Exit\n");
>>> +
>>> +     if (check_loaded_image_protocol(handle, systable) != EFI_SUCCESS) {
>>> +             con_out->output_string(con_out,
>>> +                                    L"Loaded image protocol missing\n");
>>> +             ret = EFI_NOT_FOUND;
>>> +             goto out;
>>> +     }
>>> +
>>> +     /* This return value is expected by the calling test */
>>> +     ret = EFI_UNSUPPORTED;
>>> +out:
>>> +     systable->boottime->exit(handle, ret, sizeof(text), text);
>>> +
>>> +     /*
>>> +      * This statement should not be reached.
>>> +      * To enable testing use a different return value.
>>> +      */
>>> +     return EFI_SUCCESS;
>>> +}
>>> diff --git a/lib/efi_selftest/efi_selftest_tcg2.c b/lib/efi_selftest/efi_selftest_tcg2.c
>>> index 1399309cec..50de735f5e 100644
>>> --- a/lib/efi_selftest/efi_selftest_tcg2.c
>>> +++ b/lib/efi_selftest/efi_selftest_tcg2.c
>>> @@ -9,10 +9,495 @@
>>>
>>>    #include <efi_selftest.h>
>>>    #include <efi_tcg2.h>
>>> +/* Include containing the miniapp.efi application */
>>> +#include "efi_miniapp_file_image_measuredboot.h"
>>
>> efi_miniapp_file_image_return.h
>
> As I said above, I will prepare static PE/COFF image only for the
> measurement purpose.
>
>>
>>> +
>>> +#include <linux/unaligned/access_ok.h>
>>> +#include <mapmem.h>
>>> +#include <smbios.h>
>>> +#include <tables_csum.h>
>>>
>>>    static struct efi_boot_services *boottime;
>>>    static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
>>>
>>> +/* Block size of compressed disk image */
>>> +#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
>>> +
>>> +static efi_handle_t image_handle;
>>> +/* Decompressed file image */
>>> +static u8 *image;
>>> +
>>> +/* One 8 byte block of the compressed disk image */
>>> +struct line {
>>> +     size_t addr;
>>> +     char *line;
>>> +};
>>> +
>>> +/* Compressed file image */
>>> +struct compressed_file_image {
>>> +     size_t length;
>>> +     struct line lines[];
>>> +};
>>> +
>>> +static struct compressed_file_image img = EFI_ST_DISK_IMG;
>>> +
>>> +static struct efi_tcg2_event *efi_tcg2_event;
>>> +
>>> +static struct efi_runtime_services *runtime;
>>> +#define BOOT_NAME_1000 u"Boot1000"
>>> +#define BOOT_NAME_1001 u"Boot1001"
>>> +#define BOOT_NAME_1002 u"Boot1002"
>>> +
>>> +#define DEFAULT_ATTR (EFI_VARIABLE_NON_VOLATILE | \
>>> +                   EFI_VARIABLE_BOOTSERVICE_ACCESS | \
>>> +                   EFI_VARIABLE_RUNTIME_ACCESS)
>>> +
>>> +/* "efidebug boot add -b 1000 test1000 virtio 0:1 /EFI/debian/grubaa64.efi" */
>>> +static const u8 boot_1000[] = {
>>> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
>>> +0x74, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
>>> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
>>> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
>>> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
>>> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
>>> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
>>> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
>>> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
>>> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
>>> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
>>> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
>>> +0xff, 0x04, 0x00 };
>>> +
>>> +/* "efidebug boot add -b 1001 test1001 virtio 0:1 /EFI/debian/grubaa64.efi" */
>>> +static const u8 boot_1001[] = {
>>> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
>>> +0x74, 0x00, 0x31, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
>>> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
>>> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
>>> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
>>> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
>>> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
>>> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
>>> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
>>> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
>>> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
>>> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
>>> +0xff, 0x04, 0x00 };
>>> +
>>> +/* "efidebug boot add -b 1002 test1002 virtio 0:1 /EFI/debian/grubaa64.efi" */
>>> +static const u8 boot_1002[] = {
>>> +0x01, 0x00, 0x00, 0x00, 0x8d, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
>>> +0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x01, 0x04, 0x14, 0x00, 0xb9, 0x73,
>>> +0x1d, 0xe6, 0x84, 0xa3, 0xcc, 0x4a, 0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3,
>>> +0x62, 0x8b, 0x01, 0x04, 0x15, 0x00, 0x92, 0x37, 0x29, 0x63, 0xf5, 0xad,
>>> +0x25, 0x93, 0xb9, 0x9f, 0x4e, 0x0e, 0x45, 0x5c, 0x1b, 0x1e, 0x00, 0x04,
>>> +0x01, 0x2a, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57,
>>> +0x5a, 0x47, 0xc2, 0x35, 0x27, 0x44, 0x47, 0x9f, 0x01, 0x67, 0xfe, 0xfa,
>>> +0x1d, 0x06, 0xae, 0x02, 0x02, 0x04, 0x04, 0x36, 0x00, 0x5c, 0x00, 0x45,
>>> +0x00, 0x46, 0x00, 0x49, 0x00, 0x5c, 0x00, 0x64, 0x00, 0x65, 0x00, 0x62,
>>> +0x00, 0x69, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x5c, 0x00, 0x67, 0x00, 0x72,
>>> +0x00, 0x75, 0x00, 0x62, 0x00, 0x61, 0x00, 0x61, 0x00, 0x36, 0x00, 0x34,
>>> +0x00, 0x2e, 0x00, 0x65, 0x00, 0x66, 0x00, 0x69, 0x00, 0x00, 0x00, 0x7f,
>>> +0xff, 0x04, 0x00};
>>> +
>>> +/* "efidebug boot order 1002 1000 1001" */
>>> +static u8 boot_order[] = {0x02, 0x10, 0x00, 0x10, 0x01, 0x10};
>>> +
>>> +static void *orig_smbios_table;
>>> +static u64 dmi_addr = U32_MAX;
>>> +#define SMBIOS_ENTRY_HEADER_SIZE 0x20
>>> +/* smbios table for the measurement test */
>>> +static u8 smbios_table_test[] = {
>>> +0x5f, 0x53, 0x4d, 0x5f, 0x2c, 0x1f, 0x03, 0x00, 0x54, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x5f, 0x44, 0x4d, 0x49, 0x5f, 0xe4, 0x5c, 0x01,
>>> +0x20, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
>>> +0x01, 0x02, 0x00, 0x00, 0x03, 0x00, 0x80, 0x08, 0x01, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x0c, 0x15, 0x0a, 0xff, 0xff, 0x55, 0x2d, 0x42, 0x6f,
>>> +0x6f, 0x74, 0x00, 0x32, 0x30, 0x32, 0x31, 0x2e, 0x31, 0x30, 0x2d, 0x72,
>>> +0x63, 0x34, 0x2d, 0x30, 0x30, 0x30, 0x30, 0x35, 0x2d, 0x67, 0x37, 0x32,
>>> +0x37, 0x63, 0x33, 0x66, 0x33, 0x32, 0x35, 0x39, 0x2d, 0x64, 0x69, 0x72,
>>> +0x74, 0x79, 0x00, 0x31, 0x30, 0x2f, 0x30, 0x31, 0x2f, 0x32, 0x30, 0x32,
>>> +0x31, 0x00, 0x00, 0x01, 0x1b, 0x01, 0x00, 0x01, 0x02, 0x00, 0x03, 0x31,
>>> +0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
>>> +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
>>> +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
>>> +0x37, 0x38, 0x00, 0x00, 0x02, 0x0e, 0x02, 0x00, 0x01, 0x02, 0x00, 0x04,
>>> +0x03, 0x01, 0x01, 0x01, 0x00, 0x0a, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77,
>>> +0x6e, 0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x20, 0x50, 0x72,
>>> +0x6f, 0x64, 0x75, 0x63, 0x74, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
>>> +0x33, 0x33, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x00,
>>> +0x00, 0x03, 0x15, 0x03, 0x00, 0x01, 0x03, 0x00, 0x02, 0x03, 0x03, 0x03,
>>> +0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x6e,
>>> +0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36,
>>> +0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x00,
>>> +0x00, 0x04, 0x30, 0x04, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +0x00, 0x01, 0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x02, 0x03, 0x04,
>>> +0x04, 0x04, 0x08, 0x00, 0x00, 0x02, 0x00, 0x08, 0x00, 0x08, 0x00, 0x01,
>>> +0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x00, 0x31, 0x32, 0x33,
>>> +0x34, 0x35, 0x36, 0x37, 0x38, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
>>> +0x33, 0x33, 0x00, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x00,
>>> +0x00, 0x20, 0x0b, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +0x00, 0x00, 0x7f, 0x04, 0x06, 0x00, 0x00, 0x00
>>> +};
>>> +
>>> +#define TPM2_CMD_BUF_SIZE 64
>>> +/* TPM command is big endian */
>>> +#define __MSB(x) ((x) >> 8)
>>> +#define __LSB(x) ((x) & 0xFF)
>>> +#define tpm_u16(x) __MSB(x), __LSB(x)
>>> +#define tpm_u32(x) tpm_u16((x) >> 16), tpm_u16((x) & 0xFFFF)
>>> +#define TPM2_PCR_READ_HEADER_SIZE 30
>>> +
>>> +static u8 *pcrs;
>>> +static u8 expected_pcrs[EFI_TCG2_MAX_PCR_INDEX + 1][TPM2_SHA256_DIGEST_SIZE] = {
>>> +     {0x91, 0x21, 0x37, 0xc7, 0x1a, 0x49, 0x19, 0xc8,
>>> +      0xf1, 0xfb, 0xa9, 0x84, 0x5c, 0x65, 0xa9, 0xdd,
>>> +      0x7b, 0xb9, 0xfe, 0xa1, 0xcd, 0x64, 0x49, 0xdd,
>>> +      0xed, 0xe2, 0x65, 0x82, 0xc5, 0x3e, 0xf4, 0xc4},
>>> +
>>> +     {0xf5, 0x79, 0xf3, 0x20, 0x62, 0x6e, 0x8b, 0x58,
>>> +      0x62, 0xa3, 0x4e, 0x2f, 0xb7, 0x10, 0xac, 0x34,
>>> +      0x4e, 0x68, 0x94, 0x37, 0x87, 0x29, 0xc4, 0xbe,
>>> +      0xa3, 0xc4, 0xd9, 0x14, 0x2b, 0x66, 0x79, 0x9b},
>>> +
>>> +     {0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
>>> +      0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
>>> +      0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
>>> +      0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
>>> +
>>> +     {0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
>>> +      0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
>>> +      0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
>>> +      0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
>>> +
>>> +     {0xbe, 0xea, 0xdc, 0xe0, 0x44, 0x5b, 0x5f, 0x14,
>>> +      0xef, 0x24, 0x5d, 0x13, 0x15, 0xfe, 0x41, 0x86,
>>> +      0xc2, 0xd5, 0xdc, 0x0d, 0x04, 0x2f, 0xd4, 0x04,
>>> +      0x0d, 0x02, 0x62, 0xc0, 0x34, 0x80, 0xee, 0xd5},
>>> +
>>> +     {0x3d, 0x45, 0x8c, 0xfe, 0x55, 0xcc, 0x03, 0xea,
>>> +      0x1f, 0x44, 0x3f, 0x15, 0x62, 0xbe, 0xec, 0x8d,
>>> +      0xf5, 0x1c, 0x75, 0xe1, 0x4a, 0x9f, 0xcf, 0x9a,
>>> +      0x72, 0x34, 0xa1, 0x3f, 0x19, 0x8e, 0x79, 0x69},
>>> +
>>> +     {0x8d, 0x28, 0xde, 0x72, 0x22, 0x3e, 0x88, 0x1a,
>>> +      0x37, 0xfa, 0x47, 0x12, 0x68, 0x45, 0xdf, 0x71,
>>> +      0x50, 0x8f, 0xab, 0x59, 0x50, 0x7b, 0x52, 0x32,
>>> +      0xa6, 0xaa, 0x03, 0x3d, 0x4e, 0x22, 0x89, 0xd7},
>>> +
>>> +     {0x96, 0x74, 0xae, 0xcd, 0x3f, 0x40, 0xb4, 0xa9,
>>> +      0x36, 0xae, 0x19, 0xc8, 0x84, 0x8a, 0xb9, 0x5a,
>>> +      0x87, 0x99, 0xd8, 0x89, 0x7f, 0xfc, 0x40, 0x48,
>>> +      0x05, 0x99, 0x65, 0x2e, 0x55, 0xd4, 0x93, 0x32},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +
>>> +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> +     {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>>> +      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
>>> +
>>> +     {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>> +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
>>> +};
>>> +
>>> +struct boot_variable {
>>> +     u16 name[16];
>>> +     u8 *buf;
>>> +     efi_uintn_t size;
>>> +     u32 attr;
>>> +     const u8 *test_data;
>>> +     efi_uintn_t test_data_size;
>>> +};
>>> +
>>> +static struct boot_variable boot_variable_test[] = {
>>> +     {u"BootOrder",          NULL, 0, DEFAULT_ATTR, boot_order, sizeof(boot_order)},
>>> +     {BOOT_NAME_1000,        NULL, 0, DEFAULT_ATTR, boot_1000, sizeof(boot_1000)},
>>> +     {BOOT_NAME_1001,        NULL, 0, DEFAULT_ATTR, boot_1001, sizeof(boot_1001)},
>>> +     {BOOT_NAME_1002,        NULL, 0, DEFAULT_ATTR, boot_1002, sizeof(boot_1002)},
>>> +};
>>> +
>>> +/*
>>> + * Decompress the disk image.
>>> + *
>>> + * @image    decompressed disk image
>>> + * @return   status code
>>> + */
>>> +static efi_status_t decompress(u8 **image)
>>> +{
>>> +     u8 *buf;
>>> +     size_t i;
>>> +     size_t addr;
>>> +     size_t len;
>>> +     efi_status_t ret;
>>> +
>>> +     ret = boottime->allocate_pool(EFI_LOADER_DATA, img.length,
>>> +                                   (void **)&buf);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("Out of memory\n");
>>> +             return ret;
>>> +     }
>>> +     boottime->set_mem(buf, img.length, 0);
>>> +
>>> +     for (i = 0; ; ++i) {
>>> +             if (!img.lines[i].line)
>>> +                     break;
>>> +             addr = img.lines[i].addr;
>>> +             len = COMPRESSED_DISK_IMAGE_BLOCK_SIZE;
>>> +             if (addr + len > img.length)
>>> +                     len = img.length - addr;
>>> +             boottime->copy_mem(buf + addr, img.lines[i].line, len);
>>> +     }
>>> +     *image = buf;
>>> +     return ret;
>>> +}
>>> +
>>> +/*
>>> + * Configure dummy boot variables.
>>
>> /**
>>    * efi_status_t setup_boot_variable() - configure dummy boot variables
>>    *
>>    * Preexisting variable values are saved and will be restored by
>>    * calling restore_boot_variable().
>>    *
>>
>>> + *
>>> + * @return   status code
>>> + */
>>> +static efi_status_t setup_boot_variable(void)
>>> +{
>>> +     efi_status_t ret;
>>> +     u32 i;
>>> +     efi_uintn_t size;
>>> +     u8 dummy;
>>
>> This variable is superfluous.
>>
>>> +
>>> +     for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
>>> +             size = 1;
>>
>> Please, set size to 0.
>>
>>> +             ret = runtime->get_variable(boot_variable_test[i].name,
>>> +                                         &efi_global_variable_guid,
>>> +                                         &boot_variable_test[i].attr,
>>> +                                         &size,
>>> +                                         &dummy);
>>
>> Instead of dummy you can use NULL if size = 0.
>>
>>> +             if (ret == EFI_BUFFER_TOO_SMALL) {
>>> +                     /* Variable exists, save the current vaiable */
>>
>> %s/vaiable/value/
>>
>>> +                     boot_variable_test[i].size = size;
>>> +                     ret = boottime->allocate_pool(EFI_LOADER_DATA,
>>> +                                                   boot_variable_test[i].size,
>>> +                                                   (void **)&boot_variable_test[i].buf);
>>> +                     if (ret != EFI_SUCCESS) {
>>> +                             efi_st_error("fail to allocate buffer for boot variable\n");
>>
>> In all other tests we use 'Failed to'
>>
>> %s/fail/Failed/
>>
>>> +                             return ret;
>>> +                     }
>>> +                     ret = runtime->get_variable(boot_variable_test[i].name,
>>> +                                                 &efi_global_variable_guid,
>>> +                                                 &boot_variable_test[i].attr,
>>> +                                                 &boot_variable_test[i].size,
>>> +                                                 boot_variable_test[i].buf);
>>> +                     if (ret != EFI_SUCCESS) {
>>> +                             efi_st_error("fail to get current boot variable\n");
>>
>> %s/fail/Failed/
>>
>>
>>> +                             return ret;
>>> +                     }
>>> +             }
>>> +
>>> +             /* set boot variable for the measurement test */
>>> +             ret = runtime->set_variable(boot_variable_test[i].name,
>>> +                                         &efi_global_variable_guid,
>>> +                                         boot_variable_test[i].attr,
>>> +                                         boot_variable_test[i].test_data_size,
>>> +                                         boot_variable_test[i].test_data);
>>> +             if (ret != EFI_SUCCESS) {
>>> +                     efi_st_error("### fail to set test boot variable(%d)n", i);
>>
>> %s/### fail/Failed/
>>
>>> +                     return ret;
>>> +             }
>>> +     }
>>> +
>>> +     return 0;
>>> +}
>>> +
>>> +/*
>>
>> /**
>>    * efi_status_t restore_boot_variable() - restore original values
>>    *
>>    * Restore the variable values saved in setup_boot_variable().
>>    *
>>
>>> + * Restore original boot variables.
>>> + *
>>> + * @return   status code
>>> + */
>>> +efi_status_t restore_boot_variable(void)
>>> +{
>>> +     int i;
>>> +     efi_status_t ret;
>>> +
>>> +     for (i = 0; i < ARRAY_SIZE(boot_variable_test); i++) {
>>> +             if (boot_variable_test[i].buf) {
>>> +                     ret = runtime->set_variable(boot_variable_test[i].name,
>>> +                                                 &efi_global_variable_guid,
>>> +                                                 boot_variable_test[i].attr,
>>> +                                                 boot_variable_test[i].size,
>>> +                                                 boot_variable_test[i].buf);
>>> +                     if (ret != EFI_SUCCESS) {
>>> +                             efi_st_error("### fail to restore boot variable\n");
>>> +                             return ret;
>>> +                     }
>>> +                     ret = boottime->free_pool(boot_variable_test[i].buf);
>>> +                     if (ret != EFI_SUCCESS) {
>>> +                             efi_st_error("Failed to free boot variable\n");
>>> +                             return ret;
>>> +                     }
>>> +             } else {
>>> +                     /* delete the variable used only for testing */
>>> +                     ret = runtime->set_variable(boot_variable_test[i].name,
>>> +                                                 &efi_global_variable_guid,
>>> +                                                 0, 0, NULL);
>>> +                     if (ret != EFI_SUCCESS) {
>>> +                             efi_st_error("### fail to delete boot variable\n");
>>
>> %s/### fail/Failed/
>>
>>> +                             return ret;
>>> +                     }
>>> +             }
>>> +     }
>>> +
>>> +     return EFI_SUCCESS;
>>> +}
>>> +
>>> +/**
>>> + * Find smbios table
>>> + *
>>> + * @systable system table
>>> + * @return   status code
>>> + */
>>> +static void *find_smbios_table(const struct efi_system_table *systable)
>>> +{
>>> +     u32 i;
>>> +
>>> +     for (i = 0; i < systable->nr_tables; i++) {
>>> +             if (!guidcmp(&smbios_guid, &systable->tables[i].guid))
>>> +                     return systable->tables[i].table;
>>> +     }
>>> +
>>> +     return NULL;
>>> +}
>>> +
>>> +/**
>>> + * Prepare the dummy SMBIOS table
>>> + *
>>> + * @systable system table
>>> + * @return   status code
>>> + */
>>> +efi_status_t setup_smbios_table(const struct efi_system_table *systable)
>>> +{
>>> +     struct smbios_entry *se;
>>> +     efi_status_t ret;
>>> +     /* Map within the low 32 bits, to allow for 32bit SMBIOS tables */
>>> +     void *dmi;
>>> +     char *istart;
>>> +     int isize;
>>> +
>>> +     if (sizeof(smbios_table_test) > EFI_PAGE_SIZE)
>>> +             return EFI_OUT_OF_RESOURCES;
>>> +
>>> +     orig_smbios_table = find_smbios_table(systable);
>>> +
>>> +     /* Reserve 4kiB page for SMBIOS */
>>> +     ret = boottime->allocate_pages(EFI_ALLOCATE_MAX_ADDRESS,
>>> +                              EFI_RUNTIME_SERVICES_DATA, 1, &dmi_addr);
>>> +
>>> +     if (ret != EFI_SUCCESS) {
>>> +             /* Could not find space in lowmem, use highmem instead */
>>> +             ret = boottime->allocate_pages(EFI_ALLOCATE_ANY_PAGES,
>>> +                                      EFI_RUNTIME_SERVICES_DATA, 1,
>>> +                                      &dmi_addr);
>>> +
>>> +             if (ret != EFI_SUCCESS)
>>> +                     return ret;
>>> +     }
>>> +
>>> +     dmi = (void *)(uintptr_t)dmi_addr;
>>> +     se = dmi;
>>> +     boottime->copy_mem(se, smbios_table_test, sizeof(smbios_table_test));
>>> +
>>> +     /* update smbios table start address */
>>> +     se->struct_table_address = (uintptr_t)((u8 *)dmi + SMBIOS_ENTRY_HEADER_SIZE);
>>> +
>>> +     /* calculate checksums */
>>> +     istart = (char *)se + SMBIOS_INTERMEDIATE_OFFSET;
>>> +     isize = sizeof(struct smbios_entry) - SMBIOS_INTERMEDIATE_OFFSET;
>>> +     se->intermediate_checksum = table_compute_checksum(istart, isize);
>>> +     se->checksum = table_compute_checksum(se, sizeof(struct smbios_entry));
>>> +
>>> +     /* Install SMBIOS information as configuration table */
>>> +     ret = boottime->install_configuration_table(&smbios_guid, dmi);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("Cannot install SMBIOS table\n");
>>> +             boottime->free_pages(dmi_addr, 1);
>>> +     }
>>> +
>>> +     return ret;
>>> +}
>>> +
>>>    /**
>>>     * efi_st_tcg2_setup() - setup test
>>>     *
>>> @@ -23,7 +508,171 @@ static const efi_guid_t guid_tcg2 = EFI_TCG2_PROTOCOL_GUID;
>>>    static int efi_st_tcg2_setup(const efi_handle_t img_handle,
>>>                             const struct efi_system_table *systable)
>>>    {
>>> +     efi_status_t ret;
>>> +     struct uefi_image_load_event image_load_event;
>>> +
>>> +     image_handle = img_handle;
>>>        boottime = systable->boottime;
>>> +     runtime = systable->runtime;
>>> +
>>> +     /* Load the application image into memory */
>>> +     decompress(&image);
>>> +
>>> +     ret = boottime->allocate_pool(EFI_LOADER_DATA,
>>> +                                   sizeof(struct efi_tcg2_event) +
>>> +                                   sizeof(struct uefi_image_load_event),
>>> +                                   (void **)&efi_tcg2_event);
>>> +     if (!efi_tcg2_event)
>>> +             return EFI_ST_FAILURE;
>>> +
>>> +     efi_tcg2_event->size = sizeof(struct efi_tcg2_event) +
>>> +                            sizeof(struct uefi_image_load_event);
>>> +     efi_tcg2_event->header.header_size = sizeof(struct efi_tcg2_event_header);
>>> +     efi_tcg2_event->header.header_version = 1;
>>> +     efi_tcg2_event->header.pcr_index = 6;
>>> +     efi_tcg2_event->header.event_type = EV_EFI_RUNTIME_SERVICES_DRIVER;
>>> +     image_load_event.image_location_in_memory = 0x12345678;
>>> +     image_load_event.image_length_in_memory = 0x300000;
>>> +     image_load_event.image_link_time_address = 0x87654321;
>>> +     image_load_event.length_of_device_path = 0;
>>> +     boottime->copy_mem(efi_tcg2_event->event, &image_load_event,
>>> +                        sizeof(struct uefi_image_load_event));
>>> +
>>> +     ret = setup_boot_variable();
>>> +     if (ret != EFI_SUCCESS)
>>> +             return EFI_ST_FAILURE;
>>> +
>>> +     ret = setup_smbios_table(systable);
>>> +     if (ret != EFI_SUCCESS)
>>> +             return EFI_ST_FAILURE;
>>> +
>>> +     ret = boottime->allocate_pool(EFI_LOADER_DATA,
>>> +                                   (EFI_TCG2_MAX_PCR_INDEX + 1) *
>>> +                                   TPM2_SHA256_DIGEST_SIZE,
>>> +                                   (void **)&pcrs);
>>> +     if (!pcrs)
>>> +             return EFI_ST_FAILURE;
>>> +
>>> +     boottime->set_mem(pcrs, (EFI_TCG2_MAX_PCR_INDEX + 1) * TPM2_SHA256_DIGEST_SIZE, 0);
>>> +
>>> +     return EFI_ST_SUCCESS;
>>> +}
>>> +
>>> +/**
>>> + * Get manufacturer_id through submit_command API
>>> + *
>>> + * @tcg2             tcg2 protocol
>>> + * @manufacturer_id  pointer to the manufacturer_id
>>> + * @return           status code
>>> + */
>>> +static efi_status_t get_manufacturer_id(struct efi_tcg2_protocol *tcg2, u32 *manufacturer_id)
>>> +{
>>> +     efi_status_t ret;
>>> +     u8 cmd[TPM2_CMD_BUF_SIZE] = {
>>> +             tpm_u16(TPM2_ST_NO_SESSIONS),           /* TAG */
>>> +             tpm_u32(22),                            /* Length */
>>> +             tpm_u32(TPM2_CC_GET_CAPABILITY),        /* Command code */
>>> +
>>> +             tpm_u32(TPM2_CAP_TPM_PROPERTIES),       /* Capability */
>>> +             tpm_u32(TPM2_PT_MANUFACTURER),          /* Property */
>>> +             tpm_u32(1),                     /* Property count */
>>> +     };
>>> +     u8 resp[TPM2_CMD_BUF_SIZE];
>>> +     unsigned int value_off;
>>> +
>>> +     ret = tcg2->submit_command(tcg2, 22, cmd,
>>> +                                TPM2_CMD_BUF_SIZE, resp);
>>> +     if (ret != EFI_SUCCESS)
>>> +             return ret;
>>> +
>>> +     /*
>>> +      * In the response buffer, the properties are located after the:
>>> +      * tag (u16), response size (u32), response code (u32),
>>> +      * YES/NO flag (u8), TPM_CAP (u32).
>>> +      * The value is located after count (u32), property (u32).
>>> +      */
>>> +     value_off = sizeof(u16) + sizeof(u32) + sizeof(u32) +
>>> +                      sizeof(u8) + sizeof(u32) + sizeof(u32) + sizeof(u32);
>>> +     *manufacturer_id = get_unaligned_be32(&resp[value_off]);
>>> +
>>> +     return ret;
>>> +}
>>> +
>>> +/**
>>> + * Read the PCR from the TPM device
>>> + *
>>> + * @tcg2     tcg2 protocol
>>> + * @idx              pcr index to read
>>> + * @return   status code
>>> + */
>>> +static efi_status_t read_pcr(struct efi_tcg2_protocol *tcg2, u32 idx)
>>> +{
>>> +     efi_status_t ret;
>>> +     u8 idx_array_sz = 3; /* support 24 PCRs */
>>
>> This is a constant.
>>
>> #define IDX_ARRAY_SZ 3
>>
>> You can move it close to the TPM2_CMD_BUF_SIZE definition.
>>
>>> +     u32 cmd_len = 17 + idx_array_sz;
>>> +     u8 cmd[TPM2_CMD_BUF_SIZE] = {
>>> +             tpm_u16(TPM2_ST_NO_SESSIONS),   /* TAG */
>>> +             tpm_u32(cmd_len),               /* Length */
>>> +             tpm_u32(TPM2_CC_PCR_READ),      /* Command code */
>>> +             /* TPML_PCR_SELECTION */
>>> +             tpm_u32(1),                     /* Number of selections */
>>> +             tpm_u16(TPM2_ALG_SHA256),       /* Algorithm of the hash */
>>> +             idx_array_sz,                   /* Array size for selection */
>>> +             /* bitmap(idx),                    Selected PCR bitmap */
>>> +     };
>>> +     u8 resp[TPM2_CMD_BUF_SIZE];
>>> +     u32 pcr_sel_idx = idx / 8;
>>> +     u8 pcr_sel_bit = BIT(idx % 8);
>>> +     u8 *dst;
>>> +
>>> +     cmd[17 + pcr_sel_idx] = pcr_sel_bit;
>>> +     ret = tcg2->submit_command(tcg2, cmd_len, cmd,
>>> +                                TPM2_CMD_BUF_SIZE, resp);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("tcg2->submit_command fail to read PCR\n");
>>> +             return ret;
>>> +     }
>>> +
>>> +     dst = pcrs + (idx * TPM2_SHA256_DIGEST_SIZE);
>>> +     boottime->copy_mem(dst, &resp[TPM2_PCR_READ_HEADER_SIZE],
>>> +                        TPM2_SHA256_DIGEST_SIZE);
>>> +
>>> +     return ret;
>>> +}
>>> +
>>> +/**
>>> + * Compare the expected and actual pcrs
>>> + *
>>> + * @return   status code
>>> + */
>>> +static int validate_pcrs(void)
>>> +{
>>> +     u32 i;
>>> +     u8 *expected = (u8 *)expected_pcrs;
>>> +     u8 *result = pcrs;
>>
>> Making expected_pcrs and pcrs arrays with elements of size
>> TPM2_SHA256_DIGEST_SIZE can replace these pointers.
>>
>>> +
>>> +     /*
>>> +      *  - Skip PCR[0] validation. PCR[0] contains U-Boot version measurement
>>> +      *    it contains the commit hash, so the measurement varies every build
>>> +      *    with different commit hash.
>>> +      *  - Skip PCR[7] validation. PCR[7] contains UEFI Secure Boot variables
>>> +      *    measurement. These variables can not be updated through efi_selftest and
>>> +      *    it varies depending on the platform.
>>
>> %s/it varies/vary/
>>
>>> +      */
>>> +     for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {
>>
>> for (i = 1; i < (EFI_TCG2_MAX_PCR_INDEX + 1); ++i) {
>>     if (i != 7)
>>          continue;
>>     if (memcmp(pcr[i], expected_pcr[i], PM2_SHA256_DIGEST_SIZE)) {
>>       if (memcmp(expected, result, TPM2_SHA256_DIGEST_SIZE)) {
>>         efi_st_printf("PCR[%d] is not the expected value\n", i);
>>         return EFI_ST_FAILURE;
>>       }
>>     }
>> }
>>
>>> +             result = pcrs + (TPM2_SHA256_DIGEST_SIZE * i);
>>> +             if (i == 0 || i == 7) {
>>> +                     expected += TPM2_SHA256_DIGEST_SIZE;
>>> +                     result += TPM2_SHA256_DIGEST_SIZE;
>>> +                     continue; /* skip validation */
>>> +             }
>>> +             if (memcmp(expected, result, TPM2_SHA256_DIGEST_SIZE)) {
>>> +                     efi_st_printf("PCR[%d] is not the expected value\n", i);
>>> +                     return EFI_ST_FAILURE;
>>> +             }
>>> +             expected += TPM2_SHA256_DIGEST_SIZE;
>>> +             result += TPM2_SHA256_DIGEST_SIZE;
>>> +     }
>>>
>>>        return EFI_ST_SUCCESS;
>>>    }
>>> @@ -31,7 +680,8 @@ static int efi_st_tcg2_setup(const efi_handle_t img_handle,
>>>    /**
>>>     * efi_st_tcg2_execute() - execute test
>>>     *
>>> - * Call the GetCapability service of the EFI_TCG2_PROTOCOL.
>>> + * Call EFI_TCG2_PROTOCOL services and check the
>>> + * Measured Boot behavior.
>>>     *
>>>     * Return:  status code
>>>     */
>>> @@ -40,12 +690,22 @@ static int efi_st_tcg2_execute(void)
>>>        struct efi_tcg2_protocol *tcg2;
>>>        struct efi_tcg2_boot_service_capability capability;
>>>        efi_status_t ret;
>>> +     u32 active_pcr_banks;
>>> +     u64 eventlog, eventlog_last_entry;
>>> +     bool eventlog_truncated;
>>> +     efi_handle_t handle;
>>> +     efi_uintn_t exit_data_size = 0;
>>> +     u16 *exit_data = NULL;
>>> +     u32 i;
>>> +     u32 manufacturer_id;
>>>
>>>        ret = boottime->locate_protocol(&guid_tcg2, NULL, (void **)&tcg2);
>>>        if (ret != EFI_SUCCESS) {
>>>                efi_st_error("TCG2 protocol is not available.\n");
>>>                return EFI_ST_FAILURE;
>>>        }
>>> +
>>> +     /* EFI_TCG2_PROTOCOL.GetCapability test */
>>>        capability.size = sizeof(struct efi_tcg2_boot_service_capability) - 1;
>>>        ret = tcg2->get_capability(tcg2, &capability);
>>>        if (ret != EFI_BUFFER_TOO_SMALL) {
>>> @@ -64,12 +724,154 @@ static int efi_st_tcg2_execute(void)
>>>        }
>>>        efi_st_printf("TPM supports 0x%.8x event logs\n",
>>>                      capability.supported_event_logs);
>>> +
>>> +     /* EFI_TCG2_PROTOCOL.GetActivePcrBanks test */
>>> +     ret = tcg2->get_active_pcr_banks(tcg2, &active_pcr_banks);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("tcg2->get_active_pcr_banks failed\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +     if (active_pcr_banks != capability.active_pcr_banks) {
>>> +             efi_st_error("tcg2->get_active_pcr_banks return wrong value\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +
>>> +     /* EFI_TCG2_PROTOCOL.HashLogExtendEvent test */
>>> +     ret = tcg2->hash_log_extend_event(tcg2, EFI_TCG2_EXTEND_ONLY,
>>> +                                       (uintptr_t)image,
>>> +                                       img.length, efi_tcg2_event);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("tcg2->hash_log_extend_event(EXTEND_ONLY) failed\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +
>>> +     ret = tcg2->hash_log_extend_event(tcg2, PE_COFF_IMAGE, (uintptr_t)image,
>>> +                                       img.length, efi_tcg2_event);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("tcg2->hash_log_extend_event(PE_COFF_IMAGE) failed\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +
>>> +     /* EFI_TCG2_PROTOCOL.SubmitCommand test */
>>> +     ret = get_manufacturer_id(tcg2, &manufacturer_id);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("get_manufacturer_id failed\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +     if (capability.manufacturer_id != manufacturer_id) {
>>> +             efi_st_error("tcg2->submit_command test failed\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +
>>> +     /* tcg2_measure_pe_image test */
>>> +     ret = boottime->load_image(false, image_handle, NULL, image,
>>> +                                img.length, &handle);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("Failed to load image\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +
>>> +     /* measure ready_to_boot event(boot variables, smbios table, etc.) */
>>> +     /* TODO: add GPT measurement test */
>>
>> lib/efi_selftest/efi_selftest_block_device.c shows how to setup a memory
>> based block device.
>
> Thank you for the information.
> I tried to copy efi_selftest_block_device but I encountered error.
>
> To test GPT measurement, I need to add the device path node having
> following type.
>      dp->type == DEVICE_PATH_TYPE_MEDIA_DEVICE
>      dp->sub_type == DEVICE_PATH_SUB_TYPE_HARD_DRIVE_PATH
> If I added this node in the device path,
> boottime->connect_controller() returns EFI_NOT_FOUND
> and I'm investigating how to use connect_controller.
>
> For other comments, I will include fixes in the next version.
>
> Thanks,
> Masahisa Kojima
>
>>
>>> +     ret = boottime->start_image(handle, &exit_data_size, &exit_data);
>>> +     if (ret != EFI_UNSUPPORTED) {
>>> +             efi_st_error("Wrong return value from application\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +     ret = boottime->free_pool(exit_data);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("Failed to free exit data\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +
>>> +     /* validate PCR read from the TPM device */
>>> +     for (i = 0; i < (EFI_TCG2_MAX_PCR_INDEX + 1); i++) {
>>> +             ret = read_pcr(tcg2, i);
>>> +             if (ret != EFI_SUCCESS) {
>>> +                     efi_st_error("read pcr error\n");
>>> +                     return EFI_ST_FAILURE;
>>> +             }
>>> +     }
>>> +     if (validate_pcrs()) {
>>> +             efi_st_error("PCR validation failed\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +
>>> +     /* EFI_TCG2_PROTOCOL.GetEventLog test */
>>> +     ret = tcg2->get_eventlog(tcg2, TCG2_EVENT_LOG_FORMAT_TCG_2, &eventlog,
>>> +                              &eventlog_last_entry, &eventlog_truncated);
>>> +     if (ret != EFI_SUCCESS) {
>>> +             efi_st_error("tcg2->get_eventlog failed\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +     /* TODO: eventlog format check */
>>> +
>>>        return EFI_ST_SUCCESS;
>>>    }
>>>
>>> +/*
>>> + * Tear down unit test.
>>
>> /**
>>    * efi_st_tcg2_teardown() - tear down unit test
>>    *
>>
>> Overall the design looks good to me.
>>
>> Best regards
>>
>> Heinrich
>>
>>> + *
>>> + * @return:  EFI_ST_SUCCESS for success
>>> + */
>>> +static int efi_st_tcg2_teardown(void)
>>> +{
>>> +     efi_status_t r = EFI_ST_SUCCESS;
>>> +
>>> +     if (image) {
>>> +             r = boottime->free_pool(image);
>>> +             if (r != EFI_SUCCESS) {
>>> +                     efi_st_error("Failed to free image\n");
>>> +                     return EFI_ST_FAILURE;
>>> +             }
>>> +     }
>>> +     if (efi_tcg2_event) {
>>> +             r = boottime->free_pool(efi_tcg2_event);
>>> +             if (r != EFI_SUCCESS) {
>>> +                     efi_st_error("Failed to free efi_tcg2_event\n");
>>> +                     return EFI_ST_FAILURE;
>>> +             }
>>> +     }
>>> +     if (pcrs) {
>>> +             r = boottime->free_pool(pcrs);
>>> +             if (r != EFI_SUCCESS) {
>>> +                     efi_st_error("Failed to free pcr\n");
>>> +                     return EFI_ST_FAILURE;
>>> +             }
>>> +     }
>>> +
>>> +     r = restore_boot_variable();
>>> +     if (r != EFI_SUCCESS) {
>>> +             efi_st_error("Failed to restore boot variables\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +
>>> +     /*
>>> +      * Restore SMBIOS table
>>> +      * If orig_smbios_table is NULL, calling install_configuration_table()
>>> +      * removes dummy SMBIOS table form systab.
>>> +      */
>>> +     r = boottime->install_configuration_table(&smbios_guid, orig_smbios_table);
>>> +     if (r != EFI_SUCCESS) {
>>> +             efi_st_error("Failed to restore SMBOIS table\n");
>>> +             return EFI_ST_FAILURE;
>>> +     }
>>> +
>>> +     if (dmi_addr) {
>>> +             r = boottime->free_pages(dmi_addr, 1);
>>> +             if (r != EFI_SUCCESS) {
>>> +                     efi_st_error("Failed to free dummy smbios table\n");
>>> +                     return EFI_ST_FAILURE;
>>> +             }
>>> +     }
>>> +
>>> +     return r;
>>> +}
>>> +
>>>    EFI_UNIT_TEST(tcg2) = {
>>>        .name = "tcg2",
>>>        .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
>>>        .execute = efi_st_tcg2_execute,
>>>        .setup = efi_st_tcg2_setup,
>>> +     .teardown = efi_st_tcg2_teardown,
>>>    };
>>>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-10-25  9:43       ` Heinrich Schuchardt
@ 2021-10-30  6:02         ` Ilias Apalodimas
  2021-10-30  6:13           ` Heinrich Schuchardt
  0 siblings, 1 reply; 16+ messages in thread
From: Ilias Apalodimas @ 2021-10-30  6:02 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Masahisa Kojima, Simon Glass, Alexander Graf, U-Boot Mailing List

Hi Heinrich

[...]

> >>> +$(obj)/efi_selftest_tcg2.o: $(obj)/efi_miniapp_file_image_measuredboot.h
> >>> diff --git a/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
> >>
> >> Thank you for going the extra mile and adding the test.
> >>
> >> Which image is actually loaded seems to be irrelevant for the test. Can
> >> we reuse an existing one, e.g. efi_miniapp_file_image_return.h?
> >>
> >> I guess the PCR related to the loaded image is not checked as it will
> >> depend on the build tools and date.
> >
> > Sorry, I'm doing wrong.
> > Actually this selftest verifies the PE/COFF image measurement, so measuremt
> > will be different depending on the build tools and date.
> >   # In my build environment, timestamp is set to all zero.
> >
> > To test the PE/COFF image measurement, I must prepare the
> > static PE/COFF image. I plan to add efi_miniapp_file_image_measuredboot.h
> > as a pre-compiled small static PE/COFF image for the measurement test,
> > instead of adding efi_selftest_miniapp_measuredboot.c or reusing existing one.
>
> You will need one image per UEFI architecture (ia32, x64, arm, aa64,
> riscv32, riscv64). You could present the image via the
> EFI_LOAD_FILE2_PROTOCOL, see lib/efi_selftest/efi_selftest_load_file.c.

The EFI TCG2 is governed by a spec.  What it basically does is extend
a number of hardware PCRs with a sha1/256/384/512 for a given image.
Wouldn't performing the selftest for arm/arm64 be enough?  What am I
missing?

[...]

Regards
/Ilias

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-10-30  6:02         ` Ilias Apalodimas
@ 2021-10-30  6:13           ` Heinrich Schuchardt
  2021-11-01  9:38             ` Masahisa Kojima
  0 siblings, 1 reply; 16+ messages in thread
From: Heinrich Schuchardt @ 2021-10-30  6:13 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Masahisa Kojima, Simon Glass, Alexander Graf, U-Boot Mailing List



Am 30. Oktober 2021 08:02:02 MESZ schrieb Ilias Apalodimas <ilias.apalodimas@linaro.org>:
>Hi Heinrich
>
>[...]
>
>> >>> +$(obj)/efi_selftest_tcg2.o: $(obj)/efi_miniapp_file_image_measuredboot.h
>> >>> diff --git a/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
>> >>
>> >> Thank you for going the extra mile and adding the test.
>> >>
>> >> Which image is actually loaded seems to be irrelevant for the test. Can
>> >> we reuse an existing one, e.g. efi_miniapp_file_image_return.h?
>> >>
>> >> I guess the PCR related to the loaded image is not checked as it will
>> >> depend on the build tools and date.
>> >
>> > Sorry, I'm doing wrong.
>> > Actually this selftest verifies the PE/COFF image measurement, so measuremt
>> > will be different depending on the build tools and date.
>> >   # In my build environment, timestamp is set to all zero.
>> >
>> > To test the PE/COFF image measurement, I must prepare the
>> > static PE/COFF image. I plan to add efi_miniapp_file_image_measuredboot.h
>> > as a pre-compiled small static PE/COFF image for the measurement test,
>> > instead of adding efi_selftest_miniapp_measuredboot.c or reusing existing one.
>>
>> You will need one image per UEFI architecture (ia32, x64, arm, aa64,
>> riscv32, riscv64). You could present the image via the
>> EFI_LOAD_FILE2_PROTOCOL, see lib/efi_selftest/efi_selftest_load_file.c.
>
>The EFI TCG2 is governed by a spec.  What it basically does is extend
>a number of hardware PCRs with a sha1/256/384/512 for a given image.
>Wouldn't performing the selftest for arm/arm64 be enough?  What am I
>missing?

People on other architectures should be able to run the selftest on a real device (not QEMU). If you have trouble building for RISC-V, I can help.

Regards

Heinrich 

>
>[...]
>
>Regards
>/Ilias

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-10-30  6:13           ` Heinrich Schuchardt
@ 2021-11-01  9:38             ` Masahisa Kojima
  0 siblings, 0 replies; 16+ messages in thread
From: Masahisa Kojima @ 2021-11-01  9:38 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: Ilias Apalodimas, Simon Glass, Alexander Graf, U-Boot Mailing List

Hi Heinrich, Ilias,

On Sat, 30 Oct 2021 at 15:18, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
>
>
> Am 30. Oktober 2021 08:02:02 MESZ schrieb Ilias Apalodimas <ilias.apalodimas@linaro.org>:
> >Hi Heinrich
> >
> >[...]
> >
> >> >>> +$(obj)/efi_selftest_tcg2.o: $(obj)/efi_miniapp_file_image_measuredboot.h
> >> >>> diff --git a/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c b/lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
> >> >>
> >> >> Thank you for going the extra mile and adding the test.
> >> >>
> >> >> Which image is actually loaded seems to be irrelevant for the test. Can
> >> >> we reuse an existing one, e.g. efi_miniapp_file_image_return.h?
> >> >>
> >> >> I guess the PCR related to the loaded image is not checked as it will
> >> >> depend on the build tools and date.
> >> >
> >> > Sorry, I'm doing wrong.
> >> > Actually this selftest verifies the PE/COFF image measurement, so measuremt
> >> > will be different depending on the build tools and date.
> >> >   # In my build environment, timestamp is set to all zero.
> >> >
> >> > To test the PE/COFF image measurement, I must prepare the
> >> > static PE/COFF image. I plan to add efi_miniapp_file_image_measuredboot.h
> >> > as a pre-compiled small static PE/COFF image for the measurement test,
> >> > instead of adding efi_selftest_miniapp_measuredboot.c or reusing existing one.
> >>
> >> You will need one image per UEFI architecture (ia32, x64, arm, aa64,
> >> riscv32, riscv64). You could present the image via the
> >> EFI_LOAD_FILE2_PROTOCOL, see lib/efi_selftest/efi_selftest_load_file.c.
> >
> >The EFI TCG2 is governed by a spec.  What it basically does is extend
> >a number of hardware PCRs with a sha1/256/384/512 for a given image.
> >Wouldn't performing the selftest for arm/arm64 be enough?  What am I
> >missing?
>
> People on other architectures should be able to run the selftest on a real device (not QEMU). If you have trouble building for RISC-V, I can help.

I am encountering errors in x86_64, riscv32 and riscv64.

[x86_64]
 - swtpm does not work on x86_64 qemu, It is probably U-Boot side issue
   but I could not run tcg2 efi_selftest for x86_64.
=====
U-Boot 2021.10-00965-g2c308dc11a (Nov 01 2021 - 14:24:18 +0900)

CPU:   QEMU Virtual CPU version 2.5+
DRAM:  128 MiB
Loading Environment from nowhere... OK
Incorrect expansion ROM header signature 4daa
Model: QEMU x86 (I440FX)
Net:   e1000: 52:54:00:12:34:56
       eth0: e1000#0
Hit any key to stop autoboot:  0
=>
=> tpm2 startup TPM2_SU_CLEAR
Couldn't set TPM 0 (rc = 1)
=====

[riscv32/riscv64]
 - riscv32/riscv64 QEMU seems not to support TPM device, qemu-system-riscv32 and
qemu-system-riscv64 ends with the error "No TPM backend types are available".
 - The available backend types are "passthrough" or "emulator",
"emulator" must be
   used for swtpm.
=====
ubuntu@ubuntu-W331AU:~/src/test/u-boot$ qemu-system-riscv32 -nographic
-machine virt -bios u-boot -chardev
socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock -tpmdev
emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0
qemu-system-riscv32: -tpmdev emulator,id=tpm0,chardev=chrtpm:
Parameter 'type' expects a TPM backend type
No TPM backend types are available
=====
=====
ubuntu@ubuntu-W331AU:~/src/test/u-boot$ qemu-system-riscv64 -nographic
-machine virt -bios u-boot -chardev
socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock -tpmdev
emulator,id=tpm0,chardev=chrtpm -device tpm-tis,tpmdev=tpm0
qemu-system-riscv64: -tpmdev emulator,id=tpm0,chardev=chrtpm:
Parameter 'type' expects a TPM backend type
No TPM backend types are available
=====

Is it OK if I add the tcg2 efi_selftest for arm/arm64 for now?

Thanks,
Masahisa Kojima




>
> Regards
>
> Heinrich
>
> >
> >[...]
> >
> >Regards
> >/Ilias

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-10-24 19:54 ` [PATCH 0/2] " Simon Glass
@ 2021-11-02  8:03   ` Masahisa Kojima
  2021-11-02 14:55     ` Simon Glass
  0 siblings, 1 reply; 16+ messages in thread
From: Masahisa Kojima @ 2021-11-02  8:03 UTC (permalink / raw)
  To: Simon Glass; +Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas

Hi Simon,

On Mon, 25 Oct 2021 at 04:54, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Masahisa,
>
> On Fri, 22 Oct 2021 at 05:23, Masahisa Kojima
> <masahisa.kojima@linaro.org> wrote:
> >
> > This patch series adds the selftest for the EFI_TCG2_PROTOCOL and
> > Measured Boot flow.
> > This selftest is verified on qemu with swtpm.
>
> Is this in CI? Where are the instructions for doing this?

Not yet included in CI.
For the instructions, Ilias is preparing the documentation at:
https://github.com/apalos/u-boot/commit/6edcf3c02996edf8c50a38632aac1091f8bcbf0b

>
> I have expressed my preference for expanding the in-tree emulator to
> handle this.

For the measured boot selftest, I need to access the efi internal data such as
SMBIOS table, that is why I chose the C based efi_selftest.
Tcg2 efi_selftest does not rely on the specific TPM backend.

Thanks,
Masahisa Kojima


>
> Regards,
> Simon
>
>
> >
> > This covers most of the functionalities, but there are some
> > limitations and TODO items.
> >
> > [Limitation]
> > - tcg2 selftest must run at the beginning of the efi_selftest because
> >   some measurement occurs in efi_tcg2_register() and boottime->image_load().
> >   Need to configure the efi_selftest with "setenv efi_selftest tcg2; bootefi selftest"
> > - Skip ExitBootService measurement test
> >    - EFI application can not read PCR after calling ExitBootService
> > - Skip EventLog Validation
> >    - Measured Boot measures U-Boot version, so EventLog varies every build having
> >      different commit hash.
> > - Skip PCR[0] validation
> >    - PCR[0] include U-Boot version measurement, this value varies every build
> >      having different commit hash.
> > - Skip PCR[7] validation
> >    - Secure Boot Variables can not be updated through efi_selftest.
> > - The initial PCR value of PCR[17 - 22] is all 0xff, I'm not sure
> >   it is expected or not.
> >
> > [TODO]
> > - GPT measurement test
> > - Secure Boot Variable test
> > - Eventlog validation
> >
> > Masahisa Kojima (2):
> >   efi_loader: add missing const qualifier
> >   efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
> >
> >  include/efi_api.h                             |   2 +-
> >  lib/efi_loader/efi_boottime.c                 |   5 +-
> >  lib/efi_selftest/Makefile                     |  10 +
> >  .../efi_selftest_miniapp_measuredboot.c       |  93 ++
> >  lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
> >  5 files changed, 910 insertions(+), 4 deletions(-)
> >  create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
> >
> > --
> > 2.17.1
> >

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-11-02  8:03   ` Masahisa Kojima
@ 2021-11-02 14:55     ` Simon Glass
  2021-11-02 16:27       ` Ilias Apalodimas
  0 siblings, 1 reply; 16+ messages in thread
From: Simon Glass @ 2021-11-02 14:55 UTC (permalink / raw)
  To: Masahisa Kojima
  Cc: U-Boot Mailing List, Heinrich Schuchardt, Ilias Apalodimas

Hi Masahisa,

On Tue, 2 Nov 2021 at 02:03, Masahisa Kojima <masahisa.kojima@linaro.org> wrote:
>
> Hi Simon,
>
> On Mon, 25 Oct 2021 at 04:54, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Masahisa,
> >
> > On Fri, 22 Oct 2021 at 05:23, Masahisa Kojima
> > <masahisa.kojima@linaro.org> wrote:
> > >
> > > This patch series adds the selftest for the EFI_TCG2_PROTOCOL and
> > > Measured Boot flow.
> > > This selftest is verified on qemu with swtpm.
> >
> > Is this in CI? Where are the instructions for doing this?
>
> Not yet included in CI.
> For the instructions, Ilias is preparing the documentation at:
> https://github.com/apalos/u-boot/commit/6edcf3c02996edf8c50a38632aac1091f8bcbf0b

OK I see.

>
> >
> > I have expressed my preference for expanding the in-tree emulator to
> > handle this.
>
> For the measured boot selftest, I need to access the efi internal data such as
> SMBIOS table, that is why I chose the C based efi_selftest.
> Tcg2 efi_selftest does not rely on the specific TPM backend.

I don't understand this answer. I would still like to know how much
code we would be talking about if we expand the TPM emulator in U-Boot
for these extra features. From my understanding, the TPMs themselves
are not that complicated and don't have a lot of code in them,
particularly for the features we use. I am willing to believe that
this might not be feasible, or be too much effort, but I have not seen
anyone attempt it, or part of it, so I don't know. With a TPM emulator
we can encode any sort of test behaviour we want. It is much harder
with QEMU. But I have not seen an answer for what is actually involved
in doing this.

I know Ilias talked about bringing in swtpm to U-Boot. It seems like a
lot of code so I am not sure if it is worth it. Perhaps it could be
built against U-Boot sandbox as an option...I'm not sure. But the goal
here is not to emulate a TPM, but to provide test coverage in an
easily maintainable way.

So to put my mind at ease, what would be involved in running this on
sandbox? Are we talking hundreds of lines of code (which I think is
worth it) or thousands (which is not)?

Regards,
Simon


>
> Thanks,
> Masahisa Kojima
>
>
> >
> > Regards,
> > Simon
> >
> >
> > >
> > > This covers most of the functionalities, but there are some
> > > limitations and TODO items.
> > >
> > > [Limitation]
> > > - tcg2 selftest must run at the beginning of the efi_selftest because
> > >   some measurement occurs in efi_tcg2_register() and boottime->image_load().
> > >   Need to configure the efi_selftest with "setenv efi_selftest tcg2; bootefi selftest"
> > > - Skip ExitBootService measurement test
> > >    - EFI application can not read PCR after calling ExitBootService
> > > - Skip EventLog Validation
> > >    - Measured Boot measures U-Boot version, so EventLog varies every build having
> > >      different commit hash.
> > > - Skip PCR[0] validation
> > >    - PCR[0] include U-Boot version measurement, this value varies every build
> > >      having different commit hash.
> > > - Skip PCR[7] validation
> > >    - Secure Boot Variables can not be updated through efi_selftest.
> > > - The initial PCR value of PCR[17 - 22] is all 0xff, I'm not sure
> > >   it is expected or not.
> > >
> > > [TODO]
> > > - GPT measurement test
> > > - Secure Boot Variable test
> > > - Eventlog validation
> > >
> > > Masahisa Kojima (2):
> > >   efi_loader: add missing const qualifier
> > >   efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
> > >
> > >  include/efi_api.h                             |   2 +-
> > >  lib/efi_loader/efi_boottime.c                 |   5 +-
> > >  lib/efi_selftest/Makefile                     |  10 +
> > >  .../efi_selftest_miniapp_measuredboot.c       |  93 ++
> > >  lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
> > >  5 files changed, 910 insertions(+), 4 deletions(-)
> > >  create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
> > >
> > > --
> > > 2.17.1
> > >

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-11-02 14:55     ` Simon Glass
@ 2021-11-02 16:27       ` Ilias Apalodimas
  2021-11-05  2:02         ` Simon Glass
  0 siblings, 1 reply; 16+ messages in thread
From: Ilias Apalodimas @ 2021-11-02 16:27 UTC (permalink / raw)
  To: Simon Glass; +Cc: Masahisa Kojima, U-Boot Mailing List, Heinrich Schuchardt

Hi Simon.

On Tue, 2 Nov 2021 at 16:55, Simon Glass <sjg@chromium.org> wrote:
>
> Hi Masahisa,
>
> On Tue, 2 Nov 2021 at 02:03, Masahisa Kojima <masahisa.kojima@linaro.org> wrote:
> >
> > Hi Simon,
> >
> > On Mon, 25 Oct 2021 at 04:54, Simon Glass <sjg@chromium.org> wrote:
> > >
> > > Hi Masahisa,
> > >
> > > On Fri, 22 Oct 2021 at 05:23, Masahisa Kojima
> > > <masahisa.kojima@linaro.org> wrote:
> > > >
> > > > This patch series adds the selftest for the EFI_TCG2_PROTOCOL and
> > > > Measured Boot flow.
> > > > This selftest is verified on qemu with swtpm.
> > >
> > > Is this in CI? Where are the instructions for doing this?
> >
> > Not yet included in CI.
> > For the instructions, Ilias is preparing the documentation at:
> > https://github.com/apalos/u-boot/commit/6edcf3c02996edf8c50a38632aac1091f8bcbf0b
>
> OK I see.
>
> >
> > >
> > > I have expressed my preference for expanding the in-tree emulator to
> > > handle this.
> >
> > For the measured boot selftest, I need to access the efi internal data such as
> > SMBIOS table, that is why I chose the C based efi_selftest.
> > Tcg2 efi_selftest does not rely on the specific TPM backend.
>
> I don't understand this answer. I would still like to know how much
> code we would be talking about if we expand the TPM emulator in U-Boot
> for these extra features. From my understanding, the TPMs themselves
> are not that complicated and don't have a lot of code in them,
> particularly for the features we use. I am willing to believe that
> this might not be feasible, or be too much effort, but I have not seen
> anyone attempt it, or part of it, so I don't know.

I don't have an exact answer for that either.  It's definitely more
than the effort we need for the QEMU though.

> With a TPM emulator
> we can encode any sort of test behaviour we want. It is much harder
> with QEMU. But I have not seen an answer for what is actually involved
> in doing this.

QEMU just provides access to a standard (TIS compliant) TPM.  So I
can't think of any tests that aren't already covered.

>
> I know Ilias talked about bringing in swtpm to U-Boot. It seems like a
> lot of code so I am not sure if it is worth it.

Just for clarification U-Boot is will get *zero* code for this wrt to
the TPM interface it self.  The only thing you need is an MMIO TPM
driver for U-Boot, but that's not only usable in QEMU.  There are
devices supported by U-Boot which have an MMIO based TPM (e.g the
synquacer box), so we need that driver regardless.  Apart from that
patchset (which I'll resend within the week) you need a QEMU instance
with swtpm support described here [1]

> Perhaps it could be
> built against U-Boot sandbox as an option...I'm not sure. But the goal
> here is not to emulate a TPM, but to provide test coverage in an
> easily maintainable way.
>
> So to put my mind at ease, what would be involved in running this on
> sandbox? Are we talking hundreds of lines of code (which I think is
> worth it) or thousands (which is not)?

Probably hundreds.  I've responded here [2] with the basic
functionality that's missing.

[1] https://github.com/apalos/u-boot/commit/6edcf3c02996edf8c50a38632aac1091f8bcbf0b
[2] https://lore.kernel.org/u-boot/CAC_iWjLY-qH0ckQHh=WhvbVc2pa_a2COjr=g3cp8ZEdVxV6=aw@mail.gmail.com/

Regards
/Ilias

>
> Regards,
> Simon
>
>
> >
> > Thanks,
> > Masahisa Kojima
> >
> >
> > >
> > > Regards,
> > > Simon
> > >
> > >
> > > >
> > > > This covers most of the functionalities, but there are some
> > > > limitations and TODO items.
> > > >
> > > > [Limitation]
> > > > - tcg2 selftest must run at the beginning of the efi_selftest because
> > > >   some measurement occurs in efi_tcg2_register() and boottime->image_load().
> > > >   Need to configure the efi_selftest with "setenv efi_selftest tcg2; bootefi selftest"
> > > > - Skip ExitBootService measurement test
> > > >    - EFI application can not read PCR after calling ExitBootService
> > > > - Skip EventLog Validation
> > > >    - Measured Boot measures U-Boot version, so EventLog varies every build having
> > > >      different commit hash.
> > > > - Skip PCR[0] validation
> > > >    - PCR[0] include U-Boot version measurement, this value varies every build
> > > >      having different commit hash.
> > > > - Skip PCR[7] validation
> > > >    - Secure Boot Variables can not be updated through efi_selftest.
> > > > - The initial PCR value of PCR[17 - 22] is all 0xff, I'm not sure
> > > >   it is expected or not.
> > > >
> > > > [TODO]
> > > > - GPT measurement test
> > > > - Secure Boot Variable test
> > > > - Eventlog validation
> > > >
> > > > Masahisa Kojima (2):
> > > >   efi_loader: add missing const qualifier
> > > >   efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
> > > >
> > > >  include/efi_api.h                             |   2 +-
> > > >  lib/efi_loader/efi_boottime.c                 |   5 +-
> > > >  lib/efi_selftest/Makefile                     |  10 +
> > > >  .../efi_selftest_miniapp_measuredboot.c       |  93 ++
> > > >  lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
> > > >  5 files changed, 910 insertions(+), 4 deletions(-)
> > > >  create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
> > > >
> > > > --
> > > > 2.17.1
> > > >

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot
  2021-11-02 16:27       ` Ilias Apalodimas
@ 2021-11-05  2:02         ` Simon Glass
  0 siblings, 0 replies; 16+ messages in thread
From: Simon Glass @ 2021-11-05  2:02 UTC (permalink / raw)
  To: Ilias Apalodimas
  Cc: Masahisa Kojima, U-Boot Mailing List, Heinrich Schuchardt

Hi Ilias,

On Tue, 2 Nov 2021 at 10:28, Ilias Apalodimas
<ilias.apalodimas@linaro.org> wrote:
>
> Hi Simon.
>
> On Tue, 2 Nov 2021 at 16:55, Simon Glass <sjg@chromium.org> wrote:
> >
> > Hi Masahisa,
> >
> > On Tue, 2 Nov 2021 at 02:03, Masahisa Kojima <masahisa.kojima@linaro.org> wrote:
> > >
> > > Hi Simon,
> > >
> > > On Mon, 25 Oct 2021 at 04:54, Simon Glass <sjg@chromium.org> wrote:
> > > >
> > > > Hi Masahisa,
> > > >
> > > > On Fri, 22 Oct 2021 at 05:23, Masahisa Kojima
> > > > <masahisa.kojima@linaro.org> wrote:
> > > > >
> > > > > This patch series adds the selftest for the EFI_TCG2_PROTOCOL and
> > > > > Measured Boot flow.
> > > > > This selftest is verified on qemu with swtpm.
> > > >
> > > > Is this in CI? Where are the instructions for doing this?
> > >
> > > Not yet included in CI.
> > > For the instructions, Ilias is preparing the documentation at:
> > > https://github.com/apalos/u-boot/commit/6edcf3c02996edf8c50a38632aac1091f8bcbf0b
> >
> > OK I see.
> >
> > >
> > > >
> > > > I have expressed my preference for expanding the in-tree emulator to
> > > > handle this.
> > >
> > > For the measured boot selftest, I need to access the efi internal data such as
> > > SMBIOS table, that is why I chose the C based efi_selftest.
> > > Tcg2 efi_selftest does not rely on the specific TPM backend.
> >
> > I don't understand this answer. I would still like to know how much
> > code we would be talking about if we expand the TPM emulator in U-Boot
> > for these extra features. From my understanding, the TPMs themselves
> > are not that complicated and don't have a lot of code in them,
> > particularly for the features we use. I am willing to believe that
> > this might not be feasible, or be too much effort, but I have not seen
> > anyone attempt it, or part of it, so I don't know.
>
> I don't have an exact answer for that either.  It's definitely more
> than the effort we need for the QEMU though.

OK. How about implementing one thing so the test gets a little way
along, to understand the effort? Or I could try it if you give
instructions on how to run it. Because there is a benefit, it is not
just all a cost.
>
> > With a TPM emulator
> > we can encode any sort of test behaviour we want. It is much harder
> > with QEMU. But I have not seen an answer for what is actually involved
> > in doing this.
>
> QEMU just provides access to a standard (TIS compliant) TPM.  So I
> can't think of any tests that aren't already covered.

Failures?

>
> >
> > I know Ilias talked about bringing in swtpm to U-Boot. It seems like a
> > lot of code so I am not sure if it is worth it.
>
> Just for clarification U-Boot is will get *zero* code for this wrt to
> the TPM interface it self.  The only thing you need is an MMIO TPM
> driver for U-Boot, but that's not only usable in QEMU.  There are
> devices supported by U-Boot which have an MMIO based TPM (e.g the
> synquacer box), so we need that driver regardless.  Apart from that
> patchset (which I'll resend within the week) you need a QEMU instance
> with swtpm support described here [1]

Yes I understand.

>
> > Perhaps it could be
> > built against U-Boot sandbox as an option...I'm not sure. But the goal
> > here is not to emulate a TPM, but to provide test coverage in an
> > easily maintainable way.
> >
> > So to put my mind at ease, what would be involved in running this on
> > sandbox? Are we talking hundreds of lines of code (which I think is
> > worth it) or thousands (which is not)?
>
> Probably hundreds.  I've responded here [2] with the basic
> functionality that's missing.

OK I can use that. So how do I to run this test on sandbox?


- Simon

>
> [1] https://github.com/apalos/u-boot/commit/6edcf3c02996edf8c50a38632aac1091f8bcbf0b
> [2] https://lore.kernel.org/u-boot/CAC_iWjLY-qH0ckQHh=WhvbVc2pa_a2COjr=g3cp8ZEdVxV6=aw@mail.gmail.com/
>
> Regards
> /Ilias
>
> >
> > Regards,
> > Simon
> >
> >
> > >
> > > Thanks,
> > > Masahisa Kojima
> > >
> > >
> > > >
> > > > Regards,
> > > > Simon
> > > >
> > > >
> > > > >
> > > > > This covers most of the functionalities, but there are some
> > > > > limitations and TODO items.
> > > > >
> > > > > [Limitation]
> > > > > - tcg2 selftest must run at the beginning of the efi_selftest because
> > > > >   some measurement occurs in efi_tcg2_register() and boottime->image_load().
> > > > >   Need to configure the efi_selftest with "setenv efi_selftest tcg2; bootefi selftest"
> > > > > - Skip ExitBootService measurement test
> > > > >    - EFI application can not read PCR after calling ExitBootService
> > > > > - Skip EventLog Validation
> > > > >    - Measured Boot measures U-Boot version, so EventLog varies every build having
> > > > >      different commit hash.
> > > > > - Skip PCR[0] validation
> > > > >    - PCR[0] include U-Boot version measurement, this value varies every build
> > > > >      having different commit hash.
> > > > > - Skip PCR[7] validation
> > > > >    - Secure Boot Variables can not be updated through efi_selftest.
> > > > > - The initial PCR value of PCR[17 - 22] is all 0xff, I'm not sure
> > > > >   it is expected or not.
> > > > >
> > > > > [TODO]
> > > > > - GPT measurement test
> > > > > - Secure Boot Variable test
> > > > > - Eventlog validation
> > > > >
> > > > > Masahisa Kojima (2):
> > > > >   efi_loader: add missing const qualifier
> > > > >   efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot
> > > > >
> > > > >  include/efi_api.h                             |   2 +-
> > > > >  lib/efi_loader/efi_boottime.c                 |   5 +-
> > > > >  lib/efi_selftest/Makefile                     |  10 +
> > > > >  .../efi_selftest_miniapp_measuredboot.c       |  93 ++
> > > > >  lib/efi_selftest/efi_selftest_tcg2.c          | 804 +++++++++++++++++-
> > > > >  5 files changed, 910 insertions(+), 4 deletions(-)
> > > > >  create mode 100644 lib/efi_selftest/efi_selftest_miniapp_measuredboot.c
> > > > >
> > > > > --
> > > > > 2.17.1
> > > > >

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2021-11-05  2:02 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-22 11:24 [PATCH 0/2] add selftest for EFI_TCG2_PROTOCOL and Measured Boot Masahisa Kojima
2021-10-22 11:24 ` [PATCH 1/2] efi_loader: add missing const qualifier Masahisa Kojima
2021-10-23  8:40   ` Heinrich Schuchardt
2021-10-23 17:21     ` Ilias Apalodimas
2021-10-22 11:24 ` [PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot Masahisa Kojima
2021-10-23  9:42   ` Heinrich Schuchardt
2021-10-25  7:59     ` Masahisa Kojima
2021-10-25  9:43       ` Heinrich Schuchardt
2021-10-30  6:02         ` Ilias Apalodimas
2021-10-30  6:13           ` Heinrich Schuchardt
2021-11-01  9:38             ` Masahisa Kojima
2021-10-24 19:54 ` [PATCH 0/2] " Simon Glass
2021-11-02  8:03   ` Masahisa Kojima
2021-11-02 14:55     ` Simon Glass
2021-11-02 16:27       ` Ilias Apalodimas
2021-11-05  2:02         ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.