linux.c 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/loader.h>
  19. #include <grub/machine/loader.h>
  20. #include <grub/file.h>
  21. #include <grub/disk.h>
  22. #include <grub/err.h>
  23. #include <grub/misc.h>
  24. #include <grub/types.h>
  25. #include <grub/dl.h>
  26. #include <grub/mm.h>
  27. #include <grub/term.h>
  28. #include <grub/cpu/linux.h>
  29. #include <grub/efi/api.h>
  30. #include <grub/efi/efi.h>
  31. #include <grub/efi/uga_draw.h>
  32. #include <grub/efi/graphics_output.h>
  33. #include <grub/pci.h>
  34. #include <grub/command.h>
  35. #include <grub/memory.h>
  36. #include <grub/i18n.h>
  37. #define GRUB_LINUX_CL_OFFSET 0x1000
  38. #define GRUB_LINUX_CL_END_OFFSET 0x2000
  39. #define NEXT_MEMORY_DESCRIPTOR(desc, size) \
  40. ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
  41. static grub_dl_t my_mod;
  42. static grub_size_t linux_mem_size;
  43. static int loaded;
  44. static void *real_mode_mem;
  45. static void *prot_mode_mem;
  46. static void *initrd_mem;
  47. static grub_efi_uintn_t real_mode_pages;
  48. static grub_efi_uintn_t prot_mode_pages;
  49. static grub_efi_uintn_t initrd_pages;
  50. static void *mmap_buf;
  51. static grub_uint8_t gdt[] __attribute__ ((aligned(16))) =
  52. {
  53. /* NULL. */
  54. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  55. /* Reserved. */
  56. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  57. /* Code segment. */
  58. 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00,
  59. /* Data segment. */
  60. 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
  61. };
  62. struct gdt_descriptor
  63. {
  64. grub_uint16_t limit;
  65. void *base;
  66. } __attribute__ ((packed));
  67. static struct gdt_descriptor gdt_desc =
  68. {
  69. sizeof (gdt) - 1,
  70. gdt
  71. };
  72. struct idt_descriptor
  73. {
  74. grub_uint16_t limit;
  75. void *base;
  76. } __attribute__ ((packed));
  77. static struct idt_descriptor idt_desc =
  78. {
  79. 0,
  80. 0
  81. };
  82. static inline grub_size_t
  83. page_align (grub_size_t size)
  84. {
  85. return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
  86. }
  87. /* Find the optimal number of pages for the memory map. Is it better to
  88. move this code to efi/mm.c? */
  89. static grub_efi_uintn_t
  90. find_mmap_size (void)
  91. {
  92. static grub_efi_uintn_t mmap_size = 0;
  93. if (mmap_size != 0)
  94. return mmap_size;
  95. mmap_size = (1 << 12);
  96. while (1)
  97. {
  98. int ret;
  99. grub_efi_memory_descriptor_t *mmap;
  100. grub_efi_uintn_t desc_size;
  101. mmap = grub_malloc (mmap_size);
  102. if (! mmap)
  103. return 0;
  104. ret = grub_efi_get_memory_map (&mmap_size, mmap, 0, &desc_size, 0);
  105. grub_free (mmap);
  106. if (ret < 0)
  107. grub_fatal ("cannot get memory map");
  108. else if (ret > 0)
  109. break;
  110. mmap_size += (1 << 12);
  111. }
  112. /* Increase the size a bit for safety, because GRUB allocates more on
  113. later, and EFI itself may allocate more. */
  114. mmap_size += (1 << 12);
  115. return page_align (mmap_size);
  116. }
  117. static void
  118. free_pages (void)
  119. {
  120. if (real_mode_mem)
  121. {
  122. grub_efi_free_pages ((grub_addr_t) real_mode_mem, real_mode_pages);
  123. real_mode_mem = 0;
  124. }
  125. if (prot_mode_mem)
  126. {
  127. grub_efi_free_pages ((grub_addr_t) prot_mode_mem, prot_mode_pages);
  128. prot_mode_mem = 0;
  129. }
  130. if (initrd_mem)
  131. {
  132. grub_efi_free_pages ((grub_addr_t) initrd_mem, initrd_pages);
  133. initrd_mem = 0;
  134. }
  135. }
  136. /* Allocate pages for the real mode code and the protected mode code
  137. for linux as well as a memory map buffer. */
  138. static int
  139. allocate_pages (grub_size_t prot_size)
  140. {
  141. grub_efi_uintn_t desc_size;
  142. grub_efi_memory_descriptor_t *mmap, *mmap_end;
  143. grub_efi_uintn_t mmap_size, tmp_mmap_size;
  144. grub_efi_memory_descriptor_t *desc;
  145. grub_size_t real_size;
  146. /* Make sure that each size is aligned to a page boundary. */
  147. real_size = GRUB_LINUX_CL_END_OFFSET;
  148. prot_size = page_align (prot_size);
  149. mmap_size = find_mmap_size ();
  150. grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
  151. (unsigned) real_size, (unsigned) prot_size, (unsigned) mmap_size);
  152. /* Calculate the number of pages; Combine the real mode code with
  153. the memory map buffer for simplicity. */
  154. real_mode_pages = ((real_size + mmap_size) >> 12);
  155. prot_mode_pages = (prot_size >> 12);
  156. /* Initialize the memory pointers with NULL for convenience. */
  157. real_mode_mem = 0;
  158. prot_mode_mem = 0;
  159. /* Read the memory map temporarily, to find free space. */
  160. mmap = grub_malloc (mmap_size);
  161. if (! mmap)
  162. return 0;
  163. tmp_mmap_size = mmap_size;
  164. if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0)
  165. grub_fatal ("cannot get memory map");
  166. mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size);
  167. /* First, find free pages for the real mode code
  168. and the memory map buffer. */
  169. for (desc = mmap;
  170. desc < mmap_end;
  171. desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
  172. {
  173. /* Probably it is better to put the real mode code in the traditional
  174. space for safety. */
  175. if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
  176. && desc->physical_start <= 0x90000
  177. && desc->num_pages >= real_mode_pages)
  178. {
  179. grub_efi_physical_address_t physical_end;
  180. grub_efi_physical_address_t addr;
  181. physical_end = desc->physical_start + (desc->num_pages << 12);
  182. if (physical_end > 0x90000)
  183. physical_end = 0x90000;
  184. grub_dprintf ("linux", "physical_start = %x, physical_end = %x\n",
  185. (unsigned) desc->physical_start,
  186. (unsigned) physical_end);
  187. addr = physical_end - real_size - mmap_size;
  188. if (addr < 0x10000)
  189. continue;
  190. grub_dprintf ("linux", "trying to allocate %u pages at %lx\n",
  191. (unsigned) real_mode_pages, (unsigned long) addr);
  192. real_mode_mem = grub_efi_allocate_pages (addr, real_mode_pages);
  193. if (! real_mode_mem)
  194. grub_fatal ("cannot allocate pages");
  195. desc->num_pages -= real_mode_pages;
  196. break;
  197. }
  198. }
  199. if (! real_mode_mem)
  200. {
  201. grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
  202. goto fail;
  203. }
  204. mmap_buf = (void *) ((char *) real_mode_mem + real_size);
  205. /* Next, find free pages for the protected mode code. */
  206. /* XXX what happens if anything is using this address? */
  207. prot_mode_mem = grub_efi_allocate_pages (0x100000, prot_mode_pages + 1);
  208. if (! prot_mode_mem)
  209. {
  210. grub_error (GRUB_ERR_OUT_OF_MEMORY,
  211. "cannot allocate protected mode pages");
  212. goto fail;
  213. }
  214. grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
  215. "prot_mode_mem = %lx, prot_mode_pages = %x\n",
  216. (unsigned long) real_mode_mem, (unsigned) real_mode_pages,
  217. (unsigned long) prot_mode_mem, (unsigned) prot_mode_pages);
  218. grub_free (mmap);
  219. return 1;
  220. fail:
  221. grub_free (mmap);
  222. free_pages ();
  223. return 0;
  224. }
  225. static void
  226. grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
  227. grub_uint64_t start, grub_uint64_t size,
  228. grub_uint32_t type)
  229. {
  230. int n = *e820_num;
  231. if (n >= GRUB_E820_MAX_ENTRY)
  232. grub_fatal ("Too many e820 memory map entries");
  233. if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
  234. (e820_map[n - 1].type == type))
  235. e820_map[n - 1].size += size;
  236. else
  237. {
  238. e820_map[n].addr = start;
  239. e820_map[n].size = size;
  240. e820_map[n].type = type;
  241. (*e820_num)++;
  242. }
  243. }
  244. #ifdef __x86_64__
  245. extern grub_uint8_t grub_linux_trampoline_start[];
  246. extern grub_uint8_t grub_linux_trampoline_end[];
  247. #endif
  248. struct grub_linux_boot_closure
  249. {
  250. struct linux_kernel_params *params;
  251. int e820_num;
  252. };
  253. static int
  254. grub_linux_boot_hook (grub_uint64_t addr, grub_uint64_t size,
  255. grub_uint32_t type, void *closure)
  256. {
  257. struct grub_linux_boot_closure *c = closure;
  258. switch (type)
  259. {
  260. case GRUB_MACHINE_MEMORY_AVAILABLE:
  261. grub_e820_add_region (c->params->e820_map, &c->e820_num,
  262. addr, size, GRUB_E820_RAM);
  263. break;
  264. #ifdef GRUB_MACHINE_MEMORY_ACPI
  265. case GRUB_MACHINE_MEMORY_ACPI:
  266. grub_e820_add_region (c->params->e820_map, &c->e820_num,
  267. addr, size, GRUB_E820_ACPI);
  268. break;
  269. #endif
  270. #ifdef GRUB_MACHINE_MEMORY_NVS
  271. case GRUB_MACHINE_MEMORY_NVS:
  272. grub_e820_add_region (c->params->e820_map, &c->e820_num,
  273. addr, size, GRUB_E820_NVS);
  274. break;
  275. #endif
  276. #ifdef GRUB_MACHINE_MEMORY_CODE
  277. case GRUB_MACHINE_MEMORY_CODE:
  278. grub_e820_add_region (c->params->e820_map, &c->e820_num,
  279. addr, size, GRUB_E820_EXEC_CODE);
  280. break;
  281. #endif
  282. default:
  283. grub_e820_add_region (c->params->e820_map, &c->e820_num,
  284. addr, size, GRUB_E820_RESERVED);
  285. }
  286. return 0;
  287. }
  288. static grub_err_t
  289. grub_linux_boot (void)
  290. {
  291. grub_efi_uintn_t mmap_size;
  292. grub_efi_uintn_t map_key;
  293. grub_efi_uintn_t desc_size;
  294. grub_efi_uint32_t desc_version;
  295. struct grub_linux_boot_closure c;
  296. c.params = real_mode_mem;
  297. grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
  298. (unsigned) c.params->code32_start,
  299. (unsigned long) &(idt_desc.limit),
  300. (unsigned long) &(gdt_desc.limit));
  301. grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n",
  302. (unsigned) idt_desc.limit, (unsigned long) idt_desc.base,
  303. (unsigned) gdt_desc.limit, (unsigned long) gdt_desc.base);
  304. c.e820_num = 0;
  305. grub_mmap_iterate (grub_linux_boot_hook, &c);
  306. c.params->mmap_size = c.e820_num;
  307. mmap_size = find_mmap_size ();
  308. if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key,
  309. &desc_size, &desc_version) <= 0)
  310. grub_fatal ("cannot get memory map");
  311. if (! grub_efi_exit_boot_services (map_key))
  312. grub_fatal ("cannot exit boot services");
  313. /* Note that no boot services are available from here. */
  314. /* Pass EFI parameters. */
  315. if (grub_le_to_cpu16 (c.params->version) >= 0x0206)
  316. {
  317. c.params->v0206.efi_mem_desc_size = desc_size;
  318. c.params->v0206.efi_mem_desc_version = desc_version;
  319. c.params->v0206.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
  320. c.params->v0206.efi_mmap_size = mmap_size;
  321. #ifdef __x86_64__
  322. c.params->v0206.efi_mmap_hi = (grub_uint32_t) ((grub_uint64_t) mmap_buf >> 32);
  323. #endif
  324. }
  325. else if (grub_le_to_cpu16 (c.params->version) >= 0x0204)
  326. {
  327. c.params->v0204.efi_mem_desc_size = desc_size;
  328. c.params->v0204.efi_mem_desc_version = desc_version;
  329. c.params->v0204.efi_mmap = (grub_uint32_t) (unsigned long) mmap_buf;
  330. c.params->v0204.efi_mmap_size = mmap_size;
  331. }
  332. #ifdef __x86_64__
  333. grub_memcpy ((char *) prot_mode_mem + (prot_mode_pages << 12),
  334. grub_linux_trampoline_start,
  335. grub_linux_trampoline_end - grub_linux_trampoline_start);
  336. ((void (*) (unsigned long, void *)) ((char *) prot_mode_mem
  337. + (prot_mode_pages << 12)))
  338. (c.params->code32_start, real_mode_mem);
  339. #else
  340. /* Hardware interrupts are not safe any longer. */
  341. asm volatile ("cli" : : );
  342. /* Load the IDT and the GDT for the bootstrap. */
  343. asm volatile ("lidt %0" : : "m" (idt_desc));
  344. asm volatile ("lgdt %0" : : "m" (gdt_desc));
  345. /* Pass parameters. */
  346. asm volatile ("movl %0, %%ecx" : : "m" (c.params->code32_start));
  347. asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem));
  348. asm volatile ("xorl %%ebx, %%ebx" : : );
  349. /* Enter Linux. */
  350. asm volatile ("jmp *%%ecx" : : );
  351. #endif
  352. /* Never reach here. */
  353. return GRUB_ERR_NONE;
  354. }
  355. static grub_err_t
  356. grub_linux_unload (void)
  357. {
  358. free_pages ();
  359. grub_dl_unref (my_mod);
  360. loaded = 0;
  361. return GRUB_ERR_NONE;
  362. }
  363. static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID;
  364. static grub_efi_guid_t graphics_output_guid = GRUB_EFI_GRAPHICS_OUTPUT_GUID;
  365. #define RGB_MASK 0xffffff
  366. #define RGB_MAGIC 0x121314
  367. #define LINE_MIN 800
  368. #define LINE_MAX 4096
  369. #define FBTEST_STEP (0x10000 >> 2)
  370. #define FBTEST_COUNT 8
  371. static int
  372. find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len)
  373. {
  374. grub_uint32_t *base = (grub_uint32_t *) (grub_target_addr_t) *fb_base;
  375. int i;
  376. for (i = 0; i < FBTEST_COUNT; i++, base += FBTEST_STEP)
  377. {
  378. if ((*base & RGB_MASK) == RGB_MAGIC)
  379. {
  380. int j;
  381. for (j = LINE_MIN; j <= LINE_MAX; j++)
  382. {
  383. if ((base[j] & RGB_MASK) == RGB_MAGIC)
  384. {
  385. *fb_base = (grub_uint32_t) (grub_target_addr_t) base;
  386. *line_len = j << 2;
  387. return 1;
  388. }
  389. }
  390. break;
  391. }
  392. }
  393. return 0;
  394. }
  395. struct find_framebuf_closure
  396. {
  397. grub_uint32_t *fb_base;
  398. grub_uint32_t *line_len;
  399. int found;
  400. };
  401. static int
  402. find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *closure)
  403. {
  404. struct find_framebuf_closure *c = closure;
  405. grub_pci_address_t addr;
  406. addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
  407. if (grub_pci_read (addr) >> 24 == 0x3)
  408. {
  409. int i;
  410. grub_printf ("Display controller: %d:%d.%d\nDevice id: %x\n",
  411. grub_pci_get_bus (dev), grub_pci_get_device (dev),
  412. grub_pci_get_function (dev), pciid);
  413. addr += 8;
  414. for (i = 0; i < 6; i++, addr += 4)
  415. {
  416. grub_uint32_t old_bar1, old_bar2, type;
  417. grub_uint64_t base64;
  418. old_bar1 = grub_pci_read (addr);
  419. if ((! old_bar1) || (old_bar1 & GRUB_PCI_ADDR_SPACE_IO))
  420. continue;
  421. type = old_bar1 & GRUB_PCI_ADDR_MEM_TYPE_MASK;
  422. if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
  423. {
  424. if (i == 5)
  425. break;
  426. old_bar2 = grub_pci_read (addr + 4);
  427. }
  428. else
  429. old_bar2 = 0;
  430. base64 = old_bar2;
  431. base64 <<= 32;
  432. base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK);
  433. grub_printf ("%s(%d): 0x%llx\n",
  434. ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ?
  435. "VMEM" : "MMIO"), i,
  436. (unsigned long long) base64);
  437. if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! c->found))
  438. {
  439. *(c->fb_base) = base64;
  440. if (find_line_len (c->fb_base, c->line_len))
  441. c->found++;
  442. }
  443. if (type == GRUB_PCI_ADDR_MEM_TYPE_64)
  444. {
  445. i++;
  446. addr += 4;
  447. }
  448. }
  449. }
  450. return c->found;
  451. }
  452. static int
  453. find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len)
  454. {
  455. struct find_framebuf_closure c;
  456. c.fb_base = fb_base;
  457. c.line_len = line_len;
  458. c.found = 0;
  459. grub_pci_iterate (find_card, &c);
  460. return c.found;
  461. }
  462. static int
  463. grub_linux_setup_video (struct linux_kernel_params *params)
  464. {
  465. struct grub_efi_graphics_output_protocol *gop;
  466. grub_uint32_t width, height, depth, fb_base, line_len;
  467. int ret;
  468. gop = grub_efi_locate_protocol (&graphics_output_guid, 0);
  469. if (gop)
  470. {
  471. width = gop->mode->info->horizontal_resolution;
  472. height = gop->mode->info->vertical_resolution;
  473. if ((gop->mode->frame_buffer_base) && (gop->mode->frame_buffer_size))
  474. {
  475. fb_base = gop->mode->frame_buffer_base;
  476. line_len = 4 * gop->mode->info->pixels_per_scan_line;
  477. }
  478. else
  479. {
  480. grub_uint32_t pixel;
  481. grub_efi_set_text_mode (0);
  482. pixel = RGB_MAGIC;
  483. efi_call_10 (gop->blt, gop, (struct grub_efi_uga_pixel *) &pixel,
  484. GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0);
  485. ret = find_framebuf (&fb_base, &line_len);
  486. grub_efi_set_text_mode (1);
  487. if (! ret)
  488. {
  489. grub_printf ("Can\'t find frame buffer address\n");
  490. return 1;
  491. }
  492. }
  493. depth = 32;
  494. }
  495. else
  496. {
  497. grub_efi_uga_draw_protocol_t *c;
  498. grub_uint32_t rate, pixel;
  499. c = grub_efi_locate_protocol (&uga_draw_guid, 0);
  500. if (! c)
  501. {
  502. grub_printf ("Can\'t locate uga protocol\n");
  503. return 1;
  504. }
  505. if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate))
  506. {
  507. grub_printf ("Can\'t get mode\n");
  508. return 1;
  509. }
  510. grub_efi_set_text_mode (0);
  511. pixel = RGB_MAGIC;
  512. efi_call_10 (c->blt, c, (struct grub_efi_uga_pixel *) &pixel,
  513. GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0);
  514. ret = find_framebuf (&fb_base, &line_len);
  515. grub_efi_set_text_mode (1);
  516. if (! ret)
  517. {
  518. grub_printf ("Can\'t find frame buffer address\n");
  519. return 1;
  520. }
  521. }
  522. grub_printf ("Video mode: %ux%u-%u\n", width, height, depth);
  523. grub_printf ("Frame buffer base: 0x%x\n", fb_base);
  524. grub_printf ("Video line length: %d\n", line_len);
  525. params->lfb_width = width;
  526. params->lfb_height = height;
  527. params->lfb_depth = depth;
  528. params->lfb_line_len = line_len;
  529. params->lfb_base = fb_base;
  530. params->lfb_size = (line_len * params->lfb_height + 65535) >> 16;
  531. params->red_mask_size = 8;
  532. params->red_field_pos = 16;
  533. params->green_mask_size = 8;
  534. params->green_field_pos = 8;
  535. params->blue_mask_size = 8;
  536. params->blue_field_pos = 0;
  537. params->reserved_mask_size = 8;
  538. params->reserved_field_pos = 24;
  539. params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA;
  540. params->vid_mode = 0x338; /* 1024x768x32 */
  541. return 0;
  542. }
  543. static grub_err_t
  544. grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
  545. int argc, char *argv[])
  546. {
  547. grub_file_t file = 0;
  548. struct linux_kernel_header lh;
  549. struct linux_kernel_params *params;
  550. grub_uint8_t setup_sects;
  551. grub_size_t real_size, prot_size;
  552. grub_ssize_t len;
  553. int i;
  554. char *dest;
  555. grub_dl_ref (my_mod);
  556. if (argc == 0)
  557. {
  558. grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified");
  559. goto fail;
  560. }
  561. file = grub_file_open (argv[0]);
  562. if (! file)
  563. goto fail;
  564. if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
  565. {
  566. grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header");
  567. goto fail;
  568. }
  569. if (lh.boot_flag != grub_cpu_to_le16 (0xaa55))
  570. {
  571. grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
  572. goto fail;
  573. }
  574. if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
  575. {
  576. grub_error (GRUB_ERR_BAD_OS, "too many setup sectors");
  577. goto fail;
  578. }
  579. /* EFI support is quite new, so reject old versions. */
  580. if (lh.header != grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE)
  581. || grub_le_to_cpu16 (lh.version) < 0x0203)
  582. {
  583. grub_error (GRUB_ERR_BAD_OS, "too old version");
  584. goto fail;
  585. }
  586. /* I'm not sure how to support zImage on EFI. */
  587. if (! (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL))
  588. {
  589. grub_error (GRUB_ERR_BAD_OS, "zImage is not supported");
  590. goto fail;
  591. }
  592. setup_sects = lh.setup_sects;
  593. /* If SETUP_SECTS is not set, set it to the default (4). */
  594. if (! setup_sects)
  595. setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
  596. real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
  597. prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
  598. if (! allocate_pages (prot_size))
  599. goto fail;
  600. params = (struct linux_kernel_params *) real_mode_mem;
  601. grub_memset (params, 0, GRUB_LINUX_CL_END_OFFSET);
  602. grub_memcpy (&params->setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
  603. params->ps_mouse = params->padding10 = 0;
  604. len = 0x400 - sizeof (lh);
  605. if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len)
  606. {
  607. grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
  608. goto fail;
  609. }
  610. params->type_of_loader = (LINUX_LOADER_ID_GRUB << 4);
  611. params->cl_magic = GRUB_LINUX_CL_MAGIC;
  612. params->cl_offset = 0x1000;
  613. params->cmd_line_ptr = (unsigned long) real_mode_mem + 0x1000;
  614. params->ramdisk_image = 0;
  615. params->ramdisk_size = 0;
  616. params->heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
  617. params->loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
  618. /* These are not needed to be precise, because Linux uses these values
  619. only to raise an error when the decompression code cannot find good
  620. space. */
  621. params->ext_mem = ((32 * 0x100000) >> 10);
  622. params->alt_mem = ((32 * 0x100000) >> 10);
  623. {
  624. grub_term_output_t term;
  625. int found = 0;
  626. FOR_ACTIVE_TERM_OUTPUTS(term)
  627. if (grub_strcmp (term->name, "vga_text") == 0
  628. || grub_strcmp (term->name, "console") == 0)
  629. {
  630. grub_uint16_t pos = grub_term_getxy (term);
  631. params->video_cursor_x = pos >> 8;
  632. params->video_cursor_y = pos & 0xff;
  633. params->video_width = grub_term_width (term);
  634. params->video_height = grub_term_height (term);
  635. found = 1;
  636. break;
  637. }
  638. if (!found)
  639. {
  640. params->video_cursor_x = 0;
  641. params->video_cursor_y = 0;
  642. params->video_width = 80;
  643. params->video_height = 25;
  644. }
  645. }
  646. params->video_page = 0; /* ??? */
  647. params->video_mode = grub_efi_system_table->con_out->mode->mode;
  648. params->video_ega_bx = 0;
  649. params->have_vga = 0;
  650. params->font_size = 16; /* XXX */
  651. if (grub_le_to_cpu16 (params->version) >= 0x0206)
  652. {
  653. params->v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
  654. params->v0206.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
  655. #ifdef __x86_64__
  656. params->v0206.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
  657. #endif
  658. }
  659. else if (grub_le_to_cpu16 (params->version) >= 0x0204)
  660. {
  661. params->v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
  662. params->v0204.efi_system_table = (grub_uint32_t) (unsigned long) grub_efi_system_table;
  663. }
  664. #if 0
  665. /* The structure is zeroed already. */
  666. /* No VBE on EFI. */
  667. params->lfb_width = 0;
  668. params->lfb_height = 0;
  669. params->lfb_depth = 0;
  670. params->lfb_base = 0;
  671. params->lfb_size = 0;
  672. params->lfb_line_len = 0;
  673. params->red_mask_size = 0;
  674. params->red_field_pos = 0;
  675. params->green_mask_size = 0;
  676. params->green_field_pos = 0;
  677. params->blue_mask_size = 0;
  678. params->blue_field_pos = 0;
  679. params->reserved_mask_size = 0;
  680. params->reserved_field_pos = 0;
  681. params->vesapm_segment = 0;
  682. params->vesapm_offset = 0;
  683. params->lfb_pages = 0;
  684. params->vesa_attrib = 0;
  685. /* No APM on EFI. */
  686. params->apm_version = 0;
  687. params->apm_code_segment = 0;
  688. params->apm_entry = 0;
  689. params->apm_16bit_code_segment = 0;
  690. params->apm_data_segment = 0;
  691. params->apm_flags = 0;
  692. params->apm_code_len = 0;
  693. params->apm_data_len = 0;
  694. /* XXX is there any way to use SpeedStep on EFI? */
  695. params->ist_signature = 0;
  696. params->ist_command = 0;
  697. params->ist_event = 0;
  698. params->ist_perf_level = 0;
  699. /* Let the kernel probe the information. */
  700. grub_memset (params->hd0_drive_info, 0, sizeof (params->hd0_drive_info));
  701. grub_memset (params->hd1_drive_info, 0, sizeof (params->hd1_drive_info));
  702. /* No MCA on EFI. */
  703. params->rom_config_len = 0;
  704. /* No need to fake the BIOS's memory map. */
  705. params->mmap_size = 0;
  706. /* Let the kernel probe the information. */
  707. params->ps_mouse = 0;
  708. /* Clear padding for future compatibility. */
  709. grub_memset (params->padding1, 0, sizeof (params->padding1));
  710. grub_memset (params->padding2, 0, sizeof (params->padding2));
  711. grub_memset (params->padding3, 0, sizeof (params->padding3));
  712. grub_memset (params->padding4, 0, sizeof (params->padding4));
  713. grub_memset (params->padding5, 0, sizeof (params->padding5));
  714. grub_memset (params->padding6, 0, sizeof (params->padding6));
  715. grub_memset (params->padding7, 0, sizeof (params->padding7));
  716. grub_memset (params->padding8, 0, sizeof (params->padding8));
  717. grub_memset (params->padding9, 0, sizeof (params->padding9));
  718. #endif
  719. /* The other EFI parameters are filled when booting. */
  720. grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
  721. /* XXX there is no way to know if the kernel really supports EFI. */
  722. grub_printf (" [Linux-bzImage, setup=0x%x, size=0x%x]\n",
  723. (unsigned) real_size, (unsigned) prot_size);
  724. grub_linux_setup_video (params);
  725. /* Detect explicitly specified memory size, if any. */
  726. linux_mem_size = 0;
  727. for (i = 1; i < argc; i++)
  728. if (grub_memcmp (argv[i], "mem=", 4) == 0)
  729. {
  730. char *val = argv[i] + 4;
  731. linux_mem_size = grub_strtoul (val, &val, 0);
  732. if (grub_errno)
  733. {
  734. grub_errno = GRUB_ERR_NONE;
  735. linux_mem_size = 0;
  736. }
  737. else
  738. {
  739. int shift = 0;
  740. switch (grub_tolower (val[0]))
  741. {
  742. case 'g':
  743. shift += 10;
  744. case 'm':
  745. shift += 10;
  746. case 'k':
  747. shift += 10;
  748. default:
  749. break;
  750. }
  751. /* Check an overflow. */
  752. if (linux_mem_size > (~0UL >> shift))
  753. linux_mem_size = 0;
  754. else
  755. linux_mem_size <<= shift;
  756. }
  757. }
  758. else if (grub_memcmp (argv[i], "video=efifb", 11) == 0)
  759. {
  760. if (params->have_vga)
  761. params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
  762. }
  763. /* Specify the boot file. */
  764. dest = grub_stpcpy ((char *) real_mode_mem + GRUB_LINUX_CL_OFFSET,
  765. "BOOT_IMAGE=");
  766. dest = grub_stpcpy (dest, argv[0]);
  767. /* Copy kernel parameters. */
  768. for (i = 1;
  769. i < argc
  770. && dest + grub_strlen (argv[i]) + 1 < ((char *) real_mode_mem
  771. + GRUB_LINUX_CL_END_OFFSET);
  772. i++)
  773. {
  774. *dest++ = ' ';
  775. dest = grub_stpcpy (dest, argv[i]);
  776. }
  777. len = prot_size;
  778. if (grub_file_read (file, (void *) GRUB_LINUX_BZIMAGE_ADDR, len) != len)
  779. grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
  780. if (grub_errno == GRUB_ERR_NONE)
  781. {
  782. grub_loader_set (grub_linux_boot, grub_linux_unload, 1);
  783. loaded = 1;
  784. }
  785. fail:
  786. if (file)
  787. grub_file_close (file);
  788. if (grub_errno != GRUB_ERR_NONE)
  789. {
  790. grub_dl_unref (my_mod);
  791. loaded = 0;
  792. }
  793. return grub_errno;
  794. }
  795. static grub_err_t
  796. grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
  797. int argc, char *argv[])
  798. {
  799. grub_file_t file = 0;
  800. grub_ssize_t size;
  801. grub_addr_t addr_min, addr_max;
  802. grub_addr_t addr;
  803. grub_efi_uintn_t mmap_size;
  804. grub_efi_memory_descriptor_t *desc;
  805. grub_efi_uintn_t desc_size;
  806. struct linux_kernel_header *lh;
  807. if (argc == 0)
  808. {
  809. grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified");
  810. goto fail;
  811. }
  812. if (! loaded)
  813. {
  814. grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the kernel first");
  815. goto fail;
  816. }
  817. file = grub_file_open (argv[0]);
  818. if (! file)
  819. goto fail;
  820. size = grub_file_size (file);
  821. initrd_pages = (page_align (size) >> 12);
  822. lh = (struct linux_kernel_header *) real_mode_mem;
  823. addr_max = (grub_cpu_to_le32 (lh->initrd_addr_max) << 10);
  824. if (linux_mem_size != 0 && linux_mem_size < addr_max)
  825. addr_max = linux_mem_size;
  826. /* Linux 2.3.xx has a bug in the memory range check, so avoid
  827. the last page.
  828. Linux 2.2.xx has a bug in the memory range check, which is
  829. worse than that of Linux 2.3.xx, so avoid the last 64kb. */
  830. addr_max -= 0x10000;
  831. /* Usually, the compression ratio is about 50%. */
  832. addr_min = (grub_addr_t) prot_mode_mem + ((prot_mode_pages * 3) << 12)
  833. + page_align (size);
  834. /* Find the highest address to put the initrd. */
  835. mmap_size = find_mmap_size ();
  836. if (grub_efi_get_memory_map (&mmap_size, mmap_buf, 0, &desc_size, 0) <= 0)
  837. grub_fatal ("cannot get memory map");
  838. addr = 0;
  839. for (desc = mmap_buf;
  840. desc < NEXT_MEMORY_DESCRIPTOR (mmap_buf, mmap_size);
  841. desc = NEXT_MEMORY_DESCRIPTOR (desc, desc_size))
  842. {
  843. if (desc->type == GRUB_EFI_CONVENTIONAL_MEMORY
  844. && desc->num_pages >= initrd_pages)
  845. {
  846. grub_efi_physical_address_t physical_end;
  847. physical_end = desc->physical_start + (desc->num_pages << 12);
  848. if (physical_end > addr_max)
  849. physical_end = addr_max;
  850. if (physical_end < page_align (size))
  851. continue;
  852. physical_end -= page_align (size);
  853. if ((physical_end >= addr_min) &&
  854. (physical_end >= desc->physical_start) &&
  855. (physical_end > addr))
  856. addr = physical_end;
  857. }
  858. }
  859. if (addr == 0)
  860. {
  861. grub_error (GRUB_ERR_OUT_OF_MEMORY, "no free pages available");
  862. goto fail;
  863. }
  864. initrd_mem = grub_efi_allocate_pages (addr, initrd_pages);
  865. if (! initrd_mem)
  866. grub_fatal ("cannot allocate pages");
  867. if (grub_file_read (file, initrd_mem, size) != size)
  868. {
  869. grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file");
  870. goto fail;
  871. }
  872. grub_printf (" [Initrd, addr=0x%x, size=0x%x]\n",
  873. (unsigned) addr, (unsigned) size);
  874. lh->ramdisk_image = addr;
  875. lh->ramdisk_size = size;
  876. lh->root_dev = 0x0100; /* XXX */
  877. fail:
  878. if (file)
  879. grub_file_close (file);
  880. return grub_errno;
  881. }
  882. static grub_command_t cmd_linux, cmd_initrd;
  883. GRUB_MOD_INIT(linux)
  884. {
  885. cmd_linux = grub_register_command ("linux", grub_cmd_linux,
  886. 0, N_("Load Linux."));
  887. cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
  888. 0, N_("Load initrd."));
  889. my_mod = mod;
  890. }
  891. GRUB_MOD_FINI(linux)
  892. {
  893. grub_unregister_command (cmd_linux);
  894. grub_unregister_command (cmd_initrd);
  895. }