Lines Matching +full:isp +full:- +full:0
1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2013--2024 Intel Corporation
9 #include <linux/dma-mapping.h>
16 #include "ipu6-bus.h"
17 #include "ipu6-cpd.h"
18 #include "ipu6-dma.h"
28 #define PKG_DIR_HDR_MARK 0x5f4955504b44525fULL
31 #define CPD_HDR_MARK 0x44504324
37 #define MAX_COMPONENT_VERSION 0xffff
39 #define MANIFEST_IDX 0
44 * 63:56 55 54:48 47:32 31:24 23:0
47 #define PKG_DIR_SIZE_MASK GENMASK_ULL(23, 0)
57 ent = (const struct ipu6_cpd_ent *)((const u8 *)cpd + cpd_hdr->hdr_len); in ipu6_cpd_get_entry()
66 ipu6_cpd_metadata_get_cmpnt(struct ipu6_device *isp, const void *metadata, in ipu6_cpd_metadata_get_cmpnt() argument
70 size_t cmpnt_count = metadata_size - extn_size; in ipu6_cpd_metadata_get_cmpnt()
72 cmpnt_count = div_u64(cmpnt_count, isp->cpd_metadata_cmpnt_size); in ipu6_cpd_metadata_get_cmpnt()
75 dev_err(&isp->pdev->dev, "Component index out of range (%d)\n", in ipu6_cpd_metadata_get_cmpnt()
77 return ERR_PTR(-EINVAL); in ipu6_cpd_metadata_get_cmpnt()
80 return metadata + extn_size + idx * isp->cpd_metadata_cmpnt_size; in ipu6_cpd_metadata_get_cmpnt()
83 static u32 ipu6_cpd_metadata_cmpnt_version(struct ipu6_device *isp, in ipu6_cpd_metadata_cmpnt_version() argument
89 cmpnt = ipu6_cpd_metadata_get_cmpnt(isp, metadata, metadata_size, idx); in ipu6_cpd_metadata_cmpnt_version()
93 return cmpnt->ver; in ipu6_cpd_metadata_cmpnt_version()
96 static int ipu6_cpd_metadata_get_cmpnt_id(struct ipu6_device *isp, in ipu6_cpd_metadata_get_cmpnt_id() argument
102 cmpnt = ipu6_cpd_metadata_get_cmpnt(isp, metadata, metadata_size, idx); in ipu6_cpd_metadata_get_cmpnt_id()
106 return cmpnt->id; in ipu6_cpd_metadata_get_cmpnt_id()
109 static int ipu6_cpd_parse_module_data(struct ipu6_device *isp, in ipu6_cpd_parse_module_data() argument
123 return -EINVAL; in ipu6_cpd_parse_module_data()
126 dir_hdr = module_data + module_data_hdr->hdr_len; in ipu6_cpd_parse_module_data()
127 len = dir_hdr->hdr_len; in ipu6_cpd_parse_module_data()
130 pkg_dir[0] = PKG_DIR_HDR_MARK; in ipu6_cpd_parse_module_data()
132 pkg_dir[1] = dir_hdr->ent_cnt + 1; in ipu6_cpd_parse_module_data()
134 for (i = 0; i < dir_hdr->ent_cnt; i++, dir_ent++) { in ipu6_cpd_parse_module_data()
138 *p++ = dma_addr_module_data + dir_ent->offset; in ipu6_cpd_parse_module_data()
139 id = ipu6_cpd_metadata_get_cmpnt_id(isp, metadata, in ipu6_cpd_parse_module_data()
141 if (id < 0 || id > MAX_COMPONENT_ID) { in ipu6_cpd_parse_module_data()
142 dev_err(&isp->pdev->dev, "Invalid CPD component id\n"); in ipu6_cpd_parse_module_data()
143 return -EINVAL; in ipu6_cpd_parse_module_data()
146 ver = ipu6_cpd_metadata_cmpnt_version(isp, metadata, in ipu6_cpd_parse_module_data()
148 if (ver < 0 || ver > MAX_COMPONENT_VERSION) { in ipu6_cpd_parse_module_data()
149 dev_err(&isp->pdev->dev, in ipu6_cpd_parse_module_data()
151 return -EINVAL; in ipu6_cpd_parse_module_data()
154 *p = FIELD_PREP(PKG_DIR_SIZE_MASK, dir_ent->len) | in ipu6_cpd_parse_module_data()
159 return 0; in ipu6_cpd_parse_module_data()
164 dma_addr_t dma_addr_src = sg_dma_address(adev->fw_sgt.sgl); in ipu6_cpd_create_pkg_dir()
166 struct ipu6_device *isp = adev->isp; in ipu6_cpd_create_pkg_dir() local
172 man_sz = man_ent->len; in ipu6_cpd_create_pkg_dir()
175 met_sz = met_ent->len; in ipu6_cpd_create_pkg_dir()
177 adev->pkg_dir_size = PKG_DIR_SIZE + man_sz + met_sz; in ipu6_cpd_create_pkg_dir()
178 adev->pkg_dir = ipu6_dma_alloc(adev, adev->pkg_dir_size, in ipu6_cpd_create_pkg_dir()
179 &adev->pkg_dir_dma_addr, GFP_KERNEL, 0); in ipu6_cpd_create_pkg_dir()
180 if (!adev->pkg_dir) in ipu6_cpd_create_pkg_dir()
181 return -ENOMEM; in ipu6_cpd_create_pkg_dir()
185 * qword | 63:56 | 55 | 54:48 | 47:32 | 31:24 | 23:0 in ipu6_cpd_create_pkg_dir()
190 * are 0 anyway. Just setting size for now. in ipu6_cpd_create_pkg_dir()
195 ret = ipu6_cpd_parse_module_data(isp, src + ent->offset, in ipu6_cpd_create_pkg_dir()
196 ent->len, dma_addr_src + ent->offset, in ipu6_cpd_create_pkg_dir()
197 adev->pkg_dir, src + met_ent->offset, in ipu6_cpd_create_pkg_dir()
198 met_ent->len); in ipu6_cpd_create_pkg_dir()
200 dev_err(&isp->pdev->dev, "Failed to parse module data\n"); in ipu6_cpd_create_pkg_dir()
201 ipu6_dma_free(adev, adev->pkg_dir_size, in ipu6_cpd_create_pkg_dir()
202 adev->pkg_dir, adev->pkg_dir_dma_addr, 0); in ipu6_cpd_create_pkg_dir()
207 pkg_dir_pos = adev->pkg_dir + PKG_DIR_ENT_LEN * MAX_PKG_DIR_ENT_CNT; in ipu6_cpd_create_pkg_dir()
208 memcpy(pkg_dir_pos, src + man_ent->offset, man_sz); in ipu6_cpd_create_pkg_dir()
212 memcpy(pkg_dir_pos, src + met_ent->offset, met_sz); in ipu6_cpd_create_pkg_dir()
214 ipu6_dma_sync_single(adev, adev->pkg_dir_dma_addr, in ipu6_cpd_create_pkg_dir()
215 adev->pkg_dir_size); in ipu6_cpd_create_pkg_dir()
217 return 0; in ipu6_cpd_create_pkg_dir()
223 ipu6_dma_free(adev, adev->pkg_dir_size, adev->pkg_dir, in ipu6_cpd_free_pkg_dir()
224 adev->pkg_dir_dma_addr, 0); in ipu6_cpd_free_pkg_dir()
228 static int ipu6_cpd_validate_cpd(struct ipu6_device *isp, const void *cpd, in ipu6_cpd_validate_cpd() argument
237 len = cpd_hdr->hdr_len; in ipu6_cpd_validate_cpd()
241 dev_err(&isp->pdev->dev, "Invalid CPD moduledata size\n"); in ipu6_cpd_validate_cpd()
242 return -EINVAL; in ipu6_cpd_validate_cpd()
246 if ((cpd_size - len) / sizeof(*ent) < cpd_hdr->ent_cnt) { in ipu6_cpd_validate_cpd()
247 dev_err(&isp->pdev->dev, "Invalid CPD header\n"); in ipu6_cpd_validate_cpd()
248 return -EINVAL; in ipu6_cpd_validate_cpd()
253 for (i = 0; i < cpd_hdr->ent_cnt; i++, ent++) { in ipu6_cpd_validate_cpd()
254 if (data_size < ent->offset || in ipu6_cpd_validate_cpd()
255 data_size - ent->offset < ent->len) { in ipu6_cpd_validate_cpd()
256 dev_err(&isp->pdev->dev, "Invalid CPD entry (%d)\n", i); in ipu6_cpd_validate_cpd()
257 return -EINVAL; in ipu6_cpd_validate_cpd()
261 return 0; in ipu6_cpd_validate_cpd()
264 static int ipu6_cpd_validate_moduledata(struct ipu6_device *isp, in ipu6_cpd_validate_moduledata() argument
273 moduledata_size < mod_hdr->hdr_len) { in ipu6_cpd_validate_moduledata()
274 dev_err(&isp->pdev->dev, "Invalid CPD moduledata size\n"); in ipu6_cpd_validate_moduledata()
275 return -EINVAL; in ipu6_cpd_validate_moduledata()
278 dev_info(&isp->pdev->dev, "FW version: %x\n", mod_hdr->fw_pkg_date); in ipu6_cpd_validate_moduledata()
279 ret = ipu6_cpd_validate_cpd(isp, moduledata + mod_hdr->hdr_len, in ipu6_cpd_validate_moduledata()
280 moduledata_size - mod_hdr->hdr_len, in ipu6_cpd_validate_moduledata()
283 dev_err(&isp->pdev->dev, "Invalid CPD in moduledata\n"); in ipu6_cpd_validate_moduledata()
287 return 0; in ipu6_cpd_validate_moduledata()
290 static int ipu6_cpd_validate_metadata(struct ipu6_device *isp, in ipu6_cpd_validate_metadata() argument
297 dev_err(&isp->pdev->dev, "Invalid CPD metadata\n"); in ipu6_cpd_validate_metadata()
298 return -EINVAL; in ipu6_cpd_validate_metadata()
302 if (extn->extn_type != IPU6_CPD_METADATA_EXTN_TYPE_IUNIT || in ipu6_cpd_validate_metadata()
303 extn->img_type != IPU6_CPD_METADATA_IMAGE_TYPE_MAIN_FIRMWARE) { in ipu6_cpd_validate_metadata()
304 dev_err(&isp->pdev->dev, in ipu6_cpd_validate_metadata()
306 extn->img_type); in ipu6_cpd_validate_metadata()
307 return -EINVAL; in ipu6_cpd_validate_metadata()
311 if ((meta_size - sizeof(*extn)) % isp->cpd_metadata_cmpnt_size) { in ipu6_cpd_validate_metadata()
312 dev_err(&isp->pdev->dev, "Invalid CPD metadata size\n"); in ipu6_cpd_validate_metadata()
313 return -EINVAL; in ipu6_cpd_validate_metadata()
316 return 0; in ipu6_cpd_validate_metadata()
319 int ipu6_cpd_validate_cpd_file(struct ipu6_device *isp, const void *cpd_file, in ipu6_cpd_validate_cpd_file() argument
326 ret = ipu6_cpd_validate_cpd(isp, cpd_file, cpd_file_size, in ipu6_cpd_validate_cpd_file()
329 dev_err(&isp->pdev->dev, "Invalid CPD in file\n"); in ipu6_cpd_validate_cpd_file()
334 if (hdr->hdr_mark != CPD_HDR_MARK) { in ipu6_cpd_validate_cpd_file()
335 dev_err(&isp->pdev->dev, "Invalid CPD header\n"); in ipu6_cpd_validate_cpd_file()
336 return -EINVAL; in ipu6_cpd_validate_cpd_file()
341 if (ent->len > MAX_MANIFEST_SIZE) { in ipu6_cpd_validate_cpd_file()
342 dev_err(&isp->pdev->dev, "Invalid CPD manifest size\n"); in ipu6_cpd_validate_cpd_file()
343 return -EINVAL; in ipu6_cpd_validate_cpd_file()
348 ret = ipu6_cpd_validate_metadata(isp, cpd_file + ent->offset, ent->len); in ipu6_cpd_validate_cpd_file()
350 dev_err(&isp->pdev->dev, "Invalid CPD metadata\n"); in ipu6_cpd_validate_cpd_file()
356 ret = ipu6_cpd_validate_moduledata(isp, cpd_file + ent->offset, in ipu6_cpd_validate_cpd_file()
357 ent->len); in ipu6_cpd_validate_cpd_file()
359 dev_err(&isp->pdev->dev, "Invalid CPD moduledata\n"); in ipu6_cpd_validate_cpd_file()