bootm.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2008 Semihalf
  4. *
  5. * (C) Copyright 2000-2006
  6. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  7. */
  8. #include <common.h>
  9. #include <bootstage.h>
  10. #include <cpu_func.h>
  11. #include <env.h>
  12. #include <init.h>
  13. #include <lmb.h>
  14. #include <watchdog.h>
  15. #include <command.h>
  16. #include <image.h>
  17. #include <malloc.h>
  18. #include <u-boot/zlib.h>
  19. #include <bzlib.h>
  20. #include <asm/byteorder.h>
  21. #include <asm/mp.h>
  22. #include <bootm.h>
  23. #include <vxworks.h>
  24. #if defined(CONFIG_OF_LIBFDT)
  25. #include <linux/libfdt.h>
  26. #include <fdt_support.h>
  27. #endif
  28. #ifdef CONFIG_SYS_INIT_RAM_LOCK
  29. #include <asm/cache.h>
  30. #endif
  31. DECLARE_GLOBAL_DATA_PTR;
  32. static ulong get_sp (void);
  33. extern void ft_fixup_num_cores(void *blob);
  34. static void set_clocks_in_mhz (bd_t *kbd);
  35. #ifndef CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE
  36. #define CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE (768*1024*1024)
  37. #endif
  38. static void boot_jump_linux(bootm_headers_t *images)
  39. {
  40. void (*kernel)(bd_t *, ulong r4, ulong r5, ulong r6,
  41. ulong r7, ulong r8, ulong r9);
  42. #ifdef CONFIG_OF_LIBFDT
  43. char *of_flat_tree = images->ft_addr;
  44. #endif
  45. kernel = (void (*)(bd_t *, ulong, ulong, ulong,
  46. ulong, ulong, ulong))images->ep;
  47. debug ("## Transferring control to Linux (at address %08lx) ...\n",
  48. (ulong)kernel);
  49. bootstage_mark(BOOTSTAGE_ID_RUN_OS);
  50. #ifdef CONFIG_BOOTSTAGE_FDT
  51. bootstage_fdt_add_report();
  52. #endif
  53. #ifdef CONFIG_BOOTSTAGE_REPORT
  54. bootstage_report();
  55. #endif
  56. #if defined(CONFIG_SYS_INIT_RAM_LOCK) && !defined(CONFIG_E500)
  57. unlock_ram_in_cache();
  58. #endif
  59. #if defined(CONFIG_OF_LIBFDT)
  60. if (of_flat_tree) { /* device tree; boot new style */
  61. /*
  62. * Linux Kernel Parameters (passing device tree):
  63. * r3: pointer to the fdt
  64. * r4: 0
  65. * r5: 0
  66. * r6: epapr magic
  67. * r7: size of IMA in bytes
  68. * r8: 0
  69. * r9: 0
  70. */
  71. debug (" Booting using OF flat tree...\n");
  72. WATCHDOG_RESET ();
  73. (*kernel) ((bd_t *)of_flat_tree, 0, 0, EPAPR_MAGIC,
  74. env_get_bootm_mapsize(), 0, 0);
  75. /* does not return */
  76. } else
  77. #endif
  78. {
  79. /*
  80. * Linux Kernel Parameters (passing board info data):
  81. * r3: ptr to board info data
  82. * r4: initrd_start or 0 if no initrd
  83. * r5: initrd_end - unused if r4 is 0
  84. * r6: Start of command line string
  85. * r7: End of command line string
  86. * r8: 0
  87. * r9: 0
  88. */
  89. ulong cmd_start = images->cmdline_start;
  90. ulong cmd_end = images->cmdline_end;
  91. ulong initrd_start = images->initrd_start;
  92. ulong initrd_end = images->initrd_end;
  93. bd_t *kbd = images->kbd;
  94. debug (" Booting using board info...\n");
  95. WATCHDOG_RESET ();
  96. (*kernel) (kbd, initrd_start, initrd_end,
  97. cmd_start, cmd_end, 0, 0);
  98. /* does not return */
  99. }
  100. return ;
  101. }
  102. void arch_lmb_reserve(struct lmb *lmb)
  103. {
  104. phys_size_t bootm_size;
  105. ulong size, sp, bootmap_base;
  106. bootmap_base = env_get_bootm_low();
  107. bootm_size = env_get_bootm_size();
  108. #ifdef DEBUG
  109. if (((u64)bootmap_base + bootm_size) >
  110. (CONFIG_SYS_SDRAM_BASE + (u64)gd->ram_size))
  111. puts("WARNING: bootm_low + bootm_size exceed total memory\n");
  112. if ((bootmap_base + bootm_size) > get_effective_memsize())
  113. puts("WARNING: bootm_low + bootm_size exceed eff. memory\n");
  114. #endif
  115. size = min(bootm_size, get_effective_memsize());
  116. size = min(size, (ulong)CONFIG_SYS_LINUX_LOWMEM_MAX_SIZE);
  117. if (size < bootm_size) {
  118. ulong base = bootmap_base + size;
  119. printf("WARNING: adjusting available memory to %lx\n", size);
  120. lmb_reserve(lmb, base, bootm_size - size);
  121. }
  122. /*
  123. * Booting a (Linux) kernel image
  124. *
  125. * Allocate space for command line and board info - the
  126. * address should be as high as possible within the reach of
  127. * the kernel (see CONFIG_SYS_BOOTMAPSZ settings), but in unused
  128. * memory, which means far enough below the current stack
  129. * pointer.
  130. */
  131. sp = get_sp();
  132. debug ("## Current stack ends at 0x%08lx\n", sp);
  133. /* adjust sp by 4K to be safe */
  134. sp -= 4096;
  135. lmb_reserve(lmb, sp, (CONFIG_SYS_SDRAM_BASE + get_effective_memsize() - sp));
  136. #ifdef CONFIG_MP
  137. cpu_mp_lmb_reserve(lmb);
  138. #endif
  139. return ;
  140. }
  141. static void boot_prep_linux(bootm_headers_t *images)
  142. {
  143. #ifdef CONFIG_MP
  144. /*
  145. * if we are MP make sure to flush the device tree so any changes are
  146. * made visibile to all other cores. In AMP boot scenarios the cores
  147. * might not be HW cache coherent with each other.
  148. */
  149. flush_cache((unsigned long)images->ft_addr, images->ft_len);
  150. #endif
  151. }
  152. static int boot_cmdline_linux(bootm_headers_t *images)
  153. {
  154. ulong of_size = images->ft_len;
  155. struct lmb *lmb = &images->lmb;
  156. ulong *cmd_start = &images->cmdline_start;
  157. ulong *cmd_end = &images->cmdline_end;
  158. int ret = 0;
  159. if (!of_size) {
  160. /* allocate space and init command line */
  161. ret = boot_get_cmdline (lmb, cmd_start, cmd_end);
  162. if (ret) {
  163. puts("ERROR with allocation of cmdline\n");
  164. return ret;
  165. }
  166. }
  167. return ret;
  168. }
  169. static int boot_bd_t_linux(bootm_headers_t *images)
  170. {
  171. ulong of_size = images->ft_len;
  172. struct lmb *lmb = &images->lmb;
  173. bd_t **kbd = &images->kbd;
  174. int ret = 0;
  175. if (!of_size) {
  176. /* allocate space for kernel copy of board info */
  177. ret = boot_get_kbd (lmb, kbd);
  178. if (ret) {
  179. puts("ERROR with allocation of kernel bd\n");
  180. return ret;
  181. }
  182. set_clocks_in_mhz(*kbd);
  183. }
  184. return ret;
  185. }
  186. static int boot_body_linux(bootm_headers_t *images)
  187. {
  188. int ret;
  189. /* allocate space for kernel copy of board info */
  190. ret = boot_bd_t_linux(images);
  191. if (ret)
  192. return ret;
  193. ret = image_setup_linux(images);
  194. if (ret)
  195. return ret;
  196. return 0;
  197. }
  198. noinline int do_bootm_linux(int flag, int argc, char *const argv[],
  199. bootm_headers_t *images)
  200. {
  201. int ret;
  202. if (flag & BOOTM_STATE_OS_CMDLINE) {
  203. boot_cmdline_linux(images);
  204. return 0;
  205. }
  206. if (flag & BOOTM_STATE_OS_BD_T) {
  207. boot_bd_t_linux(images);
  208. return 0;
  209. }
  210. if (flag & BOOTM_STATE_OS_PREP) {
  211. boot_prep_linux(images);
  212. return 0;
  213. }
  214. boot_prep_linux(images);
  215. ret = boot_body_linux(images);
  216. if (ret)
  217. return ret;
  218. boot_jump_linux(images);
  219. return 0;
  220. }
  221. static ulong get_sp (void)
  222. {
  223. ulong sp;
  224. asm( "mr %0,1": "=r"(sp) : );
  225. return sp;
  226. }
  227. static void set_clocks_in_mhz (bd_t *kbd)
  228. {
  229. char *s;
  230. s = env_get("clocks_in_mhz");
  231. if (s) {
  232. /* convert all clock information to MHz */
  233. kbd->bi_intfreq /= 1000000L;
  234. kbd->bi_busfreq /= 1000000L;
  235. #if defined(CONFIG_CPM2)
  236. kbd->bi_cpmfreq /= 1000000L;
  237. kbd->bi_brgfreq /= 1000000L;
  238. kbd->bi_sccfreq /= 1000000L;
  239. kbd->bi_vco /= 1000000L;
  240. #endif
  241. }
  242. }
  243. #if defined(CONFIG_BOOTM_VXWORKS)
  244. void boot_prep_vxworks(bootm_headers_t *images)
  245. {
  246. #if defined(CONFIG_OF_LIBFDT)
  247. int off;
  248. u64 base, size;
  249. if (!images->ft_addr)
  250. return;
  251. base = (u64)gd->bd->bi_memstart;
  252. size = (u64)gd->bd->bi_memsize;
  253. off = fdt_path_offset(images->ft_addr, "/memory");
  254. if (off < 0)
  255. fdt_fixup_memory(images->ft_addr, base, size);
  256. #if defined(CONFIG_MP)
  257. #if defined(CONFIG_MPC85xx)
  258. ft_fixup_cpu(images->ft_addr, base + size);
  259. ft_fixup_num_cores(images->ft_addr);
  260. #elif defined(CONFIG_MPC86xx)
  261. off = fdt_add_mem_rsv(images->ft_addr,
  262. determine_mp_bootpg(NULL), (u64)4096);
  263. if (off < 0)
  264. printf("## WARNING %s: %s\n", __func__, fdt_strerror(off));
  265. ft_fixup_num_cores(images->ft_addr);
  266. #endif
  267. flush_cache((unsigned long)images->ft_addr, images->ft_len);
  268. #endif
  269. #endif
  270. }
  271. void boot_jump_vxworks(bootm_headers_t *images)
  272. {
  273. /* PowerPC VxWorks boot interface conforms to the ePAPR standard
  274. * general purpuse registers:
  275. *
  276. * r3: Effective address of the device tree image
  277. * r4: 0
  278. * r5: 0
  279. * r6: ePAPR magic value
  280. * r7: shall be the size of the boot IMA in bytes
  281. * r8: 0
  282. * r9: 0
  283. * TCR: WRC = 0, no watchdog timer reset will occur
  284. */
  285. WATCHDOG_RESET();
  286. ((void (*)(void *, ulong, ulong, ulong,
  287. ulong, ulong, ulong))images->ep)(images->ft_addr,
  288. 0, 0, EPAPR_MAGIC, env_get_bootm_mapsize(), 0, 0);
  289. }
  290. #endif