pfe_firmware.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2015-2016 Freescale Semiconductor, Inc.
  4. * Copyright 2017 NXP
  5. */
  6. /*
  7. * @file
  8. * Contains all the functions to handle parsing and loading of PE firmware
  9. * files.
  10. */
  11. #include <net/pfe_eth/pfe_eth.h>
  12. #include <net/pfe_eth/pfe_firmware.h>
  13. #ifdef CONFIG_CHAIN_OF_TRUST
  14. #include <fsl_validate.h>
  15. #endif
  16. #define PFE_FIRMEWARE_FIT_CNF_NAME "config@1"
  17. static const void *pfe_fit_addr = (void *)CONFIG_SYS_LS_PFE_FW_ADDR;
  18. /*
  19. * PFE elf firmware loader.
  20. * Loads an elf firmware image into a list of PE's (specified using a bitmask)
  21. *
  22. * @param pe_mask Mask of PE id's to load firmware to
  23. * @param pfe_firmware Pointer to the firmware image
  24. *
  25. * @return 0 on success, a negative value on error
  26. */
  27. static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware)
  28. {
  29. Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *)pfe_firmware;
  30. Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum);
  31. Elf32_Shdr *shdr = (Elf32_Shdr *)(pfe_firmware +
  32. be32_to_cpu(elf_hdr->e_shoff));
  33. int id, section;
  34. int ret;
  35. debug("%s: no of sections: %d\n", __func__, sections);
  36. /* Some sanity checks */
  37. if (strncmp((char *)&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) {
  38. printf("%s: incorrect elf magic number\n", __func__);
  39. return -1;
  40. }
  41. if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
  42. printf("%s: incorrect elf class(%x)\n", __func__,
  43. elf_hdr->e_ident[EI_CLASS]);
  44. return -1;
  45. }
  46. if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) {
  47. printf("%s: incorrect elf data(%x)\n", __func__,
  48. elf_hdr->e_ident[EI_DATA]);
  49. return -1;
  50. }
  51. if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) {
  52. printf("%s: incorrect elf file type(%x)\n", __func__,
  53. be16_to_cpu(elf_hdr->e_type));
  54. return -1;
  55. }
  56. for (section = 0; section < sections; section++, shdr++) {
  57. if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC |
  58. SHF_EXECINSTR)))
  59. continue;
  60. for (id = 0; id < MAX_PE; id++)
  61. if (pe_mask & BIT(id)) {
  62. ret = pe_load_elf_section(id,
  63. pfe_firmware, shdr);
  64. if (ret < 0)
  65. goto err;
  66. }
  67. }
  68. return 0;
  69. err:
  70. return ret;
  71. }
  72. /*
  73. * Get PFE firmware from FIT image
  74. *
  75. * @param data pointer to PFE firmware
  76. * @param size pointer to size of the firmware
  77. * @param fw_name pfe firmware name, either class or tmu
  78. *
  79. * @return 0 on success, a negative value on error
  80. */
  81. static int pfe_get_fw(const void **data,
  82. size_t *size, char *fw_name)
  83. {
  84. int conf_node_off, fw_node_off;
  85. char *conf_node_name = NULL;
  86. char *desc;
  87. int ret = 0;
  88. conf_node_name = PFE_FIRMEWARE_FIT_CNF_NAME;
  89. conf_node_off = fit_conf_get_node(pfe_fit_addr, conf_node_name);
  90. if (conf_node_off < 0) {
  91. printf("PFE Firmware: %s: no such config\n", conf_node_name);
  92. return -ENOENT;
  93. }
  94. fw_node_off = fit_conf_get_prop_node(pfe_fit_addr, conf_node_off,
  95. fw_name);
  96. if (fw_node_off < 0) {
  97. printf("PFE Firmware: No '%s' in config\n",
  98. fw_name);
  99. return -ENOLINK;
  100. }
  101. if (!(fit_image_verify(pfe_fit_addr, fw_node_off))) {
  102. printf("PFE Firmware: Bad firmware image (bad CRC)\n");
  103. return -EINVAL;
  104. }
  105. if (fit_image_get_data(pfe_fit_addr, fw_node_off, data, size)) {
  106. printf("PFE Firmware: Can't get %s subimage data/size",
  107. fw_name);
  108. return -ENOENT;
  109. }
  110. ret = fit_get_desc(pfe_fit_addr, fw_node_off, &desc);
  111. if (ret)
  112. printf("PFE Firmware: Can't get description\n");
  113. else
  114. printf("%s\n", desc);
  115. return ret;
  116. }
  117. /*
  118. * Check PFE FIT image
  119. *
  120. * @return 0 on success, a negative value on error
  121. */
  122. static int pfe_fit_check(void)
  123. {
  124. int ret = 0;
  125. ret = fdt_check_header(pfe_fit_addr);
  126. if (ret) {
  127. printf("PFE Firmware: Bad firmware image (not a FIT image)\n");
  128. return ret;
  129. }
  130. if (!fit_check_format(pfe_fit_addr)) {
  131. printf("PFE Firmware: Bad firmware image (bad FIT header)\n");
  132. ret = -1;
  133. return ret;
  134. }
  135. return ret;
  136. }
  137. /*
  138. * PFE firmware initialization.
  139. * Loads different firmware files from FIT image.
  140. * Initializes PE IMEM/DMEM and UTIL-PE DDR
  141. * Initializes control path symbol addresses (by looking them up in the elf
  142. * firmware files
  143. * Takes PE's out of reset
  144. *
  145. * @return 0 on success, a negative value on error
  146. */
  147. int pfe_firmware_init(void)
  148. {
  149. #define PFE_KEY_HASH NULL
  150. char *pfe_firmware_name;
  151. const void *raw_image_addr;
  152. size_t raw_image_size = 0;
  153. u8 *pfe_firmware;
  154. #ifdef CONFIG_CHAIN_OF_TRUST
  155. uintptr_t pfe_esbc_hdr = 0;
  156. uintptr_t pfe_img_addr = 0;
  157. #endif
  158. int ret = 0;
  159. int fw_count;
  160. ret = pfe_fit_check();
  161. if (ret)
  162. goto err;
  163. #ifdef CONFIG_CHAIN_OF_TRUST
  164. pfe_esbc_hdr = CONFIG_SYS_LS_PFE_ESBC_ADDR;
  165. pfe_img_addr = (uintptr_t)pfe_fit_addr;
  166. if (fsl_check_boot_mode_secure() != 0) {
  167. /*
  168. * In case of failure in validation, fsl_secboot_validate
  169. * would not return back in case of Production environment
  170. * with ITS=1. In Development environment (ITS=0 and
  171. * SB_EN=1), the function may return back in case of
  172. * non-fatal failures.
  173. */
  174. ret = fsl_secboot_validate(pfe_esbc_hdr,
  175. PFE_KEY_HASH,
  176. &pfe_img_addr);
  177. if (ret != 0)
  178. printf("PFE firmware(s) validation failed\n");
  179. else
  180. printf("PFE firmware(s) validation Successful\n");
  181. }
  182. #endif
  183. for (fw_count = 0; fw_count < 2; fw_count++) {
  184. if (fw_count == 0)
  185. pfe_firmware_name = "class";
  186. else if (fw_count == 1)
  187. pfe_firmware_name = "tmu";
  188. pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name);
  189. pfe_firmware = malloc(raw_image_size);
  190. if (!pfe_firmware)
  191. return -ENOMEM;
  192. memcpy((void *)pfe_firmware, (void *)raw_image_addr,
  193. raw_image_size);
  194. if (fw_count == 0)
  195. ret = pfe_load_elf(CLASS_MASK, pfe_firmware);
  196. else if (fw_count == 1)
  197. ret = pfe_load_elf(TMU_MASK, pfe_firmware);
  198. if (ret < 0) {
  199. printf("%s: %s firmware load failed\n", __func__,
  200. pfe_firmware_name);
  201. goto err;
  202. }
  203. debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name);
  204. free(pfe_firmware);
  205. }
  206. tmu_enable(0xb);
  207. class_enable();
  208. gpi_enable(HGPI_BASE_ADDR);
  209. err:
  210. return ret;
  211. }
  212. /*
  213. * PFE firmware cleanup
  214. * Puts PE's in reset
  215. */
  216. void pfe_firmware_exit(void)
  217. {
  218. debug("%s\n", __func__);
  219. class_disable();
  220. tmu_disable(0xf);
  221. hif_tx_disable();
  222. hif_rx_disable();
  223. }