[PATCH v4 3/5] qemu: add sandbox driver and tests
Asherah Connor
ashe at kivikakk.ee
Wed Feb 24 04:23:22 CET 2021
We minimally exercise the sandbox driver.
Signed-off-by: Asherah Connor <ashe at kivikakk.ee>
---
(no changes since v1)
arch/sandbox/dts/sandbox.dtsi | 4 ++
arch/sandbox/dts/test.dts | 4 ++
drivers/misc/Makefile | 1 +
drivers/misc/qfw_sandbox.c | 129 ++++++++++++++++++++++++++++++++++
test/dm/Makefile | 1 +
test/dm/qfw.c | 42 +++++++++++
6 files changed, 181 insertions(+)
create mode 100644 drivers/misc/qfw_sandbox.c
create mode 100644 test/dm/qfw.c
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi
index dc933f3bfc..7ce05b9662 100644
--- a/arch/sandbox/dts/sandbox.dtsi
+++ b/arch/sandbox/dts/sandbox.dtsi
@@ -390,6 +390,10 @@
sandbox_tee {
compatible = "sandbox,tee";
};
+
+ qfw {
+ compatible = "sandbox,qemu-fw-cfg-mmio";
+ };
};
&cros_ec {
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index d4195b45bb..4b3f8831d5 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -112,6 +112,10 @@
compatible = "sandbox,dsi-host";
};
+ qfw {
+ compatible = "sandbox,qemu-fw-cfg-mmio";
+ };
+
a-test {
reg = <0 1>;
compatible = "denx,u-boot-fdt-test";
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 2988289ea3..c48f61b797 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -59,6 +59,7 @@ ifdef CONFIG_QFW
obj-y += qfw.o
obj-$(CONFIG_X86) += qfw_pio.o
obj-$(CONFIG_ARM) += qfw_mmio.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..fc7006ae19
--- /dev/null
+++ b/drivers/misc/qfw_sandbox.c
@@ -0,0 +1,129 @@
+// 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,
+};
+
+static const struct udevice_id qfw_sandbox_ids[] = {
+ { .compatible = "sandbox,qemu-fw-cfg-mmio" },
+ {}
+};
+
+U_BOOT_DRIVER(qfw_sandbox) = {
+ .name = "qfw_sandbox",
+ .id = UCLASS_QFW,
+ .of_match = qfw_sandbox_ids,
+ .plat_auto = sizeof(struct qfw_sandbox_plat),
+ .probe = qfw_sandbox_probe,
+ .ops = &qfw_sandbox_ops,
+};
diff --git a/test/dm/Makefile b/test/dm/Makefile
index 6275ec56ea..bdca7ae613 100644
--- a/test/dm/Makefile
+++ b/test/dm/Makefile
@@ -95,5 +95,6 @@ obj-$(CONFIG_SCMI_FIRMWARE) += scmi.o
ifneq ($(CONFIG_PINMUX),)
obj-$(CONFIG_PINCONF) += pinmux.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..51b1c42dda
--- /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_FDT);
+
+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_FDT);
--
2.20.1
More information about the U-Boot
mailing list