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);