image.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2019 NXP
  4. */
  5. #include <common.h>
  6. #include <errno.h>
  7. #include <malloc.h>
  8. #include <asm/io.h>
  9. #include <mmc.h>
  10. #include <spi_flash.h>
  11. #include <nand.h>
  12. #include <asm/arch/image.h>
  13. #include <asm/arch/sys_proto.h>
  14. #include <asm/mach-imx/boot_mode.h>
  15. #define MMC_DEV 0
  16. #define QSPI_DEV 1
  17. #define NAND_DEV 2
  18. #define QSPI_NOR_DEV 3
  19. static int __get_container_size(ulong addr)
  20. {
  21. struct container_hdr *phdr;
  22. struct boot_img_t *img_entry;
  23. struct signature_block_hdr *sign_hdr;
  24. u8 i = 0;
  25. u32 max_offset = 0, img_end;
  26. phdr = (struct container_hdr *)addr;
  27. if (phdr->tag != 0x87 && phdr->version != 0x0) {
  28. debug("Wrong container header\n");
  29. return -EFAULT;
  30. }
  31. max_offset = sizeof(struct container_hdr);
  32. img_entry = (struct boot_img_t *)(addr + sizeof(struct container_hdr));
  33. for (i = 0; i < phdr->num_images; i++) {
  34. img_end = img_entry->offset + img_entry->size;
  35. if (img_end > max_offset)
  36. max_offset = img_end;
  37. debug("img[%u], end = 0x%x\n", i, img_end);
  38. img_entry++;
  39. }
  40. if (phdr->sig_blk_offset != 0) {
  41. sign_hdr = (struct signature_block_hdr *)(addr + phdr->sig_blk_offset);
  42. u16 len = sign_hdr->length_lsb + (sign_hdr->length_msb << 8);
  43. if (phdr->sig_blk_offset + len > max_offset)
  44. max_offset = phdr->sig_blk_offset + len;
  45. debug("sigblk, end = 0x%x\n", phdr->sig_blk_offset + len);
  46. }
  47. return max_offset;
  48. }
  49. static int get_container_size(void *dev, int dev_type, unsigned long offset)
  50. {
  51. u8 *buf = malloc(CONTAINER_HDR_ALIGNMENT);
  52. int ret = 0;
  53. if (!buf) {
  54. printf("Malloc buffer failed\n");
  55. return -ENOMEM;
  56. }
  57. #ifdef CONFIG_SPL_MMC_SUPPORT
  58. if (dev_type == MMC_DEV) {
  59. unsigned long count = 0;
  60. struct mmc *mmc = (struct mmc *)dev;
  61. count = blk_dread(mmc_get_blk_desc(mmc),
  62. offset / mmc->read_bl_len,
  63. CONTAINER_HDR_ALIGNMENT / mmc->read_bl_len,
  64. buf);
  65. if (count == 0) {
  66. printf("Read container image from MMC/SD failed\n");
  67. return -EIO;
  68. }
  69. }
  70. #endif
  71. #ifdef CONFIG_SPL_SPI_LOAD
  72. if (dev_type == QSPI_DEV) {
  73. struct spi_flash *flash = (struct spi_flash *)dev;
  74. ret = spi_flash_read(flash, offset,
  75. CONTAINER_HDR_ALIGNMENT, buf);
  76. if (ret != 0) {
  77. printf("Read container image from QSPI failed\n");
  78. return -EIO;
  79. }
  80. }
  81. #endif
  82. #ifdef CONFIG_SPL_NAND_SUPPORT
  83. if (dev_type == NAND_DEV) {
  84. ret = nand_spl_load_image(offset, CONTAINER_HDR_ALIGNMENT,
  85. buf);
  86. if (ret != 0) {
  87. printf("Read container image from NAND failed\n");
  88. return -EIO;
  89. }
  90. }
  91. #endif
  92. #ifdef CONFIG_SPL_NOR_SUPPORT
  93. if (dev_type == QSPI_NOR_DEV)
  94. memcpy(buf, (const void *)offset, CONTAINER_HDR_ALIGNMENT);
  95. #endif
  96. ret = __get_container_size((ulong)buf);
  97. free(buf);
  98. return ret;
  99. }
  100. static unsigned long get_boot_device_offset(void *dev, int dev_type)
  101. {
  102. unsigned long offset = 0;
  103. if (dev_type == MMC_DEV) {
  104. struct mmc *mmc = (struct mmc *)dev;
  105. if (IS_SD(mmc) || mmc->part_config == MMCPART_NOAVAILABLE) {
  106. offset = CONTAINER_HDR_MMCSD_OFFSET;
  107. } else {
  108. u8 part = EXT_CSD_EXTRACT_BOOT_PART(mmc->part_config);
  109. if (part == 1 || part == 2) {
  110. if (is_imx8qxp() && is_soc_rev(CHIP_REV_B))
  111. offset = CONTAINER_HDR_MMCSD_OFFSET;
  112. else
  113. offset = CONTAINER_HDR_EMMC_OFFSET;
  114. } else {
  115. offset = CONTAINER_HDR_MMCSD_OFFSET;
  116. }
  117. }
  118. } else if (dev_type == QSPI_DEV) {
  119. offset = CONTAINER_HDR_QSPI_OFFSET;
  120. } else if (dev_type == NAND_DEV) {
  121. offset = CONTAINER_HDR_NAND_OFFSET;
  122. } else if (dev_type == QSPI_NOR_DEV) {
  123. offset = CONTAINER_HDR_QSPI_OFFSET + 0x08000000;
  124. }
  125. return offset;
  126. }
  127. static int get_imageset_end(void *dev, int dev_type)
  128. {
  129. unsigned long offset1 = 0, offset2 = 0;
  130. int value_container[2];
  131. offset1 = get_boot_device_offset(dev, dev_type);
  132. offset2 = CONTAINER_HDR_ALIGNMENT + offset1;
  133. value_container[0] = get_container_size(dev, dev_type, offset1);
  134. if (value_container[0] < 0) {
  135. printf("Parse seco container failed %d\n", value_container[0]);
  136. return value_container[0];
  137. }
  138. debug("seco container size 0x%x\n", value_container[0]);
  139. value_container[1] = get_container_size(dev, dev_type, offset2);
  140. if (value_container[1] < 0) {
  141. debug("Parse scu container failed %d, only seco container\n",
  142. value_container[1]);
  143. /* return seco container total size */
  144. return value_container[0] + offset1;
  145. }
  146. debug("scu container size 0x%x\n", value_container[1]);
  147. return value_container[1] + offset2;
  148. }
  149. #ifdef CONFIG_SPL_SPI_LOAD
  150. unsigned long spl_spi_get_uboot_offs(struct spi_flash *flash)
  151. {
  152. int end;
  153. end = get_imageset_end(flash, QSPI_DEV);
  154. end = ROUND(end, SZ_1K);
  155. printf("Load image from QSPI 0x%x\n", end);
  156. return end;
  157. }
  158. #endif
  159. #ifdef CONFIG_SPL_MMC_SUPPORT
  160. unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc)
  161. {
  162. int end;
  163. end = get_imageset_end(mmc, MMC_DEV);
  164. end = ROUND(end, SZ_1K);
  165. printf("Load image from MMC/SD 0x%x\n", end);
  166. return end / mmc->read_bl_len;
  167. }
  168. #endif
  169. #ifdef CONFIG_SPL_NAND_SUPPORT
  170. uint32_t spl_nand_get_uboot_raw_page(void)
  171. {
  172. int end;
  173. end = get_imageset_end((void *)NULL, NAND_DEV);
  174. end = ROUND(end, SZ_16K);
  175. printf("Load image from NAND 0x%x\n", end);
  176. return end;
  177. }
  178. #endif
  179. #ifdef CONFIG_SPL_NOR_SUPPORT
  180. unsigned long spl_nor_get_uboot_base(void)
  181. {
  182. int end;
  183. /* Calculate the image set end,
  184. * if it is less than CONFIG_SYS_UBOOT_BASE(0x8281000),
  185. * we use CONFIG_SYS_UBOOT_BASE
  186. * Otherwise, use the calculated address
  187. */
  188. end = get_imageset_end((void *)NULL, QSPI_NOR_DEV);
  189. if (end <= CONFIG_SYS_UBOOT_BASE)
  190. end = CONFIG_SYS_UBOOT_BASE;
  191. else
  192. end = ROUND(end, SZ_1K);
  193. printf("Load image from NOR 0x%x\n", end);
  194. return end;
  195. }
  196. #endif