pfe_firmware.c 6.8 KB

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