linux.c 31 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136
  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/memory.h>
  20. #include <grub/normal.h>
  21. #include <grub/file.h>
  22. #include <grub/disk.h>
  23. #include <grub/err.h>
  24. #include <grub/misc.h>
  25. #include <grub/types.h>
  26. #include <grub/dl.h>
  27. #include <grub/mm.h>
  28. #include <grub/term.h>
  29. #include <grub/cpu/linux.h>
  30. #include <grub/video.h>
  31. #include <grub/video_fb.h>
  32. #include <grub/command.h>
  33. #include <grub/i386/relocator.h>
  34. #include <grub/i18n.h>
  35. #include <grub/lib/cmdline.h>
  36. #include <grub/linux.h>
  37. #include <grub/machine/kernel.h>
  38. GRUB_MOD_LICENSE ("GPLv3+");
  39. #ifdef GRUB_MACHINE_PCBIOS
  40. #include <grub/i386/pc/vesa_modes_table.h>
  41. #endif
  42. #ifdef GRUB_MACHINE_EFI
  43. #include <grub/efi/efi.h>
  44. #define HAS_VGA_TEXT 0
  45. #define DEFAULT_VIDEO_MODE "auto"
  46. #define ACCEPTS_PURE_TEXT 0
  47. #elif defined (GRUB_MACHINE_IEEE1275)
  48. #include <grub/ieee1275/ieee1275.h>
  49. #define HAS_VGA_TEXT 0
  50. #define DEFAULT_VIDEO_MODE "text"
  51. #define ACCEPTS_PURE_TEXT 1
  52. #else
  53. #include <grub/i386/pc/vbe.h>
  54. #include <grub/i386/pc/console.h>
  55. #define HAS_VGA_TEXT 1
  56. #define DEFAULT_VIDEO_MODE "text"
  57. #define ACCEPTS_PURE_TEXT 1
  58. #endif
  59. static grub_dl_t my_mod;
  60. static grub_size_t linux_mem_size;
  61. static int loaded;
  62. static void *prot_mode_mem;
  63. static grub_addr_t prot_mode_target;
  64. static void *initrd_mem;
  65. static grub_addr_t initrd_mem_target;
  66. static grub_size_t prot_init_space;
  67. static struct grub_relocator *relocator = NULL;
  68. static void *efi_mmap_buf;
  69. static grub_size_t maximal_cmdline_size;
  70. static struct linux_kernel_params linux_params;
  71. static char *linux_cmdline;
  72. #ifdef GRUB_MACHINE_EFI
  73. static grub_efi_uintn_t efi_mmap_size;
  74. #else
  75. static const grub_size_t efi_mmap_size = 0;
  76. #endif
  77. /* FIXME */
  78. #if 0
  79. struct idt_descriptor
  80. {
  81. grub_uint16_t limit;
  82. void *base;
  83. } GRUB_PACKED;
  84. static struct idt_descriptor idt_desc =
  85. {
  86. 0,
  87. 0
  88. };
  89. #endif
  90. static inline grub_size_t
  91. page_align (grub_size_t size)
  92. {
  93. return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
  94. }
  95. /* Helper for find_mmap_size. */
  96. static int
  97. count_hook (grub_uint64_t addr __attribute__ ((unused)),
  98. grub_uint64_t size __attribute__ ((unused)),
  99. grub_memory_type_t type __attribute__ ((unused)), void *data)
  100. {
  101. grub_size_t *count = data;
  102. (*count)++;
  103. return 0;
  104. }
  105. /* Find the optimal number of pages for the memory map. */
  106. static grub_size_t
  107. find_mmap_size (void)
  108. {
  109. grub_size_t count = 0, mmap_size;
  110. grub_mmap_iterate (count_hook, &count);
  111. mmap_size = count * sizeof (struct grub_e820_mmap);
  112. /* Increase the size a bit for safety, because GRUB allocates more on
  113. later. */
  114. mmap_size += (1 << 12);
  115. return page_align (mmap_size);
  116. }
  117. static void
  118. free_pages (void)
  119. {
  120. grub_relocator_unload (relocator);
  121. relocator = NULL;
  122. prot_mode_mem = initrd_mem = 0;
  123. prot_mode_target = initrd_mem_target = 0;
  124. }
  125. /* Allocate pages for the real mode code and the protected mode code
  126. for linux as well as a memory map buffer. */
  127. static grub_err_t
  128. allocate_pages (grub_size_t prot_size, grub_size_t *align,
  129. grub_size_t min_align, int relocatable,
  130. grub_uint64_t preferred_address)
  131. {
  132. grub_err_t err;
  133. if (prot_size == 0)
  134. prot_size = 1;
  135. prot_size = page_align (prot_size);
  136. /* Initialize the memory pointers with NULL for convenience. */
  137. free_pages ();
  138. relocator = grub_relocator_new ();
  139. if (!relocator)
  140. {
  141. err = grub_errno;
  142. goto fail;
  143. }
  144. /* FIXME: Should request low memory from the heap when this feature is
  145. implemented. */
  146. {
  147. grub_relocator_chunk_t ch;
  148. if (relocatable)
  149. {
  150. err = grub_relocator_alloc_chunk_align (relocator, &ch,
  151. preferred_address,
  152. preferred_address,
  153. prot_size, 1,
  154. GRUB_RELOCATOR_PREFERENCE_LOW,
  155. 1);
  156. for (; err && *align + 1 > min_align; (*align)--)
  157. {
  158. grub_errno = GRUB_ERR_NONE;
  159. err = grub_relocator_alloc_chunk_align (relocator, &ch,
  160. 0x1000000,
  161. 0xffffffff & ~prot_size,
  162. prot_size, 1 << *align,
  163. GRUB_RELOCATOR_PREFERENCE_LOW,
  164. 1);
  165. }
  166. if (err)
  167. goto fail;
  168. }
  169. else
  170. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  171. preferred_address,
  172. prot_size);
  173. if (err)
  174. goto fail;
  175. prot_mode_mem = get_virtual_current_address (ch);
  176. prot_mode_target = get_physical_target_address (ch);
  177. }
  178. grub_dprintf ("linux", "prot_mode_mem = %p, prot_mode_target = %lx, prot_size = %x\n",
  179. prot_mode_mem, (unsigned long) prot_mode_target,
  180. (unsigned) prot_size);
  181. return GRUB_ERR_NONE;
  182. fail:
  183. free_pages ();
  184. return err;
  185. }
  186. static grub_err_t
  187. grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
  188. grub_uint64_t start, grub_uint64_t size,
  189. grub_uint32_t type)
  190. {
  191. int n = *e820_num;
  192. if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
  193. (e820_map[n - 1].type == type))
  194. e820_map[n - 1].size += size;
  195. else
  196. {
  197. e820_map[n].addr = start;
  198. e820_map[n].size = size;
  199. e820_map[n].type = type;
  200. (*e820_num)++;
  201. }
  202. return GRUB_ERR_NONE;
  203. }
  204. static grub_err_t
  205. grub_linux_setup_video (struct linux_kernel_params *params)
  206. {
  207. struct grub_video_mode_info mode_info;
  208. void *framebuffer;
  209. grub_err_t err;
  210. grub_video_driver_id_t driver_id;
  211. const char *gfxlfbvar = grub_env_get ("gfxpayloadforcelfb");
  212. driver_id = grub_video_get_driver_id ();
  213. if (driver_id == GRUB_VIDEO_DRIVER_NONE)
  214. return 1;
  215. err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
  216. if (err)
  217. {
  218. grub_errno = GRUB_ERR_NONE;
  219. return 1;
  220. }
  221. params->lfb_width = mode_info.width;
  222. params->lfb_height = mode_info.height;
  223. params->lfb_depth = mode_info.bpp;
  224. params->lfb_line_len = mode_info.pitch;
  225. params->lfb_base = (grub_size_t) framebuffer;
  226. #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
  227. params->ext_lfb_base = (grub_size_t) (((grub_uint64_t)(grub_size_t) framebuffer) >> 32);
  228. params->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
  229. #endif
  230. params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, 65536);
  231. params->red_mask_size = mode_info.red_mask_size;
  232. params->red_field_pos = mode_info.red_field_pos;
  233. params->green_mask_size = mode_info.green_mask_size;
  234. params->green_field_pos = mode_info.green_field_pos;
  235. params->blue_mask_size = mode_info.blue_mask_size;
  236. params->blue_field_pos = mode_info.blue_field_pos;
  237. params->reserved_mask_size = mode_info.reserved_mask_size;
  238. params->reserved_field_pos = mode_info.reserved_field_pos;
  239. if (gfxlfbvar && (gfxlfbvar[0] == '1' || gfxlfbvar[0] == 'y'))
  240. params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
  241. else
  242. {
  243. switch (driver_id)
  244. {
  245. case GRUB_VIDEO_DRIVER_VBE:
  246. params->lfb_size >>= 16;
  247. params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA;
  248. break;
  249. case GRUB_VIDEO_DRIVER_EFI_UGA:
  250. case GRUB_VIDEO_DRIVER_EFI_GOP:
  251. params->have_vga = GRUB_VIDEO_LINUX_TYPE_EFIFB;
  252. break;
  253. /* FIXME: check if better id is available. */
  254. case GRUB_VIDEO_DRIVER_SM712:
  255. case GRUB_VIDEO_DRIVER_SIS315PRO:
  256. case GRUB_VIDEO_DRIVER_VGA:
  257. case GRUB_VIDEO_DRIVER_CIRRUS:
  258. case GRUB_VIDEO_DRIVER_BOCHS:
  259. case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E:
  260. case GRUB_VIDEO_DRIVER_RADEON_YEELOONG3A:
  261. case GRUB_VIDEO_DRIVER_IEEE1275:
  262. case GRUB_VIDEO_DRIVER_COREBOOT:
  263. /* Make gcc happy. */
  264. case GRUB_VIDEO_DRIVER_XEN:
  265. case GRUB_VIDEO_DRIVER_SDL:
  266. case GRUB_VIDEO_DRIVER_NONE:
  267. case GRUB_VIDEO_ADAPTER_CAPTURE:
  268. params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
  269. break;
  270. }
  271. }
  272. #ifdef GRUB_MACHINE_PCBIOS
  273. /* VESA packed modes may come with zeroed mask sizes, which need
  274. to be set here according to DAC Palette width. If we don't,
  275. this results in Linux displaying a black screen. */
  276. if (driver_id == GRUB_VIDEO_DRIVER_VBE && mode_info.bpp <= 8)
  277. {
  278. struct grub_vbe_info_block controller_info;
  279. int status;
  280. int width = 8;
  281. status = grub_vbe_bios_get_controller_info (&controller_info);
  282. if (status == GRUB_VBE_STATUS_OK &&
  283. (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH))
  284. status = grub_vbe_bios_set_dac_palette_width (&width);
  285. if (status != GRUB_VBE_STATUS_OK)
  286. /* 6 is default after mode reset. */
  287. width = 6;
  288. params->red_mask_size = params->green_mask_size
  289. = params->blue_mask_size = width;
  290. params->reserved_mask_size = 0;
  291. }
  292. #endif
  293. return GRUB_ERR_NONE;
  294. }
  295. /* Context for grub_linux_boot. */
  296. struct grub_linux_boot_ctx
  297. {
  298. grub_addr_t real_mode_target;
  299. grub_size_t real_size;
  300. struct linux_kernel_params *params;
  301. int e820_num;
  302. };
  303. /* Helper for grub_linux_boot. */
  304. static int
  305. grub_linux_boot_mmap_find (grub_uint64_t addr, grub_uint64_t size,
  306. grub_memory_type_t type, void *data)
  307. {
  308. struct grub_linux_boot_ctx *ctx = data;
  309. /* We must put real mode code in the traditional space. */
  310. if (type != GRUB_MEMORY_AVAILABLE || addr > 0x90000)
  311. return 0;
  312. if (addr + size < 0x10000)
  313. return 0;
  314. if (addr < 0x10000)
  315. {
  316. size += addr - 0x10000;
  317. addr = 0x10000;
  318. }
  319. if (addr + size > 0x90000)
  320. size = 0x90000 - addr;
  321. if (ctx->real_size + efi_mmap_size > size)
  322. return 0;
  323. grub_dprintf ("linux", "addr = %lx, size = %x, need_size = %x\n",
  324. (unsigned long) addr,
  325. (unsigned) size,
  326. (unsigned) (ctx->real_size + efi_mmap_size));
  327. ctx->real_mode_target = ((addr + size) - (ctx->real_size + efi_mmap_size));
  328. return 1;
  329. }
  330. /* GRUB types conveniently match E820 types. */
  331. static int
  332. grub_linux_boot_mmap_fill (grub_uint64_t addr, grub_uint64_t size,
  333. grub_memory_type_t type, void *data)
  334. {
  335. struct grub_linux_boot_ctx *ctx = data;
  336. if (grub_e820_add_region (ctx->params->e820_map, &ctx->e820_num,
  337. addr, size, type))
  338. return 1;
  339. return 0;
  340. }
  341. static grub_err_t
  342. grub_linux_boot (void)
  343. {
  344. grub_err_t err = 0;
  345. const char *modevar;
  346. char *tmp;
  347. struct grub_relocator32_state state;
  348. void *real_mode_mem;
  349. struct grub_linux_boot_ctx ctx = {
  350. .real_mode_target = 0
  351. };
  352. grub_size_t mmap_size;
  353. grub_size_t cl_offset;
  354. #ifdef GRUB_MACHINE_IEEE1275
  355. {
  356. const char *bootpath;
  357. grub_ssize_t len;
  358. bootpath = grub_env_get ("root");
  359. if (bootpath)
  360. grub_ieee1275_set_property (grub_ieee1275_chosen,
  361. "bootpath", bootpath,
  362. grub_strlen (bootpath) + 1,
  363. &len);
  364. linux_params.ofw_signature = GRUB_LINUX_OFW_SIGNATURE;
  365. linux_params.ofw_num_items = 1;
  366. linux_params.ofw_cif_handler = (grub_uint32_t) grub_ieee1275_entry_fn;
  367. linux_params.ofw_idt = 0;
  368. }
  369. #endif
  370. modevar = grub_env_get ("gfxpayload");
  371. /* Now all graphical modes are acceptable.
  372. May change in future if we have modes without framebuffer. */
  373. if (modevar && *modevar != 0)
  374. {
  375. tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
  376. if (! tmp)
  377. return grub_errno;
  378. #if ACCEPTS_PURE_TEXT
  379. err = grub_video_set_mode (tmp, 0, 0);
  380. #else
  381. err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
  382. #endif
  383. grub_free (tmp);
  384. }
  385. else /* We can't go back to text mode from coreboot fb. */
  386. #ifdef GRUB_MACHINE_COREBOOT
  387. if (grub_video_get_driver_id () == GRUB_VIDEO_DRIVER_COREBOOT)
  388. err = GRUB_ERR_NONE;
  389. else
  390. #endif
  391. {
  392. #if ACCEPTS_PURE_TEXT
  393. err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
  394. #else
  395. err = grub_video_set_mode (DEFAULT_VIDEO_MODE,
  396. GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
  397. #endif
  398. }
  399. if (err)
  400. {
  401. grub_print_error ();
  402. grub_puts_ (N_("Booting in blind mode"));
  403. grub_errno = GRUB_ERR_NONE;
  404. }
  405. if (grub_linux_setup_video (&linux_params))
  406. {
  407. #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
  408. linux_params.have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT;
  409. linux_params.video_mode = 0x3;
  410. #else
  411. linux_params.have_vga = 0;
  412. linux_params.video_mode = 0;
  413. linux_params.video_width = 0;
  414. linux_params.video_height = 0;
  415. #endif
  416. }
  417. #ifndef GRUB_MACHINE_IEEE1275
  418. if (linux_params.have_vga == GRUB_VIDEO_LINUX_TYPE_TEXT)
  419. #endif
  420. {
  421. grub_term_output_t term;
  422. int found = 0;
  423. FOR_ACTIVE_TERM_OUTPUTS(term)
  424. if (grub_strcmp (term->name, "vga_text") == 0
  425. || grub_strcmp (term->name, "console") == 0
  426. || grub_strcmp (term->name, "ofconsole") == 0)
  427. {
  428. struct grub_term_coordinate pos = grub_term_getxy (term);
  429. linux_params.video_cursor_x = pos.x;
  430. linux_params.video_cursor_y = pos.y;
  431. linux_params.video_width = grub_term_width (term);
  432. linux_params.video_height = grub_term_height (term);
  433. found = 1;
  434. break;
  435. }
  436. if (!found)
  437. {
  438. linux_params.video_cursor_x = 0;
  439. linux_params.video_cursor_y = 0;
  440. linux_params.video_width = 80;
  441. linux_params.video_height = 25;
  442. }
  443. }
  444. #ifdef GRUB_KERNEL_USE_RSDP_ADDR
  445. linux_params.acpi_rsdp_addr = grub_le_to_cpu64 (grub_rsdp_addr);
  446. #endif
  447. mmap_size = find_mmap_size ();
  448. /* Make sure that each size is aligned to a page boundary. */
  449. cl_offset = ALIGN_UP (mmap_size + sizeof (linux_params), 4096);
  450. if (cl_offset < ((grub_size_t) linux_params.setup_sects << GRUB_DISK_SECTOR_BITS))
  451. cl_offset = ALIGN_UP ((grub_size_t) (linux_params.setup_sects
  452. << GRUB_DISK_SECTOR_BITS), 4096);
  453. ctx.real_size = ALIGN_UP (cl_offset + maximal_cmdline_size, 4096);
  454. #ifdef GRUB_MACHINE_EFI
  455. efi_mmap_size = grub_efi_find_mmap_size ();
  456. if (efi_mmap_size == 0)
  457. return grub_errno;
  458. #endif
  459. grub_dprintf ("linux", "real_size = %x, mmap_size = %x\n",
  460. (unsigned) ctx.real_size, (unsigned) mmap_size);
  461. #ifdef GRUB_MACHINE_EFI
  462. grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 1);
  463. if (! ctx.real_mode_target)
  464. grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 0);
  465. #else
  466. grub_mmap_iterate (grub_linux_boot_mmap_find, &ctx);
  467. #endif
  468. grub_dprintf ("linux", "real_mode_target = %lx, real_size = %x, efi_mmap_size = %x\n",
  469. (unsigned long) ctx.real_mode_target,
  470. (unsigned) ctx.real_size,
  471. (unsigned) efi_mmap_size);
  472. if (! ctx.real_mode_target)
  473. return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
  474. {
  475. grub_relocator_chunk_t ch;
  476. err = grub_relocator_alloc_chunk_addr (relocator, &ch,
  477. ctx.real_mode_target,
  478. (ctx.real_size + efi_mmap_size));
  479. if (err)
  480. return err;
  481. real_mode_mem = get_virtual_current_address (ch);
  482. }
  483. efi_mmap_buf = (grub_uint8_t *) real_mode_mem + ctx.real_size;
  484. grub_dprintf ("linux", "real_mode_mem = %p\n",
  485. real_mode_mem);
  486. ctx.params = real_mode_mem;
  487. *ctx.params = linux_params;
  488. ctx.params->cmd_line_ptr = ctx.real_mode_target + cl_offset;
  489. grub_memcpy ((char *) ctx.params + cl_offset, linux_cmdline,
  490. maximal_cmdline_size);
  491. grub_dprintf ("linux", "code32_start = %x\n",
  492. (unsigned) ctx.params->code32_start);
  493. ctx.e820_num = 0;
  494. if (grub_mmap_iterate (grub_linux_boot_mmap_fill, &ctx))
  495. return grub_errno;
  496. ctx.params->mmap_size = ctx.e820_num;
  497. #ifdef GRUB_MACHINE_EFI
  498. {
  499. grub_efi_uintn_t efi_desc_size;
  500. grub_size_t efi_mmap_target;
  501. grub_efi_uint32_t efi_desc_version;
  502. err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL,
  503. &efi_desc_size, &efi_desc_version);
  504. if (err)
  505. return err;
  506. /* Note that no boot services are available from here. */
  507. efi_mmap_target = ctx.real_mode_target
  508. + ((grub_uint8_t *) efi_mmap_buf - (grub_uint8_t *) real_mode_mem);
  509. /* Pass EFI parameters. */
  510. if (grub_le_to_cpu16 (ctx.params->version) >= 0x0208)
  511. {
  512. ctx.params->v0208.efi_mem_desc_size = efi_desc_size;
  513. ctx.params->v0208.efi_mem_desc_version = efi_desc_version;
  514. ctx.params->v0208.efi_mmap = efi_mmap_target;
  515. ctx.params->v0208.efi_mmap_size = efi_mmap_size;
  516. #ifdef __x86_64__
  517. ctx.params->v0208.efi_mmap_hi = (efi_mmap_target >> 32);
  518. #endif
  519. }
  520. else if (grub_le_to_cpu16 (ctx.params->version) >= 0x0206)
  521. {
  522. ctx.params->v0206.efi_mem_desc_size = efi_desc_size;
  523. ctx.params->v0206.efi_mem_desc_version = efi_desc_version;
  524. ctx.params->v0206.efi_mmap = efi_mmap_target;
  525. ctx.params->v0206.efi_mmap_size = efi_mmap_size;
  526. }
  527. else if (grub_le_to_cpu16 (ctx.params->version) >= 0x0204)
  528. {
  529. ctx.params->v0204.efi_mem_desc_size = efi_desc_size;
  530. ctx.params->v0204.efi_mem_desc_version = efi_desc_version;
  531. ctx.params->v0204.efi_mmap = efi_mmap_target;
  532. ctx.params->v0204.efi_mmap_size = efi_mmap_size;
  533. }
  534. }
  535. #endif
  536. /* FIXME. */
  537. /* asm volatile ("lidt %0" : : "m" (idt_desc)); */
  538. state.ebp = state.edi = state.ebx = 0;
  539. state.esi = ctx.real_mode_target;
  540. state.esp = ctx.real_mode_target;
  541. state.eip = ctx.params->code32_start;
  542. return grub_relocator32_boot (relocator, state, 0);
  543. }
  544. static grub_err_t
  545. grub_linux_unload (void)
  546. {
  547. grub_dl_unref (my_mod);
  548. loaded = 0;
  549. grub_free (linux_cmdline);
  550. linux_cmdline = 0;
  551. return GRUB_ERR_NONE;
  552. }
  553. static grub_err_t
  554. grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
  555. int argc, char *argv[])
  556. {
  557. grub_file_t file = 0;
  558. struct linux_i386_kernel_header lh;
  559. grub_uint8_t setup_sects;
  560. grub_size_t real_size, prot_size, prot_file_size;
  561. grub_ssize_t len;
  562. int i;
  563. grub_size_t align, min_align;
  564. int relocatable;
  565. grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
  566. grub_dl_ref (my_mod);
  567. if (argc == 0)
  568. {
  569. grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
  570. goto fail;
  571. }
  572. file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
  573. if (! file)
  574. goto fail;
  575. if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
  576. {
  577. if (!grub_errno)
  578. grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  579. argv[0]);
  580. goto fail;
  581. }
  582. if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
  583. {
  584. grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
  585. goto fail;
  586. }
  587. if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
  588. {
  589. grub_error (GRUB_ERR_BAD_OS, "too many setup sectors");
  590. goto fail;
  591. }
  592. /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
  593. still not support 32-bit boot. */
  594. if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
  595. || grub_le_to_cpu16 (lh.version) < 0x0203)
  596. {
  597. grub_error (GRUB_ERR_BAD_OS, "version too old for 32-bit boot"
  598. #ifdef GRUB_MACHINE_PCBIOS
  599. " (try with `linux16')"
  600. #endif
  601. );
  602. goto fail;
  603. }
  604. if (! (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL))
  605. {
  606. grub_error (GRUB_ERR_BAD_OS, "zImage doesn't support 32-bit boot"
  607. #ifdef GRUB_MACHINE_PCBIOS
  608. " (try with `linux16')"
  609. #endif
  610. );
  611. goto fail;
  612. }
  613. if (grub_le_to_cpu16 (lh.version) >= 0x0206)
  614. maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1;
  615. else
  616. maximal_cmdline_size = 256;
  617. if (maximal_cmdline_size < 128)
  618. maximal_cmdline_size = 128;
  619. setup_sects = lh.setup_sects;
  620. /* If SETUP_SECTS is not set, set it to the default (4). */
  621. if (! setup_sects)
  622. setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
  623. real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
  624. prot_file_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
  625. if (grub_le_to_cpu16 (lh.version) >= 0x205
  626. && lh.kernel_alignment != 0
  627. && ((lh.kernel_alignment - 1) & lh.kernel_alignment) == 0)
  628. {
  629. for (align = 0; align < 32; align++)
  630. if (grub_le_to_cpu32 (lh.kernel_alignment) & (1 << align))
  631. break;
  632. relocatable = grub_le_to_cpu32 (lh.relocatable);
  633. }
  634. else
  635. {
  636. align = 0;
  637. relocatable = 0;
  638. }
  639. if (grub_le_to_cpu16 (lh.version) >= 0x020a)
  640. {
  641. min_align = lh.min_alignment;
  642. prot_size = grub_le_to_cpu32 (lh.init_size);
  643. prot_init_space = page_align (prot_size);
  644. if (relocatable)
  645. preferred_address = grub_le_to_cpu64 (lh.pref_address);
  646. else
  647. preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
  648. }
  649. else
  650. {
  651. min_align = align;
  652. prot_size = prot_file_size;
  653. preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
  654. /* Usually, the compression ratio is about 50%. */
  655. prot_init_space = page_align (prot_size) * 3;
  656. }
  657. if (allocate_pages (prot_size, &align,
  658. min_align, relocatable,
  659. preferred_address))
  660. goto fail;
  661. grub_memset (&linux_params, 0, sizeof (linux_params));
  662. grub_memcpy (&linux_params.setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
  663. linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
  664. linux_params.kernel_alignment = (1 << align);
  665. linux_params.ps_mouse = linux_params.padding10 = 0;
  666. /*
  667. * The Linux 32-bit boot protocol defines the setup header end
  668. * to be at 0x202 + the byte value at 0x201.
  669. */
  670. len = 0x202 + *((char *) &linux_params.jump + 1);
  671. /* Verify the struct is big enough so we do not write past the end. */
  672. if (len > (char *) &linux_params.edd_mbr_sig_buffer - (char *) &linux_params) {
  673. grub_error (GRUB_ERR_BAD_OS, "Linux setup header too big");
  674. goto fail;
  675. }
  676. /* We've already read lh so there is no need to read it second time. */
  677. len -= sizeof(lh);
  678. if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len)
  679. {
  680. if (!grub_errno)
  681. grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  682. argv[0]);
  683. goto fail;
  684. }
  685. linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
  686. /* These two are used (instead of cmd_line_ptr) by older versions of Linux,
  687. and otherwise ignored. */
  688. linux_params.cl_magic = GRUB_LINUX_CL_MAGIC;
  689. linux_params.cl_offset = 0x1000;
  690. linux_params.ramdisk_image = 0;
  691. linux_params.ramdisk_size = 0;
  692. linux_params.heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
  693. linux_params.loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
  694. /* These are not needed to be precise, because Linux uses these values
  695. only to raise an error when the decompression code cannot find good
  696. space. */
  697. linux_params.ext_mem = ((32 * 0x100000) >> 10);
  698. linux_params.alt_mem = ((32 * 0x100000) >> 10);
  699. /* Ignored by Linux. */
  700. linux_params.video_page = 0;
  701. /* Only used when `video_mode == 0x7', otherwise ignored. */
  702. linux_params.video_ega_bx = 0;
  703. linux_params.font_size = 16; /* XXX */
  704. #ifdef GRUB_MACHINE_EFI
  705. #ifdef __x86_64__
  706. if (grub_le_to_cpu16 (linux_params.version) < 0x0208 &&
  707. ((grub_addr_t) grub_efi_system_table >> 32) != 0)
  708. return grub_error(GRUB_ERR_BAD_OS,
  709. "kernel does not support 64-bit addressing");
  710. #endif
  711. if (grub_le_to_cpu16 (linux_params.version) >= 0x0208)
  712. {
  713. linux_params.v0208.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
  714. linux_params.v0208.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
  715. #ifdef __x86_64__
  716. linux_params.v0208.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
  717. #endif
  718. }
  719. else if (grub_le_to_cpu16 (linux_params.version) >= 0x0206)
  720. {
  721. linux_params.v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
  722. linux_params.v0206.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
  723. }
  724. else if (grub_le_to_cpu16 (linux_params.version) >= 0x0204)
  725. {
  726. linux_params.v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
  727. linux_params.v0204.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
  728. }
  729. #endif
  730. /* The other parameters are filled when booting. */
  731. grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
  732. grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
  733. (unsigned) real_size, (unsigned) prot_size);
  734. /* Look for memory size and video mode specified on the command line. */
  735. linux_mem_size = 0;
  736. for (i = 1; i < argc; i++)
  737. #ifdef GRUB_MACHINE_PCBIOS
  738. if (grub_memcmp (argv[i], "vga=", 4) == 0)
  739. {
  740. /* Video mode selection support. */
  741. char *val = argv[i] + 4;
  742. unsigned vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
  743. struct grub_vesa_mode_table_entry *linux_mode;
  744. grub_err_t err;
  745. char *buf;
  746. grub_dl_load ("vbe");
  747. if (grub_strcmp (val, "normal") == 0)
  748. vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
  749. else if (grub_strcmp (val, "ext") == 0)
  750. vid_mode = GRUB_LINUX_VID_MODE_EXTENDED;
  751. else if (grub_strcmp (val, "ask") == 0)
  752. {
  753. grub_puts_ (N_("Legacy `ask' parameter no longer supported."));
  754. /* We usually would never do this in a loader, but "vga=ask" means user
  755. requested interaction, so it can't hurt to request keyboard input. */
  756. grub_wait_after_message ();
  757. goto fail;
  758. }
  759. else
  760. vid_mode = (grub_uint16_t) grub_strtoul (val, 0, 0);
  761. switch (vid_mode)
  762. {
  763. case 0:
  764. case GRUB_LINUX_VID_MODE_NORMAL:
  765. grub_env_set ("gfxpayload", "text");
  766. grub_printf_ (N_("%s is deprecated. "
  767. "Use set gfxpayload=%s before "
  768. "linux command instead.\n"),
  769. argv[i], "text");
  770. break;
  771. case 1:
  772. case GRUB_LINUX_VID_MODE_EXTENDED:
  773. /* FIXME: support 80x50 text. */
  774. grub_env_set ("gfxpayload", "text");
  775. grub_printf_ (N_("%s is deprecated. "
  776. "Use set gfxpayload=%s before "
  777. "linux command instead.\n"),
  778. argv[i], "text");
  779. break;
  780. default:
  781. /* Ignore invalid values. */
  782. if (vid_mode < GRUB_VESA_MODE_TABLE_START ||
  783. vid_mode > GRUB_VESA_MODE_TABLE_END)
  784. {
  785. grub_env_set ("gfxpayload", "text");
  786. /* TRANSLATORS: "x" has to be entered in, like an identifier,
  787. so please don't use better Unicode codepoints. */
  788. grub_printf_ (N_("%s is deprecated. VGA mode %d isn't recognized. "
  789. "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] "
  790. "before linux command instead.\n"),
  791. argv[i], vid_mode);
  792. break;
  793. }
  794. linux_mode = &grub_vesa_mode_table[vid_mode
  795. - GRUB_VESA_MODE_TABLE_START];
  796. buf = grub_xasprintf ("%ux%ux%u,%ux%u",
  797. linux_mode->width, linux_mode->height,
  798. linux_mode->depth,
  799. linux_mode->width, linux_mode->height);
  800. if (! buf)
  801. goto fail;
  802. grub_printf_ (N_("%s is deprecated. "
  803. "Use set gfxpayload=%s before "
  804. "linux command instead.\n"),
  805. argv[i], buf);
  806. err = grub_env_set ("gfxpayload", buf);
  807. grub_free (buf);
  808. if (err)
  809. goto fail;
  810. }
  811. }
  812. else
  813. #endif /* GRUB_MACHINE_PCBIOS */
  814. if (grub_memcmp (argv[i], "mem=", 4) == 0)
  815. {
  816. char *val = argv[i] + 4;
  817. linux_mem_size = grub_strtoul (val, &val, 0);
  818. if (grub_errno)
  819. {
  820. grub_errno = GRUB_ERR_NONE;
  821. linux_mem_size = 0;
  822. }
  823. else
  824. {
  825. int shift = 0;
  826. switch (grub_tolower (val[0]))
  827. {
  828. case 'g':
  829. shift += 10;
  830. /* FALLTHROUGH */
  831. case 'm':
  832. shift += 10;
  833. /* FALLTHROUGH */
  834. case 'k':
  835. shift += 10;
  836. /* FALLTHROUGH */
  837. default:
  838. break;
  839. }
  840. /* Check an overflow. */
  841. if (linux_mem_size > (~0UL >> shift))
  842. linux_mem_size = 0;
  843. else
  844. linux_mem_size <<= shift;
  845. }
  846. }
  847. else if (grub_memcmp (argv[i], "quiet", sizeof ("quiet") - 1) == 0)
  848. {
  849. linux_params.loadflags |= GRUB_LINUX_FLAG_QUIET;
  850. }
  851. /* Create kernel command line. */
  852. linux_cmdline = grub_zalloc (maximal_cmdline_size + 1);
  853. if (!linux_cmdline)
  854. goto fail;
  855. grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
  856. {
  857. grub_err_t err;
  858. err = grub_create_loader_cmdline (argc, argv,
  859. linux_cmdline
  860. + sizeof (LINUX_IMAGE) - 1,
  861. maximal_cmdline_size
  862. - (sizeof (LINUX_IMAGE) - 1),
  863. GRUB_VERIFY_KERNEL_CMDLINE);
  864. if (err)
  865. goto fail;
  866. }
  867. len = prot_file_size;
  868. if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
  869. grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
  870. argv[0]);
  871. if (grub_errno == GRUB_ERR_NONE)
  872. {
  873. grub_loader_set (grub_linux_boot, grub_linux_unload,
  874. 0 /* set noreturn=0 in order to avoid grub_console_fini() */);
  875. loaded = 1;
  876. }
  877. fail:
  878. if (file)
  879. grub_file_close (file);
  880. if (grub_errno != GRUB_ERR_NONE)
  881. {
  882. grub_dl_unref (my_mod);
  883. loaded = 0;
  884. }
  885. return grub_errno;
  886. }
  887. static grub_err_t
  888. grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
  889. int argc, char *argv[])
  890. {
  891. grub_size_t size = 0, aligned_size = 0;
  892. grub_addr_t addr_min, addr_max;
  893. grub_addr_t addr;
  894. grub_err_t err;
  895. struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
  896. if (argc == 0)
  897. {
  898. grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
  899. goto fail;
  900. }
  901. if (! loaded)
  902. {
  903. grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
  904. goto fail;
  905. }
  906. if (grub_initrd_init (argc, argv, &initrd_ctx))
  907. goto fail;
  908. size = grub_get_initrd_size (&initrd_ctx);
  909. aligned_size = ALIGN_UP (size, 4096);
  910. /* Get the highest address available for the initrd. */
  911. if (grub_le_to_cpu16 (linux_params.version) >= 0x0203)
  912. {
  913. addr_max = grub_cpu_to_le32 (linux_params.initrd_addr_max);
  914. /* XXX in reality, Linux specifies a bogus value, so
  915. it is necessary to make sure that ADDR_MAX does not exceed
  916. 0x3fffffff. */
  917. if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
  918. addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
  919. }
  920. else
  921. addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
  922. if (linux_mem_size != 0 && linux_mem_size < addr_max)
  923. addr_max = linux_mem_size;
  924. /* Linux 2.3.xx has a bug in the memory range check, so avoid
  925. the last page.
  926. Linux 2.2.xx has a bug in the memory range check, which is
  927. worse than that of Linux 2.3.xx, so avoid the last 64kb. */
  928. addr_max -= 0x10000;
  929. addr_min = (grub_addr_t) prot_mode_target + prot_init_space;
  930. /* Put the initrd as high as possible, 4KiB aligned. */
  931. addr = (addr_max - aligned_size) & ~0xFFF;
  932. if (addr < addr_min)
  933. {
  934. grub_error (GRUB_ERR_OUT_OF_RANGE, "the initrd is too big");
  935. goto fail;
  936. }
  937. {
  938. grub_relocator_chunk_t ch;
  939. err = grub_relocator_alloc_chunk_align (relocator, &ch,
  940. addr_min, addr, aligned_size,
  941. 0x1000,
  942. GRUB_RELOCATOR_PREFERENCE_HIGH,
  943. 1);
  944. if (err)
  945. return err;
  946. initrd_mem = get_virtual_current_address (ch);
  947. initrd_mem_target = get_physical_target_address (ch);
  948. }
  949. if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
  950. goto fail;
  951. grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
  952. (unsigned) addr, (unsigned) size);
  953. linux_params.ramdisk_image = initrd_mem_target;
  954. linux_params.ramdisk_size = size;
  955. linux_params.root_dev = 0x0100; /* XXX */
  956. fail:
  957. grub_initrd_close (&initrd_ctx);
  958. return grub_errno;
  959. }
  960. static grub_command_t cmd_linux, cmd_initrd;
  961. GRUB_MOD_INIT(linux)
  962. {
  963. cmd_linux = grub_register_command ("linux", grub_cmd_linux,
  964. 0, N_("Load Linux."));
  965. cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd,
  966. 0, N_("Load initrd."));
  967. my_mod = mod;
  968. }
  969. GRUB_MOD_FINI(linux)
  970. {
  971. grub_unregister_command (cmd_linux);
  972. grub_unregister_command (cmd_initrd);
  973. }