init.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /* init.c -- Initialize GRUB on the newworld mac (PPC). */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <grub/kernel.h>
  20. #include <grub/dl.h>
  21. #include <grub/disk.h>
  22. #include <grub/mm.h>
  23. #include <grub/partition.h>
  24. #include <grub/normal.h>
  25. #include <grub/fs.h>
  26. #include <grub/setjmp.h>
  27. #include <grub/env.h>
  28. #include <grub/misc.h>
  29. #include <grub/time.h>
  30. #include <grub/machine/console.h>
  31. #include <grub/machine/kernel.h>
  32. #include <grub/cpu/kernel.h>
  33. #include <grub/ieee1275/ofdisk.h>
  34. #include <grub/ieee1275/ieee1275.h>
  35. /* The minimal heap size we can live with. */
  36. #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024)
  37. /* The maximum heap size we're going to claim */
  38. #define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024)
  39. /* If possible, we will avoid claiming heap above this address, because it
  40. seems to cause relocation problems with OSes that link at 4 MiB */
  41. #define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024)
  42. void
  43. grub_exit (void)
  44. {
  45. grub_ieee1275_exit ();
  46. }
  47. /* Translate an OF filesystem path (separated by backslashes), into a GRUB
  48. path (separated by forward slashes). */
  49. static void
  50. grub_translate_ieee1275_path (char *filepath)
  51. {
  52. char *backslash;
  53. backslash = grub_strchr (filepath, '\\');
  54. while (backslash != 0)
  55. {
  56. *backslash = '/';
  57. backslash = grub_strchr (filepath, '\\');
  58. }
  59. }
  60. void
  61. grub_machine_set_prefix (void)
  62. {
  63. char bootpath[64]; /* XXX check length */
  64. char *filename;
  65. char *prefix;
  66. if (grub_prefix[0])
  67. {
  68. grub_env_set ("prefix", grub_prefix);
  69. /* Prefix is hardcoded in the core image. */
  70. return;
  71. }
  72. if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootpath", &bootpath,
  73. sizeof (bootpath), 0))
  74. {
  75. /* Should never happen. */
  76. grub_printf ("/chosen/bootpath property missing!\n");
  77. grub_env_set ("prefix", "");
  78. return;
  79. }
  80. /* Transform an OF device path to a GRUB path. */
  81. prefix = grub_ieee1275_encode_devname (bootpath);
  82. filename = grub_ieee1275_get_filename (bootpath);
  83. if (filename)
  84. {
  85. char *newprefix;
  86. char *lastslash = grub_strrchr (filename, '\\');
  87. /* Truncate at last directory. */
  88. if (lastslash)
  89. {
  90. *lastslash = '\0';
  91. grub_translate_ieee1275_path (filename);
  92. newprefix = grub_xasprintf ("%s%s", prefix, filename);
  93. if (newprefix)
  94. {
  95. grub_free (prefix);
  96. prefix = newprefix;
  97. }
  98. }
  99. }
  100. grub_env_set ("prefix", prefix);
  101. grub_free (filename);
  102. grub_free (prefix);
  103. }
  104. static int
  105. heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type,
  106. void *closure)
  107. {
  108. unsigned long *total = closure;
  109. if (type != 1)
  110. return 0;
  111. if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM))
  112. {
  113. if (addr + len <= 0x180000)
  114. return 0;
  115. if (addr < 0x180000)
  116. {
  117. len = addr + len - 0x180000;
  118. addr = 0x180000;
  119. }
  120. }
  121. len -= 1; /* Required for some firmware. */
  122. /* Never exceed HEAP_MAX_SIZE */
  123. if (*total + len > HEAP_MAX_SIZE)
  124. len = HEAP_MAX_SIZE - *total;
  125. /* Avoid claiming anything above HEAP_MAX_ADDR, if possible. */
  126. if ((addr < HEAP_MAX_ADDR) && /* if it's too late, don't bother */
  127. (addr + len > HEAP_MAX_ADDR) && /* if it wasn't available anyway, don't bother */
  128. (*total + (HEAP_MAX_ADDR - addr) > HEAP_MIN_SIZE)) /* only limit ourselves when we can afford to */
  129. len = HEAP_MAX_ADDR - addr;
  130. /* In theory, firmware should already prevent this from happening by not
  131. listing our own image in /memory/available. The check below is intended
  132. as a safeguard in case that doesn't happen. However, it doesn't protect
  133. us from corrupting our module area, which extends up to a
  134. yet-undetermined region above _end. */
  135. if ((addr < (grub_addr_t) grub_bss_end) &&
  136. ((addr + len) > (grub_addr_t) grub_code_start))
  137. {
  138. grub_printf ("Warning: attempt to claim over our own code!\n");
  139. len = 0;
  140. }
  141. if (len)
  142. {
  143. /* Claim and use it. */
  144. if (grub_claimmap (addr, len) < 0)
  145. return grub_error (GRUB_ERR_OUT_OF_MEMORY,
  146. "failed to claim heap at 0x%llx, len 0x%llx\n",
  147. addr, len);
  148. grub_mm_init_region ((void *) (grub_addr_t) addr, len);
  149. }
  150. *total += len;
  151. if (*total >= HEAP_MAX_SIZE)
  152. return 1;
  153. return 0;
  154. }
  155. /* Claim some available memory in the first /memory node. */
  156. static void grub_claim_heap (void)
  157. {
  158. unsigned long total = 0;
  159. if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_FORCE_CLAIM))
  160. {
  161. grub_addr_t start;
  162. start = ALIGN_UP ((grub_addr_t) grub_bss_end, 4096);
  163. heap_init (start, HEAP_MAX_ADDR - start, 1, &total);
  164. }
  165. else
  166. grub_machine_mmap_iterate (heap_init, &total);
  167. }
  168. #ifdef __i386__
  169. grub_uint32_t grub_upper_mem;
  170. static int
  171. find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type,
  172. void *closure __attribute__ ((unused)))
  173. {
  174. if (type == 1 && addr == 0x100000)
  175. {
  176. grub_upper_mem = len;
  177. return 1;
  178. }
  179. return 0;
  180. }
  181. /* We need to call this before grub_claim_memory. */
  182. static void
  183. grub_get_extended_memory (void)
  184. {
  185. grub_machine_mmap_iterate (find_ext_mem, 0);
  186. }
  187. #endif
  188. static grub_uint64_t ieee1275_get_time_ms (void);
  189. void
  190. grub_machine_init (void)
  191. {
  192. char args[256];
  193. grub_ssize_t actual;
  194. grub_ieee1275_init ();
  195. grub_console_init ();
  196. #ifdef __i386__
  197. grub_get_extended_memory ();
  198. #endif
  199. grub_claim_heap ();
  200. grub_ofdisk_init ();
  201. /* Process commandline. */
  202. if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
  203. sizeof args, &actual) == 0
  204. && actual > 1)
  205. {
  206. int i = 0;
  207. while (i < actual)
  208. {
  209. char *command = &args[i];
  210. char *end;
  211. char *val;
  212. end = grub_strchr (command, ';');
  213. if (end == 0)
  214. i = actual; /* No more commands after this one. */
  215. else
  216. {
  217. *end = '\0';
  218. i += end - command + 1;
  219. while (grub_isspace(args[i]))
  220. i++;
  221. }
  222. /* Process command. */
  223. val = grub_strchr (command, '=');
  224. if (val)
  225. {
  226. *val = '\0';
  227. grub_env_set (command, val + 1);
  228. }
  229. }
  230. }
  231. grub_install_get_time_ms (ieee1275_get_time_ms);
  232. }
  233. void
  234. grub_machine_fini (void)
  235. {
  236. grub_ofdisk_fini ();
  237. grub_console_fini ();
  238. }
  239. static grub_uint64_t
  240. ieee1275_get_time_ms (void)
  241. {
  242. grub_uint32_t msecs = 0;
  243. grub_ieee1275_milliseconds (&msecs);
  244. return msecs;
  245. }
  246. grub_uint32_t
  247. grub_get_rtc (void)
  248. {
  249. return ieee1275_get_time_ms ();
  250. }