2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
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.
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.
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/>.
19 #include <grub/loader.h>
20 #include <grub/memory.h>
21 #include <grub/normal.h>
22 #include <grub/file.h>
23 #include <grub/disk.h>
25 #include <grub/misc.h>
26 #include <grub/types.h>
29 #include <grub/term.h>
30 #include <grub/cpu/linux.h>
31 #include <grub/video.h>
32 #include <grub/video_fb.h>
33 #include <grub/command.h>
34 #include <grub/i386/relocator.h>
35 #include <grub/i18n.h>
36 #include <grub/lib/cmdline.h>
38 GRUB_MOD_LICENSE ("GPLv3+");
40 #ifdef GRUB_MACHINE_PCBIOS
41 #include <grub/i386/pc/vesa_modes_table.h>
44 #ifdef GRUB_MACHINE_EFI
45 #include <grub/efi/efi.h>
46 #define HAS_VGA_TEXT 0
47 #define DEFAULT_VIDEO_MODE "auto"
48 #define ACCEPTS_PURE_TEXT 0
49 #elif defined (GRUB_MACHINE_IEEE1275)
50 #include <grub/ieee1275/ieee1275.h>
51 #define HAS_VGA_TEXT 0
52 #define DEFAULT_VIDEO_MODE "text"
53 #define ACCEPTS_PURE_TEXT 1
55 #include <grub/i386/pc/vbe.h>
56 #include <grub/i386/pc/console.h>
57 #define HAS_VGA_TEXT 1
58 #define DEFAULT_VIDEO_MODE "text"
59 #define ACCEPTS_PURE_TEXT 1
62 static grub_dl_t my_mod
;
64 static grub_size_t linux_mem_size
;
66 static void *prot_mode_mem
;
67 static grub_addr_t prot_mode_target
;
68 static void *initrd_mem
;
69 static grub_addr_t initrd_mem_target
;
70 static grub_size_t prot_init_space
;
71 static grub_uint32_t initrd_pages
;
72 static struct grub_relocator
*relocator
= NULL
;
73 static void *efi_mmap_buf
;
74 static grub_size_t maximal_cmdline_size
;
75 static struct linux_kernel_params linux_params
;
76 static char *linux_cmdline
;
77 #ifdef GRUB_MACHINE_EFI
78 static grub_efi_uintn_t efi_mmap_size
;
80 static const grub_size_t efi_mmap_size
= 0;
89 } __attribute__ ((packed
));
91 static struct idt_descriptor idt_desc
=
98 static inline grub_size_t
99 page_align (grub_size_t size
)
101 return (size
+ (1 << 12) - 1) & (~((1 << 12) - 1));
104 #ifdef GRUB_MACHINE_EFI
105 /* Find the optimal number of pages for the memory map. Is it better to
106 move this code to efi/mm.c? */
107 static grub_efi_uintn_t
108 find_efi_mmap_size (void)
110 static grub_efi_uintn_t mmap_size
= 0;
115 mmap_size
= (1 << 12);
119 grub_efi_memory_descriptor_t
*mmap
;
120 grub_efi_uintn_t desc_size
;
122 mmap
= grub_malloc (mmap_size
);
126 ret
= grub_efi_get_memory_map (&mmap_size
, mmap
, 0, &desc_size
, 0);
131 grub_error (GRUB_ERR_IO
, "cannot get memory map");
137 mmap_size
+= (1 << 12);
140 /* Increase the size a bit for safety, because GRUB allocates more on
141 later, and EFI itself may allocate more. */
142 mmap_size
+= (3 << 12);
144 mmap_size
= page_align (mmap_size
);
150 /* Find the optimal number of pages for the memory map. */
152 find_mmap_size (void)
154 grub_size_t count
= 0, mmap_size
;
156 auto int NESTED_FUNC_ATTR
hook (grub_uint64_t
, grub_uint64_t
,
158 int NESTED_FUNC_ATTR
hook (grub_uint64_t addr
__attribute__ ((unused
)),
159 grub_uint64_t size
__attribute__ ((unused
)),
160 grub_memory_type_t type
__attribute__ ((unused
)))
166 grub_mmap_iterate (hook
);
168 mmap_size
= count
* sizeof (struct grub_e820_mmap
);
170 /* Increase the size a bit for safety, because GRUB allocates more on
172 mmap_size
+= (1 << 12);
174 return page_align (mmap_size
);
180 grub_relocator_unload (relocator
);
182 prot_mode_mem
= initrd_mem
= 0;
183 prot_mode_target
= initrd_mem_target
= 0;
186 /* Allocate pages for the real mode code and the protected mode code
187 for linux as well as a memory map buffer. */
189 allocate_pages (grub_size_t prot_size
, grub_size_t
*align
,
190 grub_size_t min_align
, int relocatable
,
191 grub_uint64_t prefered_address
)
195 prot_size
= page_align (prot_size
);
197 /* Initialize the memory pointers with NULL for convenience. */
200 relocator
= grub_relocator_new ();
207 /* FIXME: Should request low memory from the heap when this feature is
211 grub_relocator_chunk_t ch
;
214 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
218 GRUB_RELOCATOR_PREFERENCE_LOW
,
220 for (; err
&& *align
+ 1 > min_align
; (*align
)--)
222 grub_errno
= GRUB_ERR_NONE
;
223 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
225 0xffffffff & ~prot_size
,
226 prot_size
, 1 << *align
,
227 GRUB_RELOCATOR_PREFERENCE_LOW
,
234 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
239 prot_mode_mem
= get_virtual_current_address (ch
);
240 prot_mode_target
= get_physical_target_address (ch
);
243 grub_dprintf ("linux", "prot_mode_mem = %lx, prot_mode_target = %lx, prot_size = %x\n",
244 (unsigned long) prot_mode_mem
, (unsigned long) prot_mode_target
,
245 (unsigned) prot_size
);
246 return GRUB_ERR_NONE
;
254 grub_e820_add_region (struct grub_e820_mmap
*e820_map
, int *e820_num
,
255 grub_uint64_t start
, grub_uint64_t size
,
260 if ((n
> 0) && (e820_map
[n
- 1].addr
+ e820_map
[n
- 1].size
== start
) &&
261 (e820_map
[n
- 1].type
== type
))
262 e820_map
[n
- 1].size
+= size
;
265 e820_map
[n
].addr
= start
;
266 e820_map
[n
].size
= size
;
267 e820_map
[n
].type
= type
;
270 return GRUB_ERR_NONE
;
274 grub_linux_setup_video (struct linux_kernel_params
*params
)
276 struct grub_video_mode_info mode_info
;
279 grub_video_driver_id_t driver_id
;
280 const char *gfxlfbvar
= grub_env_get ("gfxpayloadforcelfb");
282 driver_id
= grub_video_get_driver_id ();
284 if (driver_id
== GRUB_VIDEO_DRIVER_NONE
)
287 err
= grub_video_get_info_and_fini (&mode_info
, &framebuffer
);
291 grub_errno
= GRUB_ERR_NONE
;
295 params
->lfb_width
= mode_info
.width
;
296 params
->lfb_height
= mode_info
.height
;
297 params
->lfb_depth
= mode_info
.bpp
;
298 params
->lfb_line_len
= mode_info
.pitch
;
300 params
->lfb_base
= (grub_size_t
) framebuffer
;
301 params
->lfb_size
= ALIGN_UP (params
->lfb_line_len
* params
->lfb_height
, 65536);
303 params
->red_mask_size
= mode_info
.red_mask_size
;
304 params
->red_field_pos
= mode_info
.red_field_pos
;
305 params
->green_mask_size
= mode_info
.green_mask_size
;
306 params
->green_field_pos
= mode_info
.green_field_pos
;
307 params
->blue_mask_size
= mode_info
.blue_mask_size
;
308 params
->blue_field_pos
= mode_info
.blue_field_pos
;
309 params
->reserved_mask_size
= mode_info
.reserved_mask_size
;
310 params
->reserved_field_pos
= mode_info
.reserved_field_pos
;
312 if (gfxlfbvar
&& (gfxlfbvar
[0] == '1' || gfxlfbvar
[0] == 'y'))
313 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_SIMPLE
;
318 case GRUB_VIDEO_DRIVER_VBE
:
319 params
->lfb_size
>>= 16;
320 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_VESA
;
323 case GRUB_VIDEO_DRIVER_EFI_UGA
:
324 case GRUB_VIDEO_DRIVER_EFI_GOP
:
325 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_EFIFB
;
328 /* FIXME: check if better id is available. */
329 case GRUB_VIDEO_DRIVER_SM712
:
330 case GRUB_VIDEO_DRIVER_SIS315PRO
:
331 case GRUB_VIDEO_DRIVER_VGA
:
332 case GRUB_VIDEO_DRIVER_CIRRUS
:
333 case GRUB_VIDEO_DRIVER_BOCHS
:
334 case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E
:
335 /* Make gcc happy. */
336 case GRUB_VIDEO_DRIVER_SDL
:
337 case GRUB_VIDEO_DRIVER_NONE
:
338 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_SIMPLE
;
343 #ifdef GRUB_MACHINE_PCBIOS
344 /* VESA packed modes may come with zeroed mask sizes, which need
345 to be set here according to DAC Palette width. If we don't,
346 this results in Linux displaying a black screen. */
347 if (driver_id
== GRUB_VIDEO_DRIVER_VBE
&& mode_info
.bpp
<= 8)
349 struct grub_vbe_info_block controller_info
;
353 status
= grub_vbe_bios_get_controller_info (&controller_info
);
355 if (status
== GRUB_VBE_STATUS_OK
&&
356 (controller_info
.capabilities
& GRUB_VBE_CAPABILITY_DACWIDTH
))
357 status
= grub_vbe_bios_set_dac_palette_width (&width
);
359 if (status
!= GRUB_VBE_STATUS_OK
)
360 /* 6 is default after mode reset. */
363 params
->red_mask_size
= params
->green_mask_size
364 = params
->blue_mask_size
= width
;
365 params
->reserved_mask_size
= 0;
369 return GRUB_ERR_NONE
;
373 grub_linux_boot (void)
379 struct grub_relocator32_state state
;
381 grub_addr_t real_mode_target
= 0;
382 grub_size_t real_size
, mmap_size
;
383 grub_size_t cl_offset
;
385 #ifdef GRUB_MACHINE_IEEE1275
387 const char *bootpath
;
390 bootpath
= grub_env_get ("root");
392 grub_ieee1275_set_property (grub_ieee1275_chosen
,
393 "bootpath", bootpath
,
394 grub_strlen (bootpath
) + 1,
396 linux_params
.ofw_signature
= GRUB_LINUX_OFW_SIGNATURE
;
397 linux_params
.ofw_num_items
= 1;
398 linux_params
.ofw_cif_handler
= (grub_uint32_t
) grub_ieee1275_entry_fn
;
399 linux_params
.ofw_idt
= 0;
403 modevar
= grub_env_get ("gfxpayload");
405 /* Now all graphical modes are acceptable.
406 May change in future if we have modes without framebuffer. */
407 if (modevar
&& *modevar
!= 0)
409 tmp
= grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE
, modevar
);
412 #if ACCEPTS_PURE_TEXT
413 err
= grub_video_set_mode (tmp
, 0, 0);
415 err
= grub_video_set_mode (tmp
, GRUB_VIDEO_MODE_TYPE_PURE_TEXT
, 0);
421 #if ACCEPTS_PURE_TEXT
422 err
= grub_video_set_mode (DEFAULT_VIDEO_MODE
, 0, 0);
424 err
= grub_video_set_mode (DEFAULT_VIDEO_MODE
,
425 GRUB_VIDEO_MODE_TYPE_PURE_TEXT
, 0);
432 grub_puts_ (N_("Booting in blind mode"));
433 grub_errno
= GRUB_ERR_NONE
;
436 if (grub_linux_setup_video (&linux_params
))
438 #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
439 linux_params
.have_vga
= GRUB_VIDEO_LINUX_TYPE_TEXT
;
440 linux_params
.video_mode
= 0x3;
442 linux_params
.have_vga
= 0;
443 linux_params
.video_mode
= 0;
444 linux_params
.video_width
= 0;
445 linux_params
.video_height
= 0;
450 #ifndef GRUB_MACHINE_IEEE1275
451 if (linux_params
.have_vga
== GRUB_VIDEO_LINUX_TYPE_TEXT
)
454 grub_term_output_t term
;
456 FOR_ACTIVE_TERM_OUTPUTS(term
)
457 if (grub_strcmp (term
->name
, "vga_text") == 0
458 || grub_strcmp (term
->name
, "console") == 0
459 || grub_strcmp (term
->name
, "ofconsole") == 0)
461 grub_uint16_t pos
= grub_term_getxy (term
);
462 linux_params
.video_cursor_x
= pos
>> 8;
463 linux_params
.video_cursor_y
= pos
& 0xff;
464 linux_params
.video_width
= grub_term_width (term
);
465 linux_params
.video_height
= grub_term_height (term
);
471 linux_params
.video_cursor_x
= 0;
472 linux_params
.video_cursor_y
= 0;
473 linux_params
.video_width
= 80;
474 linux_params
.video_height
= 25;
478 mmap_size
= find_mmap_size ();
479 /* Make sure that each size is aligned to a page boundary. */
480 cl_offset
= ALIGN_UP (mmap_size
+ sizeof (linux_params
), 4096);
481 if (cl_offset
< ((grub_size_t
) linux_params
.setup_sects
<< GRUB_DISK_SECTOR_BITS
))
482 cl_offset
= ALIGN_UP ((grub_size_t
) (linux_params
.setup_sects
483 << GRUB_DISK_SECTOR_BITS
), 4096);
484 real_size
= ALIGN_UP (cl_offset
+ maximal_cmdline_size
, 4096);
486 #ifdef GRUB_MACHINE_EFI
487 efi_mmap_size
= find_efi_mmap_size ();
488 if (efi_mmap_size
== 0)
492 grub_dprintf ("linux", "real_size = %x, mmap_size = %x\n",
493 (unsigned) real_size
, (unsigned) mmap_size
);
495 auto int NESTED_FUNC_ATTR
hook (grub_uint64_t
, grub_uint64_t
,
497 int NESTED_FUNC_ATTR
hook (grub_uint64_t addr
, grub_uint64_t size
,
498 grub_memory_type_t type
)
500 /* We must put real mode code in the traditional space. */
501 if (type
!= GRUB_MEMORY_AVAILABLE
|| addr
> 0x90000)
504 if (addr
+ size
< 0x10000)
509 size
+= addr
- 0x10000;
513 if (addr
+ size
> 0x90000)
514 size
= 0x90000 - addr
;
516 if (real_size
+ efi_mmap_size
> size
)
519 grub_dprintf ("linux", "addr = %lx, size = %x, need_size = %x\n",
520 (unsigned long) addr
,
522 (unsigned) (real_size
+ efi_mmap_size
));
523 real_mode_target
= ((addr
+ size
) - (real_size
+ efi_mmap_size
));
526 #ifdef GRUB_MACHINE_EFI
527 grub_efi_mmap_iterate (hook
, 1);
528 if (! real_mode_target
)
529 grub_efi_mmap_iterate (hook
, 0);
531 grub_mmap_iterate (hook
);
533 grub_dprintf ("linux", "real_mode_target = %lx, real_size = %x, efi_mmap_size = %x\n",
534 (unsigned long) real_mode_target
,
535 (unsigned) real_size
,
536 (unsigned) efi_mmap_size
);
538 if (! real_mode_target
)
539 return grub_error (GRUB_ERR_OUT_OF_MEMORY
, "cannot allocate real mode pages");
542 grub_relocator_chunk_t ch
;
543 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
545 (real_size
+ efi_mmap_size
));
548 real_mode_mem
= get_virtual_current_address (ch
);
550 efi_mmap_buf
= (grub_uint8_t
*) real_mode_mem
+ real_size
;
552 grub_dprintf ("linux", "real_mode_mem = %lx\n",
553 (unsigned long) real_mode_mem
);
555 struct linux_kernel_params
*params
;
557 params
= real_mode_mem
;
559 *params
= linux_params
;
560 params
->cmd_line_ptr
= real_mode_target
+ cl_offset
;
561 grub_memcpy ((char *) params
+ cl_offset
, linux_cmdline
,
562 maximal_cmdline_size
);
564 grub_dprintf ("linux", "code32_start = %x\n",
565 (unsigned) params
->code32_start
);
567 auto int NESTED_FUNC_ATTR
hook_fill (grub_uint64_t
, grub_uint64_t
,
569 int NESTED_FUNC_ATTR
hook_fill (grub_uint64_t addr
, grub_uint64_t size
,
570 grub_memory_type_t type
)
572 grub_uint32_t e820_type
;
575 case GRUB_MEMORY_AVAILABLE
:
576 e820_type
= GRUB_E820_RAM
;
579 case GRUB_MEMORY_ACPI
:
580 e820_type
= GRUB_E820_ACPI
;
583 case GRUB_MEMORY_NVS
:
584 e820_type
= GRUB_E820_NVS
;
587 case GRUB_MEMORY_BADRAM
:
588 e820_type
= GRUB_E820_BADRAM
;
592 e820_type
= GRUB_E820_RESERVED
;
594 if (grub_e820_add_region (params
->e820_map
, &e820_num
,
595 addr
, size
, e820_type
))
602 if (grub_mmap_iterate (hook_fill
))
604 params
->mmap_size
= e820_num
;
606 #ifdef GRUB_MACHINE_EFI
608 grub_efi_uintn_t efi_desc_size
;
609 grub_size_t efi_mmap_target
;
610 grub_efi_uint32_t efi_desc_version
;
611 err
= grub_efi_finish_boot_services (&efi_mmap_size
, efi_mmap_buf
, NULL
,
612 &efi_desc_size
, &efi_desc_version
);
616 /* Note that no boot services are available from here. */
617 efi_mmap_target
= real_mode_target
618 + ((grub_uint8_t
*) efi_mmap_buf
- (grub_uint8_t
*) real_mode_mem
);
619 /* Pass EFI parameters. */
620 if (grub_le_to_cpu16 (params
->version
) >= 0x0208)
622 params
->v0208
.efi_mem_desc_size
= efi_desc_size
;
623 params
->v0208
.efi_mem_desc_version
= efi_desc_version
;
624 params
->v0208
.efi_mmap
= efi_mmap_target
;
625 params
->v0208
.efi_mmap_size
= efi_mmap_size
;
628 params
->v0208
.efi_mmap_hi
= (efi_mmap_target
>> 32);
631 else if (grub_le_to_cpu16 (params
->version
) >= 0x0206)
633 params
->v0206
.efi_mem_desc_size
= efi_desc_size
;
634 params
->v0206
.efi_mem_desc_version
= efi_desc_version
;
635 params
->v0206
.efi_mmap
= efi_mmap_target
;
636 params
->v0206
.efi_mmap_size
= efi_mmap_size
;
638 else if (grub_le_to_cpu16 (params
->version
) >= 0x0204)
640 params
->v0204
.efi_mem_desc_size
= efi_desc_size
;
641 params
->v0204
.efi_mem_desc_version
= efi_desc_version
;
642 params
->v0204
.efi_mmap
= efi_mmap_target
;
643 params
->v0204
.efi_mmap_size
= efi_mmap_size
;
649 /* asm volatile ("lidt %0" : : "m" (idt_desc)); */
650 state
.ebp
= state
.edi
= state
.ebx
= 0;
651 state
.esi
= real_mode_target
;
652 state
.esp
= real_mode_target
;
653 state
.eip
= params
->code32_start
;
654 return grub_relocator32_boot (relocator
, state
, 0);
658 grub_linux_unload (void)
660 grub_dl_unref (my_mod
);
662 grub_free (linux_cmdline
);
664 return GRUB_ERR_NONE
;
668 grub_cmd_linux (grub_command_t cmd
__attribute__ ((unused
)),
669 int argc
, char *argv
[])
671 grub_file_t file
= 0;
672 struct linux_kernel_header lh
;
673 struct linux_kernel_params
*params
;
674 grub_uint8_t setup_sects
;
675 grub_size_t real_size
, prot_size
, prot_file_size
;
678 grub_size_t align
, min_align
;
680 grub_uint64_t preffered_address
= GRUB_LINUX_BZIMAGE_ADDR
;
682 grub_dl_ref (my_mod
);
686 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
690 file
= grub_file_open (argv
[0]);
694 if (grub_file_read (file
, &lh
, sizeof (lh
)) != sizeof (lh
))
697 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
702 if (lh
.boot_flag
!= grub_cpu_to_le16 (0xaa55))
704 grub_error (GRUB_ERR_BAD_OS
, "invalid magic number");
708 if (lh
.setup_sects
> GRUB_LINUX_MAX_SETUP_SECTS
)
710 grub_error (GRUB_ERR_BAD_OS
, "too many setup sectors");
714 /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
715 still not support 32-bit boot. */
716 if (lh
.header
!= grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE
)
717 || grub_le_to_cpu16 (lh
.version
) < 0x0203)
719 grub_error (GRUB_ERR_BAD_OS
, "version too old for 32-bit boot"
720 #ifdef GRUB_MACHINE_PCBIOS
721 " (try with `linux16')"
727 if (! (lh
.loadflags
& GRUB_LINUX_FLAG_BIG_KERNEL
))
729 grub_error (GRUB_ERR_BAD_OS
, "zImage doesn't support 32-bit boot"
730 #ifdef GRUB_MACHINE_PCBIOS
731 " (try with `linux16')"
737 if (grub_le_to_cpu16 (lh
.version
) >= 0x0206)
738 maximal_cmdline_size
= grub_le_to_cpu32 (lh
.cmdline_size
) + 1;
740 maximal_cmdline_size
= 256;
742 if (maximal_cmdline_size
< 128)
743 maximal_cmdline_size
= 128;
745 setup_sects
= lh
.setup_sects
;
747 /* If SETUP_SECTS is not set, set it to the default (4). */
749 setup_sects
= GRUB_LINUX_DEFAULT_SETUP_SECTS
;
751 real_size
= setup_sects
<< GRUB_DISK_SECTOR_BITS
;
752 prot_file_size
= grub_file_size (file
) - real_size
- GRUB_DISK_SECTOR_SIZE
;
754 if (grub_le_to_cpu16 (lh
.version
) >= 0x205
755 && lh
.kernel_alignment
!= 0
756 && ((lh
.kernel_alignment
- 1) & lh
.kernel_alignment
) == 0)
758 for (align
= 0; align
< 32; align
++)
759 if (grub_le_to_cpu32 (lh
.kernel_alignment
) & (1 << align
))
761 relocatable
= grub_le_to_cpu32 (lh
.relocatable
);
769 if (grub_le_to_cpu16 (lh
.version
) >= 0x020a)
771 min_align
= lh
.min_alignment
;
772 prot_size
= grub_le_to_cpu32 (lh
.init_size
);
773 prot_init_space
= page_align (prot_size
);
775 preffered_address
= grub_le_to_cpu64 (lh
.pref_address
);
777 preffered_address
= GRUB_LINUX_BZIMAGE_ADDR
;
782 prot_size
= prot_file_size
;
783 preffered_address
= GRUB_LINUX_BZIMAGE_ADDR
;
784 /* Usually, the compression ratio is about 50%. */
785 prot_init_space
= page_align (prot_size
) * 3;
788 if (allocate_pages (prot_size
, &align
,
789 min_align
, relocatable
,
793 params
= (struct linux_kernel_params
*) &linux_params
;
794 grub_memset (params
, 0, sizeof (*params
));
795 grub_memcpy (¶ms
->setup_sects
, &lh
.setup_sects
, sizeof (lh
) - 0x1F1);
797 params
->code32_start
= prot_mode_target
+ lh
.code32_start
- GRUB_LINUX_BZIMAGE_ADDR
;
798 params
->kernel_alignment
= (1 << align
);
799 params
->ps_mouse
= params
->padding10
= 0;
801 len
= sizeof (*params
) - sizeof (lh
);
802 if (grub_file_read (file
, (char *) params
+ sizeof (lh
), len
) != len
)
805 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
810 params
->type_of_loader
= GRUB_LINUX_BOOT_LOADER_TYPE
;
812 /* These two are used (instead of cmd_line_ptr) by older versions of Linux,
813 and otherwise ignored. */
814 params
->cl_magic
= GRUB_LINUX_CL_MAGIC
;
815 params
->cl_offset
= 0x1000;
817 params
->ramdisk_image
= 0;
818 params
->ramdisk_size
= 0;
820 params
->heap_end_ptr
= GRUB_LINUX_HEAP_END_OFFSET
;
821 params
->loadflags
|= GRUB_LINUX_FLAG_CAN_USE_HEAP
;
823 /* These are not needed to be precise, because Linux uses these values
824 only to raise an error when the decompression code cannot find good
826 params
->ext_mem
= ((32 * 0x100000) >> 10);
827 params
->alt_mem
= ((32 * 0x100000) >> 10);
829 /* Ignored by Linux. */
830 params
->video_page
= 0;
832 /* Only used when `video_mode == 0x7', otherwise ignored. */
833 params
->video_ega_bx
= 0;
835 params
->font_size
= 16; /* XXX */
837 #ifdef GRUB_MACHINE_EFI
839 if (grub_le_to_cpu16 (params
->version
< 0x0208) &&
840 ((grub_addr_t
) grub_efi_system_table
>> 32) != 0)
841 return grub_error(GRUB_ERR_BAD_OS
,
842 "kernel does not support 64-bit addressing");
845 if (grub_le_to_cpu16 (params
->version
) >= 0x0208)
847 params
->v0208
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE
;
848 params
->v0208
.efi_system_table
= (grub_uint32_t
) (unsigned long) grub_efi_system_table
;
850 params
->v0208
.efi_system_table_hi
= (grub_uint32_t
) ((grub_uint64_t
) grub_efi_system_table
>> 32);
853 else if (grub_le_to_cpu16 (params
->version
) >= 0x0206)
855 params
->v0206
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE
;
856 params
->v0206
.efi_system_table
= (grub_uint32_t
) (unsigned long) grub_efi_system_table
;
858 else if (grub_le_to_cpu16 (params
->version
) >= 0x0204)
860 params
->v0204
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE_0204
;
861 params
->v0204
.efi_system_table
= (grub_uint32_t
) (unsigned long) grub_efi_system_table
;
865 /* The other parameters are filled when booting. */
867 grub_file_seek (file
, real_size
+ GRUB_DISK_SECTOR_SIZE
);
869 grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
870 (unsigned) real_size
, (unsigned) prot_size
);
872 /* Look for memory size and video mode specified on the command line. */
874 for (i
= 1; i
< argc
; i
++)
875 #ifdef GRUB_MACHINE_PCBIOS
876 if (grub_memcmp (argv
[i
], "vga=", 4) == 0)
878 /* Video mode selection support. */
879 char *val
= argv
[i
] + 4;
880 unsigned vid_mode
= GRUB_LINUX_VID_MODE_NORMAL
;
881 struct grub_vesa_mode_table_entry
*linux_mode
;
885 grub_dl_load ("vbe");
887 if (grub_strcmp (val
, "normal") == 0)
888 vid_mode
= GRUB_LINUX_VID_MODE_NORMAL
;
889 else if (grub_strcmp (val
, "ext") == 0)
890 vid_mode
= GRUB_LINUX_VID_MODE_EXTENDED
;
891 else if (grub_strcmp (val
, "ask") == 0)
893 grub_puts_ (N_("Legacy `ask' parameter no longer supported."));
895 /* We usually would never do this in a loader, but "vga=ask" means user
896 requested interaction, so it can't hurt to request keyboard input. */
897 grub_wait_after_message ();
902 vid_mode
= (grub_uint16_t
) grub_strtoul (val
, 0, 0);
907 case GRUB_LINUX_VID_MODE_NORMAL
:
908 grub_env_set ("gfxpayload", "text");
909 grub_printf_ (N_("%s is deprecated. "
910 "Use set gfxpayload=%s before "
911 "linux command instead.\n"), "text",
916 case GRUB_LINUX_VID_MODE_EXTENDED
:
917 /* FIXME: support 80x50 text. */
918 grub_env_set ("gfxpayload", "text");
919 grub_printf_ (N_("%s is deprecated. "
920 "Use set gfxpayload=%s before "
921 "linux command instead.\n"), "text",
925 /* Ignore invalid values. */
926 if (vid_mode
< GRUB_VESA_MODE_TABLE_START
||
927 vid_mode
> GRUB_VESA_MODE_TABLE_END
)
929 grub_env_set ("gfxpayload", "text");
930 /* TRANSLATORS: "x" has to be entered in, like an identifier,
931 so please don't use better Unicode codepoints. */
932 grub_printf_ (N_("%s is deprecated. VGA mode %d isn't recognized. "
933 "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] "
934 "before linux command instead.\n"),
939 linux_mode
= &grub_vesa_mode_table
[vid_mode
940 - GRUB_VESA_MODE_TABLE_START
];
942 buf
= grub_xasprintf ("%ux%ux%u,%ux%u",
943 linux_mode
->width
, linux_mode
->height
,
945 linux_mode
->width
, linux_mode
->height
);
949 grub_printf_ (N_("%s is deprecated. "
950 "Use set gfxpayload=%s before "
951 "linux command instead.\n"),
953 err
= grub_env_set ("gfxpayload", buf
);
960 #endif /* GRUB_MACHINE_PCBIOS */
961 if (grub_memcmp (argv
[i
], "mem=", 4) == 0)
963 char *val
= argv
[i
] + 4;
965 linux_mem_size
= grub_strtoul (val
, &val
, 0);
969 grub_errno
= GRUB_ERR_NONE
;
976 switch (grub_tolower (val
[0]))
988 /* Check an overflow. */
989 if (linux_mem_size
> (~0UL >> shift
))
992 linux_mem_size
<<= shift
;
995 else if (grub_memcmp (argv
[i
], "quiet", sizeof ("quiet") - 1) == 0)
997 params
->loadflags
|= GRUB_LINUX_FLAG_QUIET
;
1000 /* Create kernel command line. */
1001 linux_cmdline
= grub_zalloc (maximal_cmdline_size
+ 1);
1004 grub_memcpy (linux_cmdline
, LINUX_IMAGE
, sizeof (LINUX_IMAGE
));
1005 grub_create_loader_cmdline (argc
, argv
,
1007 + sizeof (LINUX_IMAGE
) - 1,
1008 maximal_cmdline_size
1009 - (sizeof (LINUX_IMAGE
) - 1));
1011 len
= prot_file_size
;
1012 if (grub_file_read (file
, prot_mode_mem
, len
) != len
&& !grub_errno
)
1013 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
1016 if (grub_errno
== GRUB_ERR_NONE
)
1018 grub_loader_set (grub_linux_boot
, grub_linux_unload
,
1019 0 /* set noreturn=0 in order to avoid grub_console_fini() */);
1026 grub_file_close (file
);
1028 if (grub_errno
!= GRUB_ERR_NONE
)
1030 grub_dl_unref (my_mod
);
1038 grub_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
1039 int argc
, char *argv
[])
1041 grub_file_t
*files
= 0;
1042 grub_size_t size
= 0;
1043 grub_addr_t addr_min
, addr_max
;
1052 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
1058 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("you need to load the kernel first"));
1062 files
= grub_zalloc (argc
* sizeof (files
[0]));
1066 for (i
= 0; i
< argc
; i
++)
1068 grub_file_filter_disable_compression ();
1069 files
[i
] = grub_file_open (argv
[i
]);
1073 size
+= ALIGN_UP (grub_file_size (files
[i
]), 4);
1076 initrd_pages
= (page_align (size
) >> 12);
1078 /* Get the highest address available for the initrd. */
1079 if (grub_le_to_cpu16 (linux_params
.version
) >= 0x0203)
1081 addr_max
= grub_cpu_to_le32 (linux_params
.initrd_addr_max
);
1083 /* XXX in reality, Linux specifies a bogus value, so
1084 it is necessary to make sure that ADDR_MAX does not exceed
1086 if (addr_max
> GRUB_LINUX_INITRD_MAX_ADDRESS
)
1087 addr_max
= GRUB_LINUX_INITRD_MAX_ADDRESS
;
1090 addr_max
= GRUB_LINUX_INITRD_MAX_ADDRESS
;
1092 if (linux_mem_size
!= 0 && linux_mem_size
< addr_max
)
1093 addr_max
= linux_mem_size
;
1095 /* Linux 2.3.xx has a bug in the memory range check, so avoid
1097 Linux 2.2.xx has a bug in the memory range check, which is
1098 worse than that of Linux 2.3.xx, so avoid the last 64kb. */
1099 addr_max
-= 0x10000;
1101 addr_min
= (grub_addr_t
) prot_mode_target
+ prot_init_space
1102 + page_align (size
);
1104 /* Put the initrd as high as possible, 4KiB aligned. */
1105 addr
= (addr_max
- size
) & ~0xFFF;
1107 if (addr
< addr_min
)
1109 grub_error (GRUB_ERR_OUT_OF_RANGE
, "the initrd is too big");
1114 grub_relocator_chunk_t ch
;
1115 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
1116 addr_min
, addr
, size
, 0x1000,
1117 GRUB_RELOCATOR_PREFERENCE_HIGH
,
1121 initrd_mem
= get_virtual_current_address (ch
);
1122 initrd_mem_target
= get_physical_target_address (ch
);
1126 for (i
= 0; i
< nfiles
; i
++)
1128 grub_ssize_t cursize
= grub_file_size (files
[i
]);
1129 if (grub_file_read (files
[i
], ptr
, cursize
) != cursize
)
1132 grub_error (GRUB_ERR_FILE_READ_ERROR
, N_("premature end of file %s"),
1137 grub_memset (ptr
, 0, ALIGN_UP_OVERHEAD (cursize
, 4));
1138 ptr
+= ALIGN_UP_OVERHEAD (cursize
, 4);
1141 grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
1142 (unsigned) addr
, (unsigned) size
);
1144 linux_params
.ramdisk_image
= initrd_mem_target
;
1145 linux_params
.ramdisk_size
= size
;
1146 linux_params
.root_dev
= 0x0100; /* XXX */
1149 for (i
= 0; i
< nfiles
; i
++)
1150 grub_file_close (files
[i
]);
1156 static grub_command_t cmd_linux
, cmd_initrd
;
1158 GRUB_MOD_INIT(linux
)
1160 cmd_linux
= grub_register_command ("linux", grub_cmd_linux
,
1161 0, N_("Load Linux."));
1162 cmd_initrd
= grub_register_command ("initrd", grub_cmd_initrd
,
1163 0, N_("Load initrd."));
1167 GRUB_MOD_FINI(linux
)
1169 grub_unregister_command (cmd_linux
);
1170 grub_unregister_command (cmd_initrd
);