init.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945
  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 <stddef.h> /* offsetof() */
  20. #include <grub/kernel.h>
  21. #include <grub/dl.h>
  22. #include <grub/disk.h>
  23. #include <grub/mm.h>
  24. #include <grub/partition.h>
  25. #include <grub/normal.h>
  26. #include <grub/fs.h>
  27. #include <grub/setjmp.h>
  28. #include <grub/env.h>
  29. #include <grub/misc.h>
  30. #include <grub/time.h>
  31. #include <grub/ieee1275/console.h>
  32. #include <grub/ieee1275/ofdisk.h>
  33. #ifdef __sparc__
  34. #include <grub/ieee1275/obdisk.h>
  35. #endif
  36. #include <grub/ieee1275/ieee1275.h>
  37. #include <grub/net.h>
  38. #include <grub/offsets.h>
  39. #include <grub/memory.h>
  40. #include <grub/loader.h>
  41. #ifdef __i386__
  42. #include <grub/cpu/tsc.h>
  43. #endif
  44. #ifdef __sparc__
  45. #include <grub/machine/kernel.h>
  46. #endif
  47. #if defined(__powerpc__) || defined(__i386__)
  48. #include <grub/ieee1275/alloc.h>
  49. #endif
  50. /* The maximum heap size we're going to claim at boot. Not used by sparc. */
  51. #ifdef __i386__
  52. #define HEAP_MAX_SIZE (unsigned long) (64 * 1024 * 1024)
  53. #else /* __powerpc__ */
  54. #define HEAP_MAX_SIZE (unsigned long) (32 * 1024 * 1024)
  55. #endif
  56. /* RMO max. address at 768 MB */
  57. #define RMO_ADDR_MAX (grub_uint64_t) (768 * 1024 * 1024)
  58. /*
  59. * The amount of OF space we will not claim here so as to leave space for
  60. * the loader and linux to service early allocations.
  61. *
  62. * In 2021, Daniel Axtens claims that we should leave at least 128MB to
  63. * ensure we can load a stock kernel and initrd on a pseries guest with
  64. * a 512MB real memory area under PowerVM.
  65. */
  66. #define RUNTIME_MIN_SPACE (128UL * 1024 * 1024)
  67. extern char _start[];
  68. extern char _end[];
  69. #ifdef __sparc__
  70. grub_addr_t grub_ieee1275_original_stack;
  71. #endif
  72. /* Options vector5 properties. */
  73. #define LPAR 0x80
  74. #define SPLPAR 0x40
  75. #define DYN_RCON_MEM 0x20
  76. #define LARGE_PAGES 0x10
  77. #define DONATE_DCPU_CLS 0x02
  78. #define PCI_EXP 0x01
  79. #define BYTE2 (LPAR | SPLPAR | DYN_RCON_MEM | LARGE_PAGES | DONATE_DCPU_CLS | PCI_EXP)
  80. #define CMOC 0x80
  81. #define EXT_CMO 0x40
  82. #define CMO (CMOC | EXT_CMO)
  83. #define ASSOC_REF 0x80
  84. #define AFFINITY 0x40
  85. #define NUMA 0x20
  86. #define ASSOCIATIVITY (ASSOC_REF | AFFINITY | NUMA)
  87. #define HOTPLUG_INTRPT 0x04
  88. #define HPT_RESIZE 0x01
  89. #define BIN_OPTS (HOTPLUG_INTRPT | HPT_RESIZE)
  90. #define MAX_CPU 256
  91. #define PFO_HWRNG 0x80000000
  92. #define PFO_HW_COMP 0x40000000
  93. #define PFO_ENCRYPT 0x20000000
  94. #define PLATFORM_FACILITIES (PFO_HWRNG | PFO_HW_COMP | PFO_ENCRYPT)
  95. #define SUB_PROCESSORS 1
  96. #define DY_MEM_V2 0x80
  97. #define DRC_INFO 0x40
  98. #define BYTE22 (DY_MEM_V2 | DRC_INFO)
  99. void
  100. grub_exit (void)
  101. {
  102. grub_ieee1275_exit ();
  103. }
  104. /* Translate an OF filesystem path (separated by backslashes), into a GRUB
  105. path (separated by forward slashes). */
  106. static void
  107. grub_translate_ieee1275_path (char *filepath)
  108. {
  109. char *backslash;
  110. backslash = grub_strchr (filepath, '\\');
  111. while (backslash != 0)
  112. {
  113. *backslash = '/';
  114. backslash = grub_strchr (filepath, '\\');
  115. }
  116. }
  117. void (*grub_ieee1275_net_config) (const char *dev, char **device, char **path,
  118. char *bootpath);
  119. void
  120. grub_machine_get_bootlocation (char **device, char **path)
  121. {
  122. char *bootpath;
  123. char *filename;
  124. char *type;
  125. bootpath = grub_ieee1275_get_boot_dev ();
  126. if (! bootpath)
  127. return;
  128. /* Transform an OF device path to a GRUB path. */
  129. type = grub_ieee1275_get_device_type (bootpath);
  130. if (type && grub_strcmp (type, "network") == 0)
  131. {
  132. char *dev, *canon;
  133. char *ptr;
  134. dev = grub_ieee1275_get_aliasdevname (bootpath);
  135. canon = grub_ieee1275_canonicalise_devname (dev);
  136. if (! canon)
  137. return;
  138. ptr = canon + grub_strlen (canon) - 1;
  139. while (ptr > canon && (*ptr == ',' || *ptr == ':'))
  140. ptr--;
  141. ptr++;
  142. *ptr = 0;
  143. if (grub_ieee1275_net_config)
  144. grub_ieee1275_net_config (canon, device, path, bootpath);
  145. grub_free (dev);
  146. grub_free (canon);
  147. }
  148. else
  149. *device = grub_ieee1275_encode_devname (bootpath);
  150. grub_free (type);
  151. filename = grub_ieee1275_get_filename (bootpath);
  152. if (filename)
  153. {
  154. char *lastslash = grub_strrchr (filename, '\\');
  155. /* Truncate at last directory. */
  156. if (lastslash)
  157. {
  158. *lastslash = '\0';
  159. grub_translate_ieee1275_path (filename);
  160. *path = filename;
  161. }
  162. }
  163. grub_free (bootpath);
  164. }
  165. /* Claim some available memory in the first /memory node. */
  166. #ifdef __sparc__
  167. static void
  168. grub_claim_heap (void)
  169. {
  170. grub_mm_init_region ((void *) (grub_modules_get_end ()
  171. + GRUB_KERNEL_MACHINE_STACK_SIZE), 0x200000);
  172. }
  173. #else
  174. /* Helpers for mm on powerpc. */
  175. /* ibm,kernel-dump data structures */
  176. struct kd_section
  177. {
  178. grub_uint32_t flags;
  179. grub_uint16_t src_datatype;
  180. #define KD_SRC_DATATYPE_REAL_MODE_REGION 0x0011
  181. grub_uint16_t error_flags;
  182. grub_uint64_t src_address;
  183. grub_uint64_t num_bytes;
  184. grub_uint64_t act_bytes;
  185. grub_uint64_t dst_address;
  186. } GRUB_PACKED;
  187. #define MAX_KD_SECTIONS 10
  188. struct kernel_dump
  189. {
  190. grub_uint32_t format;
  191. grub_uint16_t num_sections;
  192. grub_uint16_t status_flags;
  193. grub_uint32_t offset_1st_section;
  194. grub_uint32_t num_blocks;
  195. grub_uint64_t start_block;
  196. grub_uint64_t num_blocks_avail;
  197. grub_uint32_t offet_path_string;
  198. grub_uint32_t max_time_allowed;
  199. struct kd_section kds[MAX_KD_SECTIONS]; /* offset_1st_section should point to kds[0] */
  200. } GRUB_PACKED;
  201. /*
  202. * Determine if a kernel dump exists and if it does, then determine the highest
  203. * address that grub can use for memory allocations.
  204. * The caller must have initialized *highest to rmo_top. *highest will not
  205. * be modified if no kernel dump is found.
  206. */
  207. static void
  208. check_kernel_dump (grub_uint64_t *highest)
  209. {
  210. struct kernel_dump kernel_dump;
  211. grub_ssize_t kernel_dump_size;
  212. grub_ieee1275_phandle_t rtas;
  213. struct kd_section *kds;
  214. grub_size_t i;
  215. /* If there's a kernel-dump it must have at least one section */
  216. if (grub_ieee1275_finddevice ("/rtas", &rtas) ||
  217. grub_ieee1275_get_property (rtas, "ibm,kernel-dump", &kernel_dump,
  218. sizeof (kernel_dump), &kernel_dump_size) ||
  219. kernel_dump_size <= (grub_ssize_t) offsetof (struct kernel_dump, kds[1]))
  220. return;
  221. kernel_dump_size = grub_min (kernel_dump_size, (grub_ssize_t) sizeof (kernel_dump));
  222. if (grub_be_to_cpu32 (kernel_dump.format) != 1)
  223. {
  224. grub_printf (_("Error: ibm,kernel-dump has an unexpected format version '%u'\n"),
  225. grub_be_to_cpu32 (kernel_dump.format));
  226. return;
  227. }
  228. if (grub_be_to_cpu16 (kernel_dump.num_sections) > MAX_KD_SECTIONS)
  229. {
  230. grub_printf (_("Error: Too many kernel dump sections: %d\n"),
  231. grub_be_to_cpu32 (kernel_dump.num_sections));
  232. return;
  233. }
  234. for (i = 0; i < grub_be_to_cpu16 (kernel_dump.num_sections); i++)
  235. {
  236. kds = (struct kd_section *) ((grub_addr_t) &kernel_dump +
  237. grub_be_to_cpu32 (kernel_dump.offset_1st_section) +
  238. i * sizeof (struct kd_section));
  239. /* sanity check the address is within the 'kernel_dump' struct */
  240. if ((grub_addr_t) kds > (grub_addr_t) &kernel_dump + kernel_dump_size + sizeof (*kds))
  241. {
  242. grub_printf (_("Error: 'kds' address beyond last available section\n"));
  243. return;
  244. }
  245. if ((grub_be_to_cpu16 (kds->src_datatype) == KD_SRC_DATATYPE_REAL_MODE_REGION) &&
  246. (grub_be_to_cpu64 (kds->src_address) == 0))
  247. {
  248. *highest = grub_min (*highest, grub_be_to_cpu64 (kds->num_bytes));
  249. break;
  250. }
  251. }
  252. return;
  253. }
  254. /*
  255. * How much memory does OF believe exists in total?
  256. *
  257. * This isn't necessarily the true total. It can be the total memory
  258. * accessible in real mode for a pseries guest, for example.
  259. */
  260. static grub_uint64_t rmo_top;
  261. static int
  262. count_free (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
  263. void *data)
  264. {
  265. if (type != GRUB_MEMORY_AVAILABLE)
  266. return 0;
  267. /* Do not consider memory beyond 4GB */
  268. if (addr > 0xffffffffULL)
  269. return 0;
  270. if (addr + len > 0xffffffffULL)
  271. len = 0xffffffffULL - addr;
  272. *(grub_uint32_t *) data += len;
  273. return 0;
  274. }
  275. int
  276. grub_regions_claim (grub_uint64_t addr, grub_uint64_t len,
  277. grub_memory_type_t type, void *data)
  278. {
  279. struct regions_claim_request *rcr = data;
  280. grub_uint64_t linux_rmo_save;
  281. if (type != GRUB_MEMORY_AVAILABLE)
  282. return 0;
  283. /* Do not consider memory beyond 4GB */
  284. if (addr > 0xffffffffULL)
  285. return 0;
  286. if (addr + len > 0xffffffffULL)
  287. len = 0xffffffffULL - addr;
  288. if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM))
  289. {
  290. if (addr + len <= 0x180000)
  291. return 0;
  292. if (addr < 0x180000)
  293. {
  294. len = addr + len - 0x180000;
  295. addr = 0x180000;
  296. }
  297. }
  298. /* In theory, firmware should already prevent this from happening by not
  299. listing our own image in /memory/available. The check below is intended
  300. as a safeguard in case that doesn't happen. However, it doesn't protect
  301. us from corrupting our module area, which extends up to a
  302. yet-undetermined region above _end. */
  303. if ((addr < (grub_addr_t) _end) && ((addr + len) > (grub_addr_t) _start))
  304. {
  305. grub_printf ("Warning: attempt to claim over our own code!\n");
  306. len = 0;
  307. }
  308. /*
  309. * Linux likes to claim memory at min(RMO top, 768MB) and works down
  310. * without reference to /memory/available. (See prom_init.c::alloc_down)
  311. *
  312. * If this block contains min(RMO top, 768MB), do not claim below that for
  313. * at least a few MB (this is where RTAS, SML and potentially TCEs live).
  314. *
  315. * We also need to leave enough space for the DT in the RMA. (See
  316. * prom_init.c::alloc_up)
  317. *
  318. * Finally, we also want to make sure that when grub loads the kernel,
  319. * it isn't going to use up all the memory we're trying to reserve! So
  320. * enforce our entire RUNTIME_MIN_SPACE here (no fadump):
  321. *
  322. * | Top of memory == upper_mem_limit -|
  323. * | |
  324. * | available |
  325. * | |
  326. * |---------- 768 MB ----------|
  327. * | |
  328. * | reserved |
  329. * | |
  330. * |--- 768 MB - runtime min space ---|
  331. * | |
  332. * | available |
  333. * | |
  334. * |---------- 0 MB ----------|
  335. *
  336. * In case fadump is used, we allow the following:
  337. *
  338. * |---------- Top of memory ----------|
  339. * | |
  340. * | unavailable |
  341. * | (kernel dump area) |
  342. * | |
  343. * |--------- upper_mem_limit ---------|
  344. * | |
  345. * | available |
  346. * | |
  347. * |---------- 768 MB ----------|
  348. * | |
  349. * | reserved |
  350. * | |
  351. * |--- 768 MB - runtime min space ---|
  352. * | |
  353. * | available |
  354. * | |
  355. * |---------- 0 MB ----------|
  356. *
  357. * Edge cases:
  358. *
  359. * - Total memory less than RUNTIME_MIN_SPACE: only claim up to HEAP_MAX_SIZE.
  360. * (enforced elsewhere)
  361. *
  362. * - Total memory between RUNTIME_MIN_SPACE and 768MB:
  363. *
  364. * |---------- Top of memory ----------|
  365. * | |
  366. * | reserved |
  367. * | |
  368. * |---- top - runtime min space ----|
  369. * | |
  370. * | available |
  371. * | |
  372. * |---------- 0 MB ----------|
  373. *
  374. * This by itself would not leave us with RUNTIME_MIN_SPACE of free bytes: if
  375. * rmo_top < 768MB, we will almost certainly have FW claims in the reserved
  376. * region. We try to address that elsewhere: grub_ieee1275_mm_add_region will
  377. * not call us if the resulting free space would be less than RUNTIME_MIN_SPACE.
  378. */
  379. linux_rmo_save = grub_min (RMO_ADDR_MAX, rmo_top) - RUNTIME_MIN_SPACE;
  380. if (rmo_top > RUNTIME_MIN_SPACE)
  381. {
  382. if (rmo_top <= RMO_ADDR_MAX)
  383. {
  384. if (addr > linux_rmo_save)
  385. {
  386. grub_dprintf ("ieee1275", "rejecting region in RUNTIME_MIN_SPACE reservation (%llx)\n",
  387. addr);
  388. return 0;
  389. }
  390. else if (addr + len > linux_rmo_save)
  391. {
  392. grub_dprintf ("ieee1275", "capping region: (%llx -> %llx) -> (%llx -> %llx)\n",
  393. addr, addr + len, addr, rmo_top - RUNTIME_MIN_SPACE);
  394. len = linux_rmo_save - addr;
  395. }
  396. }
  397. else
  398. {
  399. grub_uint64_t upper_mem_limit = rmo_top;
  400. grub_uint64_t orig_addr = addr;
  401. check_kernel_dump (&upper_mem_limit);
  402. grub_dprintf ("ieee1275", "upper_mem_limit is at %llx (%lld MiB)\n",
  403. upper_mem_limit, upper_mem_limit >> 20);
  404. /*
  405. * we order these cases to prefer higher addresses and avoid some
  406. * splitting issues
  407. * The following shows the order of variables:
  408. * no kernel dump: linux_rmo_save < RMO_ADDR_MAX <= upper_mem_limit == rmo_top
  409. * with kernel dump: liuxx_rmo_save < RMO_ADDR_MAX <= upper_mem_limit <= rmo_top
  410. */
  411. if (addr < RMO_ADDR_MAX && (addr + len) > RMO_ADDR_MAX && upper_mem_limit >= RMO_ADDR_MAX)
  412. {
  413. grub_dprintf ("ieee1275",
  414. "adjusting region for RUNTIME_MIN_SPACE: (%llx -> %llx) -> (%llx -> %llx)\n",
  415. addr, addr + len, RMO_ADDR_MAX, addr + len);
  416. len = (addr + len) - RMO_ADDR_MAX;
  417. addr = RMO_ADDR_MAX;
  418. /* We must not exceed the upper_mem_limit (assuming it's >= RMO_ADDR_MAX) */
  419. if (addr + len > upper_mem_limit)
  420. {
  421. /* Take the bigger chunk from either below linux_rmo_save or above RMO_ADDR_MAX. */
  422. len = upper_mem_limit - addr;
  423. if (orig_addr < linux_rmo_save && linux_rmo_save - orig_addr > len)
  424. {
  425. /* lower part is bigger */
  426. addr = orig_addr;
  427. len = linux_rmo_save - addr;
  428. }
  429. grub_dprintf ("ieee1275", "re-adjusted region to: (%llx -> %llx)\n",
  430. addr, addr + len);
  431. if (len == 0)
  432. return 0;
  433. }
  434. }
  435. else if ((addr < linux_rmo_save) && ((addr + len) > linux_rmo_save))
  436. {
  437. grub_dprintf ("ieee1275", "capping region: (%llx -> %llx) -> (%llx -> %llx)\n",
  438. addr, addr + len, addr, linux_rmo_save);
  439. len = linux_rmo_save - addr;
  440. }
  441. else if (addr >= linux_rmo_save && (addr + len) <= RMO_ADDR_MAX)
  442. {
  443. grub_dprintf ("ieee1275", "rejecting region in RUNTIME_MIN_SPACE reservation (%llx)\n",
  444. addr);
  445. return 0;
  446. }
  447. }
  448. }
  449. /* Honor alignment restrictions on candidate addr */
  450. if (rcr->align)
  451. {
  452. grub_uint64_t align_addr = ALIGN_UP (addr, rcr->align);
  453. grub_uint64_t d = align_addr - addr;
  454. if (d > len)
  455. return 0;
  456. len -= d;
  457. addr = align_addr;
  458. }
  459. if (rcr->flags & GRUB_MM_ADD_REGION_CONSECUTIVE && len < rcr->total)
  460. return 0;
  461. if (len > rcr->total)
  462. len = rcr->total;
  463. if (len)
  464. {
  465. grub_err_t err;
  466. /* Claim and use it. */
  467. err = grub_claimmap (addr, len);
  468. if (err)
  469. return err;
  470. if (rcr->init_region)
  471. grub_mm_init_region ((void *) (grub_addr_t) addr, len);
  472. rcr->total -= len;
  473. rcr->addr = addr;
  474. }
  475. *(grub_uint32_t *) data = rcr->total;
  476. if (rcr->total == 0)
  477. return 1;
  478. return 0;
  479. }
  480. static int
  481. heap_init (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
  482. void *data)
  483. {
  484. struct regions_claim_request rcr = {
  485. .flags = GRUB_MM_ADD_REGION_NONE,
  486. .total = *(grub_uint32_t *) data,
  487. .init_region = true,
  488. };
  489. int ret;
  490. ret = grub_regions_claim (addr, len, type, &rcr);
  491. *(grub_uint32_t *) data = rcr.total;
  492. return ret;
  493. }
  494. static int
  495. region_claim (grub_uint64_t addr, grub_uint64_t len, grub_memory_type_t type,
  496. void *data)
  497. {
  498. struct regions_claim_request rcr = {
  499. .flags = GRUB_MM_ADD_REGION_CONSECUTIVE,
  500. .total = *(grub_uint32_t *) data,
  501. .init_region = true,
  502. };
  503. int ret;
  504. ret = grub_regions_claim (addr, len, type, &rcr);
  505. *(grub_uint32_t *) data = rcr.total;
  506. return ret;
  507. }
  508. static grub_err_t
  509. grub_ieee1275_mm_add_region (grub_size_t size, unsigned int flags)
  510. {
  511. grub_uint32_t free_memory = 0;
  512. grub_uint32_t avail = 0;
  513. grub_uint32_t total;
  514. grub_dprintf ("ieee1275", "mm requested region of size %x, flags %x\n",
  515. size, flags);
  516. /*
  517. * Update free memory each time, which is a bit inefficient but guards us
  518. * against a situation where some OF driver goes out to firmware for
  519. * memory and we don't realise.
  520. */
  521. grub_machine_mmap_iterate (count_free, &free_memory);
  522. /* Ensure we leave enough space to boot. */
  523. if (free_memory <= RUNTIME_MIN_SPACE + size)
  524. {
  525. grub_dprintf ("ieee1275", "Cannot satisfy allocation and retain minimum runtime space\n");
  526. return GRUB_ERR_OUT_OF_MEMORY;
  527. }
  528. if (free_memory > RUNTIME_MIN_SPACE)
  529. avail = free_memory - RUNTIME_MIN_SPACE;
  530. grub_dprintf ("ieee1275", "free = 0x%x available = 0x%x\n", free_memory, avail);
  531. if (flags & GRUB_MM_ADD_REGION_CONSECUTIVE)
  532. {
  533. /* first try rounding up hard for the sake of speed */
  534. total = grub_max (ALIGN_UP (size, 1024 * 1024) + 1024 * 1024, 32 * 1024 * 1024);
  535. total = grub_min (avail, total);
  536. grub_dprintf ("ieee1275", "looking for %x bytes of memory (%x requested)\n", total, size);
  537. grub_machine_mmap_iterate (region_claim, &total);
  538. grub_dprintf ("ieee1275", "get memory from fw %s\n", total == 0 ? "succeeded" : "failed");
  539. if (total != 0)
  540. {
  541. total = grub_min (avail, size);
  542. grub_dprintf ("ieee1275", "fallback for %x bytes of memory (%x requested)\n", total, size);
  543. grub_machine_mmap_iterate (region_claim, &total);
  544. grub_dprintf ("ieee1275", "fallback from fw %s\n", total == 0 ? "succeeded" : "failed");
  545. }
  546. }
  547. else
  548. {
  549. /* provide padding for a grub_mm_header_t and region */
  550. total = grub_min (avail, size);
  551. grub_machine_mmap_iterate (heap_init, &total);
  552. grub_dprintf ("ieee1275", "get noncontig memory from fw %s\n", total == 0 ? "succeeded" : "failed");
  553. }
  554. if (total == 0)
  555. return GRUB_ERR_NONE;
  556. else
  557. return GRUB_ERR_OUT_OF_MEMORY;
  558. }
  559. /*
  560. * How much memory does OF believe it has? (regardless of whether
  561. * it's accessible or not)
  562. */
  563. static grub_err_t
  564. grub_ieee1275_total_mem (grub_uint64_t *total)
  565. {
  566. grub_ieee1275_phandle_t root;
  567. grub_ieee1275_phandle_t memory;
  568. grub_uint32_t reg[4];
  569. grub_ssize_t reg_size;
  570. grub_uint32_t address_cells = 1;
  571. grub_uint32_t size_cells = 1;
  572. grub_uint64_t size;
  573. /* If we fail to get to the end, report 0. */
  574. *total = 0;
  575. /* Determine the format of each entry in `reg'. */
  576. if (grub_ieee1275_finddevice ("/", &root))
  577. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find / node");
  578. if (grub_ieee1275_get_integer_property (root, "#address-cells", &address_cells,
  579. sizeof (address_cells), 0))
  580. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine #address-cells");
  581. if (grub_ieee1275_get_integer_property (root, "#size-cells", &size_cells,
  582. sizeof (size_cells), 0))
  583. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine #size-cells");
  584. if (size_cells > address_cells)
  585. address_cells = size_cells;
  586. /* Load `/memory/reg'. */
  587. if (grub_ieee1275_finddevice ("/memory", &memory))
  588. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't find /memory node");
  589. if (grub_ieee1275_get_integer_property (memory, "reg", reg,
  590. sizeof (reg), &reg_size))
  591. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "couldn't examine /memory/reg property");
  592. if (reg_size < 0 || (grub_size_t) reg_size > sizeof (reg))
  593. return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "/memory response buffer exceeded");
  594. if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_BROKEN_ADDRESS_CELLS))
  595. {
  596. address_cells = 1;
  597. size_cells = 1;
  598. }
  599. /* Decode only the size */
  600. size = reg[address_cells];
  601. if (size_cells == 2)
  602. size = (size << 32) | reg[address_cells + 1];
  603. *total = size;
  604. return grub_errno;
  605. }
  606. #if defined(__powerpc__)
  607. /* See PAPR or arch/powerpc/kernel/prom_init.c */
  608. struct option_vector2
  609. {
  610. grub_uint8_t byte1;
  611. grub_uint16_t reserved;
  612. grub_uint32_t real_base;
  613. grub_uint32_t real_size;
  614. grub_uint32_t virt_base;
  615. grub_uint32_t virt_size;
  616. grub_uint32_t load_base;
  617. grub_uint32_t min_rma;
  618. grub_uint32_t min_load;
  619. grub_uint8_t min_rma_percent;
  620. grub_uint8_t max_pft_size;
  621. } GRUB_PACKED;
  622. struct option_vector5
  623. {
  624. grub_uint8_t byte1;
  625. grub_uint8_t byte2;
  626. grub_uint8_t byte3;
  627. grub_uint8_t cmo;
  628. grub_uint8_t associativity;
  629. grub_uint8_t bin_opts;
  630. grub_uint8_t micro_checkpoint;
  631. grub_uint8_t reserved0;
  632. grub_uint32_t max_cpus;
  633. grub_uint16_t base_papr;
  634. grub_uint16_t mem_reference;
  635. grub_uint32_t platform_facilities;
  636. grub_uint8_t sub_processors;
  637. grub_uint8_t byte22;
  638. } GRUB_PACKED;
  639. struct pvr_entry
  640. {
  641. grub_uint32_t mask;
  642. grub_uint32_t entry;
  643. };
  644. struct cas_vector
  645. {
  646. struct
  647. {
  648. struct pvr_entry terminal;
  649. } pvr_list;
  650. grub_uint8_t num_vecs;
  651. grub_uint8_t vec1_size;
  652. grub_uint8_t vec1;
  653. grub_uint8_t vec2_size;
  654. struct option_vector2 vec2;
  655. grub_uint8_t vec3_size;
  656. grub_uint16_t vec3;
  657. grub_uint8_t vec4_size;
  658. grub_uint16_t vec4;
  659. grub_uint8_t vec5_size;
  660. struct option_vector5 vec5;
  661. } GRUB_PACKED;
  662. /*
  663. * Call ibm,client-architecture-support to try to get more RMA.
  664. * We ask for 512MB which should be enough to verify a distro kernel.
  665. * We ignore most errors: if we don't succeed we'll proceed with whatever
  666. * memory we have.
  667. */
  668. static void
  669. grub_ieee1275_ibm_cas (void)
  670. {
  671. int rc;
  672. grub_ieee1275_ihandle_t root;
  673. struct cas_args
  674. {
  675. struct grub_ieee1275_common_hdr common;
  676. grub_ieee1275_cell_t method;
  677. grub_ieee1275_ihandle_t ihandle;
  678. grub_ieee1275_cell_t cas_addr;
  679. grub_ieee1275_cell_t result;
  680. } args;
  681. struct cas_vector vector =
  682. {
  683. .pvr_list = { { 0x00000000, 0xffffffff } }, /* any processor */
  684. .num_vecs = 5 - 1,
  685. .vec1_size = 0,
  686. .vec1 = 0x80, /* ignore */
  687. .vec2_size = 1 + sizeof (struct option_vector2) - 2,
  688. .vec2 = {
  689. 0, 0, -1, -1, -1, -1, -1, 512, -1, 0, 48
  690. },
  691. .vec3_size = 2 - 1,
  692. .vec3 = 0x00e0, /* ask for FP + VMX + DFP but don't halt if unsatisfied */
  693. .vec4_size = 2 - 1,
  694. .vec4 = 0x0001, /* set required minimum capacity % to the lowest value */
  695. .vec5_size = 1 + sizeof (struct option_vector5) - 2,
  696. .vec5 = {
  697. 0, BYTE2, 0, CMO, ASSOCIATIVITY, BIN_OPTS, 0, 0, MAX_CPU, 0, 0, PLATFORM_FACILITIES, SUB_PROCESSORS, BYTE22
  698. }
  699. };
  700. INIT_IEEE1275_COMMON (&args.common, "call-method", 3, 2);
  701. args.method = (grub_ieee1275_cell_t) "ibm,client-architecture-support";
  702. rc = grub_ieee1275_open ("/", &root);
  703. if (rc)
  704. {
  705. grub_error (GRUB_ERR_IO, "could not open root when trying to call CAS");
  706. return;
  707. }
  708. args.ihandle = root;
  709. args.cas_addr = (grub_ieee1275_cell_t) &vector;
  710. grub_printf ("Calling ibm,client-architecture-support from grub...");
  711. IEEE1275_CALL_ENTRY_FN (&args);
  712. grub_printf ("done\n");
  713. grub_ieee1275_close (root);
  714. }
  715. #endif /* __powerpc__ */
  716. static void
  717. grub_claim_heap (void)
  718. {
  719. grub_err_t err;
  720. grub_uint32_t total = HEAP_MAX_SIZE;
  721. err = grub_ieee1275_total_mem (&rmo_top);
  722. /*
  723. * If we cannot size the available memory, we can't be sure we're leaving
  724. * space for the kernel, initrd and things Linux loads early in boot. So only
  725. * allow further allocations from firmware on success
  726. */
  727. if (err == GRUB_ERR_NONE)
  728. grub_mm_add_region_fn = grub_ieee1275_mm_add_region;
  729. #if defined(__powerpc__)
  730. if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CAN_TRY_CAS_FOR_MORE_MEMORY))
  731. {
  732. /* if we have an error, don't call CAS, just hope for the best */
  733. if (err == GRUB_ERR_NONE && rmo_top < (512 * 1024 * 1024))
  734. grub_ieee1275_ibm_cas ();
  735. }
  736. #endif
  737. grub_machine_mmap_iterate (heap_init, &total);
  738. }
  739. #endif
  740. static void
  741. grub_parse_cmdline (void)
  742. {
  743. grub_ssize_t actual;
  744. char args[256];
  745. if (grub_ieee1275_get_property (grub_ieee1275_chosen, "bootargs", &args,
  746. sizeof args, &actual) == 0
  747. && actual > 1)
  748. {
  749. int i = 0;
  750. while (i < actual)
  751. {
  752. char *command = &args[i];
  753. char *end;
  754. char *val;
  755. end = grub_strchr (command, ';');
  756. if (end == 0)
  757. i = actual; /* No more commands after this one. */
  758. else
  759. {
  760. *end = '\0';
  761. i += end - command + 1;
  762. while (grub_isspace(args[i]))
  763. i++;
  764. }
  765. /* Process command. */
  766. val = grub_strchr (command, '=');
  767. if (val)
  768. {
  769. *val = '\0';
  770. grub_env_set (command, val + 1);
  771. }
  772. }
  773. }
  774. }
  775. grub_addr_t grub_modbase;
  776. void
  777. grub_machine_init (void)
  778. {
  779. grub_modbase = ALIGN_UP((grub_addr_t) _end
  780. + GRUB_KERNEL_MACHINE_MOD_GAP,
  781. GRUB_KERNEL_MACHINE_MOD_ALIGN);
  782. grub_ieee1275_init ();
  783. grub_console_init_early ();
  784. grub_claim_heap ();
  785. grub_console_init_lately ();
  786. #ifdef __sparc__
  787. grub_obdisk_init ();
  788. #else
  789. grub_ofdisk_init ();
  790. #endif
  791. grub_parse_cmdline ();
  792. #ifdef __i386__
  793. grub_tsc_init ();
  794. #else
  795. grub_install_get_time_ms (grub_rtc_get_time_ms);
  796. #endif
  797. }
  798. void
  799. grub_machine_fini (int flags)
  800. {
  801. if (flags & GRUB_LOADER_FLAG_NORETURN)
  802. {
  803. #ifdef __sparc__
  804. grub_obdisk_fini ();
  805. #else
  806. grub_ofdisk_fini ();
  807. #endif
  808. grub_console_fini ();
  809. }
  810. }
  811. grub_uint64_t
  812. grub_rtc_get_time_ms (void)
  813. {
  814. grub_uint32_t msecs = 0;
  815. grub_ieee1275_milliseconds (&msecs);
  816. return msecs;
  817. }