diff mbox series

[2/2] efi: ESRT cration unit test

Message ID 20210208125246.32547-3-jose.marinho@arm.com
State Superseded
Delegated to: Heinrich Schuchardt
Headers show
Series Add ESRT and test ESRT creation | expand

Commit Message

Jose Marinho Feb. 8, 2021, 12:52 p.m. UTC
This commit exercises the ESRT creation -- introduced in the previous
commit.

A fake FMP, controlling TEST_ESRT_NUM_ENTRIES, is installed in the system
leading to the corresponding ESRT entries being populated.
The ESRT entries are checked against the FMP initialization input
datastructure.

Signed-off-by: Jose Marinho <jose.marinho@arm.com>

CC: Heinrich Schuchardt	<xypron.glpk@gmx.de>
CC: Sughosh Ganu <sughosh.ganu@linaro.org>
CC: AKASHI Takahiro <takahiro.akashi@linaro.org>
CC: Ilias Apalodimas <ilias.apalodimas@linaro.org>
CC: Andre Przywara <andre.przywara@arm.com>
CC: Alexander Graf <agraf@csgraf.de>
CC: nd@arm.com

---
 test/lib/Makefile   |   1 +
 test/lib/efi_esrt.c | 188 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 189 insertions(+)
 create mode 100644 test/lib/efi_esrt.c

Comments

AKASHI Takahiro Feb. 17, 2021, 5:26 a.m. UTC | #1
On Mon, Feb 08, 2021 at 12:52:46PM +0000, Jose Marinho wrote:
> This commit exercises the ESRT creation -- introduced in the previous
> commit.
> 
> A fake FMP, controlling TEST_ESRT_NUM_ENTRIES, is installed in the system
> leading to the corresponding ESRT entries being populated.
> The ESRT entries are checked against the FMP initialization input
> datastructure.

I hope that you will also provide a pytest to make sure that
an entry in ESRT is correctly updated after capsule update.

There are already some tests for capsule update.

-Takahiro Akashi


