From: Antti Laakso <antti.laakso@linux.intel.com>
To: linux-media@vger.kernel.org, mchehab@kernel.org,
sakari.ailus@linux.intel.com
Cc: daxing.li@intel.com, ong.hock.yu@intel.com, antti.laakso@linux.intel.com
Subject: [PATCH v2 15/44] media: ipu6: Add ipu7 cpd handling
Date: Fri, 21 Aug 2026 14:42:33 +0300 [thread overview]
Message-ID: <20260821114302.365532-16-antti.laakso@linux.intel.com> (raw)
In-Reply-To: <20260821114302.365532-1-antti.laakso@linux.intel.com>
The firmware format differs slightly between ipu6 and ipu7.
Add support for ipu7 firmware validation and handling.
Signed-off-by: Antti Laakso <antti.laakso@linux.intel.com>
---
drivers/media/pci/intel/ipu6/ipu6-cpd.c | 169 +++++++++++++++++++++---
drivers/media/pci/intel/ipu6/ipu6-cpd.h | 43 ++++++
2 files changed, 197 insertions(+), 15 deletions(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-cpd.c b/drivers/media/pci/intel/ipu6/ipu6-cpd.c
index 966a16a300f8..8e59406a725c 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-cpd.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-cpd.c
@@ -16,6 +16,7 @@
#include "ipu6-bus.h"
#include "ipu6-cpd.h"
#include "ipu6-dma.h"
+#include "ipu7-mmu-hw.h"
/* 15 entries + header*/
#define MAX_PKG_DIR_ENT_CNT 16
@@ -62,6 +63,20 @@ static inline const struct ipu6_cpd_ent *ipu6_cpd_get_entry(const void *cpd,
#define ipu6_cpd_get_metadata(cpd) ipu6_cpd_get_entry(cpd, METADATA_IDX)
#define ipu6_cpd_get_moduledata(cpd) ipu6_cpd_get_entry(cpd, MODULEDATA_IDX)
+#define IPU7_CPD_BINARY_START_IDX 1U
+#define IPU7_CPD_METADATA_START_IDX 2U
+#define IPU7_CPD_BINARY_NUM 2U /* ISYS + PSYS */
+#define IPU7_CPD_METADATA_ATTR 0xa
+#define IPU7_CPD_METADATA_IPL 0x1c
+/*
+ * Entries include:
+ * 1 manifest entry.
+ * 1 metadata entry for each sub system(ISYS and PSYS).
+ * 1 binary entry for each sub system(ISYS and PSYS).
+ */
+#define IPU7_CPD_ENTRY_NUM (IPU7_CPD_BINARY_NUM * 2U + 1U)
+#define IPU7_MAX_MANIFEST_SIZE (SZ_4K * sizeof(u32))
+
static const struct ipu6_cpd_metadata_cmpnt_hdr *
ipu6_cpd_metadata_get_cmpnt(struct ipu6_device *isp, const void *metadata,
unsigned int metadata_size, u8 idx)
@@ -309,39 +324,163 @@ static int ipu6_cpd_validate_metadata(struct ipu6_device *isp,
return 0;
}
-int ipu6_cpd_validate_cpd_file(struct ipu6_device *isp, const void *cpd_file,
- unsigned long cpd_file_size)
+static struct ipu7_cpd_metadata *ipu7_cpd_get_metadata(const void *cpd, int idx)
{
- const struct ipu6_cpd_hdr *hdr = cpd_file;
- const struct ipu6_cpd_ent *ent;
- int ret;
+ const struct ipu6_cpd_ent *cpd_ent =
+ ipu6_cpd_get_entry(cpd, IPU7_CPD_METADATA_START_IDX + idx * 2);
- ret = ipu6_cpd_validate_cpd(isp, cpd_file, cpd_file_size,
- cpd_file_size);
- if (ret)
- return ret;
+ return (struct ipu7_cpd_metadata *)((u8 *)cpd + cpd_ent->offset);
+}
- /* Check for CPD file marker */
- if (hdr->hdr_mark != CPD_HDR_MARK) {
- dev_err(&isp->pdev->dev, "Invalid CPD header\n");
+static int ipu7_cpd_validate_metadata(struct ipu6_device *isp,
+ const void *cpd, int idx)
+{
+ const struct ipu6_cpd_ent *cpd_ent =
+ ipu6_cpd_get_entry(cpd, IPU7_CPD_METADATA_START_IDX + idx * 2);
+ const struct ipu6_cpd_ent *bin_ent =
+ ipu6_cpd_get_entry(cpd, IPU7_CPD_BINARY_START_IDX + idx * 2);
+ const struct ipu7_cpd_metadata *metadata =
+ ipu7_cpd_get_metadata(cpd, idx);
+ struct device *dev = &isp->pdev->dev;
+ u32 offset;
+
+ /* Sanity check for metadata size */
+ if (cpd_ent->len != sizeof(struct ipu7_cpd_metadata)) {
+ dev_err(dev, "Invalid metadata size\n");
+ return -EINVAL;
+ }
+
+ /* Validate type and length of metadata sections */
+ if (metadata->attr.hdr.type != IPU7_CPD_METADATA_ATTR) {
+ dev_err(dev, "Invalid metadata attr type (%d)\n",
+ metadata->attr.hdr.type);
return -EINVAL;
}
+ if (metadata->attr.hdr.len != sizeof(struct ipu7_cpd_metadata_attr)) {
+ dev_err(dev, "Invalid metadata attr size (%d)\n",
+ metadata->attr.hdr.len);
+ return -EINVAL;
+ }
+ if (metadata->ipl.hdr.type != IPU7_CPD_METADATA_IPL) {
+ dev_err(dev, "Invalid metadata ipl type (%d)\n",
+ metadata->ipl.hdr.type);
+ return -EINVAL;
+ }
+ if (metadata->ipl.hdr.len != sizeof(struct ipu7_cpd_metadata_ipl)) {
+ dev_err(dev, "Invalid metadata ipl size (%d)\n",
+ metadata->ipl.hdr.len);
+ return -EINVAL;
+ }
+
+ offset = metadata->ipl.param[0];
+ if (offset > IPU7_FW_CODE_REGION_SIZE ||
+ bin_ent->len > IPU7_FW_CODE_REGION_SIZE - offset) {
+ dev_err(dev, "Incorrect binary size %u and offset %u\n",
+ bin_ent->len, offset);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __ipu7_validate_cpd_file(struct ipu6_device *isp, const void *cpd_file,
+ unsigned long cpd_file_size)
+{
+ const struct ipu6_cpd_ent *ent;
+ const struct ipu7_cpd_hdr *hdr = cpd_file;
+ unsigned int i;
- /* Sanity check for manifest size */
ent = ipu6_cpd_get_manifest(cpd_file);
- if (ent->len > MAX_MANIFEST_SIZE) {
+ if (ent->len > IPU7_MAX_MANIFEST_SIZE) {
dev_err(&isp->pdev->dev, "Invalid CPD manifest size\n");
return -EINVAL;
}
+ /* Sanity check for CPD entry header */
+ if (hdr->ent_cnt != IPU7_CPD_ENTRY_NUM) {
+ dev_err(&isp->pdev->dev, "Invalid CPD entry number %d\n",
+ hdr->ent_cnt);
+ return -EINVAL;
+ }
/* Validate metadata */
+ for (i = 0; i < IPU7_CPD_BINARY_NUM; i++) {
+ int ret = ipu7_cpd_validate_metadata(isp, cpd_file, i);
+
+ if (ret) {
+ dev_err(&isp->pdev->dev, "Invalid metadata(%d)\n", i);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int __ipu6_validate_cpd_file(struct ipu6_device *isp, const void *cpd_file,
+ unsigned long cpd_file_size)
+{
+ const struct ipu6_cpd_ent *ent;
+ int ret;
+
+ ent = ipu6_cpd_get_manifest(cpd_file);
+ if (ent->len > MAX_MANIFEST_SIZE) {
+ dev_err(&isp->pdev->dev, "Invalid CPD manifest size\n");
+ return -EINVAL;
+ }
+
ent = ipu6_cpd_get_metadata(cpd_file);
ret = ipu6_cpd_validate_metadata(isp, cpd_file + ent->offset, ent->len);
if (ret)
return ret;
- /* Validate moduledata */
ent = ipu6_cpd_get_moduledata(cpd_file);
return ipu6_cpd_validate_moduledata(isp, cpd_file + ent->offset,
ent->len);
}
+
+int ipu6_cpd_validate_cpd_file(struct ipu6_device *isp, const void *cpd_file,
+ unsigned long cpd_file_size)
+{
+ const struct ipu6_cpd_hdr *hdr = cpd_file;
+ int ret;
+
+ ret = ipu6_cpd_validate_cpd(isp, cpd_file, cpd_file_size,
+ cpd_file_size);
+ if (ret)
+ return ret;
+
+ /* Check for CPD file marker */
+ if (hdr->hdr_mark != CPD_HDR_MARK) {
+ dev_err(&isp->pdev->dev, "Invalid CPD header\n");
+ return -EINVAL;
+ }
+
+ if (IS_IPU7(isp))
+ return __ipu7_validate_cpd_file(isp, cpd_file, cpd_file_size);
+
+ return __ipu6_validate_cpd_file(isp, cpd_file, cpd_file_size);
+}
+
+int ipu7_cpd_copy_binary(const void *cpd, const char *name, void *dst,
+ u32 *entry)
+{
+ unsigned int i;
+
+ for (i = 0; i < IPU7_CPD_BINARY_NUM; i++) {
+ const struct ipu7_cpd_metadata *metadata;
+ u8 idx = IPU7_CPD_BINARY_START_IDX + i * 2U;
+ const struct ipu6_cpd_ent *ent =
+ ipu6_cpd_get_entry(cpd, idx);
+
+ if (strncmp(ent->name, name, sizeof(ent->name)))
+ continue;
+
+ metadata = ipu7_cpd_get_metadata(cpd, i);
+ memcpy(dst + metadata->ipl.param[0], cpd + ent->offset,
+ ent->len);
+ *entry = metadata->ipl.param[2];
+
+ return 0;
+ }
+
+ return -ENOENT;
+}
+EXPORT_SYMBOL_NS_GPL(ipu7_cpd_copy_binary, "INTEL_IPU6");
diff --git a/drivers/media/pci/intel/ipu6/ipu6-cpd.h b/drivers/media/pci/intel/ipu6/ipu6-cpd.h
index e0e4fdeca902..b614ed0004bb 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-cpd.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-cpd.h
@@ -98,8 +98,51 @@ struct ipu6_cpd_client_pkg_hdr {
u32 prog_bin_size;
} __packed;
+/* IPU7 */
+
+struct ipu7_cpd_hdr {
+ u32 hdr_mark;
+ u32 ent_cnt;
+ u8 hdr_ver;
+ u8 ent_ver;
+ u8 hdr_len;
+ u8 rsvd;
+ u8 partition_name[4];
+ u32 crc32;
+} __packed;
+
+struct ipu7_cpd_metadata_hdr {
+ u32 type;
+ u32 len;
+} __packed;
+
+struct ipu7_cpd_metadata_attr {
+ struct ipu7_cpd_metadata_hdr hdr;
+ u8 compression_type;
+ u8 encryption_type;
+ u8 rsvd[2];
+ u32 uncompressed_size;
+ u32 compressed_size;
+ u32 module_id;
+ u8 hash[48];
+} __packed;
+
+struct ipu7_cpd_metadata_ipl {
+ struct ipu7_cpd_metadata_hdr hdr;
+ u32 param[4];
+ u8 rsvd[8];
+} __packed;
+
+struct ipu7_cpd_metadata {
+ struct ipu7_cpd_metadata_attr attr;
+ struct ipu7_cpd_metadata_ipl ipl;
+} __packed;
+
int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src);
void ipu6_cpd_free_pkg_dir(struct ipu6_bus_device *adev);
int ipu6_cpd_validate_cpd_file(struct ipu6_device *isp, const void *cpd_file,
unsigned long cpd_file_size);
+int ipu7_cpd_copy_binary(const void *cpd, const char *name, void *dst,
+ u32 *entry);
+
#endif /* IPU6_CPD_H */
--
2.55.0
next prev parent reply other threads:[~2026-08-21 11:44 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 11:42 [PATCH v2 00/44] media: ipu6: Add support for ipu7 hardware Antti Laakso
2026-08-21 11:42 ` [PATCH v2 01/44] media: ipu6: Add helpers for IPU runtime variation Antti Laakso
2026-08-21 11:42 ` [PATCH v2 02/44] media: ipu6: Rename pointer to firmware context Antti Laakso
2026-08-21 11:42 ` [PATCH v2 03/44] media: ipu6: Rename buttress_ipc pointer Antti Laakso
2026-08-21 11:42 ` [PATCH v2 04/44] media: ipu6: Remove duplicate warnings in cpd validation Antti Laakso
2026-08-21 11:42 ` [PATCH v2 05/44] media: ipu6: Remove unused ipu6 firmware struct Antti Laakso
2026-08-21 11:42 ` [PATCH v2 06/44] media: ipu6: Cleanup ipu6_mmu_init() Antti Laakso
2026-08-21 11:42 ` [PATCH v2 07/44] media: ipu6: Simplify firmware com arguments Antti Laakso
2026-08-21 11:42 ` [PATCH v2 08/44] media: ipu6: Add helper to identify ipu7 Antti Laakso
2026-08-21 11:42 ` [PATCH v2 09/44] media: ipu6: Prepare buttress for ipu7 support Antti Laakso
2026-08-21 11:42 ` [PATCH v2 10/44] media: ipu6: Use single struct for registers Antti Laakso
2026-08-21 11:42 ` [PATCH v2 11/44] media: ipu6: Rename IPU subsys ID Antti Laakso
2026-08-21 11:42 ` [PATCH v2 12/44] media: ipu6: Add ipu7 buttress support Antti Laakso
2026-08-21 11:42 ` [PATCH v2 13/44] media: ipu6: Prepare mmu driver for hw variation Antti Laakso
2026-08-21 11:42 ` [PATCH v2 14/44] media: ipu6: Add ipu7 mmu support Antti Laakso
2026-08-21 11:42 ` Antti Laakso [this message]
2026-08-21 11:42 ` [PATCH v2 16/44] media: ipu6: Add check for pkg_dir before freeing Antti Laakso
2026-08-21 11:42 ` [PATCH v2 17/44] media: ipu6: Rename isys fw msg union Antti Laakso
2026-08-21 11:42 ` [PATCH v2 18/44] media: ipu6: Move isys isr handlers to fw file Antti Laakso
2026-08-21 11:42 ` [PATCH v2 19/44] media: ipu6: Move hw specific buffer handling down Antti Laakso
2026-08-21 11:42 ` [PATCH v2 20/44] media: ipu6: Isolate hw specific buffer handling Antti Laakso
2026-08-21 11:42 ` [PATCH v2 21/44] media: ipu6: Add isys firmware ops Antti Laakso
2026-08-21 11:42 ` [PATCH v2 22/44] media: ipu6: Add ipu7 fw start/stop functionality Antti Laakso
2026-08-21 11:42 ` [PATCH v2 23/44] media: ipu6: Add ipu7 fw com methods Antti Laakso
2026-08-21 11:42 ` [PATCH v2 24/44] media: ipu6: Add ipu7 fw isys ops Antti Laakso
2026-08-21 11:42 ` [PATCH v2 25/44] media: ipu6: Add ipu7 csi2 register definitions Antti Laakso
2026-08-21 11:42 ` [PATCH v2 26/44] media: ipu6: Add ipu7 isr handler Antti Laakso
2026-08-21 11:42 ` [PATCH v2 27/44] media: ipu6: Add ipu7 csi phy driver Antti Laakso
2026-08-21 11:42 ` [PATCH v2 28/44] media: ipu6: Split ipu6 csi2 stream enable/disable Antti Laakso
2026-08-21 11:42 ` [PATCH v2 29/44] media: ipu6: Add support for ipu7 csi2 receiver Antti Laakso
2026-08-21 11:42 ` [PATCH v2 30/44] media: ipu6: Parse bus type for ipu7 Antti Laakso
2026-08-21 11:42 ` [PATCH v2 31/44] media: ipu6: Enable ipu7 isys interrupts Antti Laakso
2026-08-21 11:42 ` [PATCH v2 32/44] media: ipu6: Skip watermark configuration for ipu7 Antti Laakso
2026-08-21 11:42 ` [PATCH v2 33/44] media: ipu6: The SPC init is valid only for ipu6 Antti Laakso
2026-08-21 11:42 ` [PATCH v2 34/44] media: ipu6: The VC arbitration mechanism is ipu6 only Antti Laakso
2026-08-21 11:42 ` [PATCH v2 35/44] media: ipu6: Move buttress mem alloc out from probe Antti Laakso
2026-08-21 11:42 ` [PATCH v2 36/44] media: ipu6: Read correct SKU ID for ipu7 Antti Laakso
2026-08-21 11:42 ` [PATCH v2 37/44] media: ipu6: Add support for fixed iova region Antti Laakso
2026-08-21 11:42 ` [PATCH v2 38/44] media: ipu6: Make fw mapping function reusable Antti Laakso
2026-08-21 11:42 ` [PATCH v2 39/44] media: ipu6: Move isys fw mapping to pci_probe Antti Laakso
2026-08-21 18:17 ` Sakari Ailus
2026-08-21 11:42 ` [PATCH v2 40/44] media: ipu6: Map ipu7 firmware Antti Laakso
2026-08-21 18:23 ` Sakari Ailus
2026-08-26 6:56 ` Antti Laakso
2026-08-26 7:54 ` Sakari Ailus
2026-08-21 11:42 ` [PATCH v2 41/44] media: ipu6: Set model name for ipu7 Antti Laakso
2026-08-21 11:43 ` [PATCH v2 42/44] media: ipu6: Add ipu7.5 buttress support Antti Laakso
2026-08-21 11:43 ` [PATCH v2 43/44] media: ipu6: Add ipu7.5 mmu initialization data Antti Laakso
2026-08-21 11:43 ` [PATCH v2 44/44] media: ipu6: Enable ipu7 and ipu7.5 Antti Laakso
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260821114302.365532-16-antti.laakso@linux.intel.com \
--to=antti.laakso@linux.intel.com \
--cc=daxing.li@intel.com \
--cc=linux-media@vger.kernel.org \
--cc=mchehab@kernel.org \
--cc=ong.hock.yu@intel.com \
--cc=sakari.ailus@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.