cam_icp_utils.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  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. {
  34. int32_t rc = 0;
  35. int32_t i = 0;
  36. uint32_t num_prg_hdrs;
  37. unsigned char *icp_prg_hdr_tbl;
  38. uint32_t seg_mem_size = 0;
  39. struct elf32_hdr *elf_hdr;
  40. struct elf32_phdr *prg_hdr;
  41. if (!elf || !fw_size) {
  42. CAM_ERR(CAM_ICP, "invalid args");
  43. return -EINVAL;
  44. }
  45. *fw_size = 0;
  46. elf_hdr = (struct elf32_hdr *)elf;
  47. num_prg_hdrs = elf_hdr->e_phnum;
  48. icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff;
  49. prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
  50. if (!prg_hdr) {
  51. CAM_ERR(CAM_ICP, "failed to get elf program header attr");
  52. return -EINVAL;
  53. }
  54. CAM_DBG(CAM_ICP, "num_prg_hdrs = %d", num_prg_hdrs);
  55. for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) {
  56. if (prg_hdr->p_flags == 0)
  57. continue;
  58. seg_mem_size = (prg_hdr->p_memsz + prg_hdr->p_align - 1) &
  59. ~(prg_hdr->p_align - 1);
  60. seg_mem_size += prg_hdr->p_paddr;
  61. CAM_DBG(CAM_ICP, "memsz:%x align:%x addr:%x seg_mem_size:%x",
  62. (int)prg_hdr->p_memsz, (int)prg_hdr->p_align,
  63. (int)prg_hdr->p_paddr, (int)seg_mem_size);
  64. if (*fw_size < seg_mem_size)
  65. *fw_size = seg_mem_size;
  66. }
  67. if (*fw_size == 0) {
  68. CAM_ERR(CAM_ICP, "invalid elf fw file");
  69. return -EINVAL;
  70. }
  71. return rc;
  72. }
  73. int32_t cam_icp_program_fw(const uint8_t *elf,
  74. uintptr_t fw_kva_addr)
  75. {
  76. int32_t rc = 0;
  77. uint32_t num_prg_hdrs;
  78. unsigned char *icp_prg_hdr_tbl;
  79. int32_t i = 0;
  80. u8 *dest;
  81. u8 *src;
  82. struct elf32_hdr *elf_hdr;
  83. struct elf32_phdr *prg_hdr;
  84. elf_hdr = (struct elf32_hdr *)elf;
  85. num_prg_hdrs = elf_hdr->e_phnum;
  86. icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff;
  87. prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
  88. if (!prg_hdr) {
  89. CAM_ERR(CAM_ICP, "failed to get elf program header attr");
  90. return -EINVAL;
  91. }
  92. for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) {
  93. if (prg_hdr->p_flags == 0)
  94. continue;
  95. CAM_DBG(CAM_ICP, "Loading FW header size: %u paddr: %pK",
  96. prg_hdr->p_filesz, prg_hdr->p_paddr);
  97. if (prg_hdr->p_filesz != 0) {
  98. src = (u8 *)((u8 *)elf + prg_hdr->p_offset);
  99. dest = (u8 *)(((u8 *)fw_kva_addr) +
  100. prg_hdr->p_paddr);
  101. memcpy_toio(dest, src, prg_hdr->p_filesz);
  102. }
  103. }
  104. return rc;
  105. }