summaryrefslogtreecommitdiff
path: root/gcip-kernel-driver/include/gcip/gcip-image-config.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcip-kernel-driver/include/gcip/gcip-image-config.h')
-rw-r--r--gcip-kernel-driver/include/gcip/gcip-image-config.h153
1 files changed, 153 insertions, 0 deletions
diff --git a/gcip-kernel-driver/include/gcip/gcip-image-config.h b/gcip-kernel-driver/include/gcip/gcip-image-config.h
new file mode 100644
index 0000000..a995188
--- /dev/null
+++ b/gcip-kernel-driver/include/gcip/gcip-image-config.h
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Framework for parsing the firmware image configuration.
+ *
+ * Copyright (C) 2022 Google LLC
+ */
+
+#ifndef __GCIP_IMAGE_CONFIG_H__
+#define __GCIP_IMAGE_CONFIG_H__
+
+#include <linux/types.h>
+
+#define GCIP_FW_NUM_VERSIONS 4
+#define GCIP_IMG_CFG_MAX_IOMMU_MAPPINGS 22
+#define GCIP_IMG_CFG_MAX_NS_IOMMU_MAPPINGS 5
+
+#define GCIP_FW_PRIV_LEVEL_GSA 0
+#define GCIP_FW_PRIV_LEVEL_TZ 1
+#define GCIP_FW_PRIV_LEVEL_NS 2
+
+/*
+ * The image configuration attached to the signed firmware.
+ */
+struct gcip_image_config {
+ __u32 carveout_base;
+ __u32 firmware_base;
+ __u32 firmware_size;
+ __u32 firmware_versions[GCIP_FW_NUM_VERSIONS];
+ __u32 config_version;
+ __u32 privilege_level;
+ __u32 remapped_region_start;
+ __u32 remapped_region_size;
+ __u32 num_iommu_mappings;
+ struct {
+ /* Device virtual address */
+ __u32 virt_address;
+ /*
+ * Encodes a 12-bit aligned address and the corresponding size
+ * into a 32-bit value.
+ * Detailed encoding method is defined in gcip-image-config.c.
+ */
+ __u32 image_config_value;
+ } iommu_mappings[GCIP_IMG_CFG_MAX_IOMMU_MAPPINGS];
+ __u32 remapped_data_start;
+ __u32 remapped_data_size;
+ __u32 num_ns_iommu_mappings;
+ __u32 ns_iommu_mappings[GCIP_IMG_CFG_MAX_NS_IOMMU_MAPPINGS];
+} __packed;
+
+#define GCIP_IMAGE_CONFIG_FLAGS_SECURE (1u << 0)
+
+struct gcip_image_config_ops {
+ /*
+ * Adds an IOMMU mapping from @daddr to @paddr with size @size.
+ *
+ * It is ensured that there is no overflow on @paddr + @size before calling this function.
+ *
+ * @flags is a bit-field with the following attributes:
+ * [0:0] - Security. 1 for secure and 0 for non-secure.
+ * [31:1] - Reserved.
+ *
+ * Returns 0 on success. Otherwise a negative errno.
+ * Mandatory.
+ */
+ int (*map)(void *data, dma_addr_t daddr, phys_addr_t paddr, size_t size,
+ unsigned int flags);
+ /*
+ * Removes the IOMMU mapping previously added by @map.
+ *
+ * Mandatory.
+ */
+ void (*unmap)(void *data, dma_addr_t daddr, size_t size, unsigned int flags);
+};
+
+struct gcip_image_config_parser {
+ struct device *dev;
+ void *data; /* User-specify data, will be passed to ops. */
+ const struct gcip_image_config_ops *ops;
+ /* The last image config being successfully parsed. */
+ struct gcip_image_config last_config;
+};
+
+/*
+ * Initializes the image configuration parser.
+ *
+ * @dev is only used for logging.
+ * @data will be passed to operations.
+ *
+ * Returns 0 on success. Returns -EINVAL when any mandatory operations is NULL.
+ */
+int gcip_image_config_parser_init(struct gcip_image_config_parser *parser,
+ const struct gcip_image_config_ops *ops, struct device *dev,
+ void *data);
+
+/*
+ * Parses the image configuration and adds specified IOMMU mappings by calling pre-registered
+ * operations.
+ *
+ * Number of mappings to be added might be different according to the value of
+ * @config->privilege_level:
+ * - GCIP_FW_PRIV_LEVEL_NS:
+ * Both @iommu_mappings and @ns_iommu_mappings will be added. Because GCIP_FW_PRIV_LEVEL_NS means
+ * the firmware will run in non-secure mode and all transactions will go through the non-secure
+ * IOMMU.
+ * - Otherwise:
+ * Only @ns_iommu_mappings are considered. TZ/GSA will be the one who programs secure IOMMU for
+ * those secure IOMMU mappings.
+ *
+ * Before parsing the newly passed @config, the mappings of the last record (stored by @parser
+ * internally) will be reverted. If there is any mapping in the new config fails to be mapped, the
+ * reverted last config will be reverted again. i.e. This function will keep the mapping state the
+ * same as before calling it on any error happens. But if the IOMMU state is somehow corrupted and
+ * hence fails to roll back the reverted last image config, only an error is logged. See the pseudo
+ * code below:
+ *
+ * gcip_image_config_parse(config):
+ * unmap(last_image_config)
+ * if ret = map(config) fails:
+ * LOG("Failed to map image config, rolling back to the last image config.")
+ * if map(last_image_config) fails:
+ * LOG("Failed to roll back the last image config.")
+ * return ret
+ * else:
+ * last_image_config = config
+ * return SUCCESS
+ *
+ * A special case being considered is if the content of @config is identical to the last
+ * successfully parsed image config, this function will return 0 immediately without removing /
+ * adding any mapping.
+ *
+ * Returns 0 on success. Otherwise an errno, which usually would be the one returned by
+ * gcip_image_config_ops.map. On error no new mapping specified in @config is added.
+ */
+int gcip_image_config_parse(struct gcip_image_config_parser *parser,
+ struct gcip_image_config *config);
+
+/*
+ * Clears the mappings specified in the last image config.
+ *
+ * It's valid to call this function without any image config has been successfully parsed, or when
+ * the last image config is already cleared. In which case this function works as no-op.
+ */
+void gcip_image_config_clear(struct gcip_image_config_parser *parser);
+
+/*
+ * Returns whether the privilege level specified by @config is non-secure.
+ */
+static inline bool gcip_image_config_is_ns(struct gcip_image_config *config)
+{
+ return config->privilege_level == GCIP_FW_PRIV_LEVEL_NS;
+}
+
+#endif /* __GCIP_IMAGE_CONFIG_H__ */