cam_icp_utils.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include "cam_icp_utils.h"
  6. int32_t cam_icp_validate_fw(const uint8_t *elf,
  7. uint32_t machine_id)
  8. {
  9. struct elf32_hdr *elf_hdr;
  10. if (!elf) {
  11. CAM_ERR(CAM_ICP, "Invalid params");
  12. return -EINVAL;
  13. }
  14. elf_hdr = (struct elf32_hdr *)elf;
  15. if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG)) {
  16. CAM_ERR(CAM_ICP, "ICP elf identifier is failed");
  17. return -EINVAL;
  18. }
  19. /* check architecture */
  20. if (elf_hdr->e_machine != machine_id) {
  21. CAM_ERR(CAM_ICP, "unsupported arch: 0x%x", elf_hdr->e_machine);
  22. return -EINVAL;
  23. }
  24. /* check elf bit format */
  25. if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
  26. CAM_ERR(CAM_ICP, "elf doesn't support 32 bit format");
  27. return -EINVAL;
  28. }
  29. return 0;
  30. }
  31. int32_t cam_icp_get_fw_size(
  32. const uint8_t *elf, uint32_t *fw_size,
  33. struct cam_icp_proc_params *params)
  34. {
  35. int32_t rc = 0;
  36. int32_t i = 0;
  37. uint32_t num_prg_hdrs;
  38. unsigned char *icp_prg_hdr_tbl;
  39. uint32_t seg_mem_size = 0;
  40. struct elf32_hdr *elf_hdr;
  41. struct elf32_phdr *prg_hdr;
  42. if (!elf || !fw_size || !params) {
  43. CAM_ERR(CAM_ICP, "invalid args");
  44. return -EINVAL;
  45. }
  46. *fw_size = 0;
  47. elf_hdr = (struct elf32_hdr *)elf;
  48. num_prg_hdrs = elf_hdr->e_phnum;
  49. icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff;
  50. prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
  51. if (!prg_hdr) {
  52. CAM_ERR(CAM_ICP, "failed to get elf program header attr");
  53. return -EINVAL;
  54. }
  55. CAM_DBG(CAM_ICP, "num_prg_hdrs = %d", num_prg_hdrs);
  56. for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) {
  57. if (prg_hdr->p_flags == 0)
  58. continue;
  59. if ((params->skip_seg) &&
  60. ((prg_hdr->p_vaddr == params->vaddr[0]) ||
  61. (prg_hdr->p_vaddr == params->vaddr[1])))
  62. continue;
  63. seg_mem_size = (prg_hdr->p_memsz + prg_hdr->p_align - 1) &
  64. ~(prg_hdr->p_align - 1);
  65. seg_mem_size += prg_hdr->p_vaddr;
  66. CAM_DBG(CAM_ICP, "memsz:%x align:%x addr:%x seg_mem_size:%x",
  67. (int)prg_hdr->p_memsz, (int)prg_hdr->p_align,
  68. (int)prg_hdr->p_vaddr, (int)seg_mem_size);
  69. if (*fw_size < seg_mem_size)
  70. *fw_size = seg_mem_size;
  71. }
  72. if (*fw_size == 0) {
  73. CAM_ERR(CAM_ICP, "invalid elf fw file");
  74. return -EINVAL;
  75. }
  76. return rc;
  77. }
  78. int32_t cam_icp_program_fw(const uint8_t *elf,
  79. uintptr_t fw_kva_addr,
  80. struct cam_icp_proc_params *params)
  81. {
  82. int32_t rc = 0;
  83. uint32_t num_prg_hdrs;
  84. unsigned char *icp_prg_hdr_tbl;
  85. int32_t i = 0;
  86. u8 *dest;
  87. u8 *src;
  88. struct elf32_hdr *elf_hdr;
  89. struct elf32_phdr *prg_hdr;
  90. elf_hdr = (struct elf32_hdr *)elf;
  91. num_prg_hdrs = elf_hdr->e_phnum;
  92. icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff;
  93. prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
  94. if (!prg_hdr) {
  95. CAM_ERR(CAM_ICP, "failed to get elf program header attr");
  96. return -EINVAL;
  97. }
  98. for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) {
  99. if (prg_hdr->p_flags == 0)
  100. continue;
  101. if ((params->skip_seg) &&
  102. ((prg_hdr->p_vaddr == params->vaddr[0]) ||
  103. (prg_hdr->p_vaddr == params->vaddr[1])))
  104. continue;
  105. CAM_DBG(CAM_ICP, "Loading FW header size: %u",
  106. prg_hdr->p_filesz);
  107. if (prg_hdr->p_filesz != 0) {
  108. src = (u8 *)((u8 *)elf + prg_hdr->p_offset);
  109. dest = (u8 *)(((u8 *)fw_kva_addr) +
  110. prg_hdr->p_vaddr);
  111. memcpy_toio(dest, src, prg_hdr->p_filesz);
  112. }
  113. }
  114. return rc;
  115. }