[PATCH v2 2/2] drivers: misc: Add driver to access ZynqMP efuses

2024-05-15 Thread lukas . funke-oss
From: Lukas Funke 

Add driver to access ZynqMP efuses. This is a u-boot port of [1].

[1] 
https://lore.kernel.org/all/20240224114516.86365-8-srinivas.kandaga...@linaro.org/

Signed-off-by: Lukas Funke 
---

Changes in v2:
- Drop vendor specific fuse cmd, use existing fuse cmd
- Minor code refactoring (reverse x-mas tree)

 drivers/misc/Kconfig|   8 +
 drivers/misc/Makefile   |   1 +
 drivers/misc/zynqmp_efuse.c | 324 
 3 files changed, 333 insertions(+)
 create mode 100644 drivers/misc/zynqmp_efuse.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6009d55f400..c07f50c9a76 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -298,6 +298,14 @@ config FSL_SEC_MON
  Security Monitor can be transitioned on any security failures,
  like software violations or hardware security violations.
 
+config ZYNQMP_EFUSE
+   bool "Enable ZynqMP eFUSE Driver"
+   depends on ZYNQMP_FIRMWARE
+   help
+ Enable access to Zynq UltraScale (ZynqMP) eFUSEs thought PMU firmware
+ interface. ZnyqMP has 256 eFUSEs where some of them are security 
related
+ and cannot be read back (i.e. AES key).
+
 choice
prompt "Security monitor interaction endianess"
depends on FSL_SEC_MON
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e53d52c47b3..68ba5648eab 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -92,3 +92,4 @@ obj-$(CONFIG_ESM_K3) += k3_esm.o
 obj-$(CONFIG_ESM_PMIC) += esm_pmic.o
 obj-$(CONFIG_SL28CPLD) += sl28cpld.o
 obj-$(CONFIG_SPL_SOCFPGA_DT_REG) += socfpga_dtreg.o
+obj-$(CONFIG_ZYNQMP_EFUSE) += zynqmp_efuse.o
diff --git a/drivers/misc/zynqmp_efuse.c b/drivers/misc/zynqmp_efuse.c
new file mode 100644
index 000..98a39c1ebdd
--- /dev/null
+++ b/drivers/misc/zynqmp_efuse.c
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 - 2015 Xilinx, Inc.
+ * Michal Simek 
+ *
+ * (C) Copyright 2024 Weidmueller Interface GmbH
+ * Lukas Funke 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SILICON_REVISION_MASK 0xF
+#define P_USER_0_64_UPPER_MASK 0x5FFF
+#define P_USER_127_LOWER_4_BIT_MASK 0xF
+#define WORD_INBYTES   (4)
+#define SOC_VER_SIZE   (0x4)
+#define SOC_VERSION_OFFSET (0x0)
+#define EFUSE_START_OFFSET (0xC)
+#define EFUSE_END_OFFSET   (0xFC)
+#define EFUSE_PUF_START_OFFSET (0x100)
+#define EFUSE_PUF_MID_OFFSET   (0x140)
+#define EFUSE_PUF_END_OFFSET   (0x17F)
+#define EFUSE_NOT_ENABLED  (29)
+#define EFUSE_READ (0)
+#define EFUSE_WRITE(1)
+
+/**
+ * struct efuse_map_entry - offset and length of zynqmp fuses
+ * @offset:offset of efuse to be read/write
+ * @length:length of efuse
+ */
+struct efuse_map_entry {
+   u32 offset;
+   u32 length;
+};
+
+struct efuse_map_entry zynqmp_efuse_table[] = {
+   {0x000, 0x04}, /* soc revision */
+   {0x00c, 0x0c}, /* SoC DNA */
+   {0x020, 0x04}, /* efuse-usr0 */
+   {0x024, 0x04}, /* efuse-usr1 */
+   {0x028, 0x04}, /* efuse-usr2 */
+   {0x02c, 0x04}, /* efuse-usr3 */
+   {0x030, 0x04}, /* efuse-usr4 */
+   {0x034, 0x04}, /* efuse-usr5 */
+   {0x038, 0x04}, /* efuse-usr6 */
+   {0x03c, 0x04}, /* efuse-usr7 */
+   {0x040, 0x04}, /* efuse-miscusr */
+   {0x050, 0x04}, /* efuse-chash */
+   {0x054, 0x04}, /* efuse-pufmisc */
+   {0x058, 0x04}, /* efuse-sec */
+   {0x05c, 0x04}, /* efuse-spkid */
+   {0x060, 0x30}, /* efuse-aeskey */
+   {0x0a0, 0x30}, /* ppk0-hash */
+   {0x0d0, 0x30}, /* ppk1-hash */
+   {0x100, 0x7f}, /* pufuser */
+};
+
+/**
+ * struct xilinx_efuse - the basic structure
+ * @src:   address of the buffer to store the data to be write/read
+ * @size:  no of words to be read/write
+ * @offset:offset to be read/write`
+ * @flag:  0 - represents efuse read and 1- represents efuse write
+ * @pufuserfuse:0 - represents non-puf efuses, offset is used for read/write
+ * 1 - represents puf user fuse row number.
+ *
+ * this structure stores all the required details to
+ * read/write efuse memory.
+ */
+struct xilinx_efuse {
+   u64 src;
+   u32 size;
+   u32 offset;
+   u32 flag;
+   u32 pufuserfuse;
+};
+
+static int zynqmp_efuse_get_length(u32 offset, u32 *base_offset, u32 *len)
+{
+   struct efuse_map_entry *fuse;
+   int i;
+
+   for (i = 0; i < ARRAY_SIZE(zynqmp_efuse_table); ++i) {
+   fuse = _efuse_table[i];
+   if (offset >= fuse->offset &&
+   offset < fuse->offset + fuse->length) {
+   *base_offset = fuse->offset;
+   *len = fuse->length;
+   return 0;
+   }
+   }
+
+   return -ENOENT;
+}
+
+static int zynqmp_efuse_access(struct udevice *dev, unsigned int offset,
+ 

[PATCH v2 1/2] firmware: zynqmp: Add support to access efuses

2024-05-15 Thread lukas . funke-oss
From: Lukas Funke 

Add functions to access efuses through PMU firmware
interface.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 drivers/firmware/firmware-zynqmp.c | 31 ++
 include/zynqmp_firmware.h  |  2 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/firmware/firmware-zynqmp.c 
b/drivers/firmware/firmware-zynqmp.c
index f99507d86c6..d7fbe6a3efb 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -210,6 +210,37 @@ int zynqmp_pm_feature(const u32 api_id)
return ret_payload[1] & FIRMWARE_VERSION_MASK;
 }
 
+int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
+{
+   u32 ret_payload[PAYLOAD_ARG_CNT];
+   int ret;
+
+   if (!idcode || !version)
+   return -EINVAL;
+
+   ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
+   *idcode = ret_payload[1];
+   *version = ret_payload[2];
+
+   return ret;
+}
+
+int zynqmp_pm_efuse_access(const u64 address, u32 *out)
+{
+   u32 ret_payload[PAYLOAD_ARG_CNT];
+   int ret;
+
+   if (!out)
+   return -EINVAL;
+
+   ret = xilinx_pm_request(PM_EFUSE_ACCESS, upper_32_bits(address),
+   lower_32_bits(address), 0, 0, ret_payload);
+
+   *out = ret_payload[1];
+
+   return ret;
+}
+
 int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
 {
int ret;
diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
index 73198a6a6ea..7f18b4d59bf 100644
--- a/include/zynqmp_firmware.h
+++ b/include/zynqmp_firmware.h
@@ -453,6 +453,8 @@ int xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 
arg2,
 int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 
value);
 int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
 u32 value);
+int zynqmp_pm_get_chipid(u32 *idcode, u32 *version);
+int zynqmp_pm_efuse_access(const u64 address, u32 *out);
 int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id);
 int zynqmp_mmio_read(const u32 address, u32 *value);
 int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value);
-- 
2.30.2



[PATCH v2 0/2] Add eFuse access for ZynqMP

2024-05-15 Thread lukas . funke-oss
From: Lukas Funke 


This series adds a driver to read and write ZynqMP eFuses [1]. The
driver can be accessed by the 'fuse read' and 'fuse write' commands

Example:

=> fuse read 0 0xc 3
Reading bank 0:

Word 0x000c: 3cb16685 013af244 4000

Note: Accessing eFuses requires eFuse access to be enabled in the
underlying PMU firmware.

Use cases are:
 - Reading/writing user specific eFuses to enable device specific
   implementations
 - Revoking SPK IDs
 - Reading SoC version/DNA

[1] https://docs.amd.com/r/en-US/ug1085-zynq-ultrascale-trm/eFUSE


Changes in v2:
- Drop vendor specific fuse cmd, use existing fuse cmd
- Minor code refactoring (reverse x-mas tree)

Lukas Funke (2):
  firmware: zynqmp: Add support to access efuses
  drivers: misc: Add driver to access ZynqMP efuses

 drivers/firmware/firmware-zynqmp.c |  31 +++
 drivers/misc/Kconfig   |   8 +
 drivers/misc/Makefile  |   1 +
 drivers/misc/zynqmp_efuse.c| 324 +
 include/zynqmp_firmware.h  |   2 +
 5 files changed, 366 insertions(+)
 create mode 100644 drivers/misc/zynqmp_efuse.c

-- 
2.30.2



[PATCH 3/3] drivers: misc: Add driver to access ZynqMP efuses

2024-05-14 Thread lukas . funke-oss
From: Lukas Funke 

Add driver to access ZynqMP efuses. This is a u-boot port of [1].

[1] 
https://lore.kernel.org/all/20240224114516.86365-8-srinivas.kandaga...@linaro.org/

Signed-off-by: Lukas Funke 
---

 drivers/misc/Kconfig|   8 ++
 drivers/misc/Makefile   |   1 +
 drivers/misc/zynqmp_efuse.c | 213 
 3 files changed, 222 insertions(+)
 create mode 100644 drivers/misc/zynqmp_efuse.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 6009d55f400..c07f50c9a76 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -298,6 +298,14 @@ config FSL_SEC_MON
  Security Monitor can be transitioned on any security failures,
  like software violations or hardware security violations.
 
+config ZYNQMP_EFUSE
+   bool "Enable ZynqMP eFUSE Driver"
+   depends on ZYNQMP_FIRMWARE
+   help
+ Enable access to Zynq UltraScale (ZynqMP) eFUSEs thought PMU firmware
+ interface. ZnyqMP has 256 eFUSEs where some of them are security 
related
+ and cannot be read back (i.e. AES key).
+
 choice
prompt "Security monitor interaction endianess"
depends on FSL_SEC_MON
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e53d52c47b3..68ba5648eab 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -92,3 +92,4 @@ obj-$(CONFIG_ESM_K3) += k3_esm.o
 obj-$(CONFIG_ESM_PMIC) += esm_pmic.o
 obj-$(CONFIG_SL28CPLD) += sl28cpld.o
 obj-$(CONFIG_SPL_SOCFPGA_DT_REG) += socfpga_dtreg.o
+obj-$(CONFIG_ZYNQMP_EFUSE) += zynqmp_efuse.o
diff --git a/drivers/misc/zynqmp_efuse.c b/drivers/misc/zynqmp_efuse.c
new file mode 100644
index 000..0cfc42a4f39
--- /dev/null
+++ b/drivers/misc/zynqmp_efuse.c
@@ -0,0 +1,213 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2014 - 2015 Xilinx, Inc.
+ * Michal Simek 
+ *
+ * (C) Copyright 2024 Weidmueller Interface GmbH
+ * Lukas Funke 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SILICON_REVISION_MASK 0xF
+#define P_USER_0_64_UPPER_MASK 0x5FFF
+#define P_USER_127_LOWER_4_BIT_MASK 0xF
+#define WORD_INBYTES   (4)
+#define SOC_VER_SIZE   (0x4)
+#define EFUSE_MEMORY_SIZE  (0x177)
+#define UNUSED_SPACE   (0x8)
+#define ZYNQMP_NVMEM_SIZE  (SOC_VER_SIZE + UNUSED_SPACE + \
+EFUSE_MEMORY_SIZE)
+#define SOC_VERSION_OFFSET (0x0)
+#define EFUSE_START_OFFSET (0xC)
+#define EFUSE_END_OFFSET   (0xFC)
+#define EFUSE_PUF_START_OFFSET (0x100)
+#define EFUSE_PUF_MID_OFFSET   (0x140)
+#define EFUSE_PUF_END_OFFSET   (0x17F)
+#define EFUSE_NOT_ENABLED  (29)
+#define EFUSE_READ (0)
+#define EFUSE_WRITE(1)
+
+/**
+ * struct xilinx_efuse - the basic structure
+ * @src:   address of the buffer to store the data to be write/read
+ * @size:  no of words to be read/write
+ * @offset:offset to be read/write`
+ * @flag:  0 - represents efuse read and 1- represents efuse write
+ * @pufuserfuse:0 - represents non-puf efuses, offset is used for read/write
+ * 1 - represents puf user fuse row number.
+ *
+ * this structure stores all the required details to
+ * read/write efuse memory.
+ */
+struct xilinx_efuse {
+   u64 src;
+   u32 size;
+   u32 offset;
+   u32 flag;
+   u32 pufuserfuse;
+};
+
+static int zynqmp_efuse_access(struct udevice *dev, unsigned int offset,
+  void *val, size_t bytes, unsigned int flag,
+  unsigned int pufflag)
+{
+   size_t words = bytes / WORD_INBYTES;
+   ulong dma_addr, dma_buf;
+   struct xilinx_efuse *efuse;
+   char *data;
+   int ret, value;
+
+   if (bytes % WORD_INBYTES != 0) {
+   dev_err(dev, "Bytes requested should be word aligned\n");
+   return -EOPNOTSUPP;
+   }
+
+   if (pufflag == 0 && offset % WORD_INBYTES) {
+   dev_err(dev, "Offset requested should be word aligned\n");
+   return -EOPNOTSUPP;
+   }
+
+   if (pufflag == 1 && flag == EFUSE_WRITE) {
+   memcpy(, val, bytes);
+   if ((offset == EFUSE_PUF_START_OFFSET ||
+offset == EFUSE_PUF_MID_OFFSET) &&
+   value & P_USER_0_64_UPPER_MASK) {
+   dev_err(dev, "Only lower 4 bytes are allowed to be 
programmed in P_USER_0 & P_USER_64\n");
+   return -EOPNOTSUPP;
+   }
+
+   if (offset == EFUSE_PUF_END_OFFSET &&
+   (value & P_USER_127_LOWER_4_BIT_MASK)) {
+   dev_err(dev, "Only MSB 28 bits are allowed to be 
programmed for P_USER_127\n");
+   return -EOPNOTSUPP;
+   }
+   }
+
+   efuse = dma_alloc_coherent(sizeof(struct xilinx_efuse), _addr);
+   if (!efuse)
+   return -ENOMEM;
+
+   data = 

[PATCH 0/3] Add eFuse access for ZynqMP

2024-05-14 Thread lukas . funke-oss
From: Lukas Funke 


This series adds a driver to read and write ZynqMP eFuses [1]. The
driver can be accessed by the 'efuse_read' and 'efuse_write' subcommands
of the 'zynqmp' command.

Example:

=> zynqmp efuse_read 0xc 0xc
: 85 66 b1 32 43 f2 4a 02 00 00 00 40  .f.https://docs.amd.com/r/en-US/ug1085-zynq-ultrascale-trm/eFUSE



Lukas Funke (3):
  firmware: zynqmp: Add support to access efuses
  amd64: zynqmp: Add command to program efuses
  drivers: misc: Add driver to access ZynqMP efuses

 board/xilinx/zynqmp/cmds.c | 101 ++
 drivers/firmware/firmware-zynqmp.c |  31 +
 drivers/misc/Kconfig   |   8 ++
 drivers/misc/Makefile  |   1 +
 drivers/misc/zynqmp_efuse.c| 213 +
 include/zynqmp_firmware.h  |   2 +
 6 files changed, 356 insertions(+)
 create mode 100644 drivers/misc/zynqmp_efuse.c

-- 
2.30.2



[PATCH 2/3] amd64: zynqmp: Add command to program efuses

2024-05-14 Thread lukas . funke-oss
From: Lukas Funke 

Add subcommands to read/write eFuses using u-boot. The subcommands
through the 'zynqmp' command.

Example:

=> zynqmp efuse_read 0xc 0xc
: 85 36 b1 3c 34 f2 3b 01 00 00 00 40  .f.
---

 board/xilinx/zynqmp/cmds.c | 101 +
 1 file changed, 101 insertions(+)

diff --git a/board/xilinx/zynqmp/cmds.c b/board/xilinx/zynqmp/cmds.c
index bf39c5472ea..e8d70ffecd6 100644
--- a/board/xilinx/zynqmp/cmds.c
+++ b/board/xilinx/zynqmp/cmds.c
@@ -16,6 +16,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 static int do_zynqmp_verify_secure(struct cmd_tbl *cmdtp, int flag, int argc,
   char *const argv[])
@@ -340,6 +343,99 @@ static int do_zynqmp_sha3(struct cmd_tbl *cmdtp, int flag,
return CMD_RET_SUCCESS;
 }
 
+static int do_zynqmp_efuse_read(struct cmd_tbl *cmdtp, int flag,
+   int argc, char * const argv[])
+{
+   struct udevice *dev;
+   u32 offset, len;
+   u8 buf[32];
+   int ret;
+
+   if (!CONFIG_IS_ENABLED(ZYNQMP_EFUSE)) {
+   printf("Failed: not supported\n");
+   return CMD_RET_FAILURE;
+   }
+
+   if (argc > cmdtp->maxargs || argc < (cmdtp->maxargs - 1))
+   return CMD_RET_USAGE;
+
+   memset(buf, 0, sizeof(buf));
+
+   offset = hextoul(argv[2], NULL);
+   len = hextoul(argv[3], NULL);
+
+   if (len > sizeof(buf)) {
+   printf("Failed: length exceeds buffer size");
+   return CMD_RET_FAILURE;
+   }
+
+   ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_DRIVER_GET(zynqmp_efuse), );
+   if (ret) {
+   printf("Failed to initialize zynqmp_efuse: %d\n", ret);
+   return CMD_RET_FAILURE;
+   }
+
+   ret = misc_read(dev, offset, (void *)buf, len);
+   if (ret) {
+   printf("Failed: cannot read efuse at 0x%x, errocode %d\n",
+  offset, ret);
+   return CMD_RET_FAILURE;
+   }
+
+   if (CONFIG_IS_ENABLED(HEXDUMP))
+   print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
+
+   return CMD_RET_SUCCESS;
+}
+
+static int do_zynqmp_efuse_write(struct cmd_tbl *cmdtp, int flag,
+int argc, char * const argv[])
+{
+   struct udevice *dev;
+   u64 value;
+   u32 offset, len;
+   u8 buf[sizeof(u64)];
+   int ret;
+
+   if (!CONFIG_IS_ENABLED(ZYNQMP_EFUSE)) {
+   printf("Failed: not supported\n");
+   return CMD_RET_FAILURE;
+   }
+
+   if (argc > cmdtp->maxargs || argc < (cmdtp->maxargs - 1))
+   return CMD_RET_USAGE;
+
+   memset(buf, 0, sizeof(buf));
+
+   offset = hextoul(argv[2], NULL);
+   len = hextoul(argv[3], NULL);
+
+   if (len <= sizeof(u64)) {
+   value = hextoul(argv[4], NULL);
+   memcpy(buf, , sizeof(value));
+   } else {
+   printf("Cannot write more than %zu byte to efuse\n", 
sizeof(u64));
+   return CMD_RET_FAILURE;
+   }
+
+   ret = uclass_get_device_by_driver(UCLASS_MISC,
+ DM_DRIVER_GET(zynqmp_efuse), );
+   if (ret) {
+   printf("Failed to initialize zynqmp_efuse: %d\n", ret);
+   return CMD_RET_FAILURE;
+   }
+
+   ret = misc_write(dev, offset, (void *)buf, sizeof(buf));
+   if (ret) {
+   printf("Failed: cannot read efuse at 0x%x, errocode 0x%x\n",
+  offset, ret);
+   return CMD_RET_FAILURE;
+   }
+
+   return CMD_RET_SUCCESS;
+}
+
 static struct cmd_tbl cmd_zynqmp_sub[] = {
U_BOOT_CMD_MKENT(secure, 5, 0, do_zynqmp_verify_secure, "", ""),
U_BOOT_CMD_MKENT(pmufw, 4, 0, do_zynqmp_pmufw, "", ""),
@@ -348,6 +444,8 @@ static struct cmd_tbl cmd_zynqmp_sub[] = {
U_BOOT_CMD_MKENT(aes, 9, 0, do_zynqmp_aes, "", ""),
U_BOOT_CMD_MKENT(rsa, 7, 0, do_zynqmp_rsa, "", ""),
U_BOOT_CMD_MKENT(sha3, 5, 0, do_zynqmp_sha3, "", ""),
+   U_BOOT_CMD_MKENT(efuse_read, 4, 0, do_zynqmp_efuse_read, "", ""),
+   U_BOOT_CMD_MKENT(efuse_write, 5, 0, do_zynqmp_efuse_write, "", ""),
 #ifdef CONFIG_DEFINE_TCM_OCM_MMAP
U_BOOT_CMD_MKENT(tcminit, 3, 0, do_zynqmp_tcm_init, "", ""),
 #endif
@@ -422,6 +520,9 @@ U_BOOT_LONGHELP(zynqmp,
"   48 bytes hash value into srcaddr\n"
"   Optional key_addr can be specified for saving sha3 hash value\n"
"   Note: srcaddr/srclen should not be 0\n"
+   "zynqmp efuse_read offset len - read efuse at given offset\n"
+   "zynqmp efuse_write offset len value - write value of length \n"
+   "  to efuse at given offset\n"
);
 
 U_BOOT_CMD(
-- 
2.30.2



[PATCH 1/3] firmware: zynqmp: Add support to access efuses

2024-05-14 Thread lukas . funke-oss
From: Lukas Funke 

Add functions to access efuses through PMU firmware
interface.

Signed-off-by: Lukas Funke 
---

 drivers/firmware/firmware-zynqmp.c | 31 ++
 include/zynqmp_firmware.h  |  2 ++
 2 files changed, 33 insertions(+)

diff --git a/drivers/firmware/firmware-zynqmp.c 
b/drivers/firmware/firmware-zynqmp.c
index f99507d86c6..7483f2a8709 100644
--- a/drivers/firmware/firmware-zynqmp.c
+++ b/drivers/firmware/firmware-zynqmp.c
@@ -210,6 +210,37 @@ int zynqmp_pm_feature(const u32 api_id)
return ret_payload[1] & FIRMWARE_VERSION_MASK;
 }
 
+int zynqmp_pm_get_chipid(u32 *idcode, u32 *version)
+{
+   int ret;
+   u32 ret_payload[PAYLOAD_ARG_CNT];
+
+   if (!idcode || !version)
+   return -EINVAL;
+
+   ret = xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload);
+   *idcode = ret_payload[1];
+   *version = ret_payload[2];
+
+   return ret;
+}
+
+int zynqmp_pm_efuse_access(const u64 address, u32 *out)
+{
+   int ret;
+   u32 ret_payload[PAYLOAD_ARG_CNT];
+
+   if (!out)
+   return -EINVAL;
+
+   ret = xilinx_pm_request(PM_EFUSE_ACCESS, upper_32_bits(address),
+   lower_32_bits(address), 0, 0, ret_payload);
+
+   *out = ret_payload[1];
+
+   return ret;
+}
+
 int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id)
 {
int ret;
diff --git a/include/zynqmp_firmware.h b/include/zynqmp_firmware.h
index 73198a6a6ea..7f18b4d59bf 100644
--- a/include/zynqmp_firmware.h
+++ b/include/zynqmp_firmware.h
@@ -453,6 +453,8 @@ int xilinx_pm_request(u32 api_id, u32 arg0, u32 arg1, u32 
arg2,
 int zynqmp_pm_set_sd_config(u32 node, enum pm_sd_config_type config, u32 
value);
 int zynqmp_pm_set_gem_config(u32 node, enum pm_gem_config_type config,
 u32 value);
+int zynqmp_pm_get_chipid(u32 *idcode, u32 *version);
+int zynqmp_pm_efuse_access(const u64 address, u32 *out);
 int zynqmp_pm_is_function_supported(const u32 api_id, const u32 id);
 int zynqmp_mmio_read(const u32 address, u32 *value);
 int zynqmp_mmio_write(const u32 address, const u32 mask, const u32 value);
-- 
2.30.2



[RFC PATCH v1 1/1] mmc: zynq_sdhci: Only evaluate card-stable signal if card was detected

2024-04-24 Thread lukas . funke-oss
From: Lukas Funke 

On ZynqMp there seems to be a dependency between the card-stable bit and
the card-detect bit. The card-stable bit is set *if and only if*
the card-detect bit was set before, indicating that the signal was
stable and reliable during card insertion.

If the card-detect bit is *not* evaluated the corresponding check leads
to a timeout indicating that the card-detect was not stable.

Signed-off-by: Lukas Funke 
---

 drivers/mmc/zynq_sdhci.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c
index 935540d171..d0bccd41cc 100644
--- a/drivers/mmc/zynq_sdhci.c
+++ b/drivers/mmc/zynq_sdhci.c
@@ -1168,11 +1168,14 @@ static int arasan_sdhci_probe(struct udevice *dev)
 */
if (IS_ENABLED(CONFIG_ARCH_ZYNQMP) || IS_ENABLED(CONFIG_ARCH_VERSAL)) {
u32 timeout = 100;
+   u32 value;
 
-   while (((sdhci_readl(host, SDHCI_PRESENT_STATE) &
-SDHCI_CARD_STATE_STABLE) == 0) && timeout) {
+   value = sdhci_readl(host, SDHCI_PRESENT_STATE);
+   while ((value & SDHCI_CARD_PRESENT) &&
+  ((value & SDHCI_CARD_STATE_STABLE) == 0) && timeout) {
udelay(1);
timeout--;
+   value = sdhci_readl(host, SDHCI_PRESENT_STATE);
}
if (!timeout) {
dev_err(dev, "Sdhci card detect state not stable\n");
-- 
2.30.2



[RFC PATCH v1 0/1] mmc: zynq_sdhci: Only evaluate card-stable signal if card was detected

2024-04-24 Thread lukas . funke-oss
From: Lukas Funke 


On ZynqMp there seems to be a dependency between the card-stable bit and
the card-detect bit. The card-stable bit is set *if and only if*
the card-detect bit was set before, indicating that the signal was
stable and reliable during card insertion.

If the card-detect bit is *not* evaluated the corresponding check leads
to a timeout indicating that the card-detect was not stable.

There was another patch that tried to mitigate this behaviour:

https://lore.kernel.org/u-boot/20230516142116.29996-1-stefan.herbrechtsmeier-...@weidmueller.com/T/#m295a0158fe62da7289baa26bcd7272ad8598af56

However, the discussion stalled and the solution was not accepted. This
patch introduces another way to deal with the observed behaviour.



Lukas Funke (1):
  mmc: zynq_sdhci: Only evaluate card-stable signal if card was detected

 drivers/mmc/zynq_sdhci.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

-- 
2.30.2



[PATCH v3 2/2] board: starfive: Rename spl_soc_init() to spl_dram_init()

2024-04-24 Thread lukas . funke-oss
From: Lukas Funke 

Rename spl_soc_init() to spl_dram_init() because the generic function
name does not reflect what the function actually does. Also
spl_dram_init() is commonly used for dram initialization and should be
called from board_init_f().

Signed-off-by: Lukas Funke 
---

Changes in v3:
 - Reorganize patches such that each patch can be built individually

Changes in v2:
 - capitalized acronym DRAM

 arch/riscv/cpu/jh7110/spl.c  | 2 +-
 arch/riscv/include/asm/arch-jh7110/spl.h | 2 +-
 board/starfive/visionfive2/spl.c | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/riscv/cpu/jh7110/spl.c b/arch/riscv/cpu/jh7110/spl.c
index 6bdf8b9c72..87aaf86524 100644
--- a/arch/riscv/cpu/jh7110/spl.c
+++ b/arch/riscv/cpu/jh7110/spl.c
@@ -28,7 +28,7 @@ static bool check_ddr_size(phys_size_t size)
}
 }
 
-int spl_soc_init(void)
+int spl_dram_init(void)
 {
int ret;
struct udevice *dev;
diff --git a/arch/riscv/include/asm/arch-jh7110/spl.h 
b/arch/riscv/include/asm/arch-jh7110/spl.h
index 23ce8871b3..d73355bf35 100644
--- a/arch/riscv/include/asm/arch-jh7110/spl.h
+++ b/arch/riscv/include/asm/arch-jh7110/spl.h
@@ -7,6 +7,6 @@
 #ifndef _SPL_STARFIVE_H
 #define _SPL_STARFIVE_H
 
-int spl_soc_init(void);
+int spl_dram_init(void);
 
 #endif /* _SPL_STARFIVE_H */
diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c
index 45848db6d8..ca61b5be22 100644
--- a/board/starfive/visionfive2/spl.c
+++ b/board/starfive/visionfive2/spl.c
@@ -285,9 +285,9 @@ int spl_board_init_f(void)
 
jh7110_jtag_init();
 
-   ret = spl_soc_init();
+   ret = spl_dram_init();
if (ret) {
-   debug("JH7110 SPL init failed: %d\n", ret);
+   debug("JH7110 DRAM init failed: %d\n", ret);
return ret;
}
 
-- 
2.30.2



[PATCH v3 1/2] board: sifive: Rename spl_soc_init() to spl_dram_init()

2024-04-24 Thread lukas . funke-oss
From: Lukas Funke 

Rename spl_soc_init() to spl_dram_init() because the generic function
name does not reflect what the function actually does. Also
spl_dram_init() is commonly used for dram initialization and should be
called from board_init_f().

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 arch/riscv/cpu/fu540/spl.c  | 2 +-
 arch/riscv/cpu/fu740/spl.c  | 2 +-
 arch/riscv/include/asm/arch-fu540/spl.h | 2 +-
 arch/riscv/include/asm/arch-fu740/spl.h | 2 +-
 board/sifive/unleashed/spl.c| 4 ++--
 board/sifive/unmatched/spl.c| 4 ++--
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/riscv/cpu/fu540/spl.c b/arch/riscv/cpu/fu540/spl.c
index 45657b7909..cedb70b66a 100644
--- a/arch/riscv/cpu/fu540/spl.c
+++ b/arch/riscv/cpu/fu540/spl.c
@@ -7,7 +7,7 @@
 #include 
 #include 
 
-int spl_soc_init(void)
+int spl_dram_init(void)
 {
int ret;
struct udevice *dev;
diff --git a/arch/riscv/cpu/fu740/spl.c b/arch/riscv/cpu/fu740/spl.c
index c6816e9ed4..16b307f036 100644
--- a/arch/riscv/cpu/fu740/spl.c
+++ b/arch/riscv/cpu/fu740/spl.c
@@ -10,7 +10,7 @@
 
 #define CSR_U74_FEATURE_DISABLE0x7c1
 
-int spl_soc_init(void)
+int spl_dram_init(void)
 {
int ret;
struct udevice *dev;
diff --git a/arch/riscv/include/asm/arch-fu540/spl.h 
b/arch/riscv/include/asm/arch-fu540/spl.h
index 4697279f43..519e7eb210 100644
--- a/arch/riscv/include/asm/arch-fu540/spl.h
+++ b/arch/riscv/include/asm/arch-fu540/spl.h
@@ -9,6 +9,6 @@
 #ifndef _SPL_SIFIVE_H
 #define _SPL_SIFIVE_H
 
-int spl_soc_init(void);
+int spl_dram_init(void);
 
 #endif /* _SPL_SIFIVE_H */
diff --git a/arch/riscv/include/asm/arch-fu740/spl.h 
b/arch/riscv/include/asm/arch-fu740/spl.h
index 15ad9e7c8b..b327ac5036 100644
--- a/arch/riscv/include/asm/arch-fu740/spl.h
+++ b/arch/riscv/include/asm/arch-fu740/spl.h
@@ -9,6 +9,6 @@
 #ifndef _SPL_SIFIVE_H
 #define _SPL_SIFIVE_H
 
-int spl_soc_init(void);
+int spl_dram_init(void);
 
 #endif /* _SPL_SIFIVE_H */
diff --git a/board/sifive/unleashed/spl.c b/board/sifive/unleashed/spl.c
index fe27316b2d..9df9c68604 100644
--- a/board/sifive/unleashed/spl.c
+++ b/board/sifive/unleashed/spl.c
@@ -27,9 +27,9 @@ int spl_board_init_f(void)
 {
int ret;
 
-   ret = spl_soc_init();
+   ret = spl_dram_init();
if (ret) {
-   debug("FU540 SPL init failed: %d\n", ret);
+   debug("FU540 DRAM init failed: %d\n", ret);
return ret;
}
 
diff --git a/board/sifive/unmatched/spl.c b/board/sifive/unmatched/spl.c
index e69bed9d99..6fc1d80954 100644
--- a/board/sifive/unmatched/spl.c
+++ b/board/sifive/unmatched/spl.c
@@ -134,9 +134,9 @@ int spl_board_init_f(void)
 {
int ret;
 
-   ret = spl_soc_init();
+   ret = spl_dram_init();
if (ret) {
-   debug("HiFive Unmatched FU740 SPL init failed: %d\n", ret);
+   debug("HiFive Unmatched FU740 DRAM init failed: %d\n", ret);
goto end;
}
 
-- 
2.30.2



[PATCH v3 0/2] riscv: Rename spl_soc_init() to spl_dram_init()

2024-04-24 Thread lukas . funke-oss
From: Lukas Funke 


This patch series renames spl_soc_init() to spl_dram_init() since the
purpose of the function is to initialization the DRAM on sifive/starfive
boards. spl_dram_init() is a commonly used function for this purpose.

Changes in v3:
 - Reorganize patches such that each patch can be built individually

Changes in v2:
 - capitalized acronym DRAM

Lukas Funke (2):
  board: sifive: Rename spl_soc_init() to spl_dram_init()
  board: starfive: Rename spl_soc_init() to spl_dram_init()

 arch/riscv/cpu/fu540/spl.c   | 2 +-
 arch/riscv/cpu/fu740/spl.c   | 2 +-
 arch/riscv/cpu/jh7110/spl.c  | 2 +-
 arch/riscv/include/asm/arch-fu540/spl.h  | 2 +-
 arch/riscv/include/asm/arch-fu740/spl.h  | 2 +-
 arch/riscv/include/asm/arch-jh7110/spl.h | 2 +-
 board/sifive/unleashed/spl.c | 4 ++--
 board/sifive/unmatched/spl.c | 4 ++--
 board/starfive/visionfive2/spl.c | 4 ++--
 9 files changed, 12 insertions(+), 12 deletions(-)

-- 
2.30.2



[PATCH v2 3/3] board: starfive: Call spl_dram_init() for DRAM initialization

2024-04-23 Thread lukas . funke-oss
From: Lukas Funke 

Call spl_dram_init() since this is commonly used for dram initialization
in u-boot.

Signed-off-by: Lukas Funke 
---

Changes in v2:
 - capitalized acronym DRAM

 board/starfive/visionfive2/spl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c
index 45848db6d8..ca61b5be22 100644
--- a/board/starfive/visionfive2/spl.c
+++ b/board/starfive/visionfive2/spl.c
@@ -285,9 +285,9 @@ int spl_board_init_f(void)
 
jh7110_jtag_init();
 
-   ret = spl_soc_init();
+   ret = spl_dram_init();
if (ret) {
-   debug("JH7110 SPL init failed: %d\n", ret);
+   debug("JH7110 DRAM init failed: %d\n", ret);
return ret;
}
 
-- 
2.30.2



[PATCH v2 1/3] arch: riscv: Rename spl_soc_init() to spl_dram_init()

2024-04-23 Thread lukas . funke-oss
From: Lukas Funke 

Rename spl_soc_init() to spl_dram_init() because the generic function
name does not reflect what the function is actually doing. In addition
spl_dram_init() is commonly used for dram initialization and should
be called from board_init_f().

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 arch/riscv/cpu/fu540/spl.c   | 2 +-
 arch/riscv/cpu/fu740/spl.c   | 2 +-
 arch/riscv/cpu/jh7110/spl.c  | 2 +-
 arch/riscv/include/asm/arch-fu540/spl.h  | 2 +-
 arch/riscv/include/asm/arch-fu740/spl.h  | 2 +-
 arch/riscv/include/asm/arch-jh7110/spl.h | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/cpu/fu540/spl.c b/arch/riscv/cpu/fu540/spl.c
index 45657b7909..cedb70b66a 100644
--- a/arch/riscv/cpu/fu540/spl.c
+++ b/arch/riscv/cpu/fu540/spl.c
@@ -7,7 +7,7 @@
 #include 
 #include 
 
-int spl_soc_init(void)
+int spl_dram_init(void)
 {
int ret;
struct udevice *dev;
diff --git a/arch/riscv/cpu/fu740/spl.c b/arch/riscv/cpu/fu740/spl.c
index c6816e9ed4..16b307f036 100644
--- a/arch/riscv/cpu/fu740/spl.c
+++ b/arch/riscv/cpu/fu740/spl.c
@@ -10,7 +10,7 @@
 
 #define CSR_U74_FEATURE_DISABLE0x7c1
 
-int spl_soc_init(void)
+int spl_dram_init(void)
 {
int ret;
struct udevice *dev;
diff --git a/arch/riscv/cpu/jh7110/spl.c b/arch/riscv/cpu/jh7110/spl.c
index 6bdf8b9c72..87aaf86524 100644
--- a/arch/riscv/cpu/jh7110/spl.c
+++ b/arch/riscv/cpu/jh7110/spl.c
@@ -28,7 +28,7 @@ static bool check_ddr_size(phys_size_t size)
}
 }
 
-int spl_soc_init(void)
+int spl_dram_init(void)
 {
int ret;
struct udevice *dev;
diff --git a/arch/riscv/include/asm/arch-fu540/spl.h 
b/arch/riscv/include/asm/arch-fu540/spl.h
index 4697279f43..519e7eb210 100644
--- a/arch/riscv/include/asm/arch-fu540/spl.h
+++ b/arch/riscv/include/asm/arch-fu540/spl.h
@@ -9,6 +9,6 @@
 #ifndef _SPL_SIFIVE_H
 #define _SPL_SIFIVE_H
 
-int spl_soc_init(void);
+int spl_dram_init(void);
 
 #endif /* _SPL_SIFIVE_H */
diff --git a/arch/riscv/include/asm/arch-fu740/spl.h 
b/arch/riscv/include/asm/arch-fu740/spl.h
index 15ad9e7c8b..b327ac5036 100644
--- a/arch/riscv/include/asm/arch-fu740/spl.h
+++ b/arch/riscv/include/asm/arch-fu740/spl.h
@@ -9,6 +9,6 @@
 #ifndef _SPL_SIFIVE_H
 #define _SPL_SIFIVE_H
 
-int spl_soc_init(void);
+int spl_dram_init(void);
 
 #endif /* _SPL_SIFIVE_H */
diff --git a/arch/riscv/include/asm/arch-jh7110/spl.h 
b/arch/riscv/include/asm/arch-jh7110/spl.h
index 23ce8871b3..d73355bf35 100644
--- a/arch/riscv/include/asm/arch-jh7110/spl.h
+++ b/arch/riscv/include/asm/arch-jh7110/spl.h
@@ -7,6 +7,6 @@
 #ifndef _SPL_STARFIVE_H
 #define _SPL_STARFIVE_H
 
-int spl_soc_init(void);
+int spl_dram_init(void);
 
 #endif /* _SPL_STARFIVE_H */
-- 
2.30.2



[PATCH v2 2/3] board: sifive: Call spl_dram_init() for DRAM initialization

2024-04-23 Thread lukas . funke-oss
From: Lukas Funke 

Call spl_dram_init() since this is commonly used for DRAM initialization
in u-boot.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 board/sifive/unleashed/spl.c | 4 ++--
 board/sifive/unmatched/spl.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/board/sifive/unleashed/spl.c b/board/sifive/unleashed/spl.c
index fe27316b2d..9df9c68604 100644
--- a/board/sifive/unleashed/spl.c
+++ b/board/sifive/unleashed/spl.c
@@ -27,9 +27,9 @@ int spl_board_init_f(void)
 {
int ret;
 
-   ret = spl_soc_init();
+   ret = spl_dram_init();
if (ret) {
-   debug("FU540 SPL init failed: %d\n", ret);
+   debug("FU540 DRAM init failed: %d\n", ret);
return ret;
}
 
diff --git a/board/sifive/unmatched/spl.c b/board/sifive/unmatched/spl.c
index e69bed9d99..6fc1d80954 100644
--- a/board/sifive/unmatched/spl.c
+++ b/board/sifive/unmatched/spl.c
@@ -134,9 +134,9 @@ int spl_board_init_f(void)
 {
int ret;
 
-   ret = spl_soc_init();
+   ret = spl_dram_init();
if (ret) {
-   debug("HiFive Unmatched FU740 SPL init failed: %d\n", ret);
+   debug("HiFive Unmatched FU740 DRAM init failed: %d\n", ret);
goto end;
}
 
-- 
2.30.2



[PATCH v2 0/3] riscv: Rename spl_soc_init() to spl_dram_init()

2024-04-23 Thread lukas . funke-oss
From: Lukas Funke 


This patch series renames spl_soc_init() to spl_dram_init() since the
purpose of the function is to initialization the DRAM on sifive/starfive
boards. spl_dram_init() is a commonly used function for this purpose.

Changes in v2:
 - capitalized acronym DRAM

Lukas Funke (3):
  arch: riscv: Rename spl_soc_init() to spl_dram_init()
  board: sifive: Call spl_dram_init() for DRAM initialization
  board: starfive: Call spl_dram_init() for DRAM initialization

 arch/riscv/cpu/fu540/spl.c   | 2 +-
 arch/riscv/cpu/fu740/spl.c   | 2 +-
 arch/riscv/cpu/jh7110/spl.c  | 2 +-
 arch/riscv/include/asm/arch-fu540/spl.h  | 2 +-
 arch/riscv/include/asm/arch-fu740/spl.h  | 2 +-
 arch/riscv/include/asm/arch-jh7110/spl.h | 2 +-
 board/sifive/unleashed/spl.c | 4 ++--
 board/sifive/unmatched/spl.c | 4 ++--
 board/starfive/visionfive2/spl.c | 4 ++--
 9 files changed, 12 insertions(+), 12 deletions(-)

-- 
2.30.2



[PATCH v1 0/3] riscv: Rename spl_soc_init() to spl_dram_init()

2024-04-22 Thread lukas . funke-oss
From: Lukas Funke 


This patch series renames spl_soc_init() to spl_dram_init() since the
purpose of the function is to initialization the DRAM on sifive/starfive
boards. spl_dram_init() is a commonly used function for this purpose.


Lukas Funke (3):
  arch: riscv: Rename spl_soc_init() to spl_dram_init()
  board: sifive: Call spl_dram_init() for DRAM initialization
  board: starfive: Call spl_dram_init() for DRAM initialization

 arch/riscv/cpu/fu540/spl.c   | 2 +-
 arch/riscv/cpu/fu740/spl.c   | 2 +-
 arch/riscv/cpu/jh7110/spl.c  | 2 +-
 arch/riscv/include/asm/arch-fu540/spl.h  | 2 +-
 arch/riscv/include/asm/arch-fu740/spl.h  | 2 +-
 arch/riscv/include/asm/arch-jh7110/spl.h | 2 +-
 board/sifive/unleashed/spl.c | 4 ++--
 board/sifive/unmatched/spl.c | 4 ++--
 board/starfive/visionfive2/spl.c | 4 ++--
 9 files changed, 12 insertions(+), 12 deletions(-)

-- 
2.30.2



[PATCH v1 2/3] board: sifive: Call spl_dram_init() for DRAM initialization

2024-04-22 Thread lukas . funke-oss
From: Lukas Funke 

Call spl_dram_init() since this is commonly used for dram initialization
in u-boot.

Signed-off-by: Lukas Funke 
---

 board/sifive/unleashed/spl.c | 4 ++--
 board/sifive/unmatched/spl.c | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/board/sifive/unleashed/spl.c b/board/sifive/unleashed/spl.c
index fe27316b2d..d6725a0e0e 100644
--- a/board/sifive/unleashed/spl.c
+++ b/board/sifive/unleashed/spl.c
@@ -27,9 +27,9 @@ int spl_board_init_f(void)
 {
int ret;
 
-   ret = spl_soc_init();
+   ret = spl_dram_init();
if (ret) {
-   debug("FU540 SPL init failed: %d\n", ret);
+   debug("FU540 dram init failed: %d\n", ret);
return ret;
}
 
diff --git a/board/sifive/unmatched/spl.c b/board/sifive/unmatched/spl.c
index e69bed9d99..500f484844 100644
--- a/board/sifive/unmatched/spl.c
+++ b/board/sifive/unmatched/spl.c
@@ -134,9 +134,9 @@ int spl_board_init_f(void)
 {
int ret;
 
-   ret = spl_soc_init();
+   ret = spl_dram_init();
if (ret) {
-   debug("HiFive Unmatched FU740 SPL init failed: %d\n", ret);
+   debug("HiFive Unmatched FU740 dram init failed: %d\n", ret);
goto end;
}
 
-- 
2.30.2



[PATCH v1 3/3] board: starfive: Call spl_dram_init() for DRAM initialization

2024-04-22 Thread lukas . funke-oss
From: Lukas Funke 

Call spl_dram_init() since this is commonly used for dram initialization
in u-boot.

Signed-off-by: Lukas Funke 
---

 board/starfive/visionfive2/spl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/board/starfive/visionfive2/spl.c b/board/starfive/visionfive2/spl.c
index 45848db6d8..d1db7ee87b 100644
--- a/board/starfive/visionfive2/spl.c
+++ b/board/starfive/visionfive2/spl.c
@@ -285,9 +285,9 @@ int spl_board_init_f(void)
 
jh7110_jtag_init();
 
-   ret = spl_soc_init();
+   ret = spl_dram_init();
if (ret) {
-   debug("JH7110 SPL init failed: %d\n", ret);
+   debug("JH7110 dram init failed: %d\n", ret);
return ret;
}
 
-- 
2.30.2



[PATCH v1 1/3] arch: riscv: Rename spl_soc_init() to spl_dram_init()

2024-04-22 Thread lukas . funke-oss
From: Lukas Funke 

Rename spl_soc_init() to spl_dram_init() because the generic function
name does not reflect what the function is actually doing. In addition
spl_dram_init() is commonly used for dram initialization and should
be called from board_init_f().

Signed-off-by: Lukas Funke 
---

 arch/riscv/cpu/fu540/spl.c   | 2 +-
 arch/riscv/cpu/fu740/spl.c   | 2 +-
 arch/riscv/cpu/jh7110/spl.c  | 2 +-
 arch/riscv/include/asm/arch-fu540/spl.h  | 2 +-
 arch/riscv/include/asm/arch-fu740/spl.h  | 2 +-
 arch/riscv/include/asm/arch-jh7110/spl.h | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/cpu/fu540/spl.c b/arch/riscv/cpu/fu540/spl.c
index 45657b7909..cedb70b66a 100644
--- a/arch/riscv/cpu/fu540/spl.c
+++ b/arch/riscv/cpu/fu540/spl.c
@@ -7,7 +7,7 @@
 #include 
 #include 
 
-int spl_soc_init(void)
+int spl_dram_init(void)
 {
int ret;
struct udevice *dev;
diff --git a/arch/riscv/cpu/fu740/spl.c b/arch/riscv/cpu/fu740/spl.c
index c6816e9ed4..16b307f036 100644
--- a/arch/riscv/cpu/fu740/spl.c
+++ b/arch/riscv/cpu/fu740/spl.c
@@ -10,7 +10,7 @@
 
 #define CSR_U74_FEATURE_DISABLE0x7c1
 
-int spl_soc_init(void)
+int spl_dram_init(void)
 {
int ret;
struct udevice *dev;
diff --git a/arch/riscv/cpu/jh7110/spl.c b/arch/riscv/cpu/jh7110/spl.c
index 6bdf8b9c72..87aaf86524 100644
--- a/arch/riscv/cpu/jh7110/spl.c
+++ b/arch/riscv/cpu/jh7110/spl.c
@@ -28,7 +28,7 @@ static bool check_ddr_size(phys_size_t size)
}
 }
 
-int spl_soc_init(void)
+int spl_dram_init(void)
 {
int ret;
struct udevice *dev;
diff --git a/arch/riscv/include/asm/arch-fu540/spl.h 
b/arch/riscv/include/asm/arch-fu540/spl.h
index 4697279f43..519e7eb210 100644
--- a/arch/riscv/include/asm/arch-fu540/spl.h
+++ b/arch/riscv/include/asm/arch-fu540/spl.h
@@ -9,6 +9,6 @@
 #ifndef _SPL_SIFIVE_H
 #define _SPL_SIFIVE_H
 
-int spl_soc_init(void);
+int spl_dram_init(void);
 
 #endif /* _SPL_SIFIVE_H */
diff --git a/arch/riscv/include/asm/arch-fu740/spl.h 
b/arch/riscv/include/asm/arch-fu740/spl.h
index 15ad9e7c8b..b327ac5036 100644
--- a/arch/riscv/include/asm/arch-fu740/spl.h
+++ b/arch/riscv/include/asm/arch-fu740/spl.h
@@ -9,6 +9,6 @@
 #ifndef _SPL_SIFIVE_H
 #define _SPL_SIFIVE_H
 
-int spl_soc_init(void);
+int spl_dram_init(void);
 
 #endif /* _SPL_SIFIVE_H */
diff --git a/arch/riscv/include/asm/arch-jh7110/spl.h 
b/arch/riscv/include/asm/arch-jh7110/spl.h
index 23ce8871b3..d73355bf35 100644
--- a/arch/riscv/include/asm/arch-jh7110/spl.h
+++ b/arch/riscv/include/asm/arch-jh7110/spl.h
@@ -7,6 +7,6 @@
 #ifndef _SPL_STARFIVE_H
 #define _SPL_STARFIVE_H
 
-int spl_soc_init(void);
+int spl_dram_init(void);
 
 #endif /* _SPL_STARFIVE_H */
-- 
2.30.2



[PATCH 3/3] zynq: Add function to lock JTAG enable bits

2024-03-28 Thread lukas . funke-oss
From: Stefan Herbrechtsmeier 

Add function to prevent debug access from being enabled. If the debug
lock is set the debug access cannot be enabled after a soft-reset.
The debug access can only be enabled after a power-on-reset is
performed.

Signed-off-by: Stefan Herbrechtsmeier 
Signed-off-by: Lukas Funke 
---

 arch/arm/mach-zynq/cpu.c| 10 ++
 arch/arm/mach-zynq/include/mach/sys_proto.h |  1 +
 2 files changed, 11 insertions(+)

diff --git a/arch/arm/mach-zynq/cpu.c b/arch/arm/mach-zynq/cpu.c
index b8d413b69a..e6151bc21d 100644
--- a/arch/arm/mach-zynq/cpu.c
+++ b/arch/arm/mach-zynq/cpu.c
@@ -20,6 +20,7 @@
 #define ZYNQ_DEV_CFG_CTRL_SPIDEM   BIT(5)
 #define ZYNQ_DEV_CFG_CTRL_SPNIDEN  BIT(6)
 #define ZYNQ_DEV_CFG_CTRL_JTAG_CHAIN_DIS   BIT(23)
+#define ZYNQ_DEV_CFG_LOCK_DBG_LOCK BIT(0)
 
 #define ZYNQ_SILICON_VER_MASK  0xF000
 #define ZYNQ_SILICON_VER_SHIFT 28
@@ -93,6 +94,15 @@ void zynq_enable_jtag(void)
writel(v, _base->ctrl);
 }
 
+void zynq_lock_jtag(void)
+{
+   unsigned int v;
+
+   v = readl(_base->lock);
+   v |= ZYNQ_DEV_CFG_LOCK_DBG_LOCK;
+   writel(v, _base->lock);
+}
+
 unsigned int zynq_get_silicon_version(void)
 {
return (readl(_base->mctrl) & ZYNQ_SILICON_VER_MASK)
diff --git a/arch/arm/mach-zynq/include/mach/sys_proto.h 
b/arch/arm/mach-zynq/include/mach/sys_proto.h
index f583ef090d..3377fe2c23 100644
--- a/arch/arm/mach-zynq/include/mach/sys_proto.h
+++ b/arch/arm/mach-zynq/include/mach/sys_proto.h
@@ -16,6 +16,7 @@ extern u32 zynq_slcr_get_idcode(void);
 extern int zynq_slcr_get_mio_pin_status(const char *periph);
 extern void zynq_ddrc_init(void);
 extern void zynq_enable_jtag(void);
+extern void zynq_lock_jtag(void);
 extern unsigned int zynq_get_silicon_version(void);
 extern unsigned int zynq_get_mulitboot_addr(void);
 extern void zynq_set_mulitboot_addr(unsigned int);
-- 
2.30.2



[PATCH 2/3] zynq: Add function to enable JTAG

2024-03-28 Thread lukas . funke-oss
From: Stefan Herbrechtsmeier 

In non-secure boot mode jtag is restored by the BootROM. In secure boot
mode jtag has to be restored by the trusted application, i.e. the
bootloader.

This commit adds a function to enable the jtag interface on zynq
devices from u-boot.

Signed-off-by: Stefan Herbrechtsmeier 
Signed-off-by: Lukas Funke 
---

 arch/arm/mach-zynq/cpu.c| 19 +++
 arch/arm/mach-zynq/include/mach/sys_proto.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/arch/arm/mach-zynq/cpu.c b/arch/arm/mach-zynq/cpu.c
index 3d2866422e..b8d413b69a 100644
--- a/arch/arm/mach-zynq/cpu.c
+++ b/arch/arm/mach-zynq/cpu.c
@@ -14,6 +14,13 @@
 #include 
 #include 
 
+#define ZYNQ_DEV_CFG_CTRL_DAP_EN   GENMASK(0, 2)
+#define ZYNQ_DEV_CFG_CTRL_DBGENBIT(3)
+#define ZYNQ_DEV_CFG_CTRL_NIDENBIT(4)
+#define ZYNQ_DEV_CFG_CTRL_SPIDEM   BIT(5)
+#define ZYNQ_DEV_CFG_CTRL_SPNIDEN  BIT(6)
+#define ZYNQ_DEV_CFG_CTRL_JTAG_CHAIN_DIS   BIT(23)
+
 #define ZYNQ_SILICON_VER_MASK  0xF000
 #define ZYNQ_SILICON_VER_SHIFT 28
 #define ZYNQ_MULTIBOOT_ADDR_MASK   0x1FFF
@@ -74,6 +81,18 @@ int arch_cpu_init(void)
return 0;
 }
 
+void zynq_enable_jtag(void)
+{
+   unsigned int v;
+
+   v = readl(_base->ctrl);
+   v &= ~ZYNQ_DEV_CFG_CTRL_JTAG_CHAIN_DIS;
+   v |= ZYNQ_DEV_CFG_CTRL_DAP_EN | ZYNQ_DEV_CFG_CTRL_DBGEN
+  | ZYNQ_DEV_CFG_CTRL_NIDEN | ZYNQ_DEV_CFG_CTRL_NIDEN
+  | ZYNQ_DEV_CFG_CTRL_SPIDEM | ZYNQ_DEV_CFG_CTRL_SPNIDEN;
+   writel(v, _base->ctrl);
+}
+
 unsigned int zynq_get_silicon_version(void)
 {
return (readl(_base->mctrl) & ZYNQ_SILICON_VER_MASK)
diff --git a/arch/arm/mach-zynq/include/mach/sys_proto.h 
b/arch/arm/mach-zynq/include/mach/sys_proto.h
index 6b85682808..f583ef090d 100644
--- a/arch/arm/mach-zynq/include/mach/sys_proto.h
+++ b/arch/arm/mach-zynq/include/mach/sys_proto.h
@@ -15,6 +15,7 @@ extern u32 zynq_slcr_get_boot_mode(void);
 extern u32 zynq_slcr_get_idcode(void);
 extern int zynq_slcr_get_mio_pin_status(const char *periph);
 extern void zynq_ddrc_init(void);
+extern void zynq_enable_jtag(void);
 extern unsigned int zynq_get_silicon_version(void);
 extern unsigned int zynq_get_mulitboot_addr(void);
 extern void zynq_set_mulitboot_addr(unsigned int);
-- 
2.30.2



[PATCH 1/3] zynq: Add get function for multi boot address register

2024-03-28 Thread lukas . funke-oss
From: Stefan Herbrechtsmeier 

This commit adds a function to get/set the multiboot register. This
becomes handy in order to ensure a fresh bootimage search after reset.

Signed-off-by: Stefan Herbrechtsmeier 
Signed-off-by: Lukas Funke 
---

 arch/arm/mach-zynq/cpu.c| 19 +--
 arch/arm/mach-zynq/include/mach/hardware.h  |  3 ++-
 arch/arm/mach-zynq/include/mach/sys_proto.h |  2 ++
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-zynq/cpu.c b/arch/arm/mach-zynq/cpu.c
index 3b6518c71c..3d2866422e 100644
--- a/arch/arm/mach-zynq/cpu.c
+++ b/arch/arm/mach-zynq/cpu.c
@@ -14,8 +14,9 @@
 #include 
 #include 
 
-#define ZYNQ_SILICON_VER_MASK  0xF000
-#define ZYNQ_SILICON_VER_SHIFT 28
+#define ZYNQ_SILICON_VER_MASK  0xF000
+#define ZYNQ_SILICON_VER_SHIFT 28
+#define ZYNQ_MULTIBOOT_ADDR_MASK   0x1FFF
 
 #if CONFIG_IS_ENABLED(FPGA)
 xilinx_desc fpga = {
@@ -79,6 +80,20 @@ unsigned int zynq_get_silicon_version(void)
>> ZYNQ_SILICON_VER_SHIFT;
 }
 
+unsigned int zynq_get_mulitboot_addr(void)
+{
+   return readl(_base->multiboot_addr) & ZYNQ_MULTIBOOT_ADDR_MASK;
+}
+
+void zynq_set_mulitboot_addr(unsigned int value)
+{
+   unsigned int v = readl(_base->multiboot_addr);
+
+   v &= ~ZYNQ_MULTIBOOT_ADDR_MASK;
+   v |= value & ZYNQ_MULTIBOOT_ADDR_MASK;
+   writel(v, _base->multiboot_addr);
+}
+
 void reset_cpu(void)
 {
zynq_slcr_cpu_reset();
diff --git a/arch/arm/mach-zynq/include/mach/hardware.h 
b/arch/arm/mach-zynq/include/mach/hardware.h
index 89eb565c94..9199baccfa 100644
--- a/arch/arm/mach-zynq/include/mach/hardware.h
+++ b/arch/arm/mach-zynq/include/mach/hardware.h
@@ -96,7 +96,8 @@ struct devcfg_regs {
u32 dma_src_len; /* 0x20 */
u32 dma_dst_len; /* 0x24 */
u32 rom_shadow; /* 0x28 */
-   u32 reserved1[2];
+   u32 multiboot_addr; /* 0x2c */
+   u32 reserved1[1];
u32 unlock; /* 0x34 */
u32 reserved2[18];
u32 mctrl; /* 0x80 */
diff --git a/arch/arm/mach-zynq/include/mach/sys_proto.h 
b/arch/arm/mach-zynq/include/mach/sys_proto.h
index 268ec50ad8..6b85682808 100644
--- a/arch/arm/mach-zynq/include/mach/sys_proto.h
+++ b/arch/arm/mach-zynq/include/mach/sys_proto.h
@@ -16,5 +16,7 @@ extern u32 zynq_slcr_get_idcode(void);
 extern int zynq_slcr_get_mio_pin_status(const char *periph);
 extern void zynq_ddrc_init(void);
 extern unsigned int zynq_get_silicon_version(void);
+extern unsigned int zynq_get_mulitboot_addr(void);
+extern void zynq_set_mulitboot_addr(unsigned int);
 
 #endif /* _SYS_PROTO_H_ */
-- 
2.30.2



[PATCH 0/3] Add support for jtag disable/enable and multiboot get/set for zynq

2024-03-28 Thread lukas . funke-oss
From: Lukas Funke 


This series adds support to enable/disable/lock the jtag interface
from u-boot. This becomes handy if secure boot is used but debugging
should be poissible for non-productions builds.

The series also adds support to get/set the multiboot register in order
to ensure a freash bootimage search after soft reset.



Stefan Herbrechtsmeier (3):
  zynq: Add get function for multi boot address register
  zynq: Add function to enable JTAG
  zynq: Add function to lock JTAG enable bits

 arch/arm/mach-zynq/cpu.c| 48 -
 arch/arm/mach-zynq/include/mach/hardware.h  |  3 +-
 arch/arm/mach-zynq/include/mach/sys_proto.h |  4 ++
 3 files changed, 52 insertions(+), 3 deletions(-)

-- 
2.30.2



[PATCH v3 1/2] spl: Introduce SoC specific init function

2024-03-27 Thread lukas . funke-oss
From: Lukas Funke 

Some architectures use spl_board_init() in their SoC specific
implementation. Board developers should be able to add board specific
implementation via spl_board_init(). Hence, introduce a spl_soc_init()
method which is called right before spl_board_init() for SoC
specific implementation.

Signed-off-by: Lukas Funke 
Reviewed-by: Devarsh Thakkar 
---

(no changes since v1)

 common/spl/Kconfig | 7 +++
 common/spl/spl.c   | 3 +++
 include/spl.h  | 8 
 3 files changed, 18 insertions(+)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6405374bcc..eece8e58ce 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -272,6 +272,13 @@ config SPL_TEXT_BASE
help
  The address in memory that SPL will be running from.
 
+config SPL_SOC_INIT
+   bool "Call SoC-specific initialization in SPL"
+   help
+ If this option is enabled, U-Boot will call the function
+ spl_soc_init() from board_init_r(). This function should be
+ provided by the SoC vendor.
+
 config SPL_BOARD_INIT
bool "Call board-specific initialization in SPL"
help
diff --git a/common/spl/spl.c b/common/spl/spl.c
index b65c439e7a..9b83c85df5 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -711,6 +711,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
}
}
 
+   if (CONFIG_IS_ENABLED(SOC_INIT))
+   spl_soc_init();
+
if (CONFIG_IS_ENABLED(BOARD_INIT))
spl_board_init();
 
diff --git a/include/spl.h b/include/spl.h
index 043875f10f..5dfdf778d2 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -816,6 +816,14 @@ int spl_early_init(void);
  */
 int spl_init(void);
 
+/*
+ * spl_soc_init() - Do architecture-specific init in SPL
+ *
+ * If SPL_SOC_INIT is enabled, this is called from board_init_r() before
+ * jumping to the next phase.
+ */
+void spl_soc_init(void);
+
 /*
  * spl_board_init() - Do board-specific init in SPL
  *
-- 
2.30.2



[PATCH v3 2/2] arm64: zynq(mp): Rename spl_board_init() to spl_soc_init()

2024-03-27 Thread lukas . funke-oss
From: Lukas Funke 

Rename spl_board_init() to spl_soc_init(). SoC specific
implementation should be separated from board specific implementation
in order to be extended by board developers.

Signed-off-by: Lukas Funke 
---

Changes in v3:
 - Rephrase Kconfig description and correct minor typo

Changes in v2:
 - Change spl_arch_init() to spl_soc_init()

 arch/arm/Kconfig   | 4 ++--
 arch/arm/mach-zynq/spl.c   | 4 ++--
 arch/arm/mach-zynqmp/spl.c | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 01d6556c42..db56db9414 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1275,7 +1275,7 @@ config ARCH_ZYNQ
select OF_CONTROL
select MTD
select SPI
-   select SPL_BOARD_INIT if SPL
+   select SPL_SOC_INIT if SPL
select SPL_CLK if SPL
select SPL_DM if SPL
select SPL_DM_SPI if SPL
@@ -1318,7 +1318,7 @@ config ARCH_ZYNQMP
imply FIRMWARE
select GICV2
select OF_CONTROL
-   select SPL_BOARD_INIT if SPL
+   select SPL_SOC_INIT if SPL
select SPL_CLK if SPL
select SPL_DM if SPL
select SPL_DM_SPI if SPI && SPL_DM
diff --git a/arch/arm/mach-zynq/spl.c b/arch/arm/mach-zynq/spl.c
index fea1c9b12a..112b44e2e1 100644
--- a/arch/arm/mach-zynq/spl.c
+++ b/arch/arm/mach-zynq/spl.c
@@ -32,8 +32,8 @@ void board_init_f(ulong dummy)
arch_cpu_init();
 }
 
-#ifdef CONFIG_SPL_BOARD_INIT
-void spl_board_init(void)
+#ifdef CONFIG_SPL_SOC_INIT
+void spl_soc_init(void)
 {
preloader_console_init();
 #if defined(CONFIG_ARCH_EARLY_INIT_R) && defined(CONFIG_SPL_FPGA)
diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c
index a0f35f36fa..71f9932525 100644
--- a/arch/arm/mach-zynqmp/spl.c
+++ b/arch/arm/mach-zynqmp/spl.c
@@ -56,8 +56,8 @@ static void ps_mode_reset(ulong mode)
 # define MODE_RESETPS_MODE1
 #endif
 
-#ifdef CONFIG_SPL_BOARD_INIT
-void spl_board_init(void)
+#ifdef CONFIG_SPL_SOC_INIT
+void spl_soc_init(void)
 {
preloader_console_init();
ps_mode_reset(MODE_RESET);
-- 
2.30.2



[PATCH v3 0/2] Introduce spl_soc_init() for SoC specific initialization

2024-03-27 Thread lukas . funke-oss
From: Lukas Funke 


Currently some vendors use spl_board_init() for their SoC
specific initialization. This prohibits board developers from adding
board init code using said function. This series introduces a new
function in order to separate SoC init code from board init code.


Changes in v3:
 - Rephrase Kconfig description and correct minor typo

Changes in v2:
 - Change spl_arch_init() to spl_soc_init()

Lukas Funke (2):
  spl: Introduce SoC specific init function
  arm64: zynq(mp): Rename spl_board_init() to spl_soc_init()

 arch/arm/Kconfig   | 4 ++--
 arch/arm/mach-zynq/spl.c   | 4 ++--
 arch/arm/mach-zynqmp/spl.c | 4 ++--
 common/spl/Kconfig | 7 +++
 common/spl/spl.c   | 3 +++
 include/spl.h  | 8 
 6 files changed, 24 insertions(+), 6 deletions(-)

-- 
2.30.2



[PATCH v2 2/2] arm64: zynq(mp): Rename spl_board_init() to spl_soc_init()

2024-03-27 Thread lukas . funke-oss
From: Lukas Funke 

Rename spl_board_init() to spl_soc_init(). SoC specific
implementation should be separated from board specific implementation
in order to be extended by board developers.

Signed-off-by: Lukas Funke 
---

Changes in v2:
 - Change spl_arch_init() to spl_soc_init()

 arch/arm/Kconfig   | 4 ++--
 arch/arm/mach-zynq/spl.c   | 4 ++--
 arch/arm/mach-zynqmp/spl.c | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 01d6556c42..db56db9414 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1275,7 +1275,7 @@ config ARCH_ZYNQ
select OF_CONTROL
select MTD
select SPI
-   select SPL_BOARD_INIT if SPL
+   select SPL_SOC_INIT if SPL
select SPL_CLK if SPL
select SPL_DM if SPL
select SPL_DM_SPI if SPL
@@ -1318,7 +1318,7 @@ config ARCH_ZYNQMP
imply FIRMWARE
select GICV2
select OF_CONTROL
-   select SPL_BOARD_INIT if SPL
+   select SPL_SOC_INIT if SPL
select SPL_CLK if SPL
select SPL_DM if SPL
select SPL_DM_SPI if SPI && SPL_DM
diff --git a/arch/arm/mach-zynq/spl.c b/arch/arm/mach-zynq/spl.c
index fea1c9b12a..112b44e2e1 100644
--- a/arch/arm/mach-zynq/spl.c
+++ b/arch/arm/mach-zynq/spl.c
@@ -32,8 +32,8 @@ void board_init_f(ulong dummy)
arch_cpu_init();
 }
 
-#ifdef CONFIG_SPL_BOARD_INIT
-void spl_board_init(void)
+#ifdef CONFIG_SPL_SOC_INIT
+void spl_soc_init(void)
 {
preloader_console_init();
 #if defined(CONFIG_ARCH_EARLY_INIT_R) && defined(CONFIG_SPL_FPGA)
diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c
index a0f35f36fa..71f9932525 100644
--- a/arch/arm/mach-zynqmp/spl.c
+++ b/arch/arm/mach-zynqmp/spl.c
@@ -56,8 +56,8 @@ static void ps_mode_reset(ulong mode)
 # define MODE_RESETPS_MODE1
 #endif
 
-#ifdef CONFIG_SPL_BOARD_INIT
-void spl_board_init(void)
+#ifdef CONFIG_SPL_SOC_INIT
+void spl_soc_init(void)
 {
preloader_console_init();
ps_mode_reset(MODE_RESET);
-- 
2.30.2



[PATCH v2 0/2] Introduce spl_soc_init() for SoC specific initialization

2024-03-27 Thread lukas . funke-oss
From: Lukas Funke 


Currently some vendors use spl_board_init() for their SoC
specific initialization. This prohibits board developers from adding
board init code using said function. This series introduces a new
function in order to separate SoC init code from board init code.


Changes in v2:
 - Change spl_arch_init() to spl_soc_init()

Lukas Funke (2):
  spl: Introduce SoC specific init function
  arm64: zynq(mp): Rename spl_board_init() to spl_soc_init()

 arch/arm/Kconfig   | 4 ++--
 arch/arm/mach-zynq/spl.c   | 4 ++--
 arch/arm/mach-zynqmp/spl.c | 4 ++--
 common/spl/Kconfig | 7 +++
 common/spl/spl.c   | 3 +++
 include/spl.h  | 8 
 6 files changed, 24 insertions(+), 6 deletions(-)

-- 
2.30.2



[PATCH v2 1/2] spl: Introduce SoC specific init function

2024-03-27 Thread lukas . funke-oss
From: Lukas Funke 

Some architectures use spl_board_init() in their SoC specific
implementation. Board developers should be able to add board specific
implementation via spl_board_init(). Hence, introduce a spl_soc_init()
method which is called right before spl_board_init() for SoC
specific implementation.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 common/spl/Kconfig | 7 +++
 common/spl/spl.c   | 3 +++
 include/spl.h  | 8 
 3 files changed, 18 insertions(+)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6405374bcc..9b5cc8daa7 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -272,6 +272,13 @@ config SPL_TEXT_BASE
help
  The address in memory that SPL will be running from.
 
+config SPL_SOC_INIT
+   bool "Call arch-specific initialization in SPL"
+   help
+ If this option is enabled, U-Boot will call the function
+ spl_soc_init() from board_init_r(). This function should be
+ provided by the architecture.
+
 config SPL_BOARD_INIT
bool "Call board-specific initialization in SPL"
help
diff --git a/common/spl/spl.c b/common/spl/spl.c
index b65c439e7a..9b83c85df5 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -711,6 +711,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
}
}
 
+   if (CONFIG_IS_ENABLED(SOC_INIT))
+   spl_soc_init();
+
if (CONFIG_IS_ENABLED(BOARD_INIT))
spl_board_init();
 
diff --git a/include/spl.h b/include/spl.h
index 043875f10f..5dfdf778d2 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -816,6 +816,14 @@ int spl_early_init(void);
  */
 int spl_init(void);
 
+/*
+ * spl_soc_init() - Do architecture-specific init in SPL
+ *
+ * If SPL_SOC_INIT is enabled, this is called from board_init_r() before
+ * jumping to the next phase.
+ */
+void spl_soc_init(void);
+
 /*
  * spl_board_init() - Do board-specific init in SPL
  *
-- 
2.30.2



[PATCH 1/2] spl: Introduce architecture specific init function

2024-03-20 Thread lukas . funke-oss
From: Lukas Funke 

Some architectures use spl_board_init() in their architecture specific
implementation. Board developers should be able to add board specific
implementation via spl_board_init(). Hence, introduce a spl_arch_init()
method which is called right before spl_board_init() for architecture
specific implementation.

Signed-off-by: Lukas Funke 
---

 common/spl/Kconfig | 7 +++
 common/spl/spl.c   | 3 +++
 include/spl.h  | 8 
 3 files changed, 18 insertions(+)

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 6405374bcc..1a987037bb 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -272,6 +272,13 @@ config SPL_TEXT_BASE
help
  The address in memory that SPL will be running from.
 
+config SPL_ARCH_INIT
+   bool "Call arch-specific initialization in SPL"
+   help
+ If this option is enabled, U-Boot will call the function
+ spl_arch_init() from board_init_r(). This function should be
+ provided by the architecture.
+
 config SPL_BOARD_INIT
bool "Call board-specific initialization in SPL"
help
diff --git a/common/spl/spl.c b/common/spl/spl.c
index b65c439e7a..2f2deae14f 100644
--- a/common/spl/spl.c
+++ b/common/spl/spl.c
@@ -711,6 +711,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
}
}
 
+   if (CONFIG_IS_ENABLED(ARCH_INIT))
+   spl_arch_init();
+
if (CONFIG_IS_ENABLED(BOARD_INIT))
spl_board_init();
 
diff --git a/include/spl.h b/include/spl.h
index 043875f10f..2d23c8c0de 100644
--- a/include/spl.h
+++ b/include/spl.h
@@ -816,6 +816,14 @@ int spl_early_init(void);
  */
 int spl_init(void);
 
+/*
+ * spl_arch_init() - Do architecture-specific init in SPL
+ *
+ * If SPL_ARCH_INIT is enabled, this is called from board_init_r() before
+ * jumping to the next phase.
+ */
+void spl_arch_init(void);
+
 /*
  * spl_board_init() - Do board-specific init in SPL
  *
-- 
2.30.2



[PATCH 2/2] arm64: zynq(mp): Rename spl_board_init() to spl_arch_init()

2024-03-20 Thread lukas . funke-oss
From: Lukas Funke 

Rename spl_board_init() to spl_arch_init(). Architecture specific
implementation should be separated from board specific implementation
in order to be extended by board developers.

Signed-off-by: Lukas Funke 
---

 arch/arm/Kconfig   | 4 ++--
 arch/arm/mach-zynq/spl.c   | 4 ++--
 arch/arm/mach-zynqmp/spl.c | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 01d6556c42..4ea889d09b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1275,7 +1275,7 @@ config ARCH_ZYNQ
select OF_CONTROL
select MTD
select SPI
-   select SPL_BOARD_INIT if SPL
+   select SPL_ARCH_INIT if SPL
select SPL_CLK if SPL
select SPL_DM if SPL
select SPL_DM_SPI if SPL
@@ -1318,7 +1318,7 @@ config ARCH_ZYNQMP
imply FIRMWARE
select GICV2
select OF_CONTROL
-   select SPL_BOARD_INIT if SPL
+   select SPL_ARCH_INIT if SPL
select SPL_CLK if SPL
select SPL_DM if SPL
select SPL_DM_SPI if SPI && SPL_DM
diff --git a/arch/arm/mach-zynq/spl.c b/arch/arm/mach-zynq/spl.c
index fea1c9b12a..0cae792e21 100644
--- a/arch/arm/mach-zynq/spl.c
+++ b/arch/arm/mach-zynq/spl.c
@@ -32,8 +32,8 @@ void board_init_f(ulong dummy)
arch_cpu_init();
 }
 
-#ifdef CONFIG_SPL_BOARD_INIT
-void spl_board_init(void)
+#ifdef CONFIG_SPL_ARCH_INIT
+void spl_arch_init(void)
 {
preloader_console_init();
 #if defined(CONFIG_ARCH_EARLY_INIT_R) && defined(CONFIG_SPL_FPGA)
diff --git a/arch/arm/mach-zynqmp/spl.c b/arch/arm/mach-zynqmp/spl.c
index a0f35f36fa..03a45173e6 100644
--- a/arch/arm/mach-zynqmp/spl.c
+++ b/arch/arm/mach-zynqmp/spl.c
@@ -56,8 +56,8 @@ static void ps_mode_reset(ulong mode)
 # define MODE_RESETPS_MODE1
 #endif
 
-#ifdef CONFIG_SPL_BOARD_INIT
-void spl_board_init(void)
+#ifdef CONFIG_SPL_ARCH_INIT
+void spl_arch_init(void)
 {
preloader_console_init();
ps_mode_reset(MODE_RESET);
-- 
2.30.2



[PATCH 0/2] Introduce spl_arch_init() for architecture specific initialization

2024-03-20 Thread lukas . funke-oss
From: Lukas Funke 


Currently some architectures use spl_board_init() for their architecture
specific initialization. This prohibits board developers from adding
board init code using said function. This series introduces a new
function in order to separate arch init code from board init code.



Lukas Funke (2):
  spl: Introduce architecture specific init function
  arm64: zynq(mp): Rename spl_board_init() to spl_arch_init()

 arch/arm/Kconfig   | 4 ++--
 arch/arm/mach-zynq/spl.c   | 4 ++--
 arch/arm/mach-zynqmp/spl.c | 4 ++--
 common/spl/Kconfig | 7 +++
 common/spl/spl.c   | 3 +++
 include/spl.h  | 8 
 6 files changed, 24 insertions(+), 6 deletions(-)

-- 
2.30.2



[PATCH v2] arm64: zynqmp: Add label to pmu fwnode

2024-03-07 Thread lukas . funke-oss
From: Lukas Funke 

ZynqMP CG series devices only have two cpus. In this
case the interrupt-affinity property has to adapted, because
cpu3 and cpu4 are missing. By adding a label to the pmu fwnode the
interrupt-affinity can be adapted in a device specific DT.

Signed-off-by: Lukas Funke 
---
 arch/arm/dts/zynqmp.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi
index b50b83b772..457f8e394f 100644
--- a/arch/arm/dts/zynqmp.dtsi
+++ b/arch/arm/dts/zynqmp.dtsi
@@ -168,7 +168,7 @@
bootph-all;
};
 
-   pmu {
+   pmu: pmu {
compatible = "arm,armv8-pmuv3";
interrupt-parent = <>;
interrupts = ,
-- 
2.30.2



[PATCH] arm64: zynqmp: Add label to pmu fwnode

2024-02-27 Thread lukas . funke-oss
From: Lukas Funke 

Some zynqmp SoCs (the cg series) only have two cpus. Thus, for some
cases the cpu-affinity has to adapted, because cpu3 and cpu4 are
missing. By adding a label to the pmu fwnode the cpu affinity can
be adapted in a device specific dt.

Signed-off-by: Lukas Funke 
---
 arch/arm/dts/zynqmp.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/dts/zynqmp.dtsi b/arch/arm/dts/zynqmp.dtsi
index b50b83b772..457f8e394f 100644
--- a/arch/arm/dts/zynqmp.dtsi
+++ b/arch/arm/dts/zynqmp.dtsi
@@ -168,7 +168,7 @@
bootph-all;
};
 
-   pmu {
+   pmu: pmu {
compatible = "arm,armv8-pmuv3";
interrupt-parent = <>;
interrupts = ,
-- 
2.39.2



[PATCH v3 11/11] cmd: printf: forward '%p' format string specifier

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Forward '%p' format specifier to the underlying format logic in order
to print pointers, especially bitmaps.

Signed-off-by: Lukas Funke 
---

Changes in v3:
- Dereference pointer argument (i.e. *value) in the
  'setexpr name fmt  value' case. This is currently only
  supported in the 'setexptr  [*]' and
  'setexptr  [*]  [*]' case

 cmd/printf.c | 51 +++
 1 file changed, 51 insertions(+)

diff --git a/cmd/printf.c b/cmd/printf.c
index f56543b79e..2e54faf339 100644
--- a/cmd/printf.c
+++ b/cmd/printf.c
@@ -85,11 +85,13 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #define WANT_HEX_ESCAPES 0
 #define PRINT_CONVERSION_ERROR 1
@@ -476,6 +478,38 @@ static int get_width_prec(const char *str)
return (int)v;
 }
 
+static int print_pointer(struct print_inf *inf, char *format,
+unsigned int fmt_length, int field_width,
+int precision, const char *argument)
+{
+   struct expr_arg aval;
+
+   if (setexpr_get_arg(skip_whitespace(argument), field_width >> 3, ))
+   return CMD_RET_FAILURE;
+
+   if (field_width > BITS_PER_LONG) {
+   printf_str(inf, format, aval.bmap);
+   free(aval.bmap);
+   } else {
+   printf_str(inf, format, );
+   }
+
+   switch (inf->error) {
+   case 0:
+   return 0;
+   case PRINT_SIZE_ERROR:
+   printf("printf: size error\n"); break;
+   case PRINT_CONVERSION_ERROR:
+   printf("printf: conversion error\n"); break;
+   case PRINT_TRUNCATED_ERROR:
+   printf("printf: output truncated\n"); break;
+   default:
+   printf("printf: unknown error\n");
+   }
+
+   return -1;
+}
+
 /* Print the text in FORMAT, using ARGV for arguments to any '%' directives.
  * Return advanced ARGV.
  */
@@ -536,6 +570,23 @@ static char **print_formatted(struct print_inf *inf, char 
*f, char **argv, int *
}
}
}
+   if (*f == 'p') {
+   static const char ptr_format_chars[] = "bl";
+   ++f;
+   ++direc_length;
+   char *p = strchr(ptr_format_chars, *f);
+   /* consume whole format token */
+   while (*f != '\0' && *(p++) == *f) {
+   ++f;
+   ++direc_length;
+   }
+   if (print_pointer(inf, direc_start, 
direc_length,
+ field_width, precision, 
*argv++)) {
+   return saved_argv - 1;
+   }
+   f--;
+   break;
+   }
 
/* Remove "lLhz" size modifiers, repeatedly.
 * bash does not like "%lld", but coreutils
-- 
2.30.2



[PATCH v3 10/11] setexptr: Extend setexpr_get_arg() to handle pointer to memory

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Extend setexpr_get_arg() function in order to handle bitmaps with
length greater than 8 byte. If the bitmap is provided as hex string
the string is parsed into a bitmap.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 cmd/setexpr.c | 29 ++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index 9caa68d20d..fed457bb7e 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "printf.h"
 
 #define MAX_STR_LEN 128
@@ -24,6 +25,8 @@
 int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
 {
struct expr_arg arg;
+   uchar *bmap;
+   ulong val;
 
/*
 * If the parameter starts with a '*' then assume it is a pointer to
@@ -32,7 +35,6 @@ int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
if (s[0] == '*') {
ulong *p;
ulong addr;
-   ulong val;
int len;
char *str;
 
@@ -71,17 +73,38 @@ int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
unmap_sysmem(p);
arg.ival = val;
break;
-   default:
+#if BITS_PER_LONG == 64
+   case 8:
p = map_sysmem(addr, sizeof(ulong));
val = *p;
unmap_sysmem(p);
arg.ival = val;
break;
+#endif
+   default:
+   p = map_sysmem(addr, w);
+   bmap = malloc(w);
+   if (!bmap) {
+   printf("Out of memory\n");
+   return -ENOMEM;
+   }
+   memcpy(bmap, p, w);
+   arg.bmap = bmap;
+   unmap_sysmem(p);
}
} else {
if (w == CMD_DATA_SIZE_STR)
return -EINVAL;
-   arg.ival = hextoul(s, NULL);
+   if (w > sizeof(ulong)) {
+   bmap = hextobarray(s);
+   if (IS_ERR(bmap)) {
+   printf("Out of memory\n");
+   return -ENOMEM;
+   }
+   arg.bmap = bmap;
+   } else {
+   arg.ival = hextoul(s, NULL);
+   }
}
*argp = arg;
 
-- 
2.30.2



[PATCH v3 07/11] lib: vsprintf: enable '%pbl' format specifier

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

The commit enables vsprintf() to handle the '%pbl' format specifier
in order to print bitmaps and its derivatives such as cpumask and
nodemask [1]. This can be used to derive kernel boot parameters from
bitmaks such as 'isolcpu' or 'nohz_full' [2].

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt
[2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html

Signed-off-by: Lukas Funke 
---

Changes in v3:
- Remove bitmap_string() conversion function since the same function
  can be achieved using other format specifier

 lib/vsprintf.c | 42 ++
 1 file changed, 42 insertions(+)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 27ea9c907a..e1779d75f8 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -24,6 +24,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)((c) >= '0' && (c) <= '9')
@@ -389,6 +390,33 @@ static char *ip4_addr_string(char *buf, char *end, u8 
*addr, int field_width,
  flags & ~SPECIAL);
 }
 
+static char *bitmap_list_string(char *buf, char *end, unsigned long *addr,
+   int field_width, int precision, int flags)
+{
+   int nr_bits = max_t(int, field_width, 0);
+   int first = 1;
+   int rbot, rtop;
+
+   for_each_set_bitrange(rbot, rtop, addr, nr_bits) {
+   if (!first) {
+   if (buf < end)
+   *buf = ',';
+   buf++;
+   }
+   first = 0;
+
+   buf = number(buf, end, rbot, 10, 0, -1, 0);
+   if (rtop == rbot + 1)
+   continue;
+
+   if (buf < end)
+   *buf = '-';
+   buf = number(++buf, end, rtop - 1, 10, 0, -1, 0);
+   }
+
+   return buf;
+}
+
 #ifdef CONFIG_LIB_UUID
 /*
  * This works (roughly) the same way as Linux's.
@@ -502,6 +530,20 @@ static char *pointer(const char *fmt, char *buf, char 
*end, void *ptr,
   precision, flags);
flags &= ~SPECIAL;
break;
+   case 'b':
+   switch (fmt[1]) {
+   case 'l':
+   /* if the field width is not a multiple of the 
underlying
+* datatype (ulong), we get incorrect results from the 
bit twiddle
+* macros. Thus, round up to a multiple of field width 
of ulong
+*/
+   field_width = field_width % BITS_PER_LONG ?
+   ALIGN(field_width, BITS_PER_LONG) : field_width;
+   return bitmap_list_string(buf, end, ptr, field_width,
+   precision, flags);
+   default:
+   return ERR_PTR(-EINVAL);
+   }
 #ifdef CONFIG_LIB_UUID
case 'U':
return uuid_string(buf, end, ptr, field_width, precision,
-- 
2.30.2



[PATCH v3 08/11] setexpr: rename 'get_arg()' to 'setexpr_get_arg()'

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Prefix the get_arg() function with 'setexpr_' in order to prepare
the removal of the static specifier. The prefix shall denote the origin
of the function.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 cmd/setexpr.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index 233471f6cb..bc57d41448 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -34,7 +34,7 @@ struct expr_arg {
};
 };
 
-static int get_arg(char *s, int w, struct expr_arg *argp)
+static int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
 {
struct expr_arg arg;
 
@@ -388,7 +388,7 @@ static int do_setexpr(struct cmd_tbl *cmdtp, int flag, int 
argc,
 
w = cmd_get_data_size(argv[0], 4);
 
-   if (get_arg(argv[2], w, ))
+   if (setexpr_get_arg(argv[2], w, ))
return CMD_RET_FAILURE;
 
/* format string assignment: "setexpr name fmt %d value" */
@@ -441,7 +441,7 @@ static int do_setexpr(struct cmd_tbl *cmdtp, int flag, int 
argc,
if (strlen(argv[3]) != 1)
return CMD_RET_USAGE;
 
-   if (get_arg(argv[4], w, )) {
+   if (setexpr_get_arg(argv[4], w, )) {
if (w == CMD_DATA_SIZE_STR)
free(aval.sval);
return CMD_RET_FAILURE;
-- 
2.30.2



[PATCH v3 09/11] setexpr: Promote 'setexpr_get_arg()' to a public function

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Promote 'setexpr_get_arg()' to a public function in order to use it
from the setexpr command and in the printf-internals.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 cmd/setexpr.c | 15 +--
 include/command.h | 27 +++
 2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/cmd/setexpr.c b/cmd/setexpr.c
index bc57d41448..9caa68d20d 100644
--- a/cmd/setexpr.c
+++ b/cmd/setexpr.c
@@ -21,20 +21,7 @@
 
 #define MAX_STR_LEN 128
 
-/**
- * struct expr_arg: Holds an argument to an expression
- *
- * @ival: Integer value (if width is not CMD_DATA_SIZE_STR)
- * @sval: String value (if width is CMD_DATA_SIZE_STR)
- */
-struct expr_arg {
-   union {
-   ulong ival;
-   char *sval;
-   };
-};
-
-static int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
+int setexpr_get_arg(char *s, int w, struct expr_arg *argp)
 {
struct expr_arg arg;
 
diff --git a/include/command.h b/include/command.h
index 4cec634545..d0aa98b1f6 100644
--- a/include/command.h
+++ b/include/command.h
@@ -248,6 +248,33 @@ int do_env_set_efi(struct cmd_tbl *cmdtp, int flag, int 
argc,
 int setexpr_regex_sub(char *data, uint data_size, char *nbuf, uint nbuf_size,
  const char *r, const char *s, bool global);
 
+/**
+ * struct expr_arg: Holds an argument to an expression
+ *
+ * @ival: Integer value (if width is not CMD_DATA_SIZE_STR)
+ * @sval: String value (if width is CMD_DATA_SIZE_STR)
+ * @bmap: Bitmap value (if width is > u64)
+ */
+struct expr_arg {
+   union {
+   ulong ival;
+   char *sval;
+   uchar *bmap;
+   };
+};
+
+/**
+ * setexpr_get_arg() - Converts a string argument to it's value. If argument
+ * starts with a '*' treat it as a pointer and dereference.
+ *
+ * @s: Argument string
+ * @w: Byte width of argument
+ * @argp: Pointer where the value should be stored
+ *
+ * Return: 0 on success, -EINVAL on failure
+ */
+int setexpr_get_arg(char *s, int w, struct expr_arg *argp);
+
 /*
  * Error codes that commands return to cmd_process(). We use the standard 0
  * and 1 for success and failure, but add one more case - failure with a
-- 
2.30.2



[PATCH v3 04/11] doc: printf() codes: Add bitmap format specifier

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Add '%pbl' printf format specifier as descriped in [1].

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt

Signed-off-by: Lukas Funke 
---

Changes in v3:
- Remove '%bp' from documentation
- Give an example output in the documentation

 doc/develop/printf.rst | 4 
 1 file changed, 4 insertions(+)

diff --git a/doc/develop/printf.rst b/doc/develop/printf.rst
index 99d05061b1..8220c7c12b 100644
--- a/doc/develop/printf.rst
+++ b/doc/develop/printf.rst
@@ -165,6 +165,10 @@ Pointers
* phys_size_t
* resource_size_t
 
+%pbl
+'%pbl' outputs a bitmap as range list with field width as
+the number of bits. e.g. '0,8-11,13-16,18-19,22-25,27,29,31'
+
 %pD
 prints a UEFI device path
 
-- 
2.30.2



[PATCH v3 06/11] lib: Add hextobarray() function

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Add a 'hextobarray()' function which converts a hex string to it's
memory representation. This can be used to represent large integer
numbers or bitmasks which do not fit in a regular unsigned long value.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 include/vsprintf.h |  7 +++
 lib/strto.c| 35 +++
 2 files changed, 42 insertions(+)

diff --git a/include/vsprintf.h b/include/vsprintf.h
index ed8a060ee1..82c8bf029e 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -368,4 +368,11 @@ int vsscanf(const char *inp, char const *fmt0, va_list ap);
  */
 int sscanf(const char *buf, const char *fmt, ...);
 
+/**
+ * hextobarray - Convert a hex-string to a byte array
+ * @cp:hex string to convert
+ * Return: a pointer to a byte array, -ENOMEM on error
+ */
+uchar *hextobarray(const char *cp);
+
 #endif
diff --git a/lib/strto.c b/lib/strto.c
index 5157332d6c..eb507e4ab8 100644
--- a/lib/strto.c
+++ b/lib/strto.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* from lib/kstrtox.c */
 static const char *_parse_integer_fixup_radix(const char *s, uint *basep)
@@ -73,6 +74,40 @@ ulong simple_strtoul(const char *cp, char **endp, uint base)
return result;
 }
 
+uchar *hextobarray(const char *cp)
+{
+   int i, len;
+   __maybe_unused unsigned int base;
+   __maybe_unused const char *endptr;
+   unsigned char *array;
+
+   len = strlen(cp);
+   array = (unsigned char *)malloc(len);
+   if (!array)
+   return ERR_PTR(-ENOMEM);
+
+   memset(array, 0, len);
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+   endptr = (cp + len - 1);
+   for (i = 0; i < len && endptr > cp; i++) {
+   array[i] |= decode_digit(*(endptr));
+   endptr--;
+   array[i] |= decode_digit(*endptr) << 4;
+   endptr--;
+   }
+#else
+   cp = _parse_integer_fixup_radix(cp, );
+   for (i = 0; i < len && *cp; i++) {
+   array[i] |= decode_digit(*cp) << 4;
+   cp++;
+   array[i] |= decode_digit(*cp);
+   cp++;
+   }
+#endif
+   return array;
+}
+
 ulong hextoul(const char *cp, char **endp)
 {
return simple_strtoul(cp, endp, 16);
-- 
2.30.2



[PATCH v3 03/11] test: cmd: setexpr: Add tests for bitmap string format

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Add tests to test the bitmap format specifier. Test different bit
widths and access to memory by pointer.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 test/cmd/setexpr.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/test/cmd/setexpr.c b/test/cmd/setexpr.c
index 312593e1e3..c536c9e963 100644
--- a/test/cmd/setexpr.c
+++ b/test/cmd/setexpr.c
@@ -465,6 +465,28 @@ static int setexpr_test_fmt(struct unit_test_state *uts)
ut_asserteq(1, run_command("setexpr fred fmt hello% bf", 0));
/* Error exceeding maximum string length */
ut_asserteq(1, run_command("setexpr fred fmt \"%0128d\" 456", 0));
+   /* Test bitmask long string */
+   ut_assertok(run_command("setexpr fred fmt isolcpu=%64pbl 0x1F1", 0));
+   ut_asserteq_str("isolcpu=0,4-8", env_get("fred"));
+   /* Test bitmask long string (more complicated) */
+   ut_assertok(run_command("setexpr fred fmt nohz_full=%32pbl 0x", 
0));
+   ut_asserteq_str("nohz_full=0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30", 
env_get("fred"));
+   ut_assertok(run_command("setexpr fred fmt %64pbl 0xdeadbeef", 0));
+   ut_asserteq_str("0-3,5-7,9-13,15-16,18-19,21,23,25-28,30-31", 
env_get("fred"));
+   /* Test bitmask on 64...256 */
+   ut_assertok(run_command("setexpr fred fmt %64pbl 0xf0f0f0f0f0f0f0f0", 
0));
+   ut_asserteq_str("4-7,12-15,20-23,28-31,36-39,44-47,52-55,60-63", 
env_get("fred"));
+   ut_assertok(run_command("setexpr fred fmt %128pbl 
0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0", 0));
+   
ut_asserteq_str("4-7,12-15,20-23,28-31,36-39,44-47,52-55,60-63,68-71,76-79,84-87,92-95,100-103,108-111,116-119,124-127",
 env_get("fred"));
+   /* clear lower bitmask, otherwise output gets truncated */
+   ut_assertok(run_command("setexpr fred fmt %256pbl 
0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0", 0));
+   
ut_asserteq_str("132-135,140-143,148-151,156-159,164-167,172-175,180-183,188-191,196-199,204-207,212-215,220-223,228-231,236-239,244-247,252-255",
 env_get("fred"));
+   /* Test memory access */
+   memset(buf, 0, BUF_SIZE);
+   ut_assertok(run_command("env set myaddr 0x0;"
+   "mw.l $myaddr 
0xdeadbeef 1;"
+   "setexpr fred fmt 
%64pbl *$myaddr", 0));
+   ut_asserteq_str("0-3,5-7,9-13,15-16,18-19,21,23,25-28,30-31", 
env_get("fred"));
 
unmap_sysmem(buf);
 
-- 
2.30.2



[PATCH v3 02/11] linux: bitmap.h: add 'for_each_set_bitrange' iteration macro

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Add 'for_each_set_bitrange' (from Linux kernel) in order to iterate
over each set bitrange of a bitmap. This becomes handy if one wants
to generate a cpu list i.e. for isolcpu or nohz_full.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 include/linux/bitmap.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 0a8503af9f..9714533078 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -159,6 +159,13 @@ static inline unsigned long find_first_bit(const unsigned 
long *addr, unsigned l
 (bit) < (size);\
 (bit) = find_next_bit((addr), (size), (bit) + 1))
 
+#define for_each_set_bitrange(b, e, addr, size)\
+   for ((b) = 0;   \
+(b) = find_next_bit((addr), (size), b),\
+(e) = find_next_zero_bit((addr), (size), (b) + 1), \
+(b) < (size);  \
+(b) = (e) + 1)
+
 static inline unsigned long
 bitmap_find_next_zero_area(unsigned long *map,
   unsigned long size,
-- 
2.30.2



[PATCH v3 05/11] cmd: printf: Correctly handle field width

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Correctly parse the field width from the format specifier. Before this
commit the field_width was simply ignored.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 cmd/printf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cmd/printf.c b/cmd/printf.c
index 0c6887e0d6..f56543b79e 100644
--- a/cmd/printf.c
+++ b/cmd/printf.c
@@ -517,7 +517,7 @@ static char **print_formatted(struct print_inf *inf, char 
*f, char **argv, int *
field_width = get_width_prec(*argv++);
} else {
while (isdigit(*f)) {
-   ++f;
+   field_width = field_width * 10 + *(f++) 
- '0';
++direc_length;
}
}
-- 
2.30.2



[PATCH v3 00/11] Enable setexpr command to print cpu-list like bitmaps

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 


This series enables the 'setexpr' command to print "cpu list"-like
bitmaps based on the printk format specifier [1].

One use-case is to pass cpu list [2] based kernel parameter like
'isolcpu', 'nohz_full', irq affinity or RCU related CPU parameter to
the kernel via a separate firmware variable without exposing the
'bootargs' variable to directly.

Example:

=> env set value 0xdeadbeef
=> setexpr a fmt isolcpus=%32pbl $value
=> echo $a
isolcpus=0-3,5-7,9-13,15-16,18-19,21,23,25-28,30-31

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt
[2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html


Changes in v3:
- Use generic find_next_zero_bit() from arch/arm/include/asm/bitops.h
- Redirect sandbox ffz() implementation to generic __ffs() impl
- Remove '%bp' from documentation
- Give an example output in the documentation
- Remove bitmap_string() conversion function since the same function
  can be achieved using other format specifier
- Dereference pointer argument (i.e. *value) in the
  'setexpr name fmt  value' case. This is currently only
  supported in the 'setexptr  [*]' and
  'setexptr  [*]  [*]' case

Changes in v2:
- Add bitmap format specifier to documentation

Lukas Funke (11):
  sandbox: add generic find_next_zero_bit implementation
  linux: bitmap.h: add 'for_each_set_bitrange' iteration macro
  test: cmd: setexpr: Add tests for bitmap string format
  doc: printf() codes: Add bitmap format specifier
  cmd: printf: Correctly handle field width
  lib: Add hextobarray() function
  lib: vsprintf: enable '%pbl' format specifier
  setexpr: rename 'get_arg()' to 'setexpr_get_arg()'
  setexpr: Promote 'setexpr_get_arg()' to a public function
  setexptr: Extend setexpr_get_arg() to handle pointer to memory
  cmd: printf: forward '%p' format string specifier

 arch/sandbox/include/asm/bitops.h | 60 +++
 cmd/printf.c  | 53 ++-
 cmd/setexpr.c | 48 +++--
 doc/develop/printf.rst|  4 +++
 include/command.h | 27 ++
 include/linux/bitmap.h|  7 
 include/vsprintf.h|  7 
 lib/strto.c   | 35 ++
 lib/vsprintf.c| 42 ++
 test/cmd/setexpr.c| 22 
 10 files changed, 263 insertions(+), 42 deletions(-)

-- 
2.30.2



[PATCH v3 01/11] sandbox: add generic find_next_zero_bit implementation

2024-01-10 Thread lukas . funke-oss
From: Lukas Funke 

Add generic 'find_next_zero_bit()' implementation in order to enable the
use of the 'for_each_set_bitrange' macro. The implementation is currently
missing for the sandbox-arch and using the function results in a linker
error. The implementation is copied from the 'arm' implementation.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

Changes in v3:
- Use generic find_next_zero_bit() from arch/arm/include/asm/bitops.h
- Redirect sandbox ffz() implementation to generic __ffs() impl

 arch/sandbox/include/asm/bitops.h | 60 +++
 1 file changed, 38 insertions(+), 22 deletions(-)

diff --git a/arch/sandbox/include/asm/bitops.h 
b/arch/sandbox/include/asm/bitops.h
index f27d5e98c5..6950916962 100644
--- a/arch/sandbox/include/asm/bitops.h
+++ b/arch/sandbox/include/asm/bitops.h
@@ -104,9 +104,6 @@ static inline int __test_and_change_bit(int nr, void *addr)
return (old & mask) != 0;
 }
 
-extern int find_first_zero_bit(void *addr, unsigned size);
-extern int find_next_zero_bit(void *addr, int size, int offset);
-
 /*
  * This routine doesn't need to be atomic.
  */
@@ -119,27 +116,46 @@ static inline int test_bit(int nr, const void *addr)
  * ffz = Find First Zero in word. Undefined if no zero exists,
  * so code should check against ~0UL first..
  */
-static inline unsigned long ffz(unsigned long word)
-{
-   int k;
-
-   word = ~word;
-   k = 31;
-   if (word & 0x) {
-   k -= 16; word <<= 16;
-   }
-   if (word & 0x00ff) {
-   k -= 8;  word <<= 8;
-   }
-   if (word & 0x0f00) {
-   k -= 4;  word <<= 4;
+#define ffz(x)  __ffs(~(x))
+
+#define find_first_zero_bit(addr, size) \
+   find_next_zero_bit((addr), (size), 0)
+
+static inline int find_next_zero_bit(const unsigned long *addr, int size,
+int offset) {
+   unsigned long *p = ((unsigned long *)addr) + (offset / BITS_PER_LONG);
+   unsigned long result = offset & ~(BITS_PER_LONG - 1);
+   unsigned long tmp;
+
+   if (offset >= size)
+   return size;
+   size -= result;
+   offset &= (BITS_PER_LONG - 1);
+   if (offset) {
+   tmp = *(p++);
+   tmp |= ~0UL >> (BITS_PER_LONG - offset);
+   if (size < BITS_PER_LONG)
+   goto found_first;
+   if (~tmp)
+   goto found_middle;
+   size -= BITS_PER_LONG;
+   result += BITS_PER_LONG;
}
-   if (word & 0x3000) {
-   k -= 2;  word <<= 2;
+   while (size & ~(BITS_PER_LONG - 1)) {
+   tmp = *(p++);
+   if (~tmp)
+   goto found_middle;
+   result += BITS_PER_LONG;
+   size -= BITS_PER_LONG;
}
-   if (word & 0x4000)
-   k -= 1;
-   return k;
+   if (!size)
+   return result;
+   tmp = *p;
+
+found_first:
+   tmp |= ~0UL << size;
+found_middle:
+   return result + ffz(tmp);
 }
 
 /*
-- 
2.30.2



[PATCH v2 6/6] cmd: printf: forward '%p' format string specifier

2023-12-12 Thread lukas . funke-oss
From: Lukas Funke 

Forward '%p' format specifier to the underlying format logic in order
to print pointers, especially bitmaps.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 cmd/printf.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/cmd/printf.c b/cmd/printf.c
index 0c6887e0d6..a90c923871 100644
--- a/cmd/printf.c
+++ b/cmd/printf.c
@@ -90,6 +90,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define WANT_HEX_ESCAPES 0
 #define PRINT_CONVERSION_ERROR 1
@@ -476,6 +477,16 @@ static int get_width_prec(const char *str)
return (int)v;
 }
 
+static int print_pointer(struct print_inf *inf, char *format,
+unsigned int fmt_length, const char *argument)
+{
+   u64 value = simple_strtoull(argument, NULL, 0);
+
+   printf_str(inf, format, );
+
+   return inf->error;
+}
+
 /* Print the text in FORMAT, using ARGV for arguments to any '%' directives.
  * Return advanced ARGV.
  */
@@ -536,6 +547,24 @@ static char **print_formatted(struct print_inf *inf, char 
*f, char **argv, int *
}
}
}
+   if (*f == 'p') {
+   static const char ptr_format_chars[] = "bl";
+   ++f;
+   ++direc_length;
+   char *p = strchr(ptr_format_chars, *f);
+   /* consume whole format token */
+   while (*f != '\0' && *(p++) == *f) {
+   ++f;
+   ++direc_length;
+   }
+   if (print_pointer(inf, direc_start, 
direc_length, *argv++)) {
+   printf("`%s': invalid format\n", 
direc_start);
+   /* causes main() to exit with error */
+   return saved_argv - 1;
+   }
+   f--;
+   break;
+   }
 
/* Remove "lLhz" size modifiers, repeatedly.
 * bash does not like "%lld", but coreutils
-- 
2.30.2



[PATCH v2 5/6] lib: vsprintf: enable '%*pb[l]' format specifier

2023-12-12 Thread lukas . funke-oss
From: Lukas Funke 

The commit enables vsprintf() to handle the '%*pb[l]' format specifier
in order to print bitmaps and its derivatives such as cpumask and
nodemask [1]. This can be used to derive kernel boot parameters from
bitmaks such as 'isolcpu' or 'nohz_full' [2].

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt
[2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 lib/vsprintf.c | 75 ++
 1 file changed, 75 insertions(+)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index e14c6ca9f9..abbd80ea9c 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)((c) >= '0' && (c) <= '9')
@@ -390,6 +391,71 @@ static char *ip4_addr_string(char *buf, char *end, u8 
*addr, int field_width,
  flags & ~SPECIAL);
 }
 
+static char *bitmap_string(char *buf, char *end, const unsigned long *bitmap,
+  int field_width, int precision, int flags)
+{
+   const int CHUNKSIZE = 32;
+   int nr_bits = max_t(int, field_width, 0);
+   int i, chunksz;
+   int first = 1;
+
+   chunksz = nr_bits & (CHUNKSIZE - 1);
+   if (chunksz == 0)
+   chunksz = CHUNKSIZE;
+
+   i = ALIGN(nr_bits, CHUNKSIZE) - CHUNKSIZE;
+   for (; i >= 0; i -= CHUNKSIZE) {
+   u32 chunkmask, val;
+   int word, bit;
+
+   chunkmask = ((1ULL << chunksz) - 1);
+   word = i / BITS_PER_LONG;
+   bit = i % BITS_PER_LONG;
+   val = (bitmap[word] >> bit) & chunkmask;
+
+   if (!first) {
+   if (buf < end)
+   *buf = ',';
+   buf++;
+   }
+   first = 0;
+
+   field_width = DIV_ROUND_UP(chunksz, 4);
+   buf = number(buf, end, val, 16, field_width, precision,
+(SMALL | ZEROPAD));
+
+   chunksz = CHUNKSIZE;
+   }
+   return buf;
+}
+
+static char *bitmap_list_string(char *buf, char *end, unsigned long *addr,
+   int field_width, int precision, int flags)
+{
+   int nr_bits = max_t(int, field_width, 0);
+   int first = 1;
+   int rbot, rtop;
+
+   for_each_set_bitrange(rbot, rtop, addr, nr_bits) {
+   if (!first) {
+   if (buf < end)
+   *buf = ',';
+   buf++;
+   }
+   first = 0;
+
+   buf = number(buf, end, rbot, 10, 0, -1, 0);
+   if (rtop == rbot + 1)
+   continue;
+
+   if (buf < end)
+   *buf = '-';
+   buf = number(++buf, end, rtop - 1, 10, 0, -1, 0);
+   }
+
+   return buf;
+}
+
 #ifdef CONFIG_LIB_UUID
 /*
  * This works (roughly) the same way as Linux's.
@@ -503,6 +569,15 @@ static char *pointer(const char *fmt, char *buf, char 
*end, void *ptr,
   precision, flags);
flags &= ~SPECIAL;
break;
+   case 'b':
+   switch (fmt[1]) {
+   case 'l':
+   return bitmap_list_string(buf, end, ptr, field_width,
+   precision, flags);
+   default:
+   return bitmap_string(buf, end, ptr, field_width,
+   precision, flags);
+   }
 #ifdef CONFIG_LIB_UUID
case 'U':
return uuid_string(buf, end, ptr, field_width, precision,
-- 
2.30.2



[PATCH v2 4/6] doc: printf() codes: Add bitmap format specifier

2023-12-12 Thread lukas . funke-oss
From: Lukas Funke 

Add '%*pb[l]' printf format specifier as descriped in [1].

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 doc/develop/printf.rst | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/doc/develop/printf.rst b/doc/develop/printf.rst
index 99d05061b1..c3537b1796 100644
--- a/doc/develop/printf.rst
+++ b/doc/develop/printf.rst
@@ -165,6 +165,12 @@ Pointers
* phys_size_t
* resource_size_t
 
+%*pb, %*pbl
+prints bitmap and its derivatives such as cpumask and nodemask.
+'%*pb' outputs the bitmap with field width as the number of bits
+and '%*pbl' outputs the bitmap as range list with field width as
+the number of bits.
+
 %pD
 prints a UEFI device path
 
-- 
2.30.2



[PATCH v2 3/6] test: cmd: setexptr: Add tests for bitmap string format

2023-12-12 Thread lukas . funke-oss
From: Lukas Funke 

Add test to test the bitmap format specifier

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 test/cmd/setexpr.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/test/cmd/setexpr.c b/test/cmd/setexpr.c
index 312593e1e3..4e1c9e983b 100644
--- a/test/cmd/setexpr.c
+++ b/test/cmd/setexpr.c
@@ -465,6 +465,15 @@ static int setexpr_test_fmt(struct unit_test_state *uts)
ut_asserteq(1, run_command("setexpr fred fmt hello% bf", 0));
/* Error exceeding maximum string length */
ut_asserteq(1, run_command("setexpr fred fmt \"%0128d\" 456", 0));
+   /* Test bitmask long string*/
+   ut_assertok(run_command("setexpr fred fmt isolcpu=%32pbl 0x1F1", 0));
+   ut_asserteq_str("isolcpu=0,4-8", env_get("fred"));
+   /* Test bitmask long string (more complicated) */
+   ut_assertok(run_command("setexpr fred fmt nohz_full=%32pbl 0x", 
0));
+   ut_asserteq_str("nohz_full=0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30", 
env_get("fred"));
+   /* Test bitmask short string*/
+   ut_assertok(run_command("setexpr fred fmt %32pb 0x", 0));
+   ut_asserteq_str("", env_get("fred"));
 
unmap_sysmem(buf);
 
-- 
2.30.2



[PATCH v2 2/6] linux: bitmap.h: add 'for_each_set_bitrange' iteration macro

2023-12-12 Thread lukas . funke-oss
From: Lukas Funke 

Add 'for_each_set_bitrange' (from Linux kernel) in order to iterate
over each set bitrange of a bitmap. This becomes handy if one wants
to generate a cpu list i.e. for isolcpu or nohz_full.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 include/linux/bitmap.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 0a8503af9f..9714533078 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -159,6 +159,13 @@ static inline unsigned long find_first_bit(const unsigned 
long *addr, unsigned l
 (bit) < (size);\
 (bit) = find_next_bit((addr), (size), (bit) + 1))
 
+#define for_each_set_bitrange(b, e, addr, size)\
+   for ((b) = 0;   \
+(b) = find_next_bit((addr), (size), b),\
+(e) = find_next_zero_bit((addr), (size), (b) + 1), \
+(b) < (size);  \
+(b) = (e) + 1)
+
 static inline unsigned long
 bitmap_find_next_zero_area(unsigned long *map,
   unsigned long size,
-- 
2.30.2



[PATCH v2 0/6] Enable setexpr command to print cpu-list like bitmaps

2023-12-12 Thread lukas . funke-oss
From: Lukas Funke 


This series enables the 'setexpr' command to print "cpu list"-like
bitmaps based on the printk format specifier [1].

One use-case is to pass cpu list [2] based kernel parameter like
'isolcpu', 'nohz_full', irq affinity or RCU related CPU parameter to
the kernel via a separate firmware variable without exposing the
'bootargs' variable to directly.

Example:

setexpr isolcpu_bootarg=%32pbl $myCPUisolation
&& env set bootargs "$isolcpu_bootarg"
&& bootm

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt
[2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html


Changes in v2:
- Add bitmap format specifier to documentation

Lukas Funke (6):
  sandbox: add generic find_next_zero_bit implementation
  linux: bitmap.h: add 'for_each_set_bitrange' iteration macro
  test: cmd: setexptr: Add tests for bitmap string format
  doc: printf() codes: Add bitmap format specifier
  lib: vsprintf: enable '%*pb[l]' format specifier
  cmd: printf: forward '%p' format string specifier

 arch/sandbox/include/asm/bitops.h | 16 ++-
 cmd/printf.c  | 29 
 doc/develop/printf.rst|  6 +++
 include/linux/bitmap.h|  7 +++
 lib/vsprintf.c| 75 +++
 test/cmd/setexpr.c|  9 
 6 files changed, 140 insertions(+), 2 deletions(-)

-- 
2.30.2



[PATCH v2 1/6] sandbox: add generic find_next_zero_bit implementation

2023-12-12 Thread lukas . funke-oss
From: Lukas Funke 

Add generic 'find_next_zero_bit' implementation in order to enable the
use of the 'for_each_set_bitrange' macro. The implementation is currently
missing for the sandbox-arch and using the function results in a linker
error.

There are more efficient implementations in the architecture specific
implementations. However, for the sandbox the implementation should be
simple and portable.

Signed-off-by: Lukas Funke 
---

(no changes since v1)

 arch/sandbox/include/asm/bitops.h | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/sandbox/include/asm/bitops.h 
b/arch/sandbox/include/asm/bitops.h
index f27d5e98c5..453ff005d2 100644
--- a/arch/sandbox/include/asm/bitops.h
+++ b/arch/sandbox/include/asm/bitops.h
@@ -104,8 +104,20 @@ static inline int __test_and_change_bit(int nr, void *addr)
return (old & mask) != 0;
 }
 
-extern int find_first_zero_bit(void *addr, unsigned size);
-extern int find_next_zero_bit(void *addr, int size, int offset);
+#define find_first_zero_bit(addr, size) \
+   find_next_zero_bit((addr), (size), 0)
+
+static inline int find_next_zero_bit(const unsigned long *addr, int size,
+int offset) {
+   unsigned long *p = ((unsigned long *)addr) + (offset >> 5);
+
+   while ((~(*p) & 0x1 << offset) == 0x0ll && (offset < size)) {
+   offset++;
+   p = ((unsigned long *)addr) + (offset >> 5);
+   }
+
+   return offset;
+}
 
 /*
  * This routine doesn't need to be atomic.
-- 
2.30.2



[PATCH 4/5] lib: vsprintf: enable '%*pb[l]' format specifier

2023-12-11 Thread lukas . funke-oss
From: Lukas Funke 

The commit enables vsprintf() to handle the '%*pb[l]' format specifier
in order to print bitmaps and its derivatives such as cpumask and
nodemask [1]. This can be used to derive kernel boot parameters from
bitmaks such as 'isolcpu' or 'nohz_full' [2].

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt
[2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html

Signed-off-by: Lukas Funke 
---

 lib/vsprintf.c | 75 ++
 1 file changed, 75 insertions(+)

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index e14c6ca9f9..abbd80ea9c 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* we use this so that we can do without the ctype library */
 #define is_digit(c)((c) >= '0' && (c) <= '9')
@@ -390,6 +391,71 @@ static char *ip4_addr_string(char *buf, char *end, u8 
*addr, int field_width,
  flags & ~SPECIAL);
 }
 
+static char *bitmap_string(char *buf, char *end, const unsigned long *bitmap,
+  int field_width, int precision, int flags)
+{
+   const int CHUNKSIZE = 32;
+   int nr_bits = max_t(int, field_width, 0);
+   int i, chunksz;
+   int first = 1;
+
+   chunksz = nr_bits & (CHUNKSIZE - 1);
+   if (chunksz == 0)
+   chunksz = CHUNKSIZE;
+
+   i = ALIGN(nr_bits, CHUNKSIZE) - CHUNKSIZE;
+   for (; i >= 0; i -= CHUNKSIZE) {
+   u32 chunkmask, val;
+   int word, bit;
+
+   chunkmask = ((1ULL << chunksz) - 1);
+   word = i / BITS_PER_LONG;
+   bit = i % BITS_PER_LONG;
+   val = (bitmap[word] >> bit) & chunkmask;
+
+   if (!first) {
+   if (buf < end)
+   *buf = ',';
+   buf++;
+   }
+   first = 0;
+
+   field_width = DIV_ROUND_UP(chunksz, 4);
+   buf = number(buf, end, val, 16, field_width, precision,
+(SMALL | ZEROPAD));
+
+   chunksz = CHUNKSIZE;
+   }
+   return buf;
+}
+
+static char *bitmap_list_string(char *buf, char *end, unsigned long *addr,
+   int field_width, int precision, int flags)
+{
+   int nr_bits = max_t(int, field_width, 0);
+   int first = 1;
+   int rbot, rtop;
+
+   for_each_set_bitrange(rbot, rtop, addr, nr_bits) {
+   if (!first) {
+   if (buf < end)
+   *buf = ',';
+   buf++;
+   }
+   first = 0;
+
+   buf = number(buf, end, rbot, 10, 0, -1, 0);
+   if (rtop == rbot + 1)
+   continue;
+
+   if (buf < end)
+   *buf = '-';
+   buf = number(++buf, end, rtop - 1, 10, 0, -1, 0);
+   }
+
+   return buf;
+}
+
 #ifdef CONFIG_LIB_UUID
 /*
  * This works (roughly) the same way as Linux's.
@@ -503,6 +569,15 @@ static char *pointer(const char *fmt, char *buf, char 
*end, void *ptr,
   precision, flags);
flags &= ~SPECIAL;
break;
+   case 'b':
+   switch (fmt[1]) {
+   case 'l':
+   return bitmap_list_string(buf, end, ptr, field_width,
+   precision, flags);
+   default:
+   return bitmap_string(buf, end, ptr, field_width,
+   precision, flags);
+   }
 #ifdef CONFIG_LIB_UUID
case 'U':
return uuid_string(buf, end, ptr, field_width, precision,
-- 
2.30.2



[PATCH 5/5] cmd: printf: forward '%p' format string specifier

2023-12-11 Thread lukas . funke-oss
From: Lukas Funke 

Forward '%p' format specifier to the underlying format logic in order
to print pointers, especially bitmaps.

Signed-off-by: Lukas Funke 
---

 cmd/printf.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/cmd/printf.c b/cmd/printf.c
index 0c6887e0d6..a90c923871 100644
--- a/cmd/printf.c
+++ b/cmd/printf.c
@@ -90,6 +90,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define WANT_HEX_ESCAPES 0
 #define PRINT_CONVERSION_ERROR 1
@@ -476,6 +477,16 @@ static int get_width_prec(const char *str)
return (int)v;
 }
 
+static int print_pointer(struct print_inf *inf, char *format,
+unsigned int fmt_length, const char *argument)
+{
+   u64 value = simple_strtoull(argument, NULL, 0);
+
+   printf_str(inf, format, );
+
+   return inf->error;
+}
+
 /* Print the text in FORMAT, using ARGV for arguments to any '%' directives.
  * Return advanced ARGV.
  */
@@ -536,6 +547,24 @@ static char **print_formatted(struct print_inf *inf, char 
*f, char **argv, int *
}
}
}
+   if (*f == 'p') {
+   static const char ptr_format_chars[] = "bl";
+   ++f;
+   ++direc_length;
+   char *p = strchr(ptr_format_chars, *f);
+   /* consume whole format token */
+   while (*f != '\0' && *(p++) == *f) {
+   ++f;
+   ++direc_length;
+   }
+   if (print_pointer(inf, direc_start, 
direc_length, *argv++)) {
+   printf("`%s': invalid format\n", 
direc_start);
+   /* causes main() to exit with error */
+   return saved_argv - 1;
+   }
+   f--;
+   break;
+   }
 
/* Remove "lLhz" size modifiers, repeatedly.
 * bash does not like "%lld", but coreutils
-- 
2.30.2



[PATCH 2/5] linux: bitmap.h: add 'for_each_set_bitrange' iteration macro

2023-12-11 Thread lukas . funke-oss
From: Lukas Funke 

Add 'for_each_set_bitrange' (from Linux kernel) in order to iterate
over each set bitrange of a bitmap. This becomes handy if one wants
to generate a cpu list i.e. for isolcpu or nohz_full.

Signed-off-by: Lukas Funke 
---

 include/linux/bitmap.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 0a8503af9f..9714533078 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -159,6 +159,13 @@ static inline unsigned long find_first_bit(const unsigned 
long *addr, unsigned l
 (bit) < (size);\
 (bit) = find_next_bit((addr), (size), (bit) + 1))
 
+#define for_each_set_bitrange(b, e, addr, size)\
+   for ((b) = 0;   \
+(b) = find_next_bit((addr), (size), b),\
+(e) = find_next_zero_bit((addr), (size), (b) + 1), \
+(b) < (size);  \
+(b) = (e) + 1)
+
 static inline unsigned long
 bitmap_find_next_zero_area(unsigned long *map,
   unsigned long size,
-- 
2.30.2



[PATCH 1/5] sandbox: add generic find_next_zero_bit implementation

2023-12-11 Thread lukas . funke-oss
From: Lukas Funke 

Add generic 'find_next_zero_bit' implementation in order to enable the
use of the 'for_each_set_bitrange' macro. The implementation is currently
missing for the sandbox-arch and using the function results in a linker
error.

There are more efficient implementations in the architecture specific
implementations. However, for the sandbox the implementation should be
simple and portable.

Signed-off-by: Lukas Funke 
---

 arch/sandbox/include/asm/bitops.h | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/sandbox/include/asm/bitops.h 
b/arch/sandbox/include/asm/bitops.h
index f27d5e98c5..453ff005d2 100644
--- a/arch/sandbox/include/asm/bitops.h
+++ b/arch/sandbox/include/asm/bitops.h
@@ -104,8 +104,20 @@ static inline int __test_and_change_bit(int nr, void *addr)
return (old & mask) != 0;
 }
 
-extern int find_first_zero_bit(void *addr, unsigned size);
-extern int find_next_zero_bit(void *addr, int size, int offset);
+#define find_first_zero_bit(addr, size) \
+   find_next_zero_bit((addr), (size), 0)
+
+static inline int find_next_zero_bit(const unsigned long *addr, int size,
+int offset) {
+   unsigned long *p = ((unsigned long *)addr) + (offset >> 5);
+
+   while ((~(*p) & 0x1 << offset) == 0x0ll && (offset < size)) {
+   offset++;
+   p = ((unsigned long *)addr) + (offset >> 5);
+   }
+
+   return offset;
+}
 
 /*
  * This routine doesn't need to be atomic.
-- 
2.30.2



[PATCH 0/5] Enable setexpr command to print cpu-list like bitmaps

2023-12-11 Thread lukas . funke-oss
From: Lukas Funke 


This series enables the 'setexpr' command to print "cpu list"-like
bitmaps based on the printk format specifier [1].

One use-case is to pass cpu list [2] based kernel parameter like
'isolcpu', 'nohz_full', irq affinity or RCU related CPU parameter to
the kernel via a separate firmware variable without exposing the
'bootargs' variable to directly.

Example:

setexpr isolcpu_bootarg=%32pbl $myCPUisolation
&& env set bootargs "$isolcpu_bootarg"
&& bootm

[1] https://www.kernel.org/doc/Documentation/printk-formats.txt
[2] https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html



Lukas Funke (5):
  sandbox: add generic find_next_zero_bit implementation
  linux: bitmap.h: add 'for_each_set_bitrange' iteration macro
  test: cmd: setexptr: Add tests for bitmap string format
  lib: vsprintf: enable '%*pb[l]' format specifier
  cmd: printf: forward '%p' format string specifier

 arch/sandbox/include/asm/bitops.h | 16 ++-
 cmd/printf.c  | 29 
 include/linux/bitmap.h|  7 +++
 lib/vsprintf.c| 75 +++
 test/cmd/setexpr.c|  9 
 5 files changed, 134 insertions(+), 2 deletions(-)

-- 
2.30.2



[PATCH 3/5] test: cmd: setexptr: Add tests for bitmap string format

2023-12-11 Thread lukas . funke-oss
From: Lukas Funke 

Add test to test the bitmap format specifier

Signed-off-by: Lukas Funke 
---

 test/cmd/setexpr.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/test/cmd/setexpr.c b/test/cmd/setexpr.c
index 312593e1e3..4e1c9e983b 100644
--- a/test/cmd/setexpr.c
+++ b/test/cmd/setexpr.c
@@ -465,6 +465,15 @@ static int setexpr_test_fmt(struct unit_test_state *uts)
ut_asserteq(1, run_command("setexpr fred fmt hello% bf", 0));
/* Error exceeding maximum string length */
ut_asserteq(1, run_command("setexpr fred fmt \"%0128d\" 456", 0));
+   /* Test bitmask long string*/
+   ut_assertok(run_command("setexpr fred fmt isolcpu=%32pbl 0x1F1", 0));
+   ut_asserteq_str("isolcpu=0,4-8", env_get("fred"));
+   /* Test bitmask long string (more complicated) */
+   ut_assertok(run_command("setexpr fred fmt nohz_full=%32pbl 0x", 
0));
+   ut_asserteq_str("nohz_full=0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30", 
env_get("fred"));
+   /* Test bitmask short string*/
+   ut_assertok(run_command("setexpr fred fmt %32pb 0x", 0));
+   ut_asserteq_str("", env_get("fred"));
 
unmap_sysmem(buf);
 
-- 
2.30.2



[PATCH] binman: bintool: Change make target arg type from string to list

2023-10-04 Thread lukas . funke-oss
From: Lukas Funke 

The argument type of `build_from_git` was changed from string to list
in d71e7116997f14097735f04cc7847f0a68dbc485.

This commit adapts the argument type of all bintools using this
function.

Signed-off-by: Lukas Funke 

---

 tools/binman/btool/bootgen.py  | 2 +-
 tools/binman/btool/fiptool.py  | 2 +-
 tools/binman/btool/futility.py | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/tools/binman/btool/bootgen.py b/tools/binman/btool/bootgen.py
index f2ca552dc2..1bc9f0aa96 100644
--- a/tools/binman/btool/bootgen.py
+++ b/tools/binman/btool/bootgen.py
@@ -132,6 +132,6 @@ class Bintoolbootgen(bintool.Bintool):
 
 result = self.build_from_git(
 'https://github.com/Xilinx/bootgen',
-'all',
+['all'],
 'bootgen')
 return result
diff --git a/tools/binman/btool/fiptool.py b/tools/binman/btool/fiptool.py
index c80f8275c4..34002f54af 100644
--- a/tools/binman/btool/fiptool.py
+++ b/tools/binman/btool/fiptool.py
@@ -109,6 +109,6 @@ class Bintoolfiptool(bintool.Bintool):
 return None
 result = self.build_from_git(
 'https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git',
-'fiptool',
+['fiptool'],
 'tools/fiptool/fiptool')
 return result
diff --git a/tools/binman/btool/futility.py b/tools/binman/btool/futility.py
index 04c9aefe9b..0d3980d071 100644
--- a/tools/binman/btool/futility.py
+++ b/tools/binman/btool/futility.py
@@ -170,7 +170,7 @@ class Bintoolfutility(bintool.Bintool):
 # .gitcookies file. So use a mirror instead.
 result = self.build_from_git(
 'https://github.com/sjg20/vboot_reference.git',
-'all',
+['all'],
 'build/futility/futility',
 flags=['USE_FLASHROM=0'])
 return result
-- 
2.30.2



[PATCH] arm64: zynqmp: Corrected pcap_prog register address

2023-09-15 Thread lukas . funke-oss
From: Lukas Funke 

Currently the pcap_prog struct variable is pointing to 0x3004 which is
incorrect according to [1]. The variable should point to 0x3000.

[1] 
https://www.xilinx.com/htmldocs/registers/ug1087/ug1087-zynq-ultrascale-registers.html#csu___pcap_prog.html

Signed-off-by: Lukas Funke 
---

 arch/arm/mach-zynqmp/include/mach/hardware.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-zynqmp/include/mach/hardware.h 
b/arch/arm/mach-zynqmp/include/mach/hardware.h
index 634bf169c6..8cb6494e52 100644
--- a/arch/arm/mach-zynqmp/include/mach/hardware.h
+++ b/arch/arm/mach-zynqmp/include/mach/hardware.h
@@ -166,7 +166,7 @@ struct csu_regs {
u32 jtag_dap_cfg;
u32 idcode;
u32 version;
-   u32 reserved2[3055];
+   u32 reserved2[3054];
u32 pcap_prog;
 };
 
-- 
2.30.2



[PATCH v4 3/3] binman: etype: Add xilinx-bootgen etype

2023-08-03 Thread lukas . funke-oss
From: Lukas Funke 

This adds a new etype 'xilinx-bootgen'. By using this etype it is
possible to created an signed SPL (FSBL in Xilinx terms) for
ZynqMP boards.

The etype uses Xilinx Bootgen tools in order to transform the SPL into
a bootable image and sign the image with a given primary and secondary
public key. For more information to signing the FSBL please refer to the
Xilinx Bootgen documentation.

Here is an example of the etype in use:

spl {
filename = "boot.signed.bin";

xilinx-bootgen {
pmufw-filename = "pmu-firmware.elf";
psk-key-name-hint = "psk0";
ssk-key-name-hint = "ssk0";
auth-params = "ppk_select=0", "spk_id=0x";

u-boot-spl-nodtb {
};
u-boot-spl-dtb {
};
};
};

For this to work the hash of the primary public key has to be fused
into the ZynqMP device and authentication (RSA_EN) has to be set.

For testing purposes: if ppk hash check should be skipped one can add
the property 'fsbl_config = "bh_auth_enable";' to the etype. However,
this should only be used for testing(!).

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 

---

Changes in v4:
- Renamed etype from "xilinx-fsbl-auth" to "xilinx-bootgen"
- Add detection of missing bintool
- Promote 'pmufw-filename' to required property

Changes in v3:
- Changed etype from entry to section
- Changed property name "psk-filename" to "psk-key-name-hint"
- Changed property name "ssk-filename" to "ssk-key-name-hint"
- Decode spl elf file instead of reading start symbol
- Improved test coverage
- Improved documentation

Changes in v2:
- Add 'keysrc-enc' property to pass down to Bootgen
- Improved documentation
- Use predictable output names for intermediated results

 tools/binman/entries.rst |  75 +
 tools/binman/etype/xilinx_bootgen.py | 225 +++
 2 files changed, 300 insertions(+)
 create mode 100644 tools/binman/etype/xilinx_bootgen.py

diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index f2376932be..e7dfe6b2a3 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -2667,3 +2667,78 @@ may be used instead.
 
 
 
+.. _etype_xilinx_bootgen:
+
+Entry: xilinx-bootgen: Signed SPL boot image for Xilinx ZynqMP devices
+--
+
+Properties / Entry arguments:
+- auth-params: (Optional) Authentication parameters passed to bootgen
+- fsbl-config: (Optional) FSBL parameters passed to bootgen
+- keysrc-enc: (Optional) Key source when using decryption engine
+- pmufw-filename: Filename of PMU firmware. Default: pmu-firmware.elf
+- psk-key-name-hint: Name of primary secret key to use for signing the
+ secondardy public key. Format: .pem file
+- ssk-key-name-hint: Name of secondardy secret key to use for signing
+ the boot image. Format: .pem file
+
+The etype is used to create a boot image for Xilinx ZynqMP
+devices.
+
+Information for signed images:
+
+In AMD/Xilinx SoCs, two pairs of public and secret keys are used
+- primary and secondary. The function of the primary public/secret key pair
+is to authenticate the secondary public/secret key pair.
+The function of the secondary key is to sign/verify the boot image. [1]
+
+AMD/Xilinx uses the following terms for private/public keys [1]:
+
+PSK = Primary Secret Key (Used to sign Secondary Public Key)
+PPK = Primary Public Key (Used to verify Secondary Public Key)
+SSK = Secondary Secret Key (Used to sign the boot image/partitions)
+SPK = Used to verify the actual boot image
+
+The following example builds a signed boot image. The fuses of
+the primary public key (ppk) should be fused together with the RSA_EN flag.
+
+Example node::
+
+spl {
+filename = "boot.signed.bin";
+
+xilinx-bootgen {
+psk-key-name-hint = "psk0";
+ssk-key-name-hint = "ssk0";
+auth-params = "ppk_select=0", "spk_id=0x";
+
+u-boot-spl-nodtb {
+};
+u-boot-spl-pubkey-dtb {
+algo = "sha384,rsa4096";
+required = "conf";
+key-name-hint = "dev";
+};
+};
+};
+
+For testing purposes, e.g. if no RSA_EN should be fused, one could add
+the "bh_auth_enable" flag in the fsbl-config field. This will skip the
+verification of the ppk fuses and boot the image, even if ppk hash is
+invalid.
+
+Example node::
+
+xilinx-bootgen {
+psk-key-name-hint = "psk0";
+psk-key-name-hint = "ssk0";
+...
+fsbl-config = "bh_auth_enable";
+...
+};
+
+[1] 
https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/Using-Authentication
+
+
+
+
diff --git a/tools/binman/etype/xilinx_bootgen.py 
b/tools/binman/etype/xilinx_bootgen.py
new file mode 100644
index 00..70a4b2e242
--- /dev/null

[PATCH v4 1/3] binman: btool: Add Xilinx Bootgen btool

2023-08-03 Thread lukas . funke-oss
From: Lukas Funke 

Add the Xilinx Bootgen as bintool. Xilinx Bootgen is used to create
bootable SPL (FSBL in Xilinx terms) images for Zynq/ZynqMP devices. The
btool creates a signed version of the SPL. Additionally to signing the
key source for the decryption engine can be passend to the boot image.

Signed-off-by: Lukas Funke 

---

Changes in v4:
- Fixed some typos

Changes in v3:
- Fixed an issue where the build result was not found
- Fixed an issue where the version string was not reported correctly

Changes in v2:
- Pass additional 'keysrc_enc' parameter to Bootgen
- Added more information and terms to documentation

 tools/binman/bintools.rst |   2 +-
 tools/binman/btool/bootgen.py | 137 ++
 2 files changed, 138 insertions(+), 1 deletion(-)
 create mode 100644 tools/binman/btool/bootgen.py

diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst
index 20ee24395a..1336f4d011 100644
--- a/tools/binman/bintools.rst
+++ b/tools/binman/bintools.rst
@@ -208,7 +208,7 @@ Using `fdt_add_pubkey` the key can be injected to the SPL 
independent of
 
 
 Bintool: bootgen: Sign ZynqMP FSBL image
--
+
 
 This bintool supports running `bootgen` in order to sign a SPL for ZynqMP
 devices.
diff --git a/tools/binman/btool/bootgen.py b/tools/binman/btool/bootgen.py
new file mode 100644
index 00..f2ca552dc2
--- /dev/null
+++ b/tools/binman/btool/bootgen.py
@@ -0,0 +1,137 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG
+# Lukas Funke 
+#
+"""Bintool implementation for bootgen
+
+bootgen allows creating bootable SPL for Zynq(MP)
+
+Documentation is available via:
+https://www.xilinx.com/support/documents/sw_manuals/xilinx2022_1/ug1283-bootgen-user-guide.pdf
+
+Source code is available at:
+https://github.com/Xilinx/bootgen
+
+"""
+
+from binman import bintool
+from u_boot_pylib import tools
+
+# pylint: disable=C0103
+class Bintoolbootgen(bintool.Bintool):
+"""Generate bootable fsbl image for zynq/zynqmp
+
+This bintools supports running Xilinx "bootgen" in order
+to generate a bootable, authenticated image form an SPL.
+
+"""
+def __init__(self, name):
+super().__init__(name, 'Xilinx Bootgen',
+ version_regex=r'^\*\*\*\*\*\* *Xilinx Bootgen *(.*)',
+ version_args='-help')
+
+# pylint: disable=R0913
+def sign(self, arch, spl_elf_fname, pmufw_elf_fname,
+ psk_fname, ssk_fname, fsbl_config, auth_params, keysrc_enc,
+ output_fname):
+"""Sign SPL elf file and bundle it with PMU firmware into an image
+
+The method bundels the SPL together with a 'Platform Management Unit'
+(PMU)[1] firmware into a single bootable image. The image in turn is
+signed with the provided 'secondary secret key' (ssk), which in turn is
+signed with the 'primary secret key' (psk). In order to verify the
+authenticity of the ppk, it's hash has to be fused into the device
+itself.
+
+In Xilinx terms the SPL is usually called 'FSBL'
+(First Stage Boot Loader). The jobs of the SPL and the FSBL are mostly
+the same: load bitstream, bootstrap u-boot.
+
+Args:
+arch (str): Xilinx SoC architecture. Currently only 'zynqmp' is
+supported.
+spl_elf_fname (str): Filename of SPL ELF file. The filename must 
end
+with '.elf' in order for bootgen to recognized it as an ELF
+file. Otherwise the start address field is missinterpreted.
+pmufw_elf_fname (str): Filename PMU ELF firmware.
+psk_fname (str): Filename of the primary secret key (psk). The psk
+is a .pem file which holds the RSA private key used for signing
+the secondary secret key.
+ssk_fname (str): Filename of the secondary secret key. The ssk
+is a .pem file which holds the RSA private key used for signing
+the actual boot firmware.
+fsbl_config (str): FSBL config options. A string list of fsbl 
config
+options. Valid values according to [2] are:
+"bh_auth_enable": Boot Header Authentication Enable: RSA
+authentication of the bootimage is done
+excluding the verification of PPK hash and SPK ID. This is
+useful for debugging before bricking a device.
+"auth_only": Boot image is only RSA signed. FSBL should not be
+decrypted. See the
+Zynq UltraScale+ Device Technical Reference Manual (UG1085)
+for more information.
+There are more options which relate to PUF (physical unclonable
+functions). Please refer to Xilinx manuals for further info.
+

[PATCH v4 2/3] binman: ftest: Add test for xilinx-bootgen etype

2023-08-03 Thread lukas . funke-oss
From: Lukas Funke 

Add test for the 'xilinx-bootgen' etype

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 

---

Changes in v4:
- Add test to check for missing bootgen tool

Changes in v3:
- Improved test coverage for xilinx-fsbl-auth etype

Changes in v2:
- Fixed typo in dts name

 tools/binman/ftest.py | 75 +++
 tools/binman/test/307_xilinx_bootgen_sign.dts | 22 ++
 .../test/308_xilinx_bootgen_sign_enc.dts  | 24 ++
 3 files changed, 121 insertions(+)
 create mode 100644 tools/binman/test/307_xilinx_bootgen_sign.dts
 create mode 100644 tools/binman/test/308_xilinx_bootgen_sign_enc.dts

diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 36428ec343..2d541c32b9 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -7139,5 +7139,80 @@ fdt fdtmapExtract the devicetree 
blob from the fdtmap
  self.assertEqual(fdt_util.GetString(key_node, "key-name-hint"),
   "key")
 
+def testXilinxBootgenSigning(self):
+"""Test xilinx-bootgen etype"""
+data = tools.read_file(self.TestFile("key.key"))
+self._MakeInputFile("psk.pem", data)
+self._MakeInputFile("ssk.pem", data)
+self._SetupPmuFwlElf()
+self._SetupSplElf()
+self._DoReadFileRealDtb('307_xilinx_bootgen_sign.dts')
+image_fname = tools.get_output_filename('image.bin')
+bootgen = bintool.Bintool.create('bootgen')
+
+# Read partition header table and check if authentication is enabled
+bootgen_out = bootgen.run_cmd("-arch", "zynqmp",
+  "-read", image_fname, "pht").splitlines()
+attributes = {"authentication": None,
+  "core": None,
+  "encryption": None}
+
+for l in bootgen_out:
+for a in attributes.keys():
+if a in l:
+   m = re.match(fr".*{a} \[([^]]+)\]", l)
+   attributes[a] = m.group(1)
+
+self.assertTrue(attributes['authentication'] == "rsa")
+self.assertTrue(attributes['core'] == "a53-0")
+self.assertTrue(attributes['encryption'] == "no")
+
+def testXilinxBootgenSigningEncryption(self):
+"""Test xilinx-bootgen etype"""
+data = tools.read_file(self.TestFile("key.key"))
+self._MakeInputFile("psk.pem", data)
+self._MakeInputFile("ssk.pem", data)
+self._SetupPmuFwlElf()
+self._SetupSplElf()
+self._DoReadFileRealDtb('308_xilinx_bootgen_sign_enc.dts')
+image_fname = tools.get_output_filename('image.bin')
+bootgen = bintool.Bintool.create('bootgen')
+
+# Read boot header in order to verify encryption source and
+# encryption parameter
+bootgen_out = bootgen.run_cmd("-arch", "zynqmp",
+  "-read", image_fname, "bh").splitlines()
+attributes = {"auth_only":
+{"re": r".*auth_only \[([^]]+)\]", "value": None},
+  "encryption_keystore":
+{"re": r" *encryption_keystore \(0x28\) : (.*)",
+"value": None},
+ }
+
+for l in bootgen_out:
+for a in attributes.keys():
+if a in l:
+   m = re.match(attributes[a]['re'], l)
+   attributes[a] = m.group(1)
+
+# Check if fsbl-attribute is set correctly
+self.assertTrue(attributes['auth_only'] == "true")
+# Check if key is stored in efuse
+self.assertTrue(attributes['encryption_keystore'] == "0xa5c3c5a3")
+
+def testXilinxBootgenMissing(self):
+"""Test that binman still produces an image if ifwitool is missing"""
+data = tools.read_file(self.TestFile("key.key"))
+self._MakeInputFile("psk.pem", data)
+self._MakeInputFile("ssk.pem", data)
+self._SetupPmuFwlElf()
+self._SetupSplElf()
+with test_util.capture_sys_output() as (_, stderr):
+self._DoTestFile('307_xilinx_bootgen_sign.dts',
+ force_missing_bintools='bootgen')
+err = stderr.getvalue()
+self.assertRegex(err,
+ "Image 'image'.*missing bintools.*: bootgen")
+
 if __name__ == "__main__":
 unittest.main()
diff --git a/tools/binman/test/307_xilinx_bootgen_sign.dts 
b/tools/binman/test/307_xilinx_bootgen_sign.dts
new file mode 100644
index 00..02acf8652a
--- /dev/null
+++ b/tools/binman/test/307_xilinx_bootgen_sign.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   binman {
+   xilinx-bootgen {
+   auth-params = "ppk_select=0", "spk_id=0x";
+   pmufw-filename = "pmu-firmware.elf";
+   psk-key-name-hint = "psk";
+

[PATCH v4 0/3] Sign Xilinx ZynqMP SPL/FSBL boot images using binman

2023-08-03 Thread lukas . funke-oss
From: Lukas Funke 


This series adds one etype to create a verified boot chain for
Xilinx ZynqMP devices. The etype 'xilinx-bootgen' is used to
create a bootable, signed image for ZynqMP boards using the Xilinx
Bootgen tool. The series also contains the corresponding btool for
calling 'bootgen'.

The following block shows an example on how to use this functionality:

spl {
filename = "boot.signed.bin";

xilinx-bootgen {
psk-key-name-hint = "psk0";
ssk-key-name-hint = "ssk0";
pmufw-filename = "pmu-firmware.elf";
auth-params = "ppk_select=0", "spk_id=0x";

u-boot-spl-nodtb {
};
u-boot-spl-pubkey-dtb {
algo = "sha384,rsa4096";
required = "conf";
key-name-hint = "dev";
};
};
};


Changes in v4:
- Fixed some typos
- Add test to check for missing bootgen tool
- Renamed etype from "xilinx-fsbl-auth" to "xilinx-bootgen"
- Add detection of missing bintool
- Promote 'pmufw-filename' to required property

Changes in v3:
- Fixed an issue where the build result was not found
- Fixed an issue where the version string was not reported correctly
- Improved test coverage for xilinx-fsbl-auth etype
- Changed etype from entry to section
- Changed property name "psk-filename" to "psk-key-name-hint"
- Changed property name "ssk-filename" to "ssk-key-name-hint"
- Decode spl elf file instead of reading start symbol
- Improved test coverage
- Improved documentation

Changes in v2:
- Pass additional 'keysrc_enc' parameter to Bootgen
- Added more information and terms to documentation
- Fixed typo in dts name
- Add 'keysrc-enc' property to pass down to Bootgen
- Improved documentation
- Use predictable output names for intermediated results

Lukas Funke (3):
  binman: btool: Add Xilinx Bootgen btool
  binman: ftest: Add test for xilinx-bootgen etype
  binman: etype: Add xilinx-bootgen etype

 tools/binman/bintools.rst |   2 +-
 tools/binman/btool/bootgen.py | 137 +++
 tools/binman/entries.rst  |  75 ++
 tools/binman/etype/xilinx_bootgen.py  | 225 ++
 tools/binman/ftest.py |  75 ++
 tools/binman/test/307_xilinx_bootgen_sign.dts |  22 ++
 .../test/308_xilinx_bootgen_sign_enc.dts  |  24 ++
 7 files changed, 559 insertions(+), 1 deletion(-)
 create mode 100644 tools/binman/btool/bootgen.py
 create mode 100644 tools/binman/etype/xilinx_bootgen.py
 create mode 100644 tools/binman/test/307_xilinx_bootgen_sign.dts
 create mode 100644 tools/binman/test/308_xilinx_bootgen_sign_enc.dts

-- 
2.30.2



[PATCH v3 11/11] binman: etype: Add xilinx_fsbl_auth etype

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

This adds a new etype 'xilinx-fsbl-auth'. By using this etype it is
possible to created an authenticated SPL (FSBL in Xilinx terms) for
ZynqMP boards.

The etype uses Xilinx Bootgen tools in order to transform the SPL into
a bootable image and sign the image with a given primary and secondary
public key. For more information to signing the FSBL please refer to the
Xilinx Bootgen documentation.

Here is an example of the etype in use:

spl {
filename = "boot.signed.bin";

xilinx-fsbl-auth {
psk-key-name-hint = "psk0";
ssk-key-name-hint = "ssk0";
auth-params = "ppk_select=0", "spk_id=0x";

u-boot-spl-nodtb {
};
u-boot-spl-dtb {
};
};
};

For this to work the hash of the primary public key has to be fused
into the ZynqMP device and authentication (RSA_EN) has to be set.

For testing purposes: if ppk hash check should be skipped one can add
the property 'fsbl_config = "bh_auth_enable";' to the etype. However,
this should only be used for testing(!).

Signed-off-by: Lukas Funke 

---

Changes in v3:
- Changed etype from entry to section
- Changed property name "psk-filename" to "psk-key-name-hint"
- Changed property name "ssk-filename" to "ssk-key-name-hint"
- Decode spl elf file instead of reading start symbol
- Improved test coverage
- Improved documentation

Changes in v2:
- Add 'keysrc-enc' property to pass down to Bootgen
- Improved documentation
- Use predictable output names for intermediated results

 tools/binman/entries.rst   |  71 
 tools/binman/etype/xilinx_fsbl_auth.py | 221 +
 2 files changed, 292 insertions(+)
 create mode 100644 tools/binman/etype/xilinx_fsbl_auth.py

diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index c368ea8053..47af8c7226 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -2462,3 +2462,74 @@ may be used instead.
 
 
 
+.. _etype_xilinx_fsbl_auth:
+
+Entry: xilinx-fsbl-auth: Authenticated SPL for booting Xilinx ZynqMP devices
+
+
+Properties / Entry arguments:
+- auth-params: (Optional) Authentication parameters passed to bootgen
+- fsbl-config: (Optional) FSBL parameters passed to bootgen
+- keysrc-enc: (Optional) Key source when using decryption engine
+- pmufw-filename: Filename of PMU firmware. Default: pmu-firmware.elf
+- psk-key-name-hint: Name of primary secret key to use for signing the
+ secondardy public key. Format: .pem file
+- ssk-key-name-hint: Name of secondardy secret key to use for signing
+ the boot image. Format: .pem file
+
+The etype is used to create an authenticated boot image for Xilinx ZynqMP
+devices. In AMD/Xilinx SoCs, two pairs of public and secret keys are used
+- primary and secondary. The function of the primary public/secret key pair
+is to authenticate the secondary public/secret key pair.
+The function of the secondary key is to sign/verify the boot image. [1]
+
+AMD/Xilinx uses the following terms for private/public keys [1]:
+
+PSK = Primary Secret Key (Used to sign Secondary Public Key)
+PPK = Primary Public Key (Used to verify Secondary Public Key)
+SSK = Secondary Secret Key (Used to sign the boot image/partitions)
+SPK = Used to verify the actual boot image
+
+The following example builds an authenticated boot image. The fuses of
+the primary public key (ppk) should be fused together with the RSA_EN flag.
+
+Example node::
+
+spl {
+filename = "boot.signed.bin";
+
+xilinx-fsbl-auth {
+psk-key-name-hint = "psk0";
+ssk-key-name-hint = "ssk0";
+auth-params = "ppk_select=0", "spk_id=0x";
+
+u-boot-spl-nodtb {
+};
+u-boot-spl-pubkey-dtb {
+algo = "sha384,rsa4096";
+required = "conf";
+key-name-hint = "dev";
+};
+};
+};
+
+For testing purposes, e.g. if no RSA_EN should be fused, one could add
+the "bh_auth_enable" flag in the fsbl-config field. This will skip the
+verification of the ppk fuses and boot the image, even if ppk hash is
+invalid.
+
+Example node::
+
+xilinx-fsbl-auth {
+psk-key-name-hint = "psk0";
+psk-key-name-hint = "ssk0";
+...
+fsbl-config = "bh_auth_enable";
+...
+};
+
+[1] 
https://docs.xilinx.com/r/en-US/ug1283-bootgen-user-guide/Using-Authentication
+
+
+
+
diff --git a/tools/binman/etype/xilinx_fsbl_auth.py 
b/tools/binman/etype/xilinx_fsbl_auth.py
new file mode 100644
index 00..1f85784024
--- /dev/null
+++ b/tools/binman/etype/xilinx_fsbl_auth.py
@@ -0,0 +1,221 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Weidmueller GmbH
+# Written by Lukas Funke 
+#
+# Entry-type module for signed ZynqMP boot 

[PATCH v3 07/11] binman: etype: Add u-boot-spl-pubkey-dtb etype

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

This adds a new etype 'u-boot-spl-pubkey-dtb'. The etype adds the public
key from a certificate to the dtb. This creates a '/signature' node which
is turn contains the fields which make up the public key. Usually this
is done by 'mkimage -K'. However, 'binman sign' does not add the public
key to the SPL. This is why the pubkey is added using this etype.

The etype calls the underlying 'fdt_add_pubkey' tool.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 

---

Changes in v3:
- Fixed minor python doc typo in u-boot-spl-pubkey-dtb etype
- Renamed key property from 'key-name' to 'key-name-hint'

Changes in v2:
- Improved rst/python documentation
- Changed u_boot_spl_pubkey_dtb to u-boot-spl-pubkey-dtb in example

 tools/binman/entries.rst|  39 +++
 tools/binman/etype/u_boot_spl_pubkey_dtb.py | 109 
 2 files changed, 148 insertions(+)
 create mode 100644 tools/binman/etype/u_boot_spl_pubkey_dtb.py

diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index b71af801fd..c368ea8053 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -1912,6 +1912,45 @@ binman uses that to look up symbols to write into the 
SPL binary.
 
 
 
+.. _etype_u_boot_spl_pubkey_dtb:
+
+Entry: u-boot-spl-pubkey-dtb: U-Boot SPL device tree including public key
+-
+
+Properties / Entry arguments:
+- key-name-hint: Public key name without extension (.crt).
+Default is determined by underlying
+bintool (fdt_add_pubkey), usually 'key'.
+- algo: (Optional) Algorithm used for signing. Default is determined by
+underlying bintool (fdt_add_pubkey), usually 'sha1,rsa2048'
+- required: (Optional) If present this indicates that the key must be
+verified for the image / configuration to be
+considered valid
+
+The following example shows an image containing an SPL which
+is packed together with the dtb. Binman will add a signature
+node to the dtb.
+
+Example node::
+
+image {
+...
+spl {
+filename = "spl.bin"
+
+u-boot-spl-nodtb {
+};
+u-boot-spl-pubkey-dtb {
+algo = "sha384,rsa4096";
+required = "conf";
+key-name-hint = "dev";
+};
+};
+...
+}
+
+
+
 .. _etype_u_boot_spl_with_ucode_ptr:
 
 Entry: u-boot-spl-with-ucode-ptr: U-Boot SPL with embedded microcode pointer
diff --git a/tools/binman/etype/u_boot_spl_pubkey_dtb.py 
b/tools/binman/etype/u_boot_spl_pubkey_dtb.py
new file mode 100644
index 00..cc92175ca3
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl_pubkey_dtb.py
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Weidmueller GmbH
+# Written by Lukas Funke 
+#
+# Entry-type module for 'u-boot-spl-pubkey.dtb'
+#
+
+import tempfile
+import os
+
+from binman.etype.blob_dtb import Entry_blob_dtb
+
+from dtoc import fdt_util
+
+from u_boot_pylib import tools
+
+# pylint: disable=C0103
+class Entry_u_boot_spl_pubkey_dtb(Entry_blob_dtb):
+"""U-Boot SPL device tree including public key
+
+Properties / Entry arguments:
+- key-name-hint: Public key name without extension (.crt).
+Default is determined by underlying
+bintool (fdt_add_pubkey), usually 'key'.
+- algo: (Optional) Algorithm used for signing. Default is determined by
+underlying bintool (fdt_add_pubkey), usually 'sha1,rsa2048'
+- required: (Optional) If present this indicates that the key must be
+verified for the image / configuration to be
+considered valid
+
+The following example shows an image containing an SPL which
+is packed together with the dtb. Binman will add a signature
+node to the dtb.
+
+Example node::
+
+image {
+...
+spl {
+filename = "spl.bin"
+
+u-boot-spl-nodtb {
+};
+u-boot-spl-pubkey-dtb {
+algo = "sha384,rsa4096";
+required = "conf";
+key-name-hint = "dev";
+};
+};
+...
+}
+"""
+
+def __init__(self, section, etype, node):
+# Put this here to allow entry-docs and help to work without libfdt
+global state
+from binman import state
+
+super().__init__(section, etype, node)
+self.required_props = ['key-name-hint']
+self.fdt_add_pubkey = None
+self._algo = fdt_util.GetString(self._node, 'algo')
+self._required = fdt_util.GetString(self._node, 'required')
+self._key_name_hint = fdt_util.GetString(self._node, 'key-name-hint')
+
+def ObtainContents(self, fake_size=0):
+"""Add public key to SPL dtb
+
+Add public 

[PATCH v3 10/11] binman: ftest: Add test for xilinx_fsbl_auth etype

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

Add test for the 'xilinx_fsbl_auth' etype

Signed-off-by: Lukas Funke 

---

Changes in v3:
- Improved test coverage for xilinx-fsbl-auth etype

Changes in v2:
- Fixed typo in dts name

 tools/binman/ftest.py | 61 +++
 tools/binman/test/280_xilinx_fsbl_auth.dts| 21 +++
 .../binman/test/280_xilinx_fsbl_auth_enc.dts  | 23 +++
 3 files changed, 105 insertions(+)
 create mode 100644 tools/binman/test/280_xilinx_fsbl_auth.dts
 create mode 100644 tools/binman/test/280_xilinx_fsbl_auth_enc.dts

diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 959c760792..fd01eb2030 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6686,6 +6686,67 @@ fdt fdtmapExtract the devicetree 
blob from the fdtmap
 ['fit'])
 self.assertIn("Node '/fit': Missing tool: 'mkimage'", str(e.exception))
 
+def testXilinxFsblAuth(self):
+"""Test xilinx_fsbl_auth etype"""
+data = tools.read_file(self.TestFile("key.key"))
+self._MakeInputFile("psk.pem", data)
+self._MakeInputFile("ssk.pem", data)
+self._SetupPmuFwlElf()
+self._SetupSplElf()
+self._DoReadFileRealDtb('280_xilinx_fsbl_auth.dts')
+image_fname = tools.get_output_filename('image.bin')
+bootgen = bintool.Bintool.create('bootgen')
+
+# Read partition header table and check if authentication is enabled
+bootgen_out = bootgen.run_cmd("-arch", "zynqmp",
+  "-read", image_fname, "pht").splitlines()
+attributes = {"authentication": None,
+  "core": None,
+  "encryption": None}
+
+for l in bootgen_out:
+for a in attributes.keys():
+if a in l:
+   m = re.match(fr".*{a} \[([^]]+)\]", l)
+   attributes[a] = m.group(1)
+
+self.assertTrue(attributes['authentication'] == "rsa")
+self.assertTrue(attributes['core'] == "a53-0")
+self.assertTrue(attributes['encryption'] == "no")
+
+def testXilinxFsblAuthAndEncryption(self):
+"""Test xilinx_fsbl_auth etype"""
+data = tools.read_file(self.TestFile("key.key"))
+self._MakeInputFile("psk.pem", data)
+self._MakeInputFile("ssk.pem", data)
+self._SetupPmuFwlElf()
+self._SetupSplElf()
+self._DoReadFileRealDtb('280_xilinx_fsbl_auth_enc.dts')
+image_fname = tools.get_output_filename('image.bin')
+bootgen = bintool.Bintool.create('bootgen')
+
+# Read boot header in order to verify encryption source and
+# encryption parameter
+bootgen_out = bootgen.run_cmd("-arch", "zynqmp",
+  "-read", image_fname, "bh").splitlines()
+attributes = {"auth_only":
+{"re": r".*auth_only \[([^]]+)\]", "value": None},
+  "encryption_keystore":
+{"re": r" *encryption_keystore \(0x28\) : (.*)",
+"value": None},
+ }
+
+for l in bootgen_out:
+for a in attributes.keys():
+if a in l:
+   m = re.match(attributes[a]['re'], l)
+   attributes[a] = m.group(1)
+
+# Check if fsbl-attribute is set correctly
+self.assertTrue(attributes['auth_only'] == "true")
+# Check if key is stored in efuse
+self.assertTrue(attributes['encryption_keystore'] == "0xa5c3c5a3")
+
 
 def testSplPubkeyDtb(self):
  """Test u_boot_spl_pubkey_dtb etype"""
diff --git a/tools/binman/test/280_xilinx_fsbl_auth.dts 
b/tools/binman/test/280_xilinx_fsbl_auth.dts
new file mode 100644
index 00..71b19edf44
--- /dev/null
+++ b/tools/binman/test/280_xilinx_fsbl_auth.dts
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   binman {
+   xilinx-fsbl-auth {
+   psk-key-name-hint = "psk";
+   ssk-key-name-hint = "ssk";
+   auth-params = "ppk_select=0", "spk_id=0x";
+
+   u-boot-spl-nodtb {
+   };
+   u-boot-spl-dtb {
+   };
+   };
+   };
+};
diff --git a/tools/binman/test/280_xilinx_fsbl_auth_enc.dts 
b/tools/binman/test/280_xilinx_fsbl_auth_enc.dts
new file mode 100644
index 00..4889ab4c27
--- /dev/null
+++ b/tools/binman/test/280_xilinx_fsbl_auth_enc.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   binman {
+   xilinx-fsbl-auth {
+   psk-key-name-hint = "psk";
+   ssk-key-name-hint = "ssk";
+   auth-params = 

[PATCH v3 09/11] binman: btool: Add Xilinx Bootgen btool

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

Add the Xilinx Bootgen as bintool. Xilinx Bootgen is used to create
bootable SPL (FSBL in Xilinx terms) images for Zynq/ZynqMP devices. The
btool creates a signed version of the SPL. Additionally to signing the
key source for the decryption engine can be passend to the boot image.

Signed-off-by: Lukas Funke 

---

Changes in v3:
- Fixed an issue where the build result was not found
- Fixed an issue where the version string was not reported correctly

Changes in v2:
- Pass additional 'keysrc_enc' parameter to Bootgen
- Added more information and terms to documentation

 tools/binman/bintools.rst |   2 +-
 tools/binman/btool/bootgen.py | 136 ++
 2 files changed, 137 insertions(+), 1 deletion(-)
 create mode 100644 tools/binman/btool/bootgen.py

diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst
index c6c9a88c21..8f58aaebf7 100644
--- a/tools/binman/bintools.rst
+++ b/tools/binman/bintools.rst
@@ -197,7 +197,7 @@ Using `fdt_add_pubkey` the key can be injected to the SPL 
independent of
 
 
 Bintool: bootgen: Sign ZynqMP FSBL image
--
+
 
 This bintool supports running `bootgen` in order to sign a SPL for ZynqMP
 devices.
diff --git a/tools/binman/btool/bootgen.py b/tools/binman/btool/bootgen.py
new file mode 100644
index 00..83bbe124dc
--- /dev/null
+++ b/tools/binman/btool/bootgen.py
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG
+# Lukas Funke 
+#
+"""Bintool implementation for bootgen
+
+bootgen allows creating bootable SPL for Zynq(MP)
+
+Documentation is available via::
+https://www.xilinx.com/support/documents/sw_manuals/xilinx2022_1/ug1283-bootgen-user-guide.pdf
+
+Source code is available at:
+
+https://github.com/Xilinx/bootgen
+
+"""
+import tempfile
+
+from binman import bintool
+from u_boot_pylib import tools
+
+# pylint: disable=C0103
+class Bintoolbootgen(bintool.Bintool):
+"""Generate bootable fsbl image for zynq/zynqmp
+
+This bintools supports running Xilinx "bootgen" in order
+to generate a bootable, authenticated image form an SPL.
+
+"""
+def __init__(self, name):
+super().__init__(name, 'Xilinx Bootgen',
+ version_regex=r'^\*\*\*\*\*\* *Xilinx Bootgen *(.*)',
+ version_args='-help')
+
+# pylint: disable=R0913
+def sign(self, arch, spl_elf_fname, pmufw_elf_fname,
+ psk_fname, ssk_fname, fsbl_config, auth_params, keysrc_enc,
+ output_fname):
+""" Sign SPL elf file and bundle it PMU firmware into an image
+
+The method bundels the SPL together with a 'Platform Management Unit'
+(PMU)[1] firmware into a single bootable image. The image in turn is
+signed with the provided 'secondary secret key' (ssk), which in turn is
+signed with the 'primary secret key' (ppk). In order to verify the
+authenticity of the ppk, it's hash has to be fused into the device
+itself.
+
+In Xilinx terms the SPL is usually called 'FSBL'
+(First Stage Boot Loder). The jobs of the SPL and the FSBL are mostly
+the same: load bitstream, bootstrap u-boot.
+
+Args:
+arch (str): Xilinx SoC architecture. Currently only 'zynqmp' is
+supported.
+spl_elf_fname (str): Filename of SPL ELF file. The filename must 
end
+with '.elf' in order for bootgen to recognized it as an ELF
+file. Otherwise the start address field is missinterpreted.
+pmufw_elf_fname (str): Filename PMU ELF firmware.
+psk_fname (str): Filename of the primary secret key (psk). The psk
+is a .pem file which holds the RSA private key used for signing
+the secondardy secret key.
+ssk_fname (str): Filename of the secondary secret key. The ssk
+is a .pem file which holds the RSA private key used for signing
+the aktual boot firmware.
+fsbl_config (str): FSBL config options. A string list of fsbl 
config
+options. Valid values according to [2] are:
+"bh_auth_enable": Boot Header Authentication Enable: RSA
+authentication of the bootimage is done
+excluding the verification of PPK hash and SPK ID. This is
+useful for debugging before bricking a device.
+"auth_only": Boot image is only RSA signed. FSBL should not be
+decrypted. See the
+Zynq UltraScale+ Device Technical Reference Manual (UG1085)
+for more information.
+There are more options which relate to PUF (physical unclonable
+functions). Please refer to Xilinx manuals for fruther info.
+auth_params (str): 

[PATCH v3 08/11] binman: doc: Add documentation for Xilinx Bootgen bintool

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

Add documentation for the 'bootgen' bintool

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/bintools.rst | 12 
 1 file changed, 12 insertions(+)

diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst
index 0c5d510886..c6c9a88c21 100644
--- a/tools/binman/bintools.rst
+++ b/tools/binman/bintools.rst
@@ -193,3 +193,15 @@ Normally signing is done using `mkimage` in context of 
`binman sign`. However,
 in this process the public key is not added to the stage before u-boot proper.
 Using `fdt_add_pubkey` the key can be injected to the SPL independent of
 `mkimage`
+
+
+
+Bintool: bootgen: Sign ZynqMP FSBL image
+-
+
+This bintool supports running `bootgen` in order to sign a SPL for ZynqMP
+devices.
+
+The bintool automatically creates an appropriate input image file (.bif) for
+bootgen based on the passed arguments. The output is a bootable,
+authenticated `boot.bin` file.
-- 
2.30.2



[PATCH v3 06/11] binman: btool: Add fdt_add_pubkey as btool

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

Add btool which calls 'fdt_add_pubkey'

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/btool/fdt_add_pubkey.py | 67 
 1 file changed, 67 insertions(+)
 create mode 100644 tools/binman/btool/fdt_add_pubkey.py

diff --git a/tools/binman/btool/fdt_add_pubkey.py 
b/tools/binman/btool/fdt_add_pubkey.py
new file mode 100644
index 00..a50774200c
--- /dev/null
+++ b/tools/binman/btool/fdt_add_pubkey.py
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG
+# Lukas Funke 
+#
+"""Bintool implementation for fdt_add_pubkey"""
+
+from binman import bintool
+
+class Bintoolfdt_add_pubkey(bintool.Bintool):
+"""Add public key to control dtb (spl or u-boot proper)
+
+This bintool supports running `fdt_add_pubkey`.
+
+Normally mkimage adds signature information to the control dtb. However
+binman images are built independent from each other. Thus it is required
+to add the public key separately from mkimage.
+"""
+def __init__(self, name):
+super().__init__(name, 'Generate image for U-Boot')
+
+# pylint: disable=R0913
+def run(self, input_fname, keydir, keyname, required, algo):
+"""Run fdt_add_pubkey
+
+Args:
+input_fname (str): dtb file to sign
+keydir (str): Directory with public key. Optional parameter,
+default value: '.' (current directory)
+keyname (str): Public key name. Optional parameter,
+default value: key
+required (str): If present this indicates that the key must be
+verified for the image / configuration to be considered valid.
+algo (str): Cryptographic algorithm. Optional parameter,
+default value: sha1,rsa2048
+"""
+args = []
+if algo:
+args += ['-a', algo]
+if keydir:
+args += ['-k', keydir]
+if keyname:
+args += ['-n', keyname]
+if required:
+args += ['-r', required]
+
+args += [ input_fname ]
+
+return self.run_cmd(*args)
+
+def fetch(self, method):
+"""Fetch handler for fdt_add_pubkey
+
+This installs fdt_add_pubkey using the apt utility.
+
+Args:
+method (FETCH_...): Method to use
+
+Returns:
+True if the file was fetched and now installed, None if a method
+other than FETCH_BIN was requested
+
+Raises:
+Valuerror: Fetching could not be completed
+"""
+if method != bintool.FETCH_BIN:
+return None
+return self.apt_install('u-boot-tools')
-- 
2.30.2



[PATCH v3 04/11] binman: doc: Add documentation for fdt_add_pubkey bintool

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

Add documentation for btool which calls 'fdt_add_pubkey'

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 

---

Changes in v3:
- Fix rst headline length

 tools/binman/bintools.rst | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst
index c30e7eb9ff..0c5d510886 100644
--- a/tools/binman/bintools.rst
+++ b/tools/binman/bintools.rst
@@ -183,3 +183,13 @@ Documentation is available via::
 
 
 
+Bintool: fdt_add_pubkey: Add public key to device tree
+--
+
+This bintool supports running `fdt_add_pubkey` in order to add a public
+key coming from a certificate to a device-tree.
+
+Normally signing is done using `mkimage` in context of `binman sign`. However,
+in this process the public key is not added to the stage before u-boot proper.
+Using `fdt_add_pubkey` the key can be injected to the SPL independent of
+`mkimage`
-- 
2.30.2



[PATCH v3 05/11] binman: ftest: Add test for u_boot_spl_pubkey_dtb

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

Add test for u_boot_spl_pubkey_dtb. The test adds a public key to the
dtb and checks if the required nodes will be added to the images dtb.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 

---

Changes in v3:
- Add newline before main
- Adapted test due to property renaming

Changes in v2:
- Changed u_boot_spl_pubkey_dtb to u-boot-spl-pubkey-dtb

 tools/binman/ftest.py| 33 
 tools/binman/test/281_spl_pubkey_dtb.dts | 16 
 2 files changed, 49 insertions(+)
 create mode 100644 tools/binman/test/281_spl_pubkey_dtb.dts

diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 43b4f850a6..959c760792 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -638,6 +638,16 @@ class TestFunctional(unittest.TestCase):
 TestFunctional._MakeInputFile('vpl/u-boot-vpl',
 tools.read_file(cls.ElfTestFile(src_fname)))
 
+@classmethod
+def _SetupPmuFwlElf(cls, src_fname='bss_data'):
+"""Set up an ELF file with a '_dt_ucode_base_size' symbol
+
+Args:
+Filename of ELF file to use as VPL
+"""
+TestFunctional._MakeInputFile('pmu-firmware.elf',
+tools.read_file(cls.ElfTestFile(src_fname)))
+
 @classmethod
 def _SetupDescriptor(cls):
 with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
@@ -6677,5 +6687,28 @@ fdt fdtmapExtract the devicetree 
blob from the fdtmap
 self.assertIn("Node '/fit': Missing tool: 'mkimage'", str(e.exception))
 
 
+def testSplPubkeyDtb(self):
+ """Test u_boot_spl_pubkey_dtb etype"""
+ data = tools.read_file(self.TestFile("key.pem"))
+ self._MakeInputFile("key.crt", data)
+ self._DoReadFileRealDtb('281_spl_pubkey_dtb.dts')
+ image = control.images['image']
+ entries = image.GetEntries()
+ dtb_entry = entries['u-boot-spl-pubkey-dtb']
+ dtb_data = dtb_entry.GetData()
+ dtb = fdt.Fdt.FromData(dtb_data)
+ dtb.Scan()
+
+ signature_node = dtb.GetNode('/signature')
+ self.assertIsNotNone(signature_node)
+ key_node = signature_node.FindNode("key-key")
+ self.assertIsNotNone(key_node)
+ self.assertEqual(fdt_util.GetString(key_node, "required"),
+  "conf")
+ self.assertEqual(fdt_util.GetString(key_node, "algo"),
+  "sha384,rsa4096")
+ self.assertEqual(fdt_util.GetString(key_node, "key-name-hint"),
+  "key")
+
 if __name__ == "__main__":
 unittest.main()
diff --git a/tools/binman/test/281_spl_pubkey_dtb.dts 
b/tools/binman/test/281_spl_pubkey_dtb.dts
new file mode 100644
index 00..3256ff970c
--- /dev/null
+++ b/tools/binman/test/281_spl_pubkey_dtb.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   binman {
+   u-boot-spl-pubkey-dtb {
+   algo = "sha384,rsa4096";
+   required = "conf";
+   key-name-hint = "key";
+   };
+   };
+};
-- 
2.30.2



[PATCH v3 02/11] binman: Don't decompress data while signing

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

While signing a fit compressed data (i.e. 'blob-ext') is decompressed,
but never compressed again. When compressed data was wrapped in a
section, decompression leads to an error because the outer section had
the original compressed size but the inner entry has the
uncompressed size now.

While singing there is no reason to decompress data. Thus, decompression
should be disabled.

Furthermore, bintools should be collected before loading the data. This
way bintools are available if processing is required on a node.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/control.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/binman/control.py b/tools/binman/control.py
index 68597c4e77..affc33ff3d 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -306,8 +306,8 @@ def BeforeReplace(image, allow_resize):
 image: Image to prepare
 """
 state.PrepareFromLoadedData(image)
-image.LoadData()
 image.CollectBintools()
+image.LoadData(decomp=False)
 
 # If repacking, drop the old offset/size values except for the original
 # ones, so we are only left with the constraints.
-- 
2.30.2



[PATCH v3 03/11] binman: blob_dtb: Add fake_size argument to ObtainContents()

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

The method 'connect_contents_to_file()' calls ObtainsContents() with
'fake_size' argument. Without providing the argument in the blob_dtb
we are not able to call this method without error.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/etype/blob_dtb.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/binman/etype/blob_dtb.py b/tools/binman/etype/blob_dtb.py
index 6a3fbc4775..d543de9f75 100644
--- a/tools/binman/etype/blob_dtb.py
+++ b/tools/binman/etype/blob_dtb.py
@@ -38,7 +38,7 @@ class Entry_blob_dtb(Entry_blob):
 self.Raise("Invalid prepend in '%s': '%s'" %
(self._node.name, self.prepend))
 
-def ObtainContents(self):
+def ObtainContents(self, fake_size=0):
 """Get the device-tree from the list held by the 'state' module"""
 self._filename = self.GetDefaultFilename()
 self._pathname, _ = state.GetFdtContents(self.GetFdtEtype())
-- 
2.30.2



[PATCH v3 00/11] Sign Xilinx ZynqMP SPL/FSBL boot images using binman

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 


This series adds two etypes to create a verified boot chain for
Xilinx ZynqMP devices. The first etype 'xilinx-fsbl-auth' is used to
create a bootable, signed image for ZynqMP boards using the Xilinx
Bootgen tool. The second etype 'u-boot-spl-pubkey-dtb' is used to add
a '/signature' node to the SPL. The public key in the signature is read
from a certificate file and added using the 'fdt_add_pubkey' tool. The
series also contains the corresponding btool for calling 'bootgen' and
'fdt_add_pubkey'.

The following block shows an example on how to use this functionality:

spl {
filename = "boot.signed.bin";

xilinx-fsbl-auth {
psk-key-name-hint = "psk0";
ssk-key-name-hint = "ssk0";
auth-params = "ppk_select=0", "spk_id=0x";

u-boot-spl-nodtb {
};
u-boot-spl-pubkey-dtb {
algo = "sha384,rsa4096";
required = "conf";
key-name-hint = "dev";
};
};
};


Changes in v3:
- Improved test coverage regarding missing libelf
- Align error message
- Fix rst headline length
- Add newline before main
- Adapted test due to property renaming
- Fixed minor python doc typo in u-boot-spl-pubkey-dtb etype
- Renamed key property from 'key-name' to 'key-name-hint'
- Fixed an issue where the build result was not found
- Fixed an issue where the version string was not reported correctly
- Improved test coverage for xilinx-fsbl-auth etype
- Changed etype from entry to section
- Changed property name "psk-filename" to "psk-key-name-hint"
- Changed property name "ssk-filename" to "ssk-key-name-hint"
- Decode spl elf file instead of reading start symbol
- Improved test coverage
- Improved documentation

Changes in v2:
- Changed u_boot_spl_pubkey_dtb to u-boot-spl-pubkey-dtb
- Improved rst/python documentation
- Changed u_boot_spl_pubkey_dtb to u-boot-spl-pubkey-dtb in example
- Pass additional 'keysrc_enc' parameter to Bootgen
- Added more information and terms to documentation
- Fixed typo in dts name
- Add 'keysrc-enc' property to pass down to Bootgen
- Improved documentation
- Use predictable output names for intermediated results

Lukas Funke (11):
  binman: elf: Check for ELF_TOOLS availability and remove extra
semicolon
  binman: Don't decompress data while signing
  binman: blob_dtb: Add fake_size argument to ObtainContents()
  binman: doc: Add documentation for fdt_add_pubkey bintool
  binman: ftest: Add test for u_boot_spl_pubkey_dtb
  binman: btool: Add fdt_add_pubkey as btool
  binman: etype: Add u-boot-spl-pubkey-dtb etype
  binman: doc: Add documentation for Xilinx Bootgen bintool
  binman: btool: Add Xilinx Bootgen btool
  binman: ftest: Add test for xilinx_fsbl_auth etype
  binman: etype: Add xilinx_fsbl_auth etype

 tools/binman/bintools.rst |  22 ++
 tools/binman/btool/bootgen.py | 136 +++
 tools/binman/btool/fdt_add_pubkey.py  |  67 ++
 tools/binman/control.py   |   2 +-
 tools/binman/elf.py   |  14 +-
 tools/binman/elf_test.py  |  11 +
 tools/binman/entries.rst  | 110 +
 tools/binman/etype/blob_dtb.py|   2 +-
 tools/binman/etype/u_boot_spl_pubkey_dtb.py   | 109 +
 tools/binman/etype/xilinx_fsbl_auth.py| 221 ++
 tools/binman/ftest.py |  94 
 tools/binman/test/280_xilinx_fsbl_auth.dts|  21 ++
 .../binman/test/280_xilinx_fsbl_auth_enc.dts  |  23 ++
 tools/binman/test/281_spl_pubkey_dtb.dts  |  16 ++
 14 files changed, 839 insertions(+), 9 deletions(-)
 create mode 100644 tools/binman/btool/bootgen.py
 create mode 100644 tools/binman/btool/fdt_add_pubkey.py
 create mode 100644 tools/binman/etype/u_boot_spl_pubkey_dtb.py
 create mode 100644 tools/binman/etype/xilinx_fsbl_auth.py
 create mode 100644 tools/binman/test/280_xilinx_fsbl_auth.dts
 create mode 100644 tools/binman/test/280_xilinx_fsbl_auth_enc.dts
 create mode 100644 tools/binman/test/281_spl_pubkey_dtb.dts

-- 
2.30.2



[PATCH v3 01/11] binman: elf: Check for ELF_TOOLS availability and remove extra semicolon

2023-07-18 Thread lukas . funke-oss
From: Lukas Funke 

Check if elf tools are available when running DecodeElf(). Also
remove superfuous semicolon at line ending.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 

---

Changes in v3:
- Improved test coverage regarding missing libelf
- Align error message

 tools/binman/elf.py  | 14 +++---
 tools/binman/elf_test.py | 11 +++
 2 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 5816284c32..e1a17cef96 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -255,9 +255,7 @@ def LookupAndWriteSymbols(elf_fname, entry, section, 
is_elf=False,
 syms = GetSymbols(fname, ['image', 'binman'])
 if is_elf:
 if not ELF_TOOLS:
-msg = ("Section '%s': entry '%s'" %
-   (section.GetPath(), entry.GetPath()))
-raise ValueError(f'{msg}: Cannot write symbols to an ELF file 
without Python elftools')
+raise ValueError("Python: No module named 'elftools'")
 new_syms = {}
 with open(fname, 'rb') as fd:
 elf = ELFFile(fd)
@@ -438,13 +436,15 @@ def DecodeElf(data, location):
 Returns:
 ElfInfo object containing information about the decoded ELF file
 """
+if not ELF_TOOLS:
+raise ValueError("Python: No module named 'elftools'")
 file_size = len(data)
 with io.BytesIO(data) as fd:
 elf = ELFFile(fd)
-data_start = 0x;
-data_end = 0;
-mem_end = 0;
-virt_to_phys = 0;
+data_start = 0x
+data_end = 0
+mem_end = 0
+virt_to_phys = 0
 
 for i in range(elf.num_segments()):
 segment = elf.get_segment(i)
diff --git a/tools/binman/elf_test.py b/tools/binman/elf_test.py
index c98083961b..f78ad647d6 100644
--- a/tools/binman/elf_test.py
+++ b/tools/binman/elf_test.py
@@ -253,6 +253,17 @@ class TestElf(unittest.TestCase):
 fname = self.ElfTestFile('embed_data')
 with self.assertRaises(ValueError) as e:
 elf.GetSymbolFileOffset(fname, ['embed_start', 'embed_end'])
+with self.assertRaises(ValueError) as e:
+elf.DecodeElf(tools.read_file(fname), 0xdeadbeef)
+with self.assertRaises(ValueError) as e:
+elf.GetFileOffset(fname, 0xdeadbeef)
+with self.assertRaises(ValueError) as e:
+elf.GetSymbolFromAddress(fname, 0xdeadbeef)
+with self.assertRaises(ValueError) as e:
+entry = FakeEntry(10)
+section = FakeSection()
+elf.LookupAndWriteSymbols(fname, entry, section, True)
+
 self.assertIn("Python: No module named 'elftools'",
   str(e.exception))
 finally:
-- 
2.30.2



[PATCH v2 09/11] binman: btool: Add Xilinx Bootgen btool

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

Add the Xilinx Bootgen as bintool. Xilinx Bootgen is used to create
bootable SPL (FSBL in Xilinx terms) images for Zynq/ZynqMP devices. The
btool creates a signed version of the SPL. Additionally to signing the
key source for the decryption engine can be passend to the boot image.

Signed-off-by: Lukas Funke 

---

Changes in v2:
- Pass additional 'keysrc_enc' parameter to Bootgen
- Added more information and terms to documentation

 tools/binman/btool/bootgen.py | 136 ++
 1 file changed, 136 insertions(+)
 create mode 100644 tools/binman/btool/bootgen.py

diff --git a/tools/binman/btool/bootgen.py b/tools/binman/btool/bootgen.py
new file mode 100644
index 00..a30268c964
--- /dev/null
+++ b/tools/binman/btool/bootgen.py
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG
+# Lukas Funke 
+#
+"""Bintool implementation for bootgen
+
+bootgen allows creating bootable SPL for Zynq(MP)
+
+Documentation is available via::
+https://www.xilinx.com/support/documents/sw_manuals/xilinx2022_1/ug1283-bootgen-user-guide.pdf
+
+Source code is available at:
+
+https://github.com/Xilinx/bootgen
+
+"""
+import tempfile
+
+from binman import bintool
+from u_boot_pylib import tools
+
+# pylint: disable=C0103
+class Bintoolbootgen(bintool.Bintool):
+"""Generate bootable fsbl image for zynq/zynqmp
+
+This bintools supports running Xilinx "bootgen" in order
+to generate a bootable, authenticated image form an SPL.
+
+"""
+def __init__(self, name):
+super().__init__(name, 'Xilinx Bootgen',
+ version_regex=r'^\*\*\*\*\*\* Xilinx Bootgen',
+ version_args='')
+
+# pylint: disable=R0913
+def sign(self, arch, spl_elf_fname, pmufw_elf_fname,
+ psk_fname, ssk_fname, fsbl_config, auth_params, keysrc_enc,
+ output_fname):
+""" Sign SPL elf file and bundle it PMU firmware into an image
+
+The method bundels the SPL together with a 'Platform Management Unit'
+(PMU)[1] firmware into a single bootable image. The image in turn is
+signed with the provided 'secondary secret key' (ssk), which in turn is
+signed with the 'primary secret key' (ppk). In order to verify the
+authenticity of the ppk, it's hash has to be fused into the device
+itself.
+
+In Xilinx terms the SPL is usually called 'FSBL'
+(First Stage Boot Loder). The jobs of the SPL and the FSBL are mostly
+the same: load bitstream, bootstrap u-boot.
+
+Args:
+arch (str): Xilinx SoC architecture. Currently only 'zynqmp' is
+supported.
+spl_elf_fname (str): Filename of SPL ELF file. The filename must 
end
+with '.elf' in order for bootgen to recognized it as an ELF
+file. Otherwise the start address field is missinterpreted.
+pmufw_elf_fname (str): Filename PMU ELF firmware.
+psk_fname (str): Filename of the primary secret key (psk). The psk
+is a .pem file which holds the RSA private key used for signing
+the secondardy secret key.
+ssk_fname (str): Filename of the secondary secret key. The ssk
+is a .pem file which holds the RSA private key used for signing
+the aktual boot firmware.
+fsbl_config (str): FSBL config options. A string list of fsbl 
config
+options. Valid values according to [2] are:
+"bh_auth_enable": Boot Header Authentication Enable: RSA
+authentication of the bootimage is done
+excluding the verification of PPK hash and SPK ID. This is
+useful for debugging before bricking a device.
+"auth_only": Boot image is only RSA signed. FSBL should not be
+decrypted. See the
+Zynq UltraScale+ Device Technical Reference Manual (UG1085)
+for more information.
+There are more options which relate to PUF (physical unclonable
+functions). Please refer to Xilinx manuals for fruther info.
+auth_params (str): Authentication parameter. A semicolon separated
+list of authentication parameters. Valid values according to 
[3]
+are:
+"ppk_select=<0|1>" - Select which ppk to use
+"spk_id=<32-bit spk id>" - Specifies which SPK can be
+used or revoked, default is 0x0
+"spk_select=" - To differentiate spk and
+user efuses.
+"auth_header" - To authenticate headers when no partition
+is authenticated.
+keysrc_enc (str): This specifies the Key source for encryption.
+Valid values according to [3] are:
+

[PATCH v2 11/11] binman: etype: Add xilinx_fsbl_auth etype

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

This adds a new etype 'xilinx_fsbl_auth'. Using this etype it is possible
to created an authenticated SPL (FSBL in Xilinx terms) for ZynqMP boards.

The etype uses Xilinx Bootgen tools in order to transform the SPL into
a bootable image and sign the image with a given primary and seconrady
public key. For more information to signing the FSBL please refer to the
Xilinx Bootgen documentation.

Here is an example of the etype in use:

spl {
filename = "boot.signed.bin";

xilinx_fsbl_auth {
psk-filename = "psk0.pem";
ssk-filename = "ssk0.pem";
auth-params = "ppk_select=0", "spk_id=0x";

u_boot_spl_nodtb {
};
u_boot_spl_dtb {
};
};
};

For this to work the hash of the primary public key has to be fused
into the ZynqMP device and authentication (RSA_EN) has to be set.

For testing purposes: if ppk hash check should be skipped one can add
the property 'fsbl_config = "bh_auth_enable";' to the etype. However,
this should only be used for testing(!).

Signed-off-by: Lukas Funke 

---

Changes in v2:
- Add 'keysrc-enc' property to pass down to Bootgen
- Improved documentation
- Use predictable output names for intermediated results

 tools/binman/entries.rst   |  53 ++
 tools/binman/etype/xilinx_fsbl_auth.py | 213 +
 2 files changed, 266 insertions(+)
 create mode 100644 tools/binman/etype/xilinx_fsbl_auth.py

diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index c3c5bda881..98ec3c82a5 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -2462,3 +2462,56 @@ may be used instead.
 
 
 
+.. _etype_xilinx_fsbl_auth:
+
+Entry: xilinx-fsbl-auth: Authenticated SPL for booting Xilinx ZynqMP devices
+
+
+Properties / Entry arguments:
+- auth-params: (Optional) Authentication parameters passed to bootgen
+- fsbl-config: (Optional) FSBL parameters passed to bootgen
+- keysrc-enc: (Optional) Key source when using decryption engine
+- pmufw-filename: Filename of PMU firmware. Default: pmu-firmware.elf
+- psk-filename: Filename of primary public key
+- ssk-filename: Filename of secondary public key
+
+The following example builds an authenticated boot image. The fuses of
+the primary public key (ppk) should be fused together with the RSA_EN flag.
+
+Example node::
+
+spl {
+filename = "boot.signed.bin";
+
+xilinx-fsbl-auth {
+psk-filename = "psk0.pem";
+ssk-filename = "ssk0.pem";
+auth-params = "ppk_select=0", "spk_id=0x";
+
+u-boot-spl-nodtb {
+};
+u-boot-spl-pubkey-dtb {
+algo = "sha384,rsa4096";
+required = "conf";
+key-name = "dev";
+};
+};
+};
+
+For testing purposes, e.g. if no RSA_EN should be fused, one could add
+the "bh_auth_enable" flag in the fsbl-config field. This will skip the
+verification of the ppk fuses and boot the image, even if ppk hash is
+invalid.
+
+Example node::
+
+xilinx-fsbl-auth {
+psk-filename = "psk0.pem";
+ssk-filename = "ssk0.pem";
+...
+fsbl-config = "bh_auth_enable";
+...
+};
+
+
+
diff --git a/tools/binman/etype/xilinx_fsbl_auth.py 
b/tools/binman/etype/xilinx_fsbl_auth.py
new file mode 100644
index 00..72794ad2bc
--- /dev/null
+++ b/tools/binman/etype/xilinx_fsbl_auth.py
@@ -0,0 +1,213 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Weidmueller GmbH
+# Written by Lukas Funke 
+#
+# Entry-type module for signed ZynqMP boot images (boot.bin)
+#
+
+import tempfile
+
+from collections import OrderedDict
+
+from binman import elf
+from binman.entry import Entry
+
+from dtoc import fdt_util
+
+from u_boot_pylib import tools
+from u_boot_pylib import command
+
+# pylint: disable=C0103
+class Entry_xilinx_fsbl_auth(Entry):
+"""Authenticated SPL for booting Xilinx ZynqMP devices
+
+Properties / Entry arguments:
+- auth-params: (Optional) Authentication parameters passed to bootgen
+- fsbl-config: (Optional) FSBL parameters passed to bootgen
+- keysrc-enc: (Optional) Key source when using decryption engine
+- pmufw-filename: Filename of PMU firmware. Default: pmu-firmware.elf
+- psk-filename: Filename of primary public key
+- ssk-filename: Filename of secondary public key
+
+The following example builds an authenticated boot image. The fuses of
+the primary public key (ppk) should be fused together with the RSA_EN flag.
+
+Example node::
+
+spl {
+filename = "boot.signed.bin";
+
+xilinx-fsbl-auth {
+psk-filename = "psk0.pem";
+ssk-filename = "ssk0.pem";
+auth-params = "ppk_select=0", "spk_id=0x";
+

[PATCH v2 07/11] binman: etype: Add u_boot_spl_pubkey_dtb etype

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

This adds a new etype 'u_boot_spl_pubkey_dtb'. The etype adds the public
key from a certificate to the dtb. This creates a '/signature' node which
is turn contains the fields which make up the public key. Usually this
is done by 'mkimage -K'. However, 'binman sign' does not add the public
key to the SPL. This is why the pubkey is added using this etype.

The etype calls the underlying 'fdt_add_pubkey' tool.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 

---

Changes in v2:
- Improved rst/python documentation
- Changed u_boot_spl_pubkey_dtb to u-boot-spl-pubkey-dtb in example

 tools/binman/entries.rst|  39 +++
 tools/binman/etype/u_boot_spl_pubkey_dtb.py | 109 
 2 files changed, 148 insertions(+)
 create mode 100644 tools/binman/etype/u_boot_spl_pubkey_dtb.py

diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst
index b71af801fd..c3c5bda881 100644
--- a/tools/binman/entries.rst
+++ b/tools/binman/entries.rst
@@ -1912,6 +1912,45 @@ binman uses that to look up symbols to write into the 
SPL binary.
 
 
 
+.. _etype_u_boot_spl_pubkey_dtb:
+
+Entry: u-boot-spl-pubkey-dtb: U-Boot SPL device tree including public key
+-
+
+Properties / Entry arguments:
+- key-name: Public key name without extension (e.g. .crt). Default is
+determined by underlying bintool (fdt_add_pubkey),
+usually 'key'
+- algo: (Optional) Algorithm used for signing. Default is determined by
+underlying bintool (fdt_add_pubkey), usually 'sha1,rsa2048'
+- required: (Optional) If present this indicates that the key must be
+verified for the image / configuration to be
+considered valid
+
+The following example shows an image containing an SPL which
+is packed together with the dtb. Binman will add a signature
+node to the dtb.
+
+Example node::
+
+image {
+...
+spl {
+filename = "spl.bin"
+
+u-boot-spl-nodtb {
+};
+u-boot-spl-pubkey-dtb {
+algo = "sha384,rsa4096";
+required = "conf";
+key-name = "dev";
+};
+};
+...
+}
+
+
+
 .. _etype_u_boot_spl_with_ucode_ptr:
 
 Entry: u-boot-spl-with-ucode-ptr: U-Boot SPL with embedded microcode pointer
diff --git a/tools/binman/etype/u_boot_spl_pubkey_dtb.py 
b/tools/binman/etype/u_boot_spl_pubkey_dtb.py
new file mode 100644
index 00..e043001b11
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl_pubkey_dtb.py
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Weidmueller GmbH
+# Written by Lukas Funke 
+#
+# Entry-type module for 'u-boot-spl-pubkey.dtb'
+#
+
+import tempfile
+import os
+
+from binman.etype.blob_dtb import Entry_blob_dtb
+
+from dtoc import fdt_util
+
+from u_boot_pylib import tools
+
+# pylint: disable=C0103
+class Entry_u_boot_spl_pubkey_dtb(Entry_blob_dtb):
+"""U-Boot SPL device tree including public key
+
+Properties / Entry arguments:
+- key-name: Public key name without extension (e.g. .crt). Default is
+determined by underlying bintool (fdt_add_pubkey),
+usually 'key'
+- algo: (Optional) Algorithm used for signing. Default is determined by
+underlying bintool (fdt_add_pubkey), usually 'sha1,rsa2048'
+- required: (Optional) If present this indicates that the key must be
+verified for the image / configuration to be
+considered valid
+
+The following example shows an image containing an SPL which
+is packed together with the dtb. Binman will add a signature
+node to the dtb.
+
+Example node::
+
+image {
+...
+spl {
+filename = "spl.bin"
+
+u-boot-spl-nodtb {
+};
+u-boot-spl-pubkey-dtb {
+algo = "sha384,rsa4096";
+required = "conf";
+key-name = "dev";
+};
+};
+...
+}
+"""
+
+def __init__(self, section, etype, node):
+# Put this here to allow entry-docs and help to work without libfdt
+global state
+from binman import state
+
+super().__init__(section, etype, node)
+self.required_props = ['key-name']
+self.fdt_add_pubkey = None
+self._algo = fdt_util.GetString(self._node, 'algo')
+self._required = fdt_util.GetString(self._node, 'required')
+self._keyname = fdt_util.GetString(self._node, 'key-name')
+
+def ObtainContents(self, fake_size=0):
+""" Add public key to SPL dtb
+
+Add public key which is pointed out by
+'key-name' to node 'signature' in the spl-dtb
+
+This is equivalent to the '-K' option of 'mkimage'
+
+

[PATCH v2 10/11] binman: ftest: Add test for xilinx_fsbl_auth etype

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

Add test for the 'xilinx_fsbl_auth' etype

Signed-off-by: Lukas Funke 

---

Changes in v2:
- Fixed typo in dts name

 tools/binman/ftest.py  |  8 
 tools/binman/test/280_xilinx_fsbl_auth.dts | 23 ++
 2 files changed, 31 insertions(+)
 create mode 100644 tools/binman/test/280_xilinx_fsbl_auth.dts

diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 0ee0ce1155..27a8a37864 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6686,6 +6686,14 @@ fdt fdtmapExtract the devicetree 
blob from the fdtmap
 ['fit'])
 self.assertIn("Node '/fit': Missing tool: 'mkimage'", str(e.exception))
 
+def testXilinxFsblAuth(self):
+"""Test xilinx_fsbl_auth etype"""
+data = tools.read_file(self.TestFile("key.key"))
+self._MakeInputFile("psk.pem", data)
+self._MakeInputFile("ssk.pem", data)
+self._SetupPmuFwlElf()
+self._SetupSplElf()
+self._DoReadFileRealDtb('280_xilinx_fsbl_auth.dts')
 
 def testSplPubkeyDtb(self):
  """Test u_boot_spl_pubkey_dtb etype"""
diff --git a/tools/binman/test/280_xilinx_fsbl_auth.dts 
b/tools/binman/test/280_xilinx_fsbl_auth.dts
new file mode 100644
index 00..a37c5aa072
--- /dev/null
+++ b/tools/binman/test/280_xilinx_fsbl_auth.dts
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   binman {
+   xilinx-fsbl-auth {
+   filename = "boot.bin";
+
+   psk-filename = "psk.pem";
+   ssk-filename = "ssk.pem";
+   auth-params = "ppk_select=0", "spk_id=0x";
+
+   u-boot-spl-nodtb {
+   };
+   u-boot-spl-dtb {
+   };
+   };
+   };
+};
-- 
2.30.2



[PATCH v2 08/11] binman: doc: Add documentation for Xilinx Bootgen bintool

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

Add documentation for the 'bootgen' bintool

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/bintools.rst | 12 
 1 file changed, 12 insertions(+)

diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst
index 88221adbe1..c8d69f7177 100644
--- a/tools/binman/bintools.rst
+++ b/tools/binman/bintools.rst
@@ -193,3 +193,15 @@ Normally signing is done using `mkimage` in context of 
`binman sign`. However,
 in this process the public key is not added to the stage before u-boot proper.
 Using `fdt_add_pubkey` the key can be injected to the SPL independent of
 `mkimage`
+
+
+
+Bintool: bootgen: Sign ZynqMP FSBL image
+-
+
+This bintool supports running `bootgen` in order to sign a SPL for ZynqMP
+devices.
+
+The bintool automatically creates an appropriate input image file (.bif) for
+bootgen based on the passed arguments. The output is a bootable,
+authenticated `boot.bin` file.
-- 
2.30.2



[PATCH v2 06/11] binman: btool: Add fdt_add_pubkey as btool

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

Add btool which calls 'fdt_add_pubkey'

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/btool/fdt_add_pubkey.py | 67 
 1 file changed, 67 insertions(+)
 create mode 100644 tools/binman/btool/fdt_add_pubkey.py

diff --git a/tools/binman/btool/fdt_add_pubkey.py 
b/tools/binman/btool/fdt_add_pubkey.py
new file mode 100644
index 00..a50774200c
--- /dev/null
+++ b/tools/binman/btool/fdt_add_pubkey.py
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG
+# Lukas Funke 
+#
+"""Bintool implementation for fdt_add_pubkey"""
+
+from binman import bintool
+
+class Bintoolfdt_add_pubkey(bintool.Bintool):
+"""Add public key to control dtb (spl or u-boot proper)
+
+This bintool supports running `fdt_add_pubkey`.
+
+Normally mkimage adds signature information to the control dtb. However
+binman images are built independent from each other. Thus it is required
+to add the public key separately from mkimage.
+"""
+def __init__(self, name):
+super().__init__(name, 'Generate image for U-Boot')
+
+# pylint: disable=R0913
+def run(self, input_fname, keydir, keyname, required, algo):
+"""Run fdt_add_pubkey
+
+Args:
+input_fname (str): dtb file to sign
+keydir (str): Directory with public key. Optional parameter,
+default value: '.' (current directory)
+keyname (str): Public key name. Optional parameter,
+default value: key
+required (str): If present this indicates that the key must be
+verified for the image / configuration to be considered valid.
+algo (str): Cryptographic algorithm. Optional parameter,
+default value: sha1,rsa2048
+"""
+args = []
+if algo:
+args += ['-a', algo]
+if keydir:
+args += ['-k', keydir]
+if keyname:
+args += ['-n', keyname]
+if required:
+args += ['-r', required]
+
+args += [ input_fname ]
+
+return self.run_cmd(*args)
+
+def fetch(self, method):
+"""Fetch handler for fdt_add_pubkey
+
+This installs fdt_add_pubkey using the apt utility.
+
+Args:
+method (FETCH_...): Method to use
+
+Returns:
+True if the file was fetched and now installed, None if a method
+other than FETCH_BIN was requested
+
+Raises:
+Valuerror: Fetching could not be completed
+"""
+if method != bintool.FETCH_BIN:
+return None
+return self.apt_install('u-boot-tools')
-- 
2.30.2



[PATCH v2 04/11] binman: doc: Add documentation for fdt_add_pubkey bintool

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

Add documentation for btool which calls 'fdt_add_pubkey'

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/bintools.rst | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst
index c30e7eb9ff..88221adbe1 100644
--- a/tools/binman/bintools.rst
+++ b/tools/binman/bintools.rst
@@ -183,3 +183,13 @@ Documentation is available via::
 
 
 
+Bintool: fdt_add_pubkey: Add public key to device tree
+-
+
+This bintool supports running `fdt_add_pubkey` in order to add a public
+key coming from a certificate to a device-tree.
+
+Normally signing is done using `mkimage` in context of `binman sign`. However,
+in this process the public key is not added to the stage before u-boot proper.
+Using `fdt_add_pubkey` the key can be injected to the SPL independent of
+`mkimage`
-- 
2.30.2



[PATCH v2 00/11] Sign Xilinx ZynqMP SPL/FSBL boot images using binman

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 


This series adds two etypes to create a verified boot chain for
Xilinx ZynqMP devices. The first etype 'xilinx_fsbl_auth' is used to
create a bootable, signed image for ZynqMP boards using the Xilinx
Bootgen tool. The second etype 'u_boot_spl_pubkey_dtb' is used to add
a '/signature' node to the SPL. The public key in the signature is read
from a certificate file and added using the 'fdt_add_pubkey' tool. The
series also contains the corresponding btool for calling 'bootgen' and
'fdt_add_pubkey'

The following block shows an example on how to use this functionality:

spl {
filename = "boot.signed.bin";

xilinx_fsbl_auth {
psk-filename = "psk0.pem";
ssk-filename = "ssk0.pem";
auth-params = "ppk_select=0", "spk_id=0x";

u_boot_spl_nodtb {
};
u_boot_spl_pubkey_dtb {
algo = "sha384,rsa4096";
required = "conf";
key-name = "dev";
};
};
};


Changes in v2:
- Changed u_boot_spl_pubkey_dtb to u-boot-spl-pubkey-dtb
- Improved rst/python documentation
- Changed u_boot_spl_pubkey_dtb to u-boot-spl-pubkey-dtb in example
- Pass additional 'keysrc_enc' parameter to Bootgen
- Added more information and terms to documentation
- Fixed typo in dts name
- Add 'keysrc-enc' property to pass down to Bootgen
- Improved documentation
- Use predictable output names for intermediated results

Lukas Funke (11):
  binman: elf: Check for ELF_TOOLS availability and remove extra
semicolon
  binman: Don't decompress data while signing
  binman: blob_dtb: Add fake_size argument to ObtainContents()
  binman: doc: Add documentation for fdt_add_pubkey bintool
  binman: ftest: Add test for u_boot_spl_pubkey_dtb
  binman: btool: Add fdt_add_pubkey as btool
  binman: etype: Add u_boot_spl_pubkey_dtb etype
  binman: doc: Add documentation for Xilinx Bootgen bintool
  binman: btool: Add Xilinx Bootgen btool
  binman: ftest: Add test for xilinx_fsbl_auth etype
  binman: etype: Add xilinx_fsbl_auth etype

 tools/binman/bintools.rst   |  22 ++
 tools/binman/btool/bootgen.py   | 136 +
 tools/binman/btool/fdt_add_pubkey.py|  67 ++
 tools/binman/control.py |   2 +-
 tools/binman/elf.py |  10 +-
 tools/binman/entries.rst|  92 +
 tools/binman/etype/blob_dtb.py  |   2 +-
 tools/binman/etype/u_boot_spl_pubkey_dtb.py | 109 ++
 tools/binman/etype/xilinx_fsbl_auth.py  | 213 
 tools/binman/ftest.py   |  42 +++-
 tools/binman/test/280_xilinx_fsbl_auth.dts  |  23 +++
 tools/binman/test/281_spl_pubkey_dtb.dts|  16 ++
 12 files changed, 727 insertions(+), 7 deletions(-)
 create mode 100644 tools/binman/btool/bootgen.py
 create mode 100644 tools/binman/btool/fdt_add_pubkey.py
 create mode 100644 tools/binman/etype/u_boot_spl_pubkey_dtb.py
 create mode 100644 tools/binman/etype/xilinx_fsbl_auth.py
 create mode 100644 tools/binman/test/280_xilinx_fsbl_auth.dts
 create mode 100644 tools/binman/test/281_spl_pubkey_dtb.dts

-- 
2.30.2



[PATCH v2 03/11] binman: blob_dtb: Add fake_size argument to ObtainContents()

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

The method 'connect_contents_to_file()' calls ObtainsContents() with
'fake_size' argument. Without providing the argument in the blob_dtb
we are not able to call this method without error.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/etype/blob_dtb.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/binman/etype/blob_dtb.py b/tools/binman/etype/blob_dtb.py
index 6a3fbc4775..d543de9f75 100644
--- a/tools/binman/etype/blob_dtb.py
+++ b/tools/binman/etype/blob_dtb.py
@@ -38,7 +38,7 @@ class Entry_blob_dtb(Entry_blob):
 self.Raise("Invalid prepend in '%s': '%s'" %
(self._node.name, self.prepend))
 
-def ObtainContents(self):
+def ObtainContents(self, fake_size=0):
 """Get the device-tree from the list held by the 'state' module"""
 self._filename = self.GetDefaultFilename()
 self._pathname, _ = state.GetFdtContents(self.GetFdtEtype())
-- 
2.30.2



[PATCH v2 05/11] binman: ftest: Add test for u_boot_spl_pubkey_dtb

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

Add test for u_boot_spl_pubkey_dtb. The test adds a public key to the
dtb and checks if the required nodes will be added to the images dtb.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 

---

Changes in v2:
- Changed u_boot_spl_pubkey_dtb to u-boot-spl-pubkey-dtb

 tools/binman/ftest.py| 32 
 tools/binman/test/281_spl_pubkey_dtb.dts | 16 
 2 files changed, 48 insertions(+)
 create mode 100644 tools/binman/test/281_spl_pubkey_dtb.dts

diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 43b4f850a6..0ee0ce1155 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -638,6 +638,16 @@ class TestFunctional(unittest.TestCase):
 TestFunctional._MakeInputFile('vpl/u-boot-vpl',
 tools.read_file(cls.ElfTestFile(src_fname)))
 
+@classmethod
+def _SetupPmuFwlElf(cls, src_fname='bss_data'):
+"""Set up an ELF file with a '_dt_ucode_base_size' symbol
+
+Args:
+Filename of ELF file to use as VPL
+"""
+TestFunctional._MakeInputFile('pmu-firmware.elf',
+tools.read_file(cls.ElfTestFile(src_fname)))
+
 @classmethod
 def _SetupDescriptor(cls):
 with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
@@ -6677,5 +6687,27 @@ fdt fdtmapExtract the devicetree 
blob from the fdtmap
 self.assertIn("Node '/fit': Missing tool: 'mkimage'", str(e.exception))
 
 
+def testSplPubkeyDtb(self):
+ """Test u_boot_spl_pubkey_dtb etype"""
+ data = tools.read_file(self.TestFile("key.pem"))
+ self._MakeInputFile("key.crt", data)
+ self._DoReadFileRealDtb('281_spl_pubkey_dtb.dts')
+ image = control.images['image']
+ entries = image.GetEntries()
+ dtb_entry = entries['u-boot-spl-pubkey-dtb']
+ dtb_data = dtb_entry.GetData()
+ dtb = fdt.Fdt.FromData(dtb_data)
+ dtb.Scan()
+
+ signature_node = dtb.GetNode('/signature')
+ self.assertIsNotNone(signature_node)
+ key_node = signature_node.FindNode("key-key")
+ self.assertIsNotNone(key_node)
+ self.assertEqual(fdt_util.GetString(key_node, "required"),
+  "conf")
+ self.assertEqual(fdt_util.GetString(key_node, "algo"),
+  "sha384,rsa4096")
+ self.assertEqual(fdt_util.GetString(key_node, "key-name-hint"),
+  "key")
 if __name__ == "__main__":
 unittest.main()
diff --git a/tools/binman/test/281_spl_pubkey_dtb.dts 
b/tools/binman/test/281_spl_pubkey_dtb.dts
new file mode 100644
index 00..f845db66f5
--- /dev/null
+++ b/tools/binman/test/281_spl_pubkey_dtb.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   binman {
+   u-boot-spl-pubkey-dtb {
+   algo = "sha384,rsa4096";
+   required = "conf";
+   key-name = "key";
+   };
+   };
+};
-- 
2.30.2



[PATCH v2 02/11] binman: Don't decompress data while signing

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

While signing a fit compressed data (i.e. 'blob-ext') is decompressed,
but never compressed again. When compressed data was wrapped in a
section, decompression leads to an error because the outer section had
the original compressed size but the inner entry has the
uncompressed size now.

While singing there is no reason to decompress data. Thus, decompression
should be disabled.

Furthermore, bintools should be collected before loading the data. This
way bintools are available if processing is required on a node.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/control.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/binman/control.py b/tools/binman/control.py
index 68597c4e77..affc33ff3d 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -306,8 +306,8 @@ def BeforeReplace(image, allow_resize):
 image: Image to prepare
 """
 state.PrepareFromLoadedData(image)
-image.LoadData()
 image.CollectBintools()
+image.LoadData(decomp=False)
 
 # If repacking, drop the old offset/size values except for the original
 # ones, so we are only left with the constraints.
-- 
2.30.2



[PATCH v2 01/11] binman: elf: Check for ELF_TOOLS availability and remove extra semicolon

2023-07-06 Thread lukas . funke-oss
From: Lukas Funke 

Check if elf tools are available when running DecodeElf(). Also
remove superfuous semicolon at line ending.

Signed-off-by: Lukas Funke 
Reviewed-by: Simon Glass 
---

(no changes since v1)

 tools/binman/elf.py | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/tools/binman/elf.py b/tools/binman/elf.py
index 5816284c32..a53f4b9c4f 100644
--- a/tools/binman/elf.py
+++ b/tools/binman/elf.py
@@ -438,13 +438,15 @@ def DecodeElf(data, location):
 Returns:
 ElfInfo object containing information about the decoded ELF file
 """
+if not ELF_TOOLS:
+raise ValueError("Python: No module named 'elftools'")
 file_size = len(data)
 with io.BytesIO(data) as fd:
 elf = ELFFile(fd)
-data_start = 0x;
-data_end = 0;
-mem_end = 0;
-virt_to_phys = 0;
+data_start = 0x
+data_end = 0
+mem_end = 0
+virt_to_phys = 0
 
 for i in range(elf.num_segments()):
 segment = elf.get_segment(i)
-- 
2.30.2



[PATCH 07/12] binman: btool: Add fdt_add_pubkey as btool

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

Add btool which calls 'fdt_add_pubkey'

Signed-off-by: Lukas Funke 
---

 tools/binman/btool/fdt_add_pubkey.py | 67 
 1 file changed, 67 insertions(+)
 create mode 100644 tools/binman/btool/fdt_add_pubkey.py

diff --git a/tools/binman/btool/fdt_add_pubkey.py 
b/tools/binman/btool/fdt_add_pubkey.py
new file mode 100644
index 00..a50774200c
--- /dev/null
+++ b/tools/binman/btool/fdt_add_pubkey.py
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG
+# Lukas Funke 
+#
+"""Bintool implementation for fdt_add_pubkey"""
+
+from binman import bintool
+
+class Bintoolfdt_add_pubkey(bintool.Bintool):
+"""Add public key to control dtb (spl or u-boot proper)
+
+This bintool supports running `fdt_add_pubkey`.
+
+Normally mkimage adds signature information to the control dtb. However
+binman images are built independent from each other. Thus it is required
+to add the public key separately from mkimage.
+"""
+def __init__(self, name):
+super().__init__(name, 'Generate image for U-Boot')
+
+# pylint: disable=R0913
+def run(self, input_fname, keydir, keyname, required, algo):
+"""Run fdt_add_pubkey
+
+Args:
+input_fname (str): dtb file to sign
+keydir (str): Directory with public key. Optional parameter,
+default value: '.' (current directory)
+keyname (str): Public key name. Optional parameter,
+default value: key
+required (str): If present this indicates that the key must be
+verified for the image / configuration to be considered valid.
+algo (str): Cryptographic algorithm. Optional parameter,
+default value: sha1,rsa2048
+"""
+args = []
+if algo:
+args += ['-a', algo]
+if keydir:
+args += ['-k', keydir]
+if keyname:
+args += ['-n', keyname]
+if required:
+args += ['-r', required]
+
+args += [ input_fname ]
+
+return self.run_cmd(*args)
+
+def fetch(self, method):
+"""Fetch handler for fdt_add_pubkey
+
+This installs fdt_add_pubkey using the apt utility.
+
+Args:
+method (FETCH_...): Method to use
+
+Returns:
+True if the file was fetched and now installed, None if a method
+other than FETCH_BIN was requested
+
+Raises:
+Valuerror: Fetching could not be completed
+"""
+if method != bintool.FETCH_BIN:
+return None
+return self.apt_install('u-boot-tools')
-- 
2.30.2



[PATCH 08/12] binman: etype: Add u_boot_spl_pubkey_dtb etype

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

This adds a new etype 'u_boot_spl_pubkey_dtb'. The etype adds the public
key from a certificate to the dtb. This creates a '/signature' node which
is turn contains the fields which make up the public key. Usually this
is done by 'mkimage -K'. However, 'binman sign' does not add the public
key to the SPL. This is why the pubkey is added using this etype.

The etype calls the underlying 'fdt_add_pubkey' tool.

Signed-off-by: Lukas Funke 
---

 tools/binman/etype/u_boot_spl_pubkey_dtb.py | 105 
 1 file changed, 105 insertions(+)
 create mode 100644 tools/binman/etype/u_boot_spl_pubkey_dtb.py

diff --git a/tools/binman/etype/u_boot_spl_pubkey_dtb.py 
b/tools/binman/etype/u_boot_spl_pubkey_dtb.py
new file mode 100644
index 00..25aa817975
--- /dev/null
+++ b/tools/binman/etype/u_boot_spl_pubkey_dtb.py
@@ -0,0 +1,105 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Weidmueller GmbH
+# Written by Lukas Funke 
+#
+# Entry-type module for 'u-boot-spl-pubkey.dtb'
+#
+
+import tempfile
+import os
+
+from binman.etype.blob_dtb import Entry_blob_dtb
+
+from dtoc import fdt_util
+
+from u_boot_pylib import tools
+
+# pylint: disable=C0103
+class Entry_u_boot_spl_pubkey_dtb(Entry_blob_dtb):
+"""U-Boot SPL device tree including public key
+
+Properties / Entry arguments:
+- key-name: Public key name without extension (e.g. .crt). Default is
+determined by underlying bintool (fdt_add_pubkey),
+usually 'key'
+- algo: (Optional) Algorithm used for signing. Default is determined by
+underlying bintool (fdt_add_pubkey), usually 'sha1,rsa2048'
+- required: (Optional) If present this indicates that the key must be
+verified for the image / configuration to be
+considered valid
+
+The following example shows an image containing an SPL which
+is packed together with the dtb. Binman will add a signature
+node to the dtb:
+
+image {
+...
+spl {
+filename = "spl.bin"
+
+u_boot_spl_nodtb {
+};
+u_boot_spl_pubkey_dtb {
+algo = "sha384,rsa4096";
+required = "conf";
+key-name = "dev";
+};
+};
+...
+}
+"""
+
+def __init__(self, section, etype, node):
+# Put this here to allow entry-docs and help to work without libfdt
+global state
+from binman import state
+
+super().__init__(section, etype, node)
+self.required_props = ['key-name']
+self.fdt_add_pubkey = None
+self._algo = fdt_util.GetString(self._node, 'algo')
+self._required = fdt_util.GetString(self._node, 'required')
+self._keyname = fdt_util.GetString(self._node, 'key-name')
+
+def ObtainContents(self, fake_size=0):
+""" Add public key which is pointed out by
+'key-name' to node 'signature' in the spl-dtb
+
+This is equivalent to the '-K' option of 'mkimage'
+
+Args:
+fake_size (int): unused
+"""
+
+# We don't pass fake_size and skip_entry upwards
+# because this is currently not support by the blob type
+super().ObtainContents()
+
+with tempfile.NamedTemporaryFile(prefix=os.path.basename(
+ self.GetFdtEtype()),
+ dir=tools.get_output_dir())\
+  as pubkey_tdb:
+tools.write_file(pubkey_tdb.name, self.GetData())
+keyname = tools.get_input_filename(self._keyname + ".crt")
+self.fdt_add_pubkey.run(pubkey_tdb.name,
+os.path.dirname(keyname),
+self._keyname,
+self._required, self._algo)
+dtb = tools.read_file(pubkey_tdb.name)
+self.SetContents(dtb)
+state.UpdateFdtContents(self.GetFdtEtype(), dtb)
+
+return True
+
+# pylint: disable=R0201,C0116
+def GetDefaultFilename(self):
+return 'spl/u-boot-spl-pubkey.dtb'
+
+# pylint: disable=R0201,C0116
+def GetFdtEtype(self):
+return 'u-boot-spl-dtb'
+
+# pylint: disable=R0201,C0116
+def AddBintools(self, btools):
+super().AddBintools(btools)
+self.fdt_add_pubkey = self.AddBintool(btools, 'fdt_add_pubkey')
-- 
2.30.2



[PATCH 03/12] binman: Don't decompress data while signing

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

While signing a fit compressed data (i.e. 'blob-ext') is decompressed,
but never compressed again. When compressed data was wrapped in a
section, decompression leads to an error because the outer section had
the original compressed size but the inner entry has the
uncompressed size now.

While singing there is no reason to decompress data. Thus, decompression
should be disabled.

Furthermore, bintools should be collected before loading the data. This
way bintools are available if processing is required on a node.

Signed-off-by: Lukas Funke 
---

 tools/binman/control.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/binman/control.py b/tools/binman/control.py
index 68597c4e77..affc33ff3d 100644
--- a/tools/binman/control.py
+++ b/tools/binman/control.py
@@ -306,8 +306,8 @@ def BeforeReplace(image, allow_resize):
 image: Image to prepare
 """
 state.PrepareFromLoadedData(image)
-image.LoadData()
 image.CollectBintools()
+image.LoadData(decomp=False)
 
 # If repacking, drop the old offset/size values except for the original
 # ones, so we are only left with the constraints.
-- 
2.30.2



[PATCH 02/12] binman: mkimage: Remove extra colon

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

Remove extra colon typo

Signed-off-by: Lukas Funke 
---

 tools/binman/etype/mkimage.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/binman/etype/mkimage.py b/tools/binman/etype/mkimage.py
index e028c44070..dd734fc779 100644
--- a/tools/binman/etype/mkimage.py
+++ b/tools/binman/etype/mkimage.py
@@ -24,7 +24,7 @@ class Entry_mkimage(Entry):
 - filename: filename of output binary generated by mkimage
 
 The data passed to mkimage via the -d flag is collected from subnodes of 
the
-mkimage node, e.g.::
+mkimage node, e.g.:
 
 mkimage {
 filename = "imximage.bin";
-- 
2.30.2



[PATCH 09/12] binman: doc: Add documentation for Xilinx Bootgen bintool

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

Add documentation for the 'bootgen' bintool

Signed-off-by: Lukas Funke 
---

 tools/binman/bintools.rst | 12 
 1 file changed, 12 insertions(+)

diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst
index 88221adbe1..c8d69f7177 100644
--- a/tools/binman/bintools.rst
+++ b/tools/binman/bintools.rst
@@ -193,3 +193,15 @@ Normally signing is done using `mkimage` in context of 
`binman sign`. However,
 in this process the public key is not added to the stage before u-boot proper.
 Using `fdt_add_pubkey` the key can be injected to the SPL independent of
 `mkimage`
+
+
+
+Bintool: bootgen: Sign ZynqMP FSBL image
+-
+
+This bintool supports running `bootgen` in order to sign a SPL for ZynqMP
+devices.
+
+The bintool automatically creates an appropriate input image file (.bif) for
+bootgen based on the passed arguments. The output is a bootable,
+authenticated `boot.bin` file.
-- 
2.30.2



[PATCH 11/12] binman: ftest: Add test for xilinx_fsbl_auth etype

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

Add test for the 'xilinx_fsbl_auth' etype

Signed-off-by: Lukas Funke 
---

 tools/binman/ftest.py |  8 
 tools/binman/test/280_xilinx_fsb_auth.dts | 22 ++
 2 files changed, 30 insertions(+)
 create mode 100644 tools/binman/test/280_xilinx_fsb_auth.dts

diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 3bd09d3fea..f0a7861649 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -6686,6 +6686,14 @@ fdt fdtmapExtract the devicetree 
blob from the fdtmap
 ['fit'])
 self.assertIn("Node '/fit': Missing tool: 'mkimage'", str(e.exception))
 
+def testXilinxFsblAuth(self):
+"""Test xilinx_fsbl_auth etype"""
+data = tools.read_file(self.TestFile("key.key"))
+self._MakeInputFile("psk.pem", data)
+self._MakeInputFile("ssk.pem", data)
+self._SetupPmuFwlElf()
+self._SetupSplElf()
+self._DoReadFileRealDtb('280_xilinx_fsb_auth.dts')
 
 def testSplPubkeyDtb(self):
  """Test u_boot_spl_pubkey_dtb etype"""
diff --git a/tools/binman/test/280_xilinx_fsb_auth.dts 
b/tools/binman/test/280_xilinx_fsb_auth.dts
new file mode 100644
index 00..2bfd36c22e
--- /dev/null
+++ b/tools/binman/test/280_xilinx_fsb_auth.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   binman {
+   xilinx_fsbl_auth {
+
+   psk-filename = "psk.pem";
+   ssk-filename = "ssk.pem";
+   auth-params = "ppk_select=0", "spk_id=0x";
+
+   u_boot_spl_nodtb {
+   };
+   u_boot_spl_dtb {
+   };
+   };
+   };
+};
-- 
2.30.2



[PATCH 05/12] binman: doc: Add documentation for fdt_add_pubkey bintool

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

Add documentation for btool which calls 'fdt_add_pubkey'

Signed-off-by: Lukas Funke 
---

 tools/binman/bintools.rst | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/tools/binman/bintools.rst b/tools/binman/bintools.rst
index c30e7eb9ff..88221adbe1 100644
--- a/tools/binman/bintools.rst
+++ b/tools/binman/bintools.rst
@@ -183,3 +183,13 @@ Documentation is available via::
 
 
 
+Bintool: fdt_add_pubkey: Add public key to device tree
+-
+
+This bintool supports running `fdt_add_pubkey` in order to add a public
+key coming from a certificate to a device-tree.
+
+Normally signing is done using `mkimage` in context of `binman sign`. However,
+in this process the public key is not added to the stage before u-boot proper.
+Using `fdt_add_pubkey` the key can be injected to the SPL independent of
+`mkimage`
-- 
2.30.2



[PATCH 06/12] binman: ftest: Add test for u_boot_spl_pubkey_dtb

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

Add test for u_boot_spl_pubkey_dtb. The test adds a public key to the
dtb and checks if the required nodes will be added to the images dtb.

Signed-off-by: Lukas Funke 
---

 tools/binman/ftest.py| 32 
 tools/binman/test/281_spl_pubkey_dtb.dts | 16 
 2 files changed, 48 insertions(+)
 create mode 100644 tools/binman/test/281_spl_pubkey_dtb.dts

diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 43b4f850a6..3bd09d3fea 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -638,6 +638,16 @@ class TestFunctional(unittest.TestCase):
 TestFunctional._MakeInputFile('vpl/u-boot-vpl',
 tools.read_file(cls.ElfTestFile(src_fname)))
 
+@classmethod
+def _SetupPmuFwlElf(cls, src_fname='bss_data'):
+"""Set up an ELF file with a '_dt_ucode_base_size' symbol
+
+Args:
+Filename of ELF file to use as VPL
+"""
+TestFunctional._MakeInputFile('pmu-firmware.elf',
+tools.read_file(cls.ElfTestFile(src_fname)))
+
 @classmethod
 def _SetupDescriptor(cls):
 with open(cls.TestFile('descriptor.bin'), 'rb') as fd:
@@ -6677,5 +6687,27 @@ fdt fdtmapExtract the devicetree 
blob from the fdtmap
 self.assertIn("Node '/fit': Missing tool: 'mkimage'", str(e.exception))
 
 
+def testSplPubkeyDtb(self):
+ """Test u_boot_spl_pubkey_dtb etype"""
+ data = tools.read_file(self.TestFile("key.pem"))
+ self._MakeInputFile("key.crt", data)
+ self._DoReadFileRealDtb('281_spl_pubkey_dtb.dts')
+ image = control.images['image']
+ entries = image.GetEntries()
+ dtb_entry = entries['u_boot_spl_pubkey_dtb']
+ dtb_data = dtb_entry.GetData()
+ dtb = fdt.Fdt.FromData(dtb_data)
+ dtb.Scan()
+
+ signature_node = dtb.GetNode('/signature')
+ self.assertIsNotNone(signature_node)
+ key_node = signature_node.FindNode("key-key")
+ self.assertIsNotNone(key_node)
+ self.assertEqual(fdt_util.GetString(key_node, "required"),
+  "conf")
+ self.assertEqual(fdt_util.GetString(key_node, "algo"),
+  "sha384,rsa4096")
+ self.assertEqual(fdt_util.GetString(key_node, "key-name-hint"),
+  "key")
 if __name__ == "__main__":
 unittest.main()
diff --git a/tools/binman/test/281_spl_pubkey_dtb.dts 
b/tools/binman/test/281_spl_pubkey_dtb.dts
new file mode 100644
index 00..5a2952ed7d
--- /dev/null
+++ b/tools/binman/test/281_spl_pubkey_dtb.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/dts-v1/;
+
+/ {
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+   binman {
+   u_boot_spl_pubkey_dtb {
+   algo = "sha384,rsa4096";
+   required = "conf";
+   key-name = "key";
+   };
+   };
+};
-- 
2.30.2



[PATCH 12/12] binman: etype: Add xilinx_fsbl_auth etype

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

This adds a new etype 'xilinx_fsbl_auth'. Using this etype it is possible
to created an authenticated SPL (FSBL in Xilinx terms) for ZynqMP boards.

The etype uses Xilinx Bootgen tools in order to transform the SPL into
a bootable image and sign the image with a given primary and seconrady
public key. For more information to signing the FSBL please refer to the
Xilinx Bootgen documentation.

Here is an example of the etype in use:

spl {
filename = "boot.signed.bin";

xilinx_fsbl_auth {
psk-filename = "psk0.pem";
ssk-filename = "ssk0.pem";
auth-params = "ppk_select=0", "spk_id=0x";

u_boot_spl_nodtb {
};
u_boot_spl_dtb {
};
};
};

For this to work the hash of the primary public key has to be fused
into the ZynqMP device and authentication (RSA_EN) has to be set.

For testing purposes: if ppk hash check should be skipped one can add
the property 'fsbl_config = "bh_auth_enable";' to the etype. However,
this should only be used for testing(!).

Signed-off-by: Lukas Funke 
---

 tools/binman/etype/xilinx_fsbl_auth.py | 186 +
 1 file changed, 186 insertions(+)
 create mode 100644 tools/binman/etype/xilinx_fsbl_auth.py

diff --git a/tools/binman/etype/xilinx_fsbl_auth.py 
b/tools/binman/etype/xilinx_fsbl_auth.py
new file mode 100644
index 00..ec70db9414
--- /dev/null
+++ b/tools/binman/etype/xilinx_fsbl_auth.py
@@ -0,0 +1,186 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (c) 2023 Weidmueller GmbH
+# Written by Lukas Funke 
+#
+# Entry-type module for signed ZynqMP boot images (boot.bin)
+#
+
+import tempfile
+
+from collections import OrderedDict
+
+from binman import elf
+from binman.entry import Entry
+
+from dtoc import fdt_util
+
+from u_boot_pylib import tools
+from u_boot_pylib import command
+
+# pylint: disable=C0103
+class Entry_xilinx_fsbl_auth(Entry):
+"""Authenticated SPL flat binary for booting Xilinx
+ZynqMP devices
+
+Properties / Entry arguments:
+- auth-params: (Optional) Authentication parameters passed to bootgen
+- fsbl-config: (Optional) FSBL parameters passed to bootgen
+- pmufw-filename: Filename of PMU firmware. Default: pmu-firmware.elf
+- psk-filename: Filename of primary public key
+- ssk-filename: Filename of secondary public key
+
+The following example builds an authenticated boot image. The fuses of
+the primary public key (ppk) should be fused together with the RSA_EN flag.
+
+spl {
+filename = "boot.signed.bin";
+
+xilinx_fsbl_auth {
+psk-filename = "psk0.pem";
+ssk-filename = "ssk0.pem";
+auth-params = "ppk_select=0", "spk_id=0x";
+
+u_boot_spl_nodtb {
+};
+u_boot_spl_pubkey_dtb {
+algo = "sha384,rsa4096";
+required = "conf";
+key-name = "dev";
+};
+};
+};
+
+For testing purposes, e.g. if no RSA_EN should be fused, one could add
+the "bh_auth_enable" flag in the fsbl-config field. This will skip the
+verification of the ppk fuses and boot the image, even if ppk hash is
+invalid:
+
+xilinx_fsbl_auth {
+psk-filename = "psk0.pem";
+ssk-filename = "ssk0.pem";
+...
+fsbl-config = "bh_auth_enable";
+...
+};
+
+"""
+def __init__(self, section, etype, node):
+super().__init__(section, etype, node)
+self.align_default = None
+self.bootgen = None
+self._entries = OrderedDict()
+self._filename = self.GetDefaultFilename()
+self.required_props = ['psk-filename', 'ssk-filename']
+
+def ReadNode(self):
+"""Read properties from the xilinx_fsbl_auth node"""
+super().ReadNode()
+self._auth_params = fdt_util.GetStringList(self._node,
+   'auth-params')
+self._fsbl_config = fdt_util.GetStringList(self._node,
+   'fsbl-config')
+self._pmufw_filename = fdt_util.GetString(self._node,
+  'pmufw-filename',
+  'pmu-firmware.elf')
+self._psk_filename = fdt_util.GetString(self._node, 'psk-filename',
+'psk.pem')
+self._ssk_filename = fdt_util.GetString(self._node, 'ssk-filename',
+'ssk.pem')
+self.ReadEntries()
+
+def ReadEntries(self):
+"""Read the subnodes to find out what should go in this image"""
+for node in self._node.subnodes:
+entry = Entry.Create(self, node)
+entry.ReadNode()
+self._entries[entry.name] = entry
+
+@classmethod
+def __ToElf(self, data, 

[PATCH 10/12] binman: btool: Add Xilinx Bootgen btool

2023-06-29 Thread lukas . funke-oss
From: Lukas Funke 

Add the Xilinx Bootgen as bintool. Xilinx Bootgen is used to create
bootable SPL (FSBL in Xilinx terms) images for Zynq/ZynqMP devices. The
btool creates a signed version of the SPL.

Signed-off-by: Lukas Funke 
---

 tools/binman/btool/bootgen.py | 82 +++
 1 file changed, 82 insertions(+)
 create mode 100644 tools/binman/btool/bootgen.py

diff --git a/tools/binman/btool/bootgen.py b/tools/binman/btool/bootgen.py
new file mode 100644
index 00..8bc727a54f
--- /dev/null
+++ b/tools/binman/btool/bootgen.py
@@ -0,0 +1,82 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright (C) 2023 Weidmüller Interface GmbH & Co. KG
+# Lukas Funke 
+#
+"""Bintool implementation for bootgen
+
+bootgen allows creating bootable SPL for Zynq(MP)
+
+Documentation is available via::
+https://www.xilinx.com/support/documents/sw_manuals/xilinx2022_1/ug1283-bootgen-user-guide.pdf
+
+Source code is available at:
+
+https://github.com/Xilinx/bootgen
+
+"""
+import tempfile
+
+from binman import bintool
+from u_boot_pylib import tools
+
+# pylint: disable=C0103
+class Bintoolbootgen(bintool.Bintool):
+"""Generate bootable fsbl image for zynq/zynqmp
+
+This bintools supports running Xilinx "bootgen" in order
+to generate a bootable, authenticated image form an SPL.
+
+"""
+def __init__(self, name):
+super().__init__(name, 'Xilinx Bootgen',
+ version_regex=r'^\*\*\*\*\*\* Xilinx Bootgen',
+ version_args='')
+
+# pylint: disable=R0913
+def sign(self, arch, spl_elf_fname, pmufw_elf_fname,
+ psk_fname, ssk_fname, fsbl_config, auth_params, output_fname):
+""" Sign FSBL(SPL) elf file and bundle it with pmu firmware
+to a bootable image
+
+Args:
+arch (str): Xilinx SoC architecture
+spl_elf_fname (str): Filename of FSBL ELF file
+pmufw_elf_fname (str): Filename pmu firmware
+psk_fname (str): Filename of the primary secret key
+ssk_fname (str): Filename of the secondary secret key
+fsbl_config (str): FSBL config options
+auth_params (str): Authentication parameter
+output_fname (str): Filename where bootgen should write the result
+"""
+
+_fsbl_config = f"[fsbl_config] {fsbl_config}" if fsbl_config else ""
+_auth_params = f"[auth_params] {auth_params}" if auth_params else ""
+
+bif_template = f"""u_boot_spl_aes_rsa: {{
+[pskfile] {psk_fname}
+[sskfile] {ssk_fname}
+{_fsbl_config}
+{_auth_params}
+[ bootloader,
+  authentication = rsa,
+  destination_cpu=a53-0] {spl_elf_fname}
+[pmufw_image] {pmufw_elf_fname}
+}}"""
+args = ["-arch", arch]
+
+with tempfile.NamedTemporaryFile(suffix=".bif",
+ dir=tools.get_output_dir()) as bif:
+tools.write_file(bif.name, bif_template, binary=False)
+args += ["-image", bif.name, '-w', '-o', output_fname]
+self.run_cmd(*args)
+
+def fetch(self, method):
+"""Fetch bootgen from git"""
+if method != bintool.FETCH_BUILD:
+return None
+
+result = self.build_from_git(
+'https://github.com/Xilinx/bootgen',
+'all',
+'build/bootgen/bootgen')
+return result
-- 
2.30.2



  1   2   >