]> git.baikalelectronics.ru Git - arm-tf.git/commitdiff
feat(ethos-n): add NPU firmware validation
authorMikael Olsson <mikael.olsson@arm.com>
Fri, 13 Jan 2023 08:56:41 +0000 (09:56 +0100)
committerJoanna Farley <joanna.farley@arm.com>
Tue, 4 Apr 2023 09:37:12 +0000 (11:37 +0200)
When the Arm(R) Ethos(TM)-N NPU driver is built with TZMP1 support, it
will now validate the NPU firmware binary that BL2 is expected to load
into the protected memory location specified by
ARM_ETHOSN_NPU_IMAGE_BASE.

Juno has been updated with a new BL31 memory mapping to allow the SiP
service to read the protected memory that contains the NPU firmware
binary.

Signed-off-by: Mikael Olsson <mikael.olsson@arm.com>
Change-Id: I633256ab7dd4f8f5a6f864c8c98a66bf9dfc37f3

drivers/arm/ethosn/ethosn_big_fw.c [new file with mode: 0644]
drivers/arm/ethosn/ethosn_big_fw.h [new file with mode: 0644]
drivers/arm/ethosn/ethosn_smc.c
plat/arm/board/juno/include/platform_def.h
plat/arm/board/juno/juno_common.c
plat/arm/common/arm_common.mk

diff --git a/drivers/arm/ethosn/ethosn_big_fw.c b/drivers/arm/ethosn/ethosn_big_fw.c
new file mode 100644 (file)
index 0000000..9bb33ea
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+
+#include "ethosn_big_fw.h"
+
+/* Magic (FourCC) number to identify the big firmware binary */
+#define ETHOSN_BIG_FW_MAGIC    ('E' | ('N' << 8) | ('F' << 16) | ('W' << 24))
+
+/* Supported big firmware version */
+#define ETHOSN_BIG_FW_VERSION_MAJOR    9
+
+#define ETHOSN_ARCH_VER_MAJOR_MASK     U(0xF000)
+#define ETHOSN_ARCH_VER_MAJOR_SHIFT    U(0xC)
+#define ETHOSN_ARCH_VER_MINOR_MASK     U(0xF00)
+#define ETHOSN_ARCH_VER_MINOR_SHIFT    U(0x8)
+#define ETHOSN_ARCH_VER_REV_MASK       U(0xFF)
+
+/* Convert Arm(R) Ethos(TM)-N NPU architecture version to big firmware format */
+#define ETHOSN_BIG_FW_FORMAT_ARCH_VER(arch_ver)                                         \
+       (arch_ver & ETHOSN_ARCH_VER_MAJOR_MASK) << ETHOSN_ARCH_VER_MAJOR_SHIFT | \
+       (arch_ver & ETHOSN_ARCH_VER_MINOR_MASK) << ETHOSN_ARCH_VER_MINOR_SHIFT | \
+       (arch_ver & ETHOSN_ARCH_VER_REV_MASK)
+
+
+bool ethosn_big_fw_verify_header(const struct ethosn_big_fw *big_fw,
+                                uint32_t npu_arch_ver)
+{
+       const uint32_t arch_ver = ETHOSN_BIG_FW_FORMAT_ARCH_VER(npu_arch_ver);
+
+       if (big_fw->fw_magic != ETHOSN_BIG_FW_MAGIC) {
+               ERROR("ETHOSN: Unable to find firmware. Invalid magic value: 0x%02x\n",
+                     big_fw->fw_magic);
+
+               return false;
+       }
+
+       if (big_fw->fw_ver_major != ETHOSN_BIG_FW_VERSION_MAJOR) {
+               ERROR("ETHOSN: Unsupported firmware version: %u.%u.%u. Expected Version %u.x.x.\n",
+                     big_fw->fw_ver_major, big_fw->fw_ver_minor,
+                     big_fw->fw_ver_patch, ETHOSN_BIG_FW_VERSION_MAJOR);
+
+               return false;
+       }
+
+       if (big_fw->arch_min > arch_ver || arch_ver > big_fw->arch_max) {
+               ERROR("ETHOSN: Firmware is not compatbile with architecture version: 0x%02x\n",
+                     npu_arch_ver);
+               return false;
+       }
+
+       return true;
+}
diff --git a/drivers/arm/ethosn/ethosn_big_fw.h b/drivers/arm/ethosn/ethosn_big_fw.h
new file mode 100644 (file)
index 0000000..a321322
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2023, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/*
+ * Big FW binary structure.
+ * Must be kept in sync with the Arm(R) Ethos(TM)-N NPU firmware binary layout.
+ */
+struct ethosn_big_fw {
+       uint32_t fw_magic;
+       uint32_t fw_ver_major;
+       uint32_t fw_ver_minor;
+       uint32_t fw_ver_patch;
+       uint32_t arch_min;
+       uint32_t arch_max;
+       uint32_t offset;
+       uint32_t size;
+       uint32_t code_offset;
+       uint32_t code_size;
+       uint32_t ple_offset;
+       uint32_t ple_size;
+       uint32_t vector_table_offset;
+       uint32_t vector_table_size;
+       uint32_t unpriv_stack_offset;
+       uint32_t unpriv_stack_size;
+       uint32_t priv_stack_offset;
+       uint32_t priv_stack_size;
+} __packed;
+
+bool ethosn_big_fw_verify_header(const struct ethosn_big_fw *big_fw,
+                                uint32_t npu_arch_ver);
index 6b1ab85dcfcfee9afc618700d68092a783b622de..e314577a3aa0a4d8585d4dfe5afe8f3aebdc098f 100644 (file)
 
 #include <platform_def.h>
 