> Signed-off-by: Jose Marinho <jose.marinho@arm.com>
> 
> CC: Heinrich Schuchardt	<xypron.glpk@gmx.de>
> CC: Sughosh Ganu <sughosh.ganu@linaro.org>
> CC: AKASHI Takahiro <takahiro.akashi@linaro.org>
> CC: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> CC: Andre Przywara <andre.przywara@arm.com>
> CC: Alexander Graf <agraf@csgraf.de>
> CC: nd@arm.com
> 
> ---
>  test/lib/Makefile   |   1 +
>  test/lib/efi_esrt.c | 188 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 189 insertions(+)
>  create mode 100644 test/lib/efi_esrt.c
> 
> diff --git a/test/lib/Makefile b/test/lib/Makefile
> index 97c11e35a8..687e791db0 100644
> --- a/test/lib/Makefile
> +++ b/test/lib/Makefile
> @@ -15,3 +15,4 @@ obj-$(CONFIG_UT_LIB_ASN1) += asn1.o
>  obj-$(CONFIG_UT_LIB_RSA) += rsa.o
>  obj-$(CONFIG_AES) += test_aes.o
>  obj-$(CONFIG_GETOPT) += getopt.o
> +obj-y += efi_esrt.o
> diff --git a/test/lib/efi_esrt.c b/test/lib/efi_esrt.c
> new file mode 100644
> index 0000000000..3c9d1de731
> --- /dev/null
> +++ b/test/lib/efi_esrt.c
> @@ -0,0 +1,188 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + *  Test ESRT tables support
> + *
> + *  Copyright (C) 2021 Arm Ltd.
> + */
> +#include <common.h>
> +#include <efi_loader.h>
> +#include <net.h>
> +#include <test/lib.h>
> +#include <test/test.h>
> +#include <test/ut.h>
> +
> +#define TEST_ESRT_NUM_ENTRIES 255
> +
> +#if 0x100 < TEST_ESRT_NUM_ENTRIES
> +#error TEST_ESRT_NUM_ENTRIES must be lower or equal to 255.
> +#endif
> +
> +static
> +struct efi_firmware_image_descriptor static_img_info[TEST_ESRT_NUM_ENTRIES];
> +static const efi_guid_t esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
> +
> +static void efi_test_esrt_init_info(void)
> +{
> +	for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++) {
> +		static_img_info[idx].image_index = 1;
> +
> +		// Note: the 16 byte value present in
> +		// static_img_info[idx].image_type_id is not strictly a GUID.
> +		// The value is used for the sake of code testing.
> +		static_img_info[idx].image_type_id.b[0] = idx;
> +
> +		static_img_info[idx].image_id = 0;
> +		static_img_info[idx].image_id_name = NULL;
> +		static_img_info[idx].version = 0;
> +		static_img_info[idx].version_name = NULL;
> +		static_img_info[idx].size = 0;
> +		static_img_info[idx].lowest_supported_image_version = 1;
> +		static_img_info[idx].last_attempt_version = 2;
> +		static_img_info[idx].last_attempt_status = 3;
> +		static_img_info[idx].hardware_instance = 1;
> +	}
> +}
> +
> +static efi_status_t
> +EFIAPI efi_test_fmp_get_image_info(struct efi_firmware_management_protocol *this,
> +				   efi_uintn_t *image_info_size,
> +				   struct efi_firmware_image_descriptor *image_info,
> +				   u32 *descriptor_version,
> +				   u8 *descriptor_count,
> +				   efi_uintn_t *descriptor_size,
> +				   u32 *package_version,
> +				   u16 **package_version_name)
> +{
> +	efi_status_t ret = EFI_SUCCESS;
> +
> +	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
> +		  image_info_size, image_info,
> +		  descriptor_version, descriptor_count, descriptor_size,
> +		  package_version, package_version_name);
> +
> +	if (!image_info_size)
> +		return EFI_EXIT(EFI_INVALID_PARAMETER);
> +
> +	if (descriptor_version)
> +		*descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
> +	if (descriptor_count)
> +		*descriptor_count = TEST_ESRT_NUM_ENTRIES;
> +	if (descriptor_size)
> +		*descriptor_size = sizeof(*image_info);
> +	if (package_version)
> +		*package_version = 0xffffffff;
> +	if (package_version_name)
> +		*package_version_name = NULL;
> +
> +	if (*image_info_size < sizeof(*image_info)) {
> +		*image_info_size = *descriptor_size * *descriptor_count;
> +		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
> +	}
> +
> +	for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
> +		image_info[idx] = static_img_info[idx];
> +
> +	return EFI_EXIT(ret);
> +}
> +
> +struct efi_firmware_management_protocol efi_test_fmp = {
> +	.get_image_info = efi_test_fmp_get_image_info,
> +	.get_image = NULL,
> +	.set_image = NULL,
> +	.check_image = NULL,
> +	.get_package_info = NULL,
> +	.set_package_info = NULL,
> +};
> +
> +static void *lib_test_get_esrt(void)
> +{
> +	for (int idx = 0; idx < systab.nr_tables; idx++)
> +		if (!guidcmp(&esrt_guid, &systab.tables[idx].guid))
> +			return systab.tables[idx].table;
> +
> +	return NULL;
> +}
> +
> +static bool lib_test_check_uuid_entry(struct efi_system_resource_table *esrt,
> +				      struct efi_firmware_image_descriptor
> +				      *img_info)
> +{
> +	const u32 filled_entries = esrt->fw_resource_count;
> +	struct efi_system_resource_entry *entry = esrt->entries;
> +
> +	for (u32 idx = 0; idx < filled_entries; idx++) {
> +		if (!guidcmp(&entry[idx].fw_class, &img_info->image_type_id)) {
> +			if (entry[idx].fw_version != img_info->version)
> +				return false;
> +
> +			if (entry[idx].lowest_supported_fw_version !=
> +				img_info->lowest_supported_image_version)
> +				return false;
> +
> +			if (entry[idx].last_attempt_version !=
> +				img_info->last_attempt_version)
> +				return false;
> +
> +			if (entry[idx].last_attempt_status !=
> +				img_info->last_attempt_status)
> +				return false;
> +
> +			/*
> +			 * The entry with fw_class = img_uuid matches with the
> +			 * remainder fmp input.
> +			 */
> +			return true;
> +		}
> +	}
> +
> +	/* There exists no entry with fw_class equal to img_uuid in the ESRT. */
> +	return false;
> +}
> +
> +int lib_test_efi_esrt(struct unit_test_state *uts)
> +{
> +	struct efi_system_resource_table *esrt;
> +	efi_status_t ret = EFI_SUCCESS;
> +	struct efi_boot_services *bt;
> +
> +	efi_test_esrt_init_info();
> +
> +	ret = efi_init_obj_list();
> +
> +	bt = systab.boottime;
> +	ut_asserteq(ret, EFI_SUCCESS);
> +
> +	assert(bt);
> +
> +	ret = EFI_CALL(bt->install_multiple_protocol_interfaces
> +		(&efi_root,
> +		 &efi_guid_firmware_management_protocol,
> +		 &efi_test_fmp,
> +		 NULL));
> +
> +	ut_asserteq(ret, EFI_SUCCESS);
> +
> +	esrt = lib_test_get_esrt();
> +	ut_assert(esrt);
> +
> +	ut_asserteq(esrt->fw_resource_count, TEST_ESRT_NUM_ENTRIES);
> +
> +	/* Add the same FMP. */
> +	efi_esrt_add_from_fmp(&efi_test_fmp);
> +
> +	/* Verify that the number of images remains the same. */
> +	ut_asserteq(esrt->fw_resource_count, TEST_ESRT_NUM_ENTRIES);
> +
> +	for (u32 idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
> +		ut_assert(lib_test_check_uuid_entry(esrt, &static_img_info[idx]));
> +
> +	ret = EFI_CALL(bt->uninstall_multiple_protocol_interfaces
> +		(efi_root, &efi_guid_firmware_management_protocol,
> +		 &efi_test_fmp, NULL));
> +
> +	ut_asserteq(ret, EFI_SUCCESS);
> +
> +	return ret;
> +}
> +
> +LIB_TEST(lib_test_efi_esrt, 0);
> -- 
> 2.17.1
>
diff mbox series

Patch

diff --git a/test/lib/Makefile b/test/lib/Makefile
index 97c11e35a8..687e791db0 100644
--- a/test/lib/Makefile
+++ b/test/lib/Makefile
@@ -15,3 +15,4 @@  obj-$(CONFIG_UT_LIB_ASN1) += asn1.o
 obj-$(CONFIG_UT_LIB_RSA) += rsa.o
 obj-$(CONFIG_AES) += test_aes.o
 obj-$(CONFIG_GETOPT) += getopt.o
+obj-y += efi_esrt.o
diff --git a/test/lib/efi_esrt.c b/test/lib/efi_esrt.c
new file mode 100644
index 0000000000..3c9d1de731
--- /dev/null
+++ b/test/lib/efi_esrt.c
@@ -0,0 +1,188 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ *  Test ESRT tables support
+ *
+ *  Copyright (C) 2021 Arm Ltd.
+ */
+#include <common.h>
+#include <efi_loader.h>
+#include <net.h>
+#include <test/lib.h>
+#include <test/test.h>
+#include <test/ut.h>
+
+#define TEST_ESRT_NUM_ENTRIES 255
+
+#if 0x100 < TEST_ESRT_NUM_ENTRIES
+#error TEST_ESRT_NUM_ENTRIES must be lower or equal to 255.
+#endif
+
+static
+struct efi_firmware_image_descriptor static_img_info[TEST_ESRT_NUM_ENTRIES];
+static const efi_guid_t esrt_guid = EFI_SYSTEM_RESOURCE_TABLE_GUID;
+
+static void efi_test_esrt_init_info(void)
+{
+	for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++) {
+		static_img_info[idx].image_index = 1;
+
+		// Note: the 16 byte value present in
+		// static_img_info[idx].image_type_id is not strictly a GUID.
+		// The value is used for the sake of code testing.
+		static_img_info[idx].image_type_id.b[0] = idx;
+
+		static_img_info[idx].image_id = 0;
+		static_img_info[idx].image_id_name = NULL;
+		static_img_info[idx].version = 0;
+		static_img_info[idx].version_name = NULL;
+		static_img_info[idx].size = 0;
+		static_img_info[idx].lowest_supported_image_version = 1;
+		static_img_info[idx].last_attempt_version = 2;
+		static_img_info[idx].last_attempt_status = 3;
+		static_img_info[idx].hardware_instance = 1;
+	}
+}
+
+static efi_status_t
+EFIAPI efi_test_fmp_get_image_info(struct efi_firmware_management_protocol *this,
+				   efi_uintn_t *image_info_size,
+				   struct efi_firmware_image_descriptor *image_info,
+				   u32 *descriptor_version,
+				   u8 *descriptor_count,
+				   efi_uintn_t *descriptor_size,
+				   u32 *package_version,
+				   u16 **package_version_name)
+{
+	efi_status_t ret = EFI_SUCCESS;
+
+	EFI_ENTRY("%p %p %p %p %p %p %p %p\n", this,
+		  image_info_size, image_info,
+		  descriptor_version, descriptor_count, descriptor_size,
+		  package_version, package_version_name);
+
+	if (!image_info_size)
+		return EFI_EXIT(EFI_INVALID_PARAMETER);
+
+	if (descriptor_version)
+		*descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
+	if (descriptor_count)
+		*descriptor_count = TEST_ESRT_NUM_ENTRIES;
+	if (descriptor_size)
+		*descriptor_size = sizeof(*image_info);
+	if (package_version)
+		*package_version = 0xffffffff;
+	if (package_version_name)
+		*package_version_name = NULL;
+
+	if (*image_info_size < sizeof(*image_info)) {
+		*image_info_size = *descriptor_size * *descriptor_count;
+		return EFI_EXIT(EFI_BUFFER_TOO_SMALL);
+	}
+
+	for (int idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
+		image_info[idx] = static_img_info[idx];
+
+	return EFI_EXIT(ret);
+}
+
+struct efi_firmware_management_protocol efi_test_fmp = {
+	.get_image_info = efi_test_fmp_get_image_info,
+	.get_image = NULL,
+	.set_image = NULL,
+	.check_image = NULL,
+	.get_package_info = NULL,
+	.set_package_info = NULL,
+};
+
+static void *lib_test_get_esrt(void)
+{
+	for (int idx = 0; idx < systab.nr_tables; idx++)
+		if (!guidcmp(&esrt_guid, &systab.tables[idx].guid))
+			return systab.tables[idx].table;
+
+	return NULL;
+}
+
+static bool lib_test_check_uuid_entry(struct efi_system_resource_table *esrt,
+				      struct efi_firmware_image_descriptor
+				      *img_info)
+{
+	const u32 filled_entries = esrt->fw_resource_count;
+	struct efi_system_resource_entry *entry = esrt->entries;
+
+	for (u32 idx = 0; idx < filled_entries; idx++) {
+		if (!guidcmp(&entry[idx].fw_class, &img_info->image_type_id)) {
+			if (entry[idx].fw_version != img_info->version)
+				return false;
+
+			if (entry[idx].lowest_supported_fw_version !=
+				img_info->lowest_supported_image_version)
+				return false;
+
+			if (entry[idx].last_attempt_version !=
+				img_info->last_attempt_version)
+				return false;
+
+			if (entry[idx].last_attempt_status !=
+				img_info->last_attempt_status)
+				return false;
+
+			/*
+			 * The entry with fw_class = img_uuid matches with the
+			 * remainder fmp input.
+			 */
+			return true;
+		}
+	}
+
+	/* There exists no entry with fw_class equal to img_uuid in the ESRT. */
+	return false;
+}
+
+int lib_test_efi_esrt(struct unit_test_state *uts)
+{
+	struct efi_system_resource_table *esrt;
+	efi_status_t ret = EFI_SUCCESS;
+	struct efi_boot_services *bt;
+
+	efi_test_esrt_init_info();
+
+	ret = efi_init_obj_list();
+
+	bt = systab.boottime;
+	ut_asserteq(ret, EFI_SUCCESS);
+
+	assert(bt);
+
+	ret = EFI_CALL(bt->install_multiple_protocol_interfaces
+		(&efi_root,
+		 &efi_guid_firmware_management_protocol,
+		 &efi_test_fmp,
+		 NULL));
+
+	ut_asserteq(ret, EFI_SUCCESS);
+
+	esrt = lib_test_get_esrt();
+	ut_assert(esrt);
+
+	ut_asserteq(esrt->fw_resource_count, TEST_ESRT_NUM_ENTRIES);
+
+	/* Add the same FMP. */
+	efi_esrt_add_from_fmp(&efi_test_fmp);
+
+	/* Verify that the number of images remains the same. */
+	ut_asserteq(esrt->fw_resource_count, TEST_ESRT_NUM_ENTRIES);
+
+	for (u32 idx = 0; idx < TEST_ESRT_NUM_ENTRIES; idx++)
+		ut_assert(lib_test_check_uuid_entry(esrt, &static_img_info[idx]));
+
+	ret = EFI_CALL(bt->uninstall_multiple_protocol_interfaces
+		(efi_root, &efi_guid_firmware_management_protocol,
+		 &efi_test_fmp, NULL));
+
+	ut_asserteq(ret, EFI_SUCCESS);
+
+	return ret;
+}
+
+LIB_TEST(lib_test_efi_esrt, 0);