msm: camera: icp: Add support for non secure FW load

Starting from waipio, ICP [lx7] FW is to loaded using
secure PIL. For debug purposes also added support for
non secure image loading for lx7.

CRs-Fixed: 2722486
Change-Id: I30026fb8e65f323ab73336e0ae787a2359bc934f
Signed-off-by: Karthik Anantha Ram <kartanan@codeaurora.org>
This commit is contained in:
Karthik Anantha Ram
2021-01-13 17:31:10 -08:00
parent 131c340861
commit a503554e2f
11 changed files with 515 additions and 142 deletions

View File

@@ -0,0 +1,142 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include "cam_icp_utils.h"
int32_t cam_icp_validate_fw(const uint8_t *elf,
uint32_t machine_id)
{
struct elf32_hdr *elf_hdr;
if (!elf) {
CAM_ERR(CAM_ICP, "Invalid params");
return -EINVAL;
}
elf_hdr = (struct elf32_hdr *)elf;
if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG)) {
CAM_ERR(CAM_ICP, "ICP elf identifier is failed");
return -EINVAL;
}
/* check architecture */
if (elf_hdr->e_machine != machine_id) {
CAM_ERR(CAM_ICP, "unsupported arch: 0x%x", elf_hdr->e_machine);
return -EINVAL;
}
/* check elf bit format */
if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
CAM_ERR(CAM_ICP, "elf doesn't support 32 bit format");
return -EINVAL;
}
return 0;
}
int32_t cam_icp_get_fw_size(
const uint8_t *elf, uint32_t *fw_size,
struct cam_icp_proc_params *params)
{
int32_t rc = 0;
int32_t i = 0;
uint32_t num_prg_hdrs;
unsigned char *icp_prg_hdr_tbl;
uint32_t seg_mem_size = 0;
struct elf32_hdr *elf_hdr;
struct elf32_phdr *prg_hdr;
if (!elf || !fw_size || !params) {
CAM_ERR(CAM_ICP, "invalid args");
return -EINVAL;
}
*fw_size = 0;
elf_hdr = (struct elf32_hdr *)elf;
num_prg_hdrs = elf_hdr->e_phnum;
icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff;
prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
if (!prg_hdr) {
CAM_ERR(CAM_ICP, "failed to get elf program header attr");
return -EINVAL;
}
CAM_DBG(CAM_ICP, "num_prg_hdrs = %d", num_prg_hdrs);
for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) {
if (prg_hdr->p_flags == 0)
continue;
if ((params->skip_seg) &&
((prg_hdr->p_vaddr == params->vaddr[0]) ||
(prg_hdr->p_vaddr == params->vaddr[1])))
continue;
seg_mem_size = (prg_hdr->p_memsz + prg_hdr->p_align - 1) &
~(prg_hdr->p_align - 1);
seg_mem_size += prg_hdr->p_vaddr;
CAM_DBG(CAM_ICP, "memsz:%x align:%x addr:%x seg_mem_size:%x",
(int)prg_hdr->p_memsz, (int)prg_hdr->p_align,
(int)prg_hdr->p_vaddr, (int)seg_mem_size);
if (*fw_size < seg_mem_size)
*fw_size = seg_mem_size;
}
if (*fw_size == 0) {
CAM_ERR(CAM_ICP, "invalid elf fw file");
return -EINVAL;
}
return rc;
}
int32_t cam_icp_program_fw(const uint8_t *elf,
uintptr_t fw_kva_addr,
struct cam_icp_proc_params *params)
{
int32_t rc = 0;
uint32_t num_prg_hdrs;
unsigned char *icp_prg_hdr_tbl;
int32_t i = 0;
u8 *dest;
u8 *src;
struct elf32_hdr *elf_hdr;
struct elf32_phdr *prg_hdr;
elf_hdr = (struct elf32_hdr *)elf;
num_prg_hdrs = elf_hdr->e_phnum;
icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff;
prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
if (!prg_hdr) {
CAM_ERR(CAM_ICP, "failed to get elf program header attr");
return -EINVAL;
}
for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) {
if (prg_hdr->p_flags == 0)
continue;
if ((params->skip_seg) &&
((prg_hdr->p_vaddr == params->vaddr[0]) ||
(prg_hdr->p_vaddr == params->vaddr[1])))
continue;
CAM_DBG(CAM_ICP, "Loading FW header size: %u",
prg_hdr->p_filesz);
if (prg_hdr->p_filesz != 0) {
src = (u8 *)((u8 *)elf + prg_hdr->p_offset);
dest = (u8 *)(((u8 *)fw_kva_addr) +
prg_hdr->p_vaddr);
memcpy_toio(dest, src, prg_hdr->p_filesz);
}
}
return rc;
}