+#if ARM_ETHOSN_NPU_TZMP1
+#include "ethosn_big_fw.h"
+#endif
+
 /*
  * Number of Arm(R) Ethos(TM)-N NPU (NPU) devices available
  */
 #define SEC_MMUSID_REG_BASE            U(0x3008)
 #define SEC_MMUSID_OFFSET              U(0x1000)
 
+#define SEC_NPU_ID_REG                 U(0xF000)
+#define SEC_NPU_ID_ARCH_VER_SHIFT      U(0X10)
+
 #define INPUT_STREAM_INDEX              U(0x6)
 #define INTERMEDIATE_STREAM_INDEX       U(0x7)
 #define OUTPUT_STREAM_INDEX             U(0x8)
 
+#if ARM_ETHOSN_NPU_TZMP1
+CASSERT(ARM_ETHOSN_NPU_FW_IMAGE_BASE > 0U, assert_ethosn_invalid_fw_image_base);
+static const struct ethosn_big_fw *big_fw;
+#endif
+
 static bool ethosn_get_device_and_core(uintptr_t core_addr,
                                       const struct ethosn_device_t **dev_match,
                                       const struct ethosn_core_t **core_match)
@@ -86,6 +98,14 @@ static bool ethosn_get_device_and_core(uintptr_t core_addr,
 }
 
 #if ARM_ETHOSN_NPU_TZMP1
