init.c 29 KB

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