bootm.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2008 - 2013 Tensilica Inc.
  4. * (C) Copyright 2014 Cadence Design Systems Inc.
  5. */
  6. #include <common.h>
  7. #include <bootstage.h>
  8. #include <command.h>
  9. #include <cpu_func.h>
  10. #include <env.h>
  11. #include <u-boot/zlib.h>
  12. #include <asm/byteorder.h>
  13. #include <asm/addrspace.h>
  14. #include <asm/bootparam.h>
  15. #include <asm/cache.h>
  16. #include <image.h>
  17. DECLARE_GLOBAL_DATA_PTR;
  18. /*
  19. * Setup boot-parameters.
  20. */
  21. static struct bp_tag *setup_first_tag(struct bp_tag *params)
  22. {
  23. params->id = BP_TAG_FIRST;
  24. params->size = sizeof(long);
  25. *(unsigned long *)&params->data = BP_VERSION;
  26. return bp_tag_next(params);
  27. }
  28. static struct bp_tag *setup_last_tag(struct bp_tag *params)
  29. {
  30. params->id = BP_TAG_LAST;
  31. params->size = 0;
  32. return bp_tag_next(params);
  33. }
  34. static struct bp_tag *setup_memory_tag(struct bp_tag *params)
  35. {
  36. struct meminfo *mem;
  37. params->id = BP_TAG_MEMORY;
  38. params->size = sizeof(struct meminfo);
  39. mem = (struct meminfo *)params->data;
  40. mem->type = MEMORY_TYPE_CONVENTIONAL;
  41. mem->start = PHYSADDR(gd->ram_base);
  42. mem->end = PHYSADDR(gd->ram_base + gd->ram_size);
  43. printf(" MEMORY: tag:0x%04x, type:0X%lx, start:0X%lx, end:0X%lx\n",
  44. BP_TAG_MEMORY, mem->type, mem->start, mem->end);
  45. return bp_tag_next(params);
  46. }
  47. static struct bp_tag *setup_commandline_tag(struct bp_tag *params,
  48. char *cmdline)
  49. {
  50. int len;
  51. if (!cmdline)
  52. return params;
  53. len = strlen(cmdline);
  54. params->id = BP_TAG_COMMAND_LINE;
  55. params->size = (len + 3) & -4;
  56. strcpy((char *)params->data, cmdline);
  57. printf(" COMMAND_LINE: tag:0x%04x, size:%u, data:'%s'\n",
  58. BP_TAG_COMMAND_LINE, params->size, cmdline);
  59. return bp_tag_next(params);
  60. }
  61. static struct bp_tag *setup_ramdisk_tag(struct bp_tag *params,
  62. unsigned long rd_start,
  63. unsigned long rd_end)
  64. {
  65. struct meminfo *mem;
  66. if (rd_start == rd_end)
  67. return params;
  68. /* Add a single banked memory */
  69. params->id = BP_TAG_INITRD;
  70. params->size = sizeof(struct meminfo);
  71. mem = (struct meminfo *)params->data;
  72. mem->type = MEMORY_TYPE_CONVENTIONAL;
  73. mem->start = PHYSADDR(rd_start);
  74. mem->end = PHYSADDR(rd_end);
  75. printf(" INITRD: tag:0x%x, type:0X%04lx, start:0X%lx, end:0X%lx\n",
  76. BP_TAG_INITRD, mem->type, mem->start, mem->end);
  77. return bp_tag_next(params);
  78. }
  79. static struct bp_tag *setup_serial_tag(struct bp_tag *params)
  80. {
  81. params->id = BP_TAG_SERIAL_BAUDRATE;
  82. params->size = sizeof(unsigned long);
  83. params->data[0] = gd->baudrate;
  84. printf(" SERIAL_BAUDRATE: tag:0x%04x, size:%u, baudrate:%lu\n",
  85. BP_TAG_SERIAL_BAUDRATE, params->size, params->data[0]);
  86. return bp_tag_next(params);
  87. }
  88. #ifdef CONFIG_OF_LIBFDT
  89. static struct bp_tag *setup_fdt_tag(struct bp_tag *params, void *fdt_start)
  90. {
  91. params->id = BP_TAG_FDT;
  92. params->size = sizeof(unsigned long);
  93. params->data[0] = (unsigned long)fdt_start;
  94. printf(" FDT: tag:0x%04x, size:%u, start:0x%lx\n",
  95. BP_TAG_FDT, params->size, params->data[0]);
  96. return bp_tag_next(params);
  97. }
  98. #endif
  99. /*
  100. * Boot Linux.
  101. */
  102. int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
  103. {
  104. struct bp_tag *params, *params_start;
  105. ulong initrd_start, initrd_end;
  106. char *commandline = env_get("bootargs");
  107. if (!(flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)))
  108. return 0;
  109. show_boot_progress(15);
  110. if (images->rd_start) {
  111. initrd_start = images->rd_start;
  112. initrd_end = images->rd_end;
  113. } else {
  114. initrd_start = 0;
  115. initrd_end = 0;
  116. }
  117. params_start = (struct bp_tag *)gd->bd->bi_boot_params;
  118. params = params_start;
  119. params = setup_first_tag(params);
  120. params = setup_memory_tag(params);
  121. params = setup_commandline_tag(params, commandline);
  122. params = setup_serial_tag(params);
  123. if (initrd_start)
  124. params = setup_ramdisk_tag(params, initrd_start, initrd_end);
  125. #ifdef CONFIG_OF_LIBFDT
  126. if (images->ft_addr)
  127. params = setup_fdt_tag(params, images->ft_addr);
  128. #endif
  129. printf("\n");
  130. params = setup_last_tag(params);
  131. show_boot_progress(15);
  132. printf("Transferring Control to Linux @0x%08lx ...\n\n",
  133. (ulong)images->ep);
  134. flush_dcache_range((unsigned long)params_start, (unsigned long)params);
  135. if (flag & BOOTM_STATE_OS_FAKE_GO)
  136. return 0;
  137. /*
  138. * _start() in vmlinux expects boot params in register a2.
  139. * NOTE:
  140. * Disable/delete your u-boot breakpoints before stepping into linux.
  141. */
  142. asm volatile ("mov a2, %0\n\t"
  143. "jx %1\n\t"
  144. : : "a" (params_start), "a" (images->ep)
  145. : "a2");
  146. /* Does not return */
  147. return 1;
  148. }