main.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /*-
  2. * Copyright (c) 2000 Benno Rice <benno@jeamland.net>
  3. * Copyright (c) 2000 Stephane Potvin <sepotvin@videotron.ca>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
  16. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  19. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  20. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  21. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  23. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  24. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  25. * SUCH DAMAGE.
  26. */
  27. #include <sys/endian.h>
  28. #include <stand.h>
  29. #include "openfirm.h"
  30. #include "libofw.h"
  31. #include "bootstrap.h"
  32. #include <machine/asm.h>
  33. #include <machine/psl.h>
  34. struct arch_switch archsw; /* MI/MD interface boundary */
  35. extern char end[];
  36. uint32_t acells, scells;
  37. static char bootargs[128];
  38. #define HEAP_SIZE 0x800000
  39. static char heap[HEAP_SIZE]; // In BSS, so uses no space
  40. #define OF_puts(fd, text) OF_write(fd, text, strlen(text))
  41. static __inline register_t
  42. mfmsr(void)
  43. {
  44. register_t value;
  45. __asm __volatile ("mfmsr %0" : "=r"(value));
  46. return (value);
  47. }
  48. void
  49. init_heap(void)
  50. {
  51. bzero(heap, HEAP_SIZE);
  52. setheap(heap, (void *)((uintptr_t)heap + HEAP_SIZE));
  53. }
  54. uint64_t
  55. memsize(void)
  56. {
  57. phandle_t memoryp;
  58. cell_t reg[24];
  59. int i, sz;
  60. uint64_t memsz;
  61. memsz = 0;
  62. memoryp = OF_instance_to_package(memory);
  63. sz = OF_getencprop(memoryp, "reg", &reg[0], sizeof(reg));
  64. sz /= sizeof(reg[0]);
  65. for (i = 0; i < sz; i += (acells + scells)) {
  66. if (scells > 1)
  67. memsz += (uint64_t)reg[i + acells] << 32;
  68. memsz += reg[i + acells + scells - 1];
  69. }
  70. return (memsz);
  71. }
  72. #ifdef CAS
  73. extern int ppc64_cas(void);
  74. static int
  75. ppc64_autoload(void)
  76. {
  77. const char *cas;
  78. if ((cas = getenv("cas")) && cas[0] == '1')
  79. if (ppc64_cas() != 0)
  80. return (-1);
  81. return (ofw_autoload());
  82. }
  83. #endif
  84. #if BYTE_ORDER == LITTLE_ENDIAN
  85. /*
  86. * In Little-endian, we cannot just branch to the client interface. Since
  87. * the client interface is big endian, we have to rfid to it.
  88. * Likewise, when execution resumes, we are in the wrong endianness so
  89. * we must do a fixup before returning to the caller.
  90. */
  91. static int (*openfirmware_entry)(void *);
  92. extern int openfirmware_trampoline(void *buf, int (*cb)(void *));
  93. /*
  94. * Wrapper to pass the real entry point to our trampoline.
  95. */
  96. static int
  97. openfirmware_docall(void *buf)
  98. {
  99. return openfirmware_trampoline(buf, openfirmware_entry);
  100. }
  101. #endif
  102. int
  103. main(int (*openfirm)(void *))
  104. {
  105. phandle_t root;
  106. int i;
  107. char bootpath[64];
  108. char *ch;
  109. int bargc;
  110. char **bargv;
  111. /*
  112. * Initialise the Open Firmware routines by giving them the entry point.
  113. */
  114. #if BYTE_ORDER == LITTLE_ENDIAN
  115. /*
  116. * Use a trampoline entry point for endian fixups.
  117. */
  118. openfirmware_entry = openfirm;
  119. OF_init(openfirmware_docall);
  120. #else
  121. OF_init(openfirm);
  122. #endif
  123. root = OF_finddevice("/");
  124. scells = acells = 1;
  125. OF_getencprop(root, "#address-cells", &acells, sizeof(acells));
  126. OF_getencprop(root, "#size-cells", &scells, sizeof(scells));
  127. /*
  128. * Initialise the heap as early as possible. Once this is done,
  129. * alloc() is usable. The stack is buried inside us, so this is
  130. * safe.
  131. */
  132. init_heap();
  133. /*
  134. * Set up console.
  135. */
  136. cons_probe();
  137. archsw.arch_getdev = ofw_getdev;
  138. archsw.arch_copyin = ofw_copyin;
  139. archsw.arch_copyout = ofw_copyout;
  140. archsw.arch_readin = ofw_readin;
  141. #ifdef CAS
  142. setenv("cas", "1", 0);
  143. archsw.arch_autoload = ppc64_autoload;
  144. #else
  145. archsw.arch_autoload = ofw_autoload;
  146. #endif
  147. /* Set up currdev variable to have hooks in place. */
  148. env_setenv("currdev", EV_VOLATILE, "", gen_setcurrdev, env_nounset);
  149. devinit();
  150. printf("\n%s", bootprog_info);
  151. printf("Memory: %lldKB\n", memsize() / 1024);
  152. OF_getprop(chosen, "bootpath", bootpath, 64);
  153. ch = strchr(bootpath, ':');
  154. *ch = '\0';
  155. printf("Booted from: %s\n", bootpath);
  156. printf("\n");
  157. /*
  158. * Only parse the first bootarg if present. It should
  159. * be simple to handle extra arguments
  160. */
  161. OF_getprop(chosen, "bootargs", bootargs, sizeof(bootargs));
  162. bargc = 0;
  163. parse(&bargc, &bargv, bootargs);
  164. if (bargc == 1)
  165. env_setenv("currdev", EV_VOLATILE, bargv[0], gen_setcurrdev,
  166. env_nounset);
  167. else
  168. env_setenv("currdev", EV_VOLATILE, bootpath,
  169. gen_setcurrdev, env_nounset);
  170. env_setenv("loaddev", EV_VOLATILE, bootpath, env_noset,
  171. env_nounset);
  172. setenv("LINES", "24", 1); /* optional */
  173. /*
  174. * On non-Apple hardware, where it works reliably, pass flattened
  175. * device trees to the kernel by default instead of OF CI pointers.
  176. * Apple hardware is the only virtual-mode OF implementation in
  177. * existence, so far as I am aware, so use that as a flag.
  178. */
  179. if (!(mfmsr() & PSL_DR))
  180. setenv("usefdt", "1", 1);
  181. interact(); /* doesn't return */
  182. OF_exit();
  183. return 0;
  184. }
  185. COMMAND_SET(halt, "halt", "halt the system", command_halt);
  186. static int
  187. command_halt(int argc, char *argv[])
  188. {
  189. OF_exit();
  190. return (CMD_OK);
  191. }
  192. COMMAND_SET(memmap, "memmap", "print memory map", command_memmap);
  193. int
  194. command_memmap(int argc, char **argv)
  195. {
  196. ofw_memmap(acells);
  197. return (CMD_OK);
  198. }