[PATCH 2/2] efi_selftest: add selftest for EFI_TCG2_PROTOCOL and Measured Boot

Masahisa Kojima masahisa.kojima at linaro.org
Mon Oct 25 09:59:27 CEST 2021


On Sat, 23 Oct 2021 at 18:42, Heinrich Schuchardt <xypron.glpk at 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 at 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,
> >   };
> >


More information about the U-Boot mailing list