pfe_firmware.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2015-2016 Freescale Semiconductor, Inc.
  4. * Copyright 2017,2021 NXP
  5. */
  6. /*
  7. * @file
  8. * Contains all the functions to handle parsing and loading of PE firmware
  9. * files.
  10. */
  11. #include <dm.h>
  12. #include <dm/device-internal.h>
  13. #include <image.h>
  14. #include <log.h>
  15. #include <malloc.h>
  16. #include <linux/bitops.h>
  17. #include <net/pfe_eth/pfe_eth.h>
  18. #include <net/pfe_eth/pfe_firmware.h>
  19. #include <spi_flash.h>
  20. #ifdef CONFIG_CHAIN_OF_TRUST
  21. #include <fsl_validate.h>
  22. #endif
  23. #define PFE_FIRMWARE_FIT_CNF_NAME "config@1"
  24. static const void *pfe_fit_addr;
  25. #ifdef CONFIG_CHAIN_OF_TRUST
  26. static const void *pfe_esbc_hdr_addr;
  27. #endif
  28. /*
  29. * PFE elf firmware loader.
  30. * Loads an elf firmware image into a list of PE's (specified using a bitmask)
  31. *
  32. * @param pe_mask Mask of PE id's to load firmware to
  33. * @param pfe_firmware Pointer to the firmware image
  34. *
  35. * @return 0 on success, a negative value on error
  36. */
  37. static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware)
  38. {
  39. Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *)pfe_firmware;
  40. Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum);
  41. Elf32_Shdr *shdr = (Elf32_Shdr *)(pfe_firmware +
  42. be32_to_cpu(elf_hdr->e_shoff));
  43. int id, section;
  44. int ret;
  45. debug("%s: no of sections: %d\n", __func__, sections);
  46. /* Some sanity checks */
  47. if (strncmp((char *)&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) {
  48. printf("%s: incorrect elf magic number\n", __func__);
  49. return -1;
  50. }
  51. if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
  52. printf("%s: incorrect elf class(%x)\n", __func__,
  53. elf_hdr->e_ident[EI_CLASS]);
  54. return -1;
  55. }
  56. if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) {
  57. printf("%s: incorrect elf data(%x)\n", __func__,
  58. elf_hdr->e_ident[EI_DATA]);
  59. return -1;
  60. }
  61. if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) {
  62. printf("%s: incorrect elf file type(%x)\n", __func__,
  63. be16_to_cpu(elf_hdr->e_type));
  64. return -1;
  65. }
  66. for (section = 0; section < sections; section++, shdr++) {
  67. if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC |
  68. SHF_EXECINSTR)))
  69. continue;
  70. for (id = 0; id < MAX_PE; id++)
  71. if (pe_mask & BIT(id)) {
  72. ret = pe_load_elf_section(id,
  73. pfe_firmware, shdr);
  74. if (ret < 0)
  75. goto err;
  76. }
  77. }
  78. return 0;
  79. err:
  80. return ret;
  81. }
  82. /*
  83. * Get PFE firmware from FIT image
  84. *
  85. * @param data pointer to PFE firmware
  86. * @param size pointer to size of the firmware
  87. * @param fw_name pfe firmware name, either class or tmu
  88. *
  89. * @return 0 on success, a negative value on error
  90. */
  91. static int pfe_get_fw(const void **data,
  92. size_t *size, char *fw_name)
  93. {
  94. int conf_node_off, fw_node_off;
  95. char *conf_node_name = NULL;
  96. char *desc;
  97. int ret = 0;
  98. conf_node_name = PFE_FIRMWARE_FIT_CNF_NAME;
  99. conf_node_off = fit_conf_get_node(pfe_fit_addr, conf_node_name);
  100. if (conf_node_off < 0) {
  101. printf("PFE Firmware: %s: no such config\n", conf_node_name);
  102. return -ENOENT;
  103. }
  104. fw_node_off = fit_conf_get_prop_node(pfe_fit_addr, conf_node_off,
  105. fw_name);
  106. if (fw_node_off < 0) {
  107. printf("PFE Firmware: No '%s' in config\n",
  108. fw_name);
  109. return -ENOLINK;
  110. }
  111. if (!(fit_image_verify(pfe_fit_addr, fw_node_off))) {
  112. printf("PFE Firmware: Bad firmware image (bad CRC)\n");
  113. return -EINVAL;
  114. }
  115. if (fit_image_get_data(pfe_fit_addr, fw_node_off, data, size)) {
  116. printf("PFE Firmware: Can't get %s subimage data/size",
  117. fw_name);
  118. return -ENOENT;
  119. }
  120. ret = fit_get_desc(pfe_fit_addr, fw_node_off, &desc);
  121. if (ret)
  122. printf("PFE Firmware: Can't get description\n");
  123. else
  124. printf("%s\n", desc);
  125. return ret;
  126. }
  127. /*
  128. * Check PFE FIT image
  129. *
  130. * @return 0 on success, a negative value on error
  131. */
  132. static int pfe_fit_check(void)
  133. {
  134. int ret = 0;
  135. ret = fdt_check_header(pfe_fit_addr);
  136. if (ret) {
  137. printf("PFE Firmware: Bad firmware image (not a FIT image)\n");
  138. return ret;
  139. }
  140. if (fit_check_format(pfe_fit_addr, IMAGE_SIZE_INVAL)) {
  141. printf("PFE Firmware: Bad firmware image (bad FIT header)\n");
  142. ret = -1;
  143. return ret;
  144. }
  145. return ret;
  146. }
  147. int pfe_spi_flash_init(void)
  148. {
  149. struct spi_flash *pfe_flash;
  150. struct udevice *new;
  151. int ret = 0;
  152. void *addr = malloc(CONFIG_SYS_LS_PFE_FW_LENGTH);
  153. if (!addr)
  154. return -ENOMEM;
  155. ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS,
  156. CONFIG_ENV_SPI_CS,
  157. CONFIG_ENV_SPI_MAX_HZ,
  158. CONFIG_ENV_SPI_MODE,
  159. &new);
  160. if (ret) {
  161. printf("SF: failed to probe spi\n");
  162. free(addr);
  163. device_remove(new, DM_REMOVE_NORMAL);
  164. return ret;
  165. }
  166. pfe_flash = dev_get_uclass_priv(new);
  167. if (!pfe_flash) {
  168. printf("SF: probe for pfe failed\n");
  169. free(addr);
  170. device_remove(new, DM_REMOVE_NORMAL);
  171. return -ENODEV;
  172. }
  173. ret = spi_flash_read(pfe_flash,
  174. CONFIG_SYS_LS_PFE_FW_ADDR,
  175. CONFIG_SYS_LS_PFE_FW_LENGTH,
  176. addr);
  177. if (ret) {
  178. printf("SF: read for pfe failed\n");
  179. free(addr);
  180. spi_flash_free(pfe_flash);
  181. return ret;
  182. }
  183. #ifdef CONFIG_CHAIN_OF_TRUST
  184. void *hdr_addr = malloc(CONFIG_SYS_LS_PFE_ESBC_LENGTH);
  185. if (!hdr_addr) {
  186. free(addr);
  187. spi_flash_free(pfe_flash);
  188. return -ENOMEM;
  189. }
  190. ret = spi_flash_read(pfe_flash,
  191. CONFIG_SYS_LS_PFE_ESBC_ADDR,
  192. CONFIG_SYS_LS_PFE_ESBC_LENGTH,
  193. hdr_addr);
  194. if (ret) {
  195. printf("SF: failed to read pfe esbc header\n");
  196. free(addr);
  197. free(hdr_addr);
  198. spi_flash_free(pfe_flash);
  199. return ret;
  200. }
  201. pfe_esbc_hdr_addr = hdr_addr;
  202. #endif
  203. pfe_fit_addr = addr;
  204. spi_flash_free(pfe_flash);
  205. return ret;
  206. }
  207. /*
  208. * PFE firmware initialization.
  209. * Loads different firmware files from FIT image.
  210. * Initializes PE IMEM/DMEM and UTIL-PE DDR
  211. * Initializes control path symbol addresses (by looking them up in the elf
  212. * firmware files
  213. * Takes PE's out of reset
  214. *
  215. * @return 0 on success, a negative value on error
  216. */
  217. int pfe_firmware_init(void)
  218. {
  219. #define PFE_KEY_HASH NULL
  220. char *pfe_firmware_name;
  221. const void *raw_image_addr;
  222. size_t raw_image_size = 0;
  223. u8 *pfe_firmware;
  224. #ifdef CONFIG_CHAIN_OF_TRUST
  225. uintptr_t pfe_esbc_hdr = 0;
  226. uintptr_t pfe_img_addr = 0;
  227. #endif
  228. int ret = 0;
  229. int fw_count, max_fw_count;
  230. const char *p;
  231. ret = pfe_spi_flash_init();
  232. if (ret)
  233. goto err;
  234. ret = pfe_fit_check();
  235. if (ret)
  236. goto err;
  237. #ifdef CONFIG_CHAIN_OF_TRUST
  238. pfe_esbc_hdr = (uintptr_t)pfe_esbc_hdr_addr;
  239. pfe_img_addr = (uintptr_t)pfe_fit_addr;
  240. if (fsl_check_boot_mode_secure() != 0) {
  241. /*
  242. * In case of failure in validation, fsl_secboot_validate
  243. * would not return back in case of Production environment
  244. * with ITS=1. In Development environment (ITS=0 and
  245. * SB_EN=1), the function may return back in case of
  246. * non-fatal failures.
  247. */
  248. ret = fsl_secboot_validate(pfe_esbc_hdr,
  249. PFE_KEY_HASH,
  250. &pfe_img_addr);
  251. if (ret != 0)
  252. printf("PFE firmware(s) validation failed\n");
  253. else
  254. printf("PFE firmware(s) validation Successful\n");
  255. }
  256. #endif
  257. p = env_get("load_util");
  258. if (!p) {
  259. max_fw_count = 2;
  260. } else {
  261. max_fw_count = dectoul(p, NULL);
  262. if (max_fw_count)
  263. max_fw_count = 3;
  264. else
  265. max_fw_count = 2;
  266. }
  267. for (fw_count = 0; fw_count < max_fw_count; fw_count++) {
  268. switch (fw_count) {
  269. case 0:
  270. pfe_firmware_name = "class_slowpath";
  271. break;
  272. case 1:
  273. pfe_firmware_name = "tmu_slowpath";
  274. break;
  275. case 2:
  276. pfe_firmware_name = "util_slowpath";
  277. break;
  278. }
  279. if (pfe_get_fw(&raw_image_addr, &raw_image_size,
  280. pfe_firmware_name)) {
  281. printf("%s firmware couldn't be found in FIT image\n",
  282. pfe_firmware_name);
  283. break;
  284. }
  285. pfe_firmware = malloc(raw_image_size);
  286. if (!pfe_firmware)
  287. return -ENOMEM;
  288. memcpy((void *)pfe_firmware, (void *)raw_image_addr,
  289. raw_image_size);
  290. switch (fw_count) {
  291. case 0:
  292. env_set_addr("class_elf_firmware", pfe_firmware);
  293. env_set_addr("class_elf_size", (void *)raw_image_size);
  294. break;
  295. case 1:
  296. env_set_addr("tmu_elf_firmware", pfe_firmware);
  297. env_set_addr("tmu_elf_size", (void *)raw_image_size);
  298. break;
  299. case 2:
  300. env_set_addr("util_elf_firmware", pfe_firmware);
  301. env_set_addr("util_elf_size", (void *)raw_image_size);
  302. break;
  303. }
  304. }
  305. raw_image_addr = NULL;
  306. pfe_firmware = NULL;
  307. raw_image_size = 0;
  308. for (fw_count = 0; fw_count < 2; fw_count++) {
  309. if (fw_count == 0)
  310. pfe_firmware_name = "class";
  311. else if (fw_count == 1)
  312. pfe_firmware_name = "tmu";
  313. pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name);
  314. pfe_firmware = malloc(raw_image_size);
  315. if (!pfe_firmware)
  316. return -ENOMEM;
  317. memcpy((void *)pfe_firmware, (void *)raw_image_addr,
  318. raw_image_size);
  319. if (fw_count == 0)
  320. ret = pfe_load_elf(CLASS_MASK, pfe_firmware);
  321. else if (fw_count == 1)
  322. ret = pfe_load_elf(TMU_MASK, pfe_firmware);
  323. if (ret < 0) {
  324. printf("%s: %s firmware load failed\n", __func__,
  325. pfe_firmware_name);
  326. goto err;
  327. }
  328. debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name);
  329. free(pfe_firmware);
  330. }
  331. tmu_enable(0xb);
  332. class_enable();
  333. gpi_enable(HGPI_BASE_ADDR);
  334. err:
  335. return ret;
  336. }
  337. /*
  338. * PFE firmware cleanup
  339. * Puts PE's in reset
  340. */
  341. void pfe_firmware_exit(void)
  342. {
  343. debug("%s\n", __func__);
  344. class_disable();
  345. tmu_disable(0xf);
  346. hif_tx_disable();
  347. hif_rx_disable();
  348. }