[PATCH v6 2/4] test: qemu: add qfw sandbox driver, dm tests, qemu tests
Asherah Connor
ashe at kivikakk.ee
Sun Mar 7 04:59:57 CET 2021
A sandbox driver and test are added for the qfw uclass, and a test in
QEMU added for qfw functionality to confirm it doesn't break in real
world use.
Signed-off-by: Asherah Connor <ashe at kivikakk.ee>
Reviewed-by: Simon Glass <sjg at chromium.org>
---
(no changes since v1)
drivers/misc/Makefile | 1 +
drivers/misc/qfw_sandbox.c | 128 +++++++++++++++++++++++++++++++++++++
test/dm/Makefile | 1 +
test/dm/qfw.c | 42 ++++++++++++
test/py/tests/test_qfw.py | 21 ++++++
5 files changed, 193 insertions(+)
create mode 100644 drivers/misc/qfw_sandbox.c
create mode 100644 test/dm/qfw.c
create mode 100644 test/py/tests/test_qfw.py
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 53bff72428..2864b84af9 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_$(SPL_)PWRSEQ) += pwrseq-uclass.o
ifdef CONFIG_QFW
obj-y += qfw.o
obj-$(CONFIG_QFW_PIO) += qfw_pio.o
+obj-$(CONFIG_SANDBOX) += qfw_sandbox.o
endif
obj-$(CONFIG_ROCKCHIP_EFUSE) += rockchip-efuse.o
obj-$(CONFIG_ROCKCHIP_OTP) += rockchip-otp.o
diff --git a/drivers/misc/qfw_sandbox.c b/drivers/misc/qfw_sandbox.c
new file mode 100644
index 0000000000..7ce532310f
--- /dev/null
+++ b/drivers/misc/qfw_sandbox.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Sandbox interface for QFW
+ *
+ * (C) Copyright 2015 Miao Yan <yanmiaobest at gmail.com>
+ * (C) Copyright 2021 Asherah Connor <ashe at kivikakk.ee>
+ */
+
+#define LOG_CATEGORY UCLASS_QFW
+
+#include <asm/types.h>
+#include <asm/io.h>
+#include <dm.h>
+#include <dm/device.h>
+#include <qfw.h>
+
+struct qfw_sandbox_plat {
+ u8 file_dir_offset;
+};
+
+static void qfw_sandbox_read_entry_io(struct udevice *dev, u16 entry, u32 size,
+ void *address)
+{
+ debug("%s: entry 0x%x size %u address %p\n", __func__, entry, size,
+ address);
+
+ switch (entry) {
+ case FW_CFG_SIGNATURE:
+ if (size == 4)
+ *((u32 *)address) = cpu_to_be32(QEMU_FW_CFG_SIGNATURE);
+ break;
+ case FW_CFG_ID:
+ /* Advertise DMA support */
+ if (size == 1)
+ *((u8 *)address) = FW_CFG_DMA_ENABLED;
+ break;
+ default:
+ debug("%s got unsupported entry 0x%x\n", __func__, entry);
+ /*
+ * Sandbox driver doesn't support other entries here, assume we use DMA
+ * to read them -- the uclass driver will exclusively use it when
+ * advertised.
+ */
+ }
+}
+
+static void qfw_sandbox_read_entry_dma(struct udevice *dev, struct qfw_dma *dma)
+{
+ u16 entry;
+ u32 control = be32_to_cpu(dma->control);
+ void *address = (void *)be64_to_cpu(dma->address);
+ u32 length = be32_to_cpu(dma->length);
+ struct qfw_sandbox_plat *plat = dev_get_plat(dev);
+ struct fw_cfg_file *file;
+
+ debug("%s\n", __func__);
+
+ if (!(control & FW_CFG_DMA_READ))
+ return;
+
+ if (control & FW_CFG_DMA_SELECT) {
+ /* Start new read. */
+ entry = control >> 16;
+
+ /* Arbitrary values to be used by tests. */
+ switch (entry) {
+ case FW_CFG_NB_CPUS:
+ if (length == 2)
+ *((u16 *)address) = cpu_to_le16(5);
+ break;
+ case FW_CFG_FILE_DIR:
+ if (length == 4) {
+ *((u32 *)address) = cpu_to_be32(2);
+ plat->file_dir_offset = 1;
+ }
+ break;
+ default:
+ debug("%s got unsupported entry 0x%x\n", __func__,
+ entry);
+ }
+ } else if (plat->file_dir_offset && length == 64) {
+ file = address;
+ switch (plat->file_dir_offset) {
+ case 1:
+ file->size = cpu_to_be32(8);
+ file->select = cpu_to_be16(FW_CFG_FILE_FIRST);
+ strcpy(file->name, "test-one");
+ plat->file_dir_offset++;
+ break;
+ case 2:
+ file->size = cpu_to_be32(8);
+ file->select = cpu_to_be16(FW_CFG_FILE_FIRST + 1);
+ strcpy(file->name, "test-two");
+ plat->file_dir_offset++;
+ break;
+ }
+ }
+
+ /*
+ * Signal that we are finished. No-one checks this in sandbox --
+ * normally the platform-specific driver looks for it -- but let's
+ * replicate the behaviour in case someone relies on it later.
+ */
+ dma->control = 0;
+}
+
+static int qfw_sandbox_probe(struct udevice *dev)
+{
+ return qfw_register(dev);
+}
+
+static struct dm_qfw_ops qfw_sandbox_ops = {
+ .read_entry_io = qfw_sandbox_read_entry_io,
+ .read_entry_dma = qfw_sandbox_read_entry_dma,
+};
+
+U_BOOT_DRIVER(qfw_sandbox) = {
+ .name = "qfw_sandbox",
+ .id = UCLASS_QFW,
+ .plat_auto = sizeof(struct qfw_sandbox_plat),
+ .probe = qfw_sandbox_probe,
+ .ops = &qfw_sandbox_ops,
+};
+
+U_BOOT_DRVINFO(qfw_sandbox) = {
+ .name = "qfw_sandbox",
+};
+
diff --git a/test/dm/Makefile b/test/dm/Makefile
index fd1455109d..fc2902a3ea 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -98,5 +98,6 @@ endif
ifneq ($(CONFIG_EFI_PARTITION),)
obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fastboot.o
endif
+obj-$(CONFIG_QFW) += qfw.o
endif
endif # !SPL
diff --git a/test/dm/qfw.c b/test/dm/qfw.c
new file mode 100644
index 0000000000..f3f3568983
--- /dev/null
+++ b/test/dm/qfw.c
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Asherah Connor <ashe at kivikakk.ee>
+ */
+
+#include <common.h>
+#include <qfw.h>
+#include <dm.h>
+#include <asm/test.h>
+#include <dm/test.h>
+#include <test/ut.h>
+
+/*
+ * Exercise the device enough to be satisfied the initialisation and DMA
+ * interfaces work.
+ */
+
+static int dm_test_qfw_cpus(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+
+ ut_assertok(uclass_first_device_err(UCLASS_QFW, &dev));
+ ut_asserteq(5, qfw_online_cpus(dev));
+
+ return 0;
+}
+
+DM_TEST(dm_test_qfw_cpus, UT_TESTF_SCAN_PDATA);
+
+static int dm_test_qfw_firmware_list(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ struct fw_file *file;
+
+ ut_assertok(uclass_first_device_err(UCLASS_QFW, &dev));
+ ut_assertok(qfw_read_firmware_list(dev));
+ ut_assertok_ptr((file = qfw_find_file(dev, "test-one")));
+
+ return 0;
+}
+
+DM_TEST(dm_test_qfw_firmware_list, UT_TESTF_SCAN_PDATA);
diff --git a/test/py/tests/test_qfw.py b/test/py/tests/test_qfw.py
new file mode 100644
index 0000000000..a2631a0fa6
--- /dev/null
+++ b/test/py/tests/test_qfw.py
@@ -0,0 +1,21 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2021, Asherah Connor <ashe at kivikakk.ee>
+
+# Test qfw command implementation
+
+import pytest
+
+ at pytest.mark.buildconfigspec('cmd_qfw')
+def test_qfw_cpus(u_boot_console):
+ "Test QEMU firmware config reports the CPU count correctly."
+
+ output = u_boot_console.run_command('qfw cpus')
+ assert '1 cpu(s) online' in output
+
+ at pytest.mark.buildconfigspec('cmd_qfw')
+def test_qfw_list(u_boot_console):
+ "Test QEMU firmware config lists devices."
+
+ output = u_boot_console.run_command('qfw list')
+ assert 'bootorder' in output
+ assert 'etc/table-loader' in output
--
2.20.1
More information about the U-Boot
mailing list