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/machine/memory.h>
21 #include <grub/machine/loader.h>
22 #include <grub/normal.h>
23 #include <grub/file.h>
24 #include <grub/disk.h>
26 #include <grub/misc.h>
27 #include <grub/types.h>
30 #include <grub/term.h>
31 #include <grub/cpu/linux.h>
32 #include <grub/video.h>
33 #include <grub/video_fb.h>
34 #include <grub/command.h>
35 #include <grub/i386/pc/vbe.h>
36 #include <grub/i386/pc/console.h>
37 #include <grub/i18n.h>
39 #define GRUB_LINUX_CL_OFFSET 0x1000
40 #define GRUB_LINUX_CL_END_OFFSET 0x2000
42 static grub_dl_t my_mod
;
44 static grub_size_t linux_mem_size
;
46 static void *real_mode_mem
;
47 static void *prot_mode_mem
;
48 static void *initrd_mem
;
49 static grub_uint32_t real_mode_pages
;
50 static grub_uint32_t prot_mode_pages
;
51 static grub_uint32_t initrd_pages
;
53 static grub_uint8_t gdt
[] __attribute__ ((aligned(16))) =
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00,
62 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
69 } __attribute__ ((packed
));
71 static struct gdt_descriptor gdt_desc
=
81 } __attribute__ ((packed
));
83 static struct idt_descriptor idt_desc
=
89 #ifdef GRUB_MACHINE_PCBIOS
90 struct linux_vesafb_res
96 struct linux_vesafb_mode
98 grub_uint8_t res_index
;
118 static struct linux_vesafb_res linux_vesafb_res
[] =
134 /* This is the reverse of the table in [linux]/Documentation/fb/vesafb.txt
135 plus a few more modes based on the table in
136 http://en.wikipedia.org/wiki/VESA_BIOS_Extensions */
137 struct linux_vesafb_mode linux_vesafb_modes
[] =
139 { VGA_640_400
, 8 }, /* 0x300 */
140 { VGA_640_480
, 8 }, /* 0x301 */
141 { VGA_800_600
, 4 }, /* 0x302 */
142 { VGA_800_600
, 8 }, /* 0x303 */
143 { VGA_1024_768
, 4 }, /* 0x304 */
144 { VGA_1024_768
, 8 }, /* 0x305 */
145 { VGA_1280_1024
, 4 }, /* 0x306 */
146 { VGA_1280_1024
, 8 }, /* 0x307 */
152 { VGA_320_200
, 15 }, /* 0x30d */
153 { VGA_320_200
, 16 }, /* 0x30e */
154 { VGA_320_200
, 24 }, /* 0x30f */
155 { VGA_640_480
, 15 }, /* 0x310 */
156 { VGA_640_480
, 16 }, /* 0x311 */
157 { VGA_640_480
, 24 }, /* 0x312 */
158 { VGA_800_600
, 15 }, /* 0x313 */
159 { VGA_800_600
, 16 }, /* 0x314 */
160 { VGA_800_600
, 24 }, /* 0x315 */
161 { VGA_1024_768
, 15 }, /* 0x316 */
162 { VGA_1024_768
, 16 }, /* 0x317 */
163 { VGA_1024_768
, 24 }, /* 0x318 */
164 { VGA_1280_1024
, 15 }, /* 0x319 */
165 { VGA_1280_1024
, 16 }, /* 0x31a */
166 { VGA_1280_1024
, 24 }, /* 0x31b */
167 { VGA_1600_1200
, 8 }, /* 0x31c */
168 { VGA_1600_1200
, 15 }, /* 0x31d */
169 { VGA_1600_1200
, 16 }, /* 0x31e */
170 { VGA_1600_1200
, 24 }, /* 0x31f */
172 { VGA_640_400
, 15 }, /* 0x321 */
173 { VGA_640_400
, 16 }, /* 0x322 */
174 { VGA_640_400
, 24 }, /* 0x323 */
175 { VGA_640_400
, 32 }, /* 0x324 */
180 { VGA_640_480
, 32 }, /* 0x329 */
186 { VGA_896_672
, 8 }, /* 0x32f */
187 { VGA_896_672
, 15 }, /* 0x330 */
188 { VGA_896_672
, 16 }, /* 0x331 */
189 { VGA_896_672
, 24 }, /* 0x332 */
190 { VGA_896_672
, 32 }, /* 0x333 */
205 { VGA_1600_1200
, 32 }, /* 0x342 */
235 { VGA_1440_900
, 8 }, /* 0x360 */
236 { VGA_1440_900
, 15 }, /* 0x361 */
237 { VGA_1440_900
, 16 }, /* 0x362 */
238 { VGA_1440_900
, 24 }, /* 0x363 */
239 { VGA_1440_900
, 32 }, /* 0x364 */
240 { VGA_1152_720
, 8 }, /* 0x365 */
241 { VGA_1152_720
, 15 }, /* 0x366 */
242 { VGA_1152_720
, 16 }, /* 0x367 */
243 { VGA_1152_720
, 24 }, /* 0x368 */
244 { VGA_1152_720
, 32 }, /* 0x369 */
245 { VGA_1024_640
, 8 }, /* 0x36a */
246 { VGA_1024_640
, 15 }, /* 0x36b */
247 { VGA_1024_640
, 16 }, /* 0x36c */
248 { VGA_1024_640
, 24 }, /* 0x36d */
249 { VGA_1024_640
, 32 }, /* 0x36e */
250 { VGA_800_500
, 8 }, /* 0x36f */
251 { VGA_800_500
, 15 }, /* 0x370 */
252 { VGA_800_500
, 16 }, /* 0x371 */
253 { VGA_800_500
, 24 }, /* 0x372 */
254 { VGA_800_500
, 32 }, /* 0x373 */
258 static inline grub_size_t
259 page_align (grub_size_t size
)
261 return (size
+ (1 << 12) - 1) & (~((1 << 12) - 1));
264 /* Find the optimal number of pages for the memory map. */
266 find_mmap_size (void)
268 grub_size_t count
= 0, mmap_size
;
270 auto int NESTED_FUNC_ATTR
hook (grub_uint64_t
, grub_uint64_t
, grub_uint32_t
);
271 int NESTED_FUNC_ATTR
hook (grub_uint64_t addr
__attribute__ ((unused
)),
272 grub_uint64_t size
__attribute__ ((unused
)),
273 grub_uint32_t type
__attribute__ ((unused
)))
279 grub_mmap_iterate (hook
);
281 mmap_size
= count
* sizeof (struct grub_e820_mmap
);
283 /* Increase the size a bit for safety, because GRUB allocates more on
285 mmap_size
+= (1 << 12);
287 return page_align (mmap_size
);
293 real_mode_mem
= prot_mode_mem
= initrd_mem
= 0;
296 /* Allocate pages for the real mode code and the protected mode code
297 for linux as well as a memory map buffer. */
299 allocate_pages (grub_size_t prot_size
)
301 grub_size_t real_size
, mmap_size
;
303 /* Make sure that each size is aligned to a page boundary. */
304 real_size
= GRUB_LINUX_CL_END_OFFSET
;
305 prot_size
= page_align (prot_size
);
306 mmap_size
= find_mmap_size ();
308 grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
309 (unsigned) real_size
, (unsigned) prot_size
, (unsigned) mmap_size
);
311 /* Calculate the number of pages; Combine the real mode code with
312 the memory map buffer for simplicity. */
313 real_mode_pages
= ((real_size
+ mmap_size
) >> 12);
314 prot_mode_pages
= (prot_size
>> 12);
316 /* Initialize the memory pointers with NULL for convenience. */
319 /* FIXME: Should request low memory from the heap when this feature is
322 auto int NESTED_FUNC_ATTR
hook (grub_uint64_t
, grub_uint64_t
, grub_uint32_t
);
323 int NESTED_FUNC_ATTR
hook (grub_uint64_t addr
, grub_uint64_t size
, grub_uint32_t type
)
325 /* We must put real mode code in the traditional space. */
327 if (type
== GRUB_MACHINE_MEMORY_AVAILABLE
332 size
+= addr
- 0x10000;
336 if (addr
+ size
> 0x90000)
337 size
= 0x90000 - addr
;
339 if (real_size
+ mmap_size
> size
)
343 (void *) (grub_size_t
) ((addr
+ size
) - (real_size
+ mmap_size
));
349 grub_mmap_iterate (hook
);
352 grub_error (GRUB_ERR_OUT_OF_MEMORY
, "cannot allocate real mode pages");
356 prot_mode_mem
= (void *) 0x100000;
358 grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
359 "prot_mode_mem = %lx, prot_mode_pages = %x\n",
360 (unsigned long) real_mode_mem
, (unsigned) real_mode_pages
,
361 (unsigned long) prot_mode_mem
, (unsigned) prot_mode_pages
);
371 grub_e820_add_region (struct grub_e820_mmap
*e820_map
, int *e820_num
,
372 grub_uint64_t start
, grub_uint64_t size
,
377 if (n
>= GRUB_E820_MAX_ENTRY
)
378 grub_fatal ("Too many e820 memory map entries");
380 if ((n
> 0) && (e820_map
[n
- 1].addr
+ e820_map
[n
- 1].size
== start
) &&
381 (e820_map
[n
- 1].type
== type
))
382 e820_map
[n
- 1].size
+= size
;
385 e820_map
[n
].addr
= start
;
386 e820_map
[n
].size
= size
;
387 e820_map
[n
].type
= type
;
393 grub_linux_setup_video (struct linux_kernel_params
*params
)
395 struct grub_video_mode_info mode_info
;
399 err
= grub_video_get_info_and_fini (&mode_info
, &framebuffer
);
403 grub_errno
= GRUB_ERR_NONE
;
407 params
->lfb_width
= mode_info
.width
;
408 params
->lfb_height
= mode_info
.height
;
409 params
->lfb_depth
= mode_info
.bpp
;
410 params
->lfb_line_len
= mode_info
.pitch
;
412 params
->lfb_base
= (grub_size_t
) framebuffer
;
413 params
->lfb_size
= ALIGN_UP (params
->lfb_line_len
* params
->lfb_height
, 65536);
415 params
->red_mask_size
= mode_info
.red_mask_size
;
416 params
->red_field_pos
= mode_info
.red_field_pos
;
417 params
->green_mask_size
= mode_info
.green_mask_size
;
418 params
->green_field_pos
= mode_info
.green_field_pos
;
419 params
->blue_mask_size
= mode_info
.blue_mask_size
;
420 params
->blue_field_pos
= mode_info
.blue_field_pos
;
421 params
->reserved_mask_size
= mode_info
.reserved_mask_size
;
422 params
->reserved_field_pos
= mode_info
.reserved_field_pos
;
425 #ifdef GRUB_MACHINE_PCBIOS
426 /* VESA packed modes may come with zeroed mask sizes, which need
427 to be set here according to DAC Palette width. If we don't,
428 this results in Linux displaying a black screen. */
429 if (mode_info
.bpp
<= 8)
431 struct grub_vbe_info_block controller_info
;
435 status
= grub_vbe_bios_get_controller_info (&controller_info
);
437 if (status
== GRUB_VBE_STATUS_OK
&&
438 (controller_info
.capabilities
& GRUB_VBE_CAPABILITY_DACWIDTH
))
439 status
= grub_vbe_bios_set_dac_palette_width (&width
);
441 if (status
!= GRUB_VBE_STATUS_OK
)
442 /* 6 is default after mode reset. */
445 params
->red_mask_size
= params
->green_mask_size
446 = params
->blue_mask_size
= width
;
447 params
->reserved_mask_size
= 0;
455 extern grub_uint8_t grub_linux_trampoline_start
[];
456 extern grub_uint8_t grub_linux_trampoline_end
[];
460 grub_linux_boot (void)
462 struct linux_kernel_params
*params
;
467 params
= real_mode_mem
;
469 grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
470 (unsigned) params
->code32_start
,
471 (unsigned long) &(idt_desc
.limit
),
472 (unsigned long) &(gdt_desc
.limit
));
473 grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n",
474 (unsigned) idt_desc
.limit
, (unsigned long) idt_desc
.base
,
475 (unsigned) gdt_desc
.limit
, (unsigned long) gdt_desc
.base
);
477 auto int NESTED_FUNC_ATTR
hook (grub_uint64_t
, grub_uint64_t
, grub_uint32_t
);
478 int NESTED_FUNC_ATTR
hook (grub_uint64_t addr
, grub_uint64_t size
, grub_uint32_t type
)
482 case GRUB_MACHINE_MEMORY_AVAILABLE
:
483 grub_e820_add_region (params
->e820_map
, &e820_num
,
484 addr
, size
, GRUB_E820_RAM
);
487 #ifdef GRUB_MACHINE_MEMORY_ACPI
488 case GRUB_MACHINE_MEMORY_ACPI
:
489 grub_e820_add_region (params
->e820_map
, &e820_num
,
490 addr
, size
, GRUB_E820_ACPI
);
494 #ifdef GRUB_MACHINE_MEMORY_NVS
495 case GRUB_MACHINE_MEMORY_NVS
:
496 grub_e820_add_region (params
->e820_map
, &e820_num
,
497 addr
, size
, GRUB_E820_NVS
);
501 #ifdef GRUB_MACHINE_MEMORY_CODE
502 case GRUB_MACHINE_MEMORY_CODE
:
503 grub_e820_add_region (params
->e820_map
, &e820_num
,
504 addr
, size
, GRUB_E820_EXEC_CODE
);
509 grub_e820_add_region (params
->e820_map
, &e820_num
,
510 addr
, size
, GRUB_E820_RESERVED
);
516 grub_mmap_iterate (hook
);
517 params
->mmap_size
= e820_num
;
519 modevar
= grub_env_get ("gfxpayload");
521 /* Now all graphical modes are acceptable.
522 May change in future if we have modes without framebuffer. */
523 if (modevar
&& *modevar
!= 0)
525 tmp
= grub_xasprintf ("%s;text", modevar
);
528 err
= grub_video_set_mode (tmp
, 0, 0);
532 err
= grub_video_set_mode ("text", 0, 0);
537 grub_printf ("Booting however\n");
538 grub_errno
= GRUB_ERR_NONE
;
541 if (! grub_linux_setup_video (params
))
543 /* Use generic framebuffer unless VESA is known to be supported. */
544 if (params
->have_vga
!= GRUB_VIDEO_LINUX_TYPE_VESA
)
545 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_SIMPLE
;
547 params
->lfb_size
>>= 16;
551 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_TEXT
;
552 params
->video_width
= 80;
553 params
->video_height
= 25;
556 /* Initialize these last, because terminal position could be affected by printfs above. */
557 if (params
->have_vga
== GRUB_VIDEO_LINUX_TYPE_TEXT
)
559 grub_term_output_t term
;
561 FOR_ACTIVE_TERM_OUTPUTS(term
)
562 if (grub_strcmp (term
->name
, "vga_text") == 0
563 || grub_strcmp (term
->name
, "console") == 0)
565 grub_uint16_t pos
= grub_term_getxy (term
);
566 params
->video_cursor_x
= pos
>> 8;
567 params
->video_cursor_y
= pos
& 0xff;
573 params
->video_cursor_x
= 0;
574 params
->video_cursor_y
= 0;
580 grub_memcpy ((char *) prot_mode_mem
+ (prot_mode_pages
<< 12),
581 grub_linux_trampoline_start
,
582 grub_linux_trampoline_end
- grub_linux_trampoline_start
);
584 ((void (*) (unsigned long, void *)) ((char *) prot_mode_mem
585 + (prot_mode_pages
<< 12)))
586 (params
->code32_start
, real_mode_mem
);
589 /* Hardware interrupts are not safe any longer. */
590 asm volatile ("cli" : : );
592 /* Load the IDT and the GDT for the bootstrap. */
593 asm volatile ("lidt %0" : : "m" (idt_desc
));
594 asm volatile ("lgdt %0" : : "m" (gdt_desc
));
597 asm volatile ("jmp *%2" : : "b" (0), "S" (real_mode_mem
), "g" (params
->code32_start
));
601 /* Never reach here. */
602 return GRUB_ERR_NONE
;
606 grub_linux_unload (void)
608 grub_dl_unref (my_mod
);
610 return GRUB_ERR_NONE
;
614 grub_cmd_linux (grub_command_t cmd
__attribute__ ((unused
)),
615 int argc
, char *argv
[])
617 grub_file_t file
= 0;
618 struct linux_kernel_header lh
;
619 struct linux_kernel_params
*params
;
620 grub_uint8_t setup_sects
;
621 grub_size_t real_size
, prot_size
;
626 grub_dl_ref (my_mod
);
630 grub_error (GRUB_ERR_BAD_ARGUMENT
, "no kernel specified");
634 file
= grub_file_open (argv
[0]);
638 if (grub_file_read (file
, &lh
, sizeof (lh
)) != sizeof (lh
))
640 grub_error (GRUB_ERR_READ_ERROR
, "cannot read the Linux header");
644 if (lh
.boot_flag
!= grub_cpu_to_le16 (0xaa55))
646 grub_error (GRUB_ERR_BAD_OS
, "invalid magic number");
650 if (lh
.setup_sects
> GRUB_LINUX_MAX_SETUP_SECTS
)
652 grub_error (GRUB_ERR_BAD_OS
, "too many setup sectors");
656 if (! (lh
.loadflags
& GRUB_LINUX_FLAG_BIG_KERNEL
))
658 grub_error (GRUB_ERR_BAD_OS
, "zImage doesn't support 32-bit boot"
659 #ifdef GRUB_MACHINE_PCBIOS
660 " (try with `linux16')"
666 /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
667 still not support 32-bit boot. */
668 if (lh
.header
!= grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE
)
669 || grub_le_to_cpu16 (lh
.version
) < 0x0203)
671 grub_error (GRUB_ERR_BAD_OS
, "version too old for 32-bit boot"
672 #ifdef GRUB_MACHINE_PCBIOS
673 " (try with `linux16')"
679 setup_sects
= lh
.setup_sects
;
681 /* If SETUP_SECTS is not set, set it to the default (4). */
683 setup_sects
= GRUB_LINUX_DEFAULT_SETUP_SECTS
;
685 real_size
= setup_sects
<< GRUB_DISK_SECTOR_BITS
;
686 prot_size
= grub_file_size (file
) - real_size
- GRUB_DISK_SECTOR_SIZE
;
688 if (! allocate_pages (prot_size
))
691 params
= (struct linux_kernel_params
*) real_mode_mem
;
692 grub_memset (params
, 0, GRUB_LINUX_CL_END_OFFSET
);
693 grub_memcpy (¶ms
->setup_sects
, &lh
.setup_sects
, sizeof (lh
) - 0x1F1);
695 params
->ps_mouse
= params
->padding10
= 0;
697 len
= 0x400 - sizeof (lh
);
698 if (grub_file_read (file
, (char *) real_mode_mem
+ sizeof (lh
), len
) != len
)
700 grub_error (GRUB_ERR_FILE_READ_ERROR
, "couldn't read file");
704 params
->type_of_loader
= (LINUX_LOADER_ID_GRUB
<< 4);
706 /* These two are used (instead of cmd_line_ptr) by older versions of Linux,
707 and otherwise ignored. */
708 params
->cl_magic
= GRUB_LINUX_CL_MAGIC
;
709 params
->cl_offset
= 0x1000;
711 params
->cmd_line_ptr
= (unsigned long) real_mode_mem
+ 0x1000;
712 params
->ramdisk_image
= 0;
713 params
->ramdisk_size
= 0;
715 params
->heap_end_ptr
= GRUB_LINUX_HEAP_END_OFFSET
;
716 params
->loadflags
|= GRUB_LINUX_FLAG_CAN_USE_HEAP
;
718 /* These are not needed to be precise, because Linux uses these values
719 only to raise an error when the decompression code cannot find good
721 params
->ext_mem
= ((32 * 0x100000) >> 10);
722 params
->alt_mem
= ((32 * 0x100000) >> 10);
724 /* Ignored by Linux. */
725 params
->video_page
= 0;
727 /* Must be non-zero even in text mode, or Linux will think there's no VGA. */
728 params
->video_mode
= 0x3;
730 /* Only used when `video_mode == 0x7', otherwise ignored. */
731 params
->video_ega_bx
= 0;
733 params
->font_size
= 16; /* XXX */
735 /* The other parameters are filled when booting. */
737 grub_file_seek (file
, real_size
+ GRUB_DISK_SECTOR_SIZE
);
739 grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
740 (unsigned) real_size
, (unsigned) prot_size
);
742 /* Look for memory size and video mode specified on the command line. */
744 for (i
= 1; i
< argc
; i
++)
745 #ifdef GRUB_MACHINE_PCBIOS
746 if (grub_memcmp (argv
[i
], "vga=", 4) == 0)
748 /* Video mode selection support. */
749 char *val
= argv
[i
] + 4;
750 unsigned vid_mode
= GRUB_LINUX_VID_MODE_NORMAL
;
751 struct linux_vesafb_mode
*linux_mode
;
755 if (grub_strcmp (val
, "normal") == 0)
756 vid_mode
= GRUB_LINUX_VID_MODE_NORMAL
;
757 else if (grub_strcmp (val
, "ext") == 0)
758 vid_mode
= GRUB_LINUX_VID_MODE_EXTENDED
;
759 else if (grub_strcmp (val
, "ask") == 0)
761 grub_printf ("Legacy `ask' parameter no longer supported.\n");
763 /* We usually would never do this in a loader, but "vga=ask" means user
764 requested interaction, so it can't hurt to request keyboard input. */
765 grub_wait_after_message ();
770 vid_mode
= (grub_uint16_t
) grub_strtoul (val
, 0, 0);
775 case GRUB_LINUX_VID_MODE_NORMAL
:
776 grub_env_set ("gfxpayload", "text");
777 grub_printf ("%s is deprecated. "
778 "Use set gfxpayload=text before "
779 "linux command instead.\n",
784 case GRUB_LINUX_VID_MODE_EXTENDED
:
785 /* FIXME: support 80x50 text. */
786 grub_env_set ("gfxpayload", "text");
787 grub_printf ("%s is deprecated. "
788 "Use set gfxpayload=text before "
789 "linux command instead.\n",
793 /* Ignore invalid values. */
794 if (vid_mode
< GRUB_LINUX_VID_MODE_VESA_START
||
795 vid_mode
>= GRUB_LINUX_VID_MODE_VESA_START
+
796 ARRAY_SIZE (linux_vesafb_modes
))
798 grub_env_set ("gfxpayload", "text");
799 grub_printf ("%s is deprecated. Mode %d isn't recognized. "
800 "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] before "
801 "linux command instead.\n",
806 /* We can't detect VESA, but user is implicitly telling us that it
807 is built-in because `vga=' parameter was used. */
808 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_VESA
;
811 = &linux_vesafb_modes
[vid_mode
- GRUB_LINUX_VID_MODE_VESA_START
];
813 buf
= grub_xasprintf ("%ux%ux%u,%ux%u",
814 linux_vesafb_res
[linux_mode
->res_index
].width
,
815 linux_vesafb_res
[linux_mode
->res_index
].height
,
817 linux_vesafb_res
[linux_mode
->res_index
].width
,
818 linux_vesafb_res
[linux_mode
->res_index
].height
);
822 grub_printf ("%s is deprecated. "
823 "Use set gfxpayload=%s before "
824 "linux command instead.\n",
826 err
= grub_env_set ("gfxpayload", buf
);
833 #endif /* GRUB_MACHINE_PCBIOS */
834 if (grub_memcmp (argv
[i
], "mem=", 4) == 0)
836 char *val
= argv
[i
] + 4;
838 linux_mem_size
= grub_strtoul (val
, &val
, 0);
842 grub_errno
= GRUB_ERR_NONE
;
849 switch (grub_tolower (val
[0]))
861 /* Check an overflow. */
862 if (linux_mem_size
> (~0UL >> shift
))
865 linux_mem_size
<<= shift
;
868 else if (grub_memcmp (argv
[i
], "quiet", sizeof ("quiet") - 1) == 0)
870 params
->loadflags
|= GRUB_LINUX_FLAG_QUIET
;
874 /* Specify the boot file. */
875 dest
= grub_stpcpy ((char *) real_mode_mem
+ GRUB_LINUX_CL_OFFSET
,
877 dest
= grub_stpcpy (dest
, argv
[0]);
879 /* Copy kernel parameters. */
882 && dest
+ grub_strlen (argv
[i
]) + 1 < ((char *) real_mode_mem
883 + GRUB_LINUX_CL_END_OFFSET
);
887 dest
= grub_stpcpy (dest
, argv
[i
]);
891 if (grub_file_read (file
, (void *) GRUB_LINUX_BZIMAGE_ADDR
, len
) != len
)
892 grub_error (GRUB_ERR_FILE_READ_ERROR
, "couldn't read file");
894 if (grub_errno
== GRUB_ERR_NONE
)
896 grub_loader_set (grub_linux_boot
, grub_linux_unload
,
897 0 /* set noreturn=0 in order to avoid grub_console_fini() */);
904 grub_file_close (file
);
906 if (grub_errno
!= GRUB_ERR_NONE
)
908 grub_dl_unref (my_mod
);
916 grub_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
917 int argc
, char *argv
[])
919 grub_file_t file
= 0;
921 grub_addr_t addr_min
, addr_max
;
923 struct linux_kernel_header
*lh
;
927 grub_error (GRUB_ERR_BAD_ARGUMENT
, "no module specified");
933 grub_error (GRUB_ERR_BAD_ARGUMENT
, "you need to load the kernel first");
937 file
= grub_file_open (argv
[0]);
941 size
= grub_file_size (file
);
942 initrd_pages
= (page_align (size
) >> 12);
944 lh
= (struct linux_kernel_header
*) real_mode_mem
;
946 /* Get the highest address available for the initrd. */
947 if (grub_le_to_cpu16 (lh
->version
) >= 0x0203)
949 addr_max
= grub_cpu_to_le32 (lh
->initrd_addr_max
);
951 /* XXX in reality, Linux specifies a bogus value, so
952 it is necessary to make sure that ADDR_MAX does not exceed
954 if (addr_max
> GRUB_LINUX_INITRD_MAX_ADDRESS
)
955 addr_max
= GRUB_LINUX_INITRD_MAX_ADDRESS
;
958 addr_max
= GRUB_LINUX_INITRD_MAX_ADDRESS
;
960 if (linux_mem_size
!= 0 && linux_mem_size
< addr_max
)
961 addr_max
= linux_mem_size
;
963 /* Linux 2.3.xx has a bug in the memory range check, so avoid
965 Linux 2.2.xx has a bug in the memory range check, which is
966 worse than that of Linux 2.3.xx, so avoid the last 64kb. */
969 /* Usually, the compression ratio is about 50%. */
970 addr_min
= (grub_addr_t
) prot_mode_mem
+ ((prot_mode_pages
* 3) << 12)
973 if (addr_max
> grub_os_area_addr
+ grub_os_area_size
)
974 addr_max
= grub_os_area_addr
+ grub_os_area_size
;
976 /* Put the initrd as high as possible, 4KiB aligned. */
977 addr
= (addr_max
- size
) & ~0xFFF;
981 grub_error (GRUB_ERR_OUT_OF_RANGE
, "the initrd is too big");
985 initrd_mem
= (void *) addr
;
987 if (grub_file_read (file
, initrd_mem
, size
) != size
)
989 grub_error (GRUB_ERR_FILE_READ_ERROR
, "couldn't read file");
993 grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
994 (unsigned) addr
, (unsigned) size
);
996 lh
->ramdisk_image
= addr
;
997 lh
->ramdisk_size
= size
;
998 lh
->root_dev
= 0x0100; /* XXX */
1002 grub_file_close (file
);
1007 static grub_command_t cmd_linux
, cmd_initrd
;
1009 GRUB_MOD_INIT(linux
)
1011 cmd_linux
= grub_register_command ("linux", grub_cmd_linux
,
1012 0, N_("Load Linux."));
1013 cmd_initrd
= grub_register_command ("initrd", grub_cmd_initrd
,
1014 0, N_("Load initrd."));
1018 GRUB_MOD_FINI(linux
)
1020 grub_unregister_command (cmd_linux
);
1021 grub_unregister_command (cmd_initrd
);