+static uint32_t ethosn_core_read_arch_version(uintptr_t core_addr)
+{
+       uint32_t npu_id = mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr,
+                                                          SEC_NPU_ID_REG));
+
+       return (npu_id >> SEC_NPU_ID_ARCH_VER_SHIFT);
+}
+
 static void ethosn_configure_stream_nsaid(const struct ethosn_core_t *core,
                                          bool is_protected)
 {
@@ -289,10 +309,39 @@ uintptr_t ethosn_smc_handler(uint32_t smc_fid,
 
 int ethosn_smc_setup(void)
 {
+#if ARM_ETHOSN_NPU_TZMP1
+       struct ethosn_device_t *dev;
+       uint32_t arch_ver;
+#endif
+
        if (ETHOSN_NUM_DEVICES == 0U) {
                ERROR("ETHOSN: No NPU found\n");
                return ETHOSN_FAILURE;
        }
 
+#if ARM_ETHOSN_NPU_TZMP1
+
+       /* Only one NPU core is supported in the TZMP1 setup */
+       if ((ETHOSN_NUM_DEVICES != 1U) ||
+           (ETHOSN_GET_DEVICE(0U)->num_cores != 1U)) {
+               ERROR("ETHOSN: TZMP1 doesn't support multiple NPU cores\n");
+               return ETHOSN_FAILURE;
+       }
+
+       dev = ETHOSN_GET_DEVICE(0U);
+       arch_ver = ethosn_core_read_arch_version(dev->cores[0U].addr);
+       big_fw = (struct ethosn_big_fw *)ARM_ETHOSN_NPU_FW_IMAGE_BASE;
+
+       if (!ethosn_big_fw_verify_header(big_fw, arch_ver)) {
+               return ETHOSN_FAILURE;
+       }
+
+       NOTICE("ETHOSN: TZMP1 setup succeeded with firmware version %u.%u.%u\n",
+              big_fw->fw_ver_major, big_fw->fw_ver_minor,
+              big_fw->fw_ver_patch);
+#else
+       NOTICE("ETHOSN: Setup succeeded\n");
+#endif
+
        return 0;
 }
index ef37104e93fca453b6b45677cc02d01d9f505d4c..5eaec698d15089813d501dcfe0bcef89b27e2618 100644 (file)
                                        MT_MEMORY | MT_RO | MT_NS)
 
 #ifdef JUNO_ETHOSN_TZMP1
+#define JUNO_ETHOSN_PROT_FW_RO MAP_REGION_FLAT(     \
+               JUNO_ETHOSN_FW_TZC_PROT_DRAM2_BASE, \
+               JUNO_ETHOSN_FW_TZC_PROT_DRAM2_SIZE, \
+               MT_RO_DATA | MT_SECURE)
+
 #define JUNO_ETHOSN_PROT_FW_RW MAP_REGION_FLAT(     \
                JUNO_ETHOSN_FW_TZC_PROT_DRAM2_BASE, \
                JUNO_ETHOSN_FW_TZC_PROT_DRAM2_SIZE, \
 #endif
 
 #ifdef IMAGE_BL31
-#  define PLAT_ARM_MMAP_ENTRIES                7
-#  define MAX_XLAT_TABLES              5
+# define PLAT_ARM_MMAP_ENTRIES         8
+# define MAX_XLAT_TABLES               6
 #endif
 
 #ifdef IMAGE_BL32
index 584b2ed72c8c784d0c8a151ec0115899ff61fe15..02614da4ad70715134307b8e76e8d7c223888069 100644 (file)
@@ -79,6 +79,9 @@ const mmap_region_t plat_arm_mmap[] = {
 #endif
        SOC_CSS_MAP_DEVICE,
        ARM_DTB_DRAM_NS,
+#ifdef JUNO_ETHOSN_TZMP1
+       JUNO_ETHOSN_PROT_FW_RO,
+#endif
        {0}
 };
 #endif
index e424ec07cde818a7c34b1791ff41a47493ef525c..fca6f4f95149ed9feb98baae59fd2c6525ce5eb3 100644 (file)
@@ -359,6 +359,9 @@ ifeq (${ARM_ETHOSN_NPU_DRIVER},1)
 ARM_SVC_HANDLER_SRCS   +=      plat/arm/common/fconf/fconf_ethosn_getter.c     \
                                drivers/delay_timer/delay_timer.c               \
                                drivers/arm/ethosn/ethosn_smc.c
+ifeq (${ARM_ETHOSN_NPU_TZMP1},1)
+ARM_SVC_HANDLER_SRCS   +=      drivers/arm/ethosn/ethosn_big_fw.c
+endif
 endif
 
 ifeq (${ARCH}, aarch64)