2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2006,2007,2008 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/loader.h>
21 #include <grub/file.h>
22 #include <grub/disk.h>
24 #include <grub/misc.h>
25 #include <grub/types.h>
26 #include <grub/rescue.h>
29 #include <grub/term.h>
30 #include <grub/cpu/linux.h>
31 #include <grub/efi/api.h>
32 #include <grub/efi/efi.h>
33 #include <grub/efi/uga_draw.h>
36 #define GRUB_LINUX_CL_OFFSET 0x1000
37 #define GRUB_LINUX_CL_END_OFFSET 0x2000
39 #define NEXT_MEMORY_DESCRIPTOR(desc, size) \
40 ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
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_efi_uintn_t real_mode_pages
;
50 static grub_efi_uintn_t prot_mode_pages
;
51 static grub_efi_uintn_t initrd_pages
;
52 static void *mmap_buf
;
54 static grub_uint8_t gdt
[] __attribute__ ((aligned(16))) =
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00,
63 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
70 } __attribute__ ((packed
));
72 static struct gdt_descriptor gdt_desc
=
82 } __attribute__ ((packed
));
84 static struct idt_descriptor idt_desc
=
90 static inline grub_size_t
91 page_align (grub_size_t size
)
93 return (size
+ (1 << 12) - 1) & (~((1 << 12) - 1));
96 /* Find the optimal number of pages for the memory map. Is it better to
97 move this code to efi/mm.c? */
98 static grub_efi_uintn_t
101 static grub_efi_uintn_t mmap_size
= 0;
106 mmap_size
= (1 << 12);
110 grub_efi_memory_descriptor_t
*mmap
;
111 grub_efi_uintn_t desc_size
;
113 mmap
= grub_malloc (mmap_size
);
117 ret
= grub_efi_get_memory_map (&mmap_size
, mmap
, 0, &desc_size
, 0);
121 grub_fatal ("cannot get memory map");
125 mmap_size
+= (1 << 12);
128 /* Increase the size a bit for safety, because GRUB allocates more on
129 later, and EFI itself may allocate more. */
130 mmap_size
+= (1 << 12);
132 return page_align (mmap_size
);
140 grub_efi_free_pages ((grub_addr_t
) real_mode_mem
, real_mode_pages
);
146 grub_efi_free_pages ((grub_addr_t
) prot_mode_mem
, prot_mode_pages
);
152 grub_efi_free_pages ((grub_addr_t
) initrd_mem
, initrd_pages
);
157 /* Allocate pages for the real mode code and the protected mode code
158 for linux as well as a memory map buffer. */
160 allocate_pages (grub_size_t prot_size
)
162 grub_efi_uintn_t desc_size
;
163 grub_efi_memory_descriptor_t
*mmap
, *mmap_end
;
164 grub_efi_uintn_t mmap_size
, tmp_mmap_size
;
165 grub_efi_memory_descriptor_t
*desc
;
166 grub_size_t real_size
;
168 /* Make sure that each size is aligned to a page boundary. */
169 real_size
= GRUB_LINUX_CL_END_OFFSET
;
170 prot_size
= page_align (prot_size
);
171 mmap_size
= find_mmap_size ();
173 grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
174 (unsigned) real_size
, (unsigned) prot_size
, (unsigned) mmap_size
);
176 /* Calculate the number of pages; Combine the real mode code with
177 the memory map buffer for simplicity. */
178 real_mode_pages
= ((real_size
+ mmap_size
) >> 12);
179 prot_mode_pages
= (prot_size
>> 12);
181 /* Initialize the memory pointers with NULL for convenience. */
185 /* Read the memory map temporarily, to find free space. */
186 mmap
= grub_malloc (mmap_size
);
190 tmp_mmap_size
= mmap_size
;
191 if (grub_efi_get_memory_map (&tmp_mmap_size
, mmap
, 0, &desc_size
, 0) <= 0)
192 grub_fatal ("cannot get memory map");
194 mmap_end
= NEXT_MEMORY_DESCRIPTOR (mmap
, tmp_mmap_size
);
196 /* First, find free pages for the real mode code
197 and the memory map buffer. */
200 desc
= NEXT_MEMORY_DESCRIPTOR (desc
, desc_size
))
202 /* Probably it is better to put the real mode code in the traditional
204 if (desc
->type
== GRUB_EFI_CONVENTIONAL_MEMORY
205 && desc
->physical_start
<= 0x90000
206 && desc
->num_pages
>= real_mode_pages
)
208 grub_efi_physical_address_t physical_end
;
209 grub_efi_physical_address_t addr
;
211 physical_end
= desc
->physical_start
+ (desc
->num_pages
<< 12);
212 if (physical_end
> 0x90000)
213 physical_end
= 0x90000;
215 grub_dprintf ("linux", "physical_start = %x, physical_end = %x\n",
216 (unsigned) desc
->physical_start
,
217 (unsigned) physical_end
);
218 addr
= physical_end
- real_size
- mmap_size
;
222 grub_dprintf ("linux", "trying to allocate %u pages at %lx\n",
223 (unsigned) real_mode_pages
, (unsigned long) addr
);
224 real_mode_mem
= grub_efi_allocate_pages (addr
, real_mode_pages
);
226 grub_fatal ("cannot allocate pages");
228 desc
->num_pages
-= real_mode_pages
;
235 grub_error (GRUB_ERR_OUT_OF_MEMORY
, "cannot allocate real mode pages");
239 mmap_buf
= (void *) ((char *) real_mode_mem
+ real_size
);
241 /* Next, find free pages for the protected mode code. */
242 /* XXX what happens if anything is using this address? */
243 prot_mode_mem
= grub_efi_allocate_pages (0x100000, prot_mode_pages
);
246 grub_error (GRUB_ERR_OUT_OF_MEMORY
,
247 "cannot allocate protected mode pages");
251 grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
252 "prot_mode_mem = %lx, prot_mode_pages = %x\n",
253 (unsigned long) real_mode_mem
, (unsigned) real_mode_pages
,
254 (unsigned long) prot_mode_mem
, (unsigned) prot_mode_pages
);
266 grub_e820_add_region (struct grub_e820_mmap
*e820_map
, int *e820_num
,
267 grub_uint64_t start
, grub_uint64_t size
,
272 if (n
>= GRUB_E820_MAX_ENTRY
)
273 grub_fatal ("Too many e820 memory map entries");
275 if ((n
> 0) && (e820_map
[n
- 1].addr
+ e820_map
[n
- 1].size
== start
) &&
276 (e820_map
[n
- 1].type
== type
))
277 e820_map
[n
- 1].size
+= size
;
280 e820_map
[n
].addr
= start
;
281 e820_map
[n
].size
= size
;
282 e820_map
[n
].type
= type
;
290 grub_uint32_t kernel_entry
;
291 grub_uint32_t kernel_cs
;
296 grub_linux_boot (void)
298 struct linux_kernel_params
*params
;
299 grub_efi_uintn_t mmap_size
;
300 grub_efi_uintn_t map_key
;
301 grub_efi_uintn_t desc_size
;
302 grub_efi_uint32_t desc_version
;
303 grub_efi_memory_descriptor_t
*desc
;
306 params
= real_mode_mem
;
308 grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
309 (unsigned) params
->code32_start
,
310 (unsigned long) &(idt_desc
.limit
),
311 (unsigned long) &(gdt_desc
.limit
));
312 grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n",
313 (unsigned) idt_desc
.limit
, (unsigned long) idt_desc
.base
,
314 (unsigned) gdt_desc
.limit
, (unsigned long) gdt_desc
.base
);
316 mmap_size
= find_mmap_size ();
317 if (grub_efi_get_memory_map (&mmap_size
, mmap_buf
, &map_key
,
318 &desc_size
, &desc_version
) <= 0)
319 grub_fatal ("cannot get memory map");
322 for (desc
= mmap_buf
;
323 desc
< NEXT_MEMORY_DESCRIPTOR (mmap_buf
, mmap_size
);
324 desc
= NEXT_MEMORY_DESCRIPTOR (desc
, desc_size
))
328 case GRUB_EFI_ACPI_RECLAIM_MEMORY
:
329 grub_e820_add_region (params
->e820_map
, &e820_num
,
330 desc
->physical_start
,
331 desc
->num_pages
<< 12,
335 case GRUB_EFI_ACPI_MEMORY_NVS
:
336 grub_e820_add_region (params
->e820_map
, &e820_num
,
337 desc
->physical_start
,
338 desc
->num_pages
<< 12,
342 case GRUB_EFI_RUNTIME_SERVICES_CODE
:
343 grub_e820_add_region (params
->e820_map
, &e820_num
,
344 desc
->physical_start
,
345 desc
->num_pages
<< 12,
346 GRUB_E820_EXEC_CODE
);
349 case GRUB_EFI_LOADER_CODE
:
350 case GRUB_EFI_LOADER_DATA
:
351 case GRUB_EFI_BOOT_SERVICES_CODE
:
352 case GRUB_EFI_BOOT_SERVICES_DATA
:
353 case GRUB_EFI_CONVENTIONAL_MEMORY
:
355 grub_uint64_t start
, size
, end
;
357 start
= desc
->physical_start
;
358 size
= desc
->num_pages
<< 12;
361 /* Skip A0000 - 100000 region. */
362 if ((start
< 0x100000ULL
) && (end
> 0xA0000ULL
))
364 if (start
< 0xA0000ULL
)
366 grub_e820_add_region (params
->e820_map
, &e820_num
,
372 if (end
<= 0x100000ULL
)
379 grub_e820_add_region (params
->e820_map
, &e820_num
,
380 start
, size
, GRUB_E820_RAM
);
385 grub_e820_add_region (params
->e820_map
, &e820_num
,
386 desc
->physical_start
,
387 desc
->num_pages
<< 12,
392 params
->mmap_size
= e820_num
;
394 if (! grub_efi_exit_boot_services (map_key
))
395 grub_fatal ("cannot exit boot services");
397 /* Note that no boot services are available from here. */
399 /* Pass EFI parameters. */
400 if (grub_le_to_cpu16 (params
->version
) >= 0x0206)
402 params
->v0206
.efi_mem_desc_size
= desc_size
;
403 params
->v0206
.efi_mem_desc_version
= desc_version
;
404 params
->v0206
.efi_mmap
= (grub_uint32_t
) (unsigned long) mmap_buf
;
405 params
->v0206
.efi_mmap_size
= mmap_size
;
407 params
->v0206
.efi_mmap_hi
= (grub_uint32_t
) ((grub_uint64_t
) mmap_buf
>> 32);
410 else if (grub_le_to_cpu16 (params
->version
) >= 0x0204)
412 params
->v0204
.efi_mem_desc_size
= desc_size
;
413 params
->v0204
.efi_mem_desc_version
= desc_version
;
414 params
->v0204
.efi_mmap
= (grub_uint32_t
) (unsigned long) mmap_buf
;
415 params
->v0204
.efi_mmap_size
= mmap_size
;
418 /* Hardware interrupts are not safe any longer. */
419 asm volatile ("cli" : : );
421 /* Load the IDT and the GDT for the bootstrap. */
422 asm volatile ("lidt %0" : : "m" (idt_desc
));
423 asm volatile ("lgdt %0" : : "m" (gdt_desc
));
427 jumpvector
.kernel_entry
= (grub_uint64_t
) grub_linux_real_boot
;
428 jumpvector
.kernel_cs
= 0x10;
430 asm volatile ( "mov %0, %%rbx" : : "m" (params
->code32_start
));
431 asm volatile ( "mov %0, %%rsi" : : "m" (real_mode_mem
));
433 asm volatile ( "ljmp *%0" : : "m" (jumpvector
));
437 /* Pass parameters. */
438 asm volatile ("movl %0, %%ecx" : : "m" (params
->code32_start
));
439 asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem
));
441 asm volatile ("xorl %%ebx, %%ebx" : : );
444 asm volatile ("jmp *%%ecx" : : );
448 /* Never reach here. */
449 return GRUB_ERR_NONE
;
453 grub_linux_unload (void)
456 grub_dl_unref (my_mod
);
458 return GRUB_ERR_NONE
;
461 grub_uint64_t video_base
;
464 grub_find_video_card (int bus
, int dev
, int func
,
465 grub_pci_id_t pciid
__attribute__ ((unused
)))
467 grub_pci_address_t addr
;
469 addr
= grub_pci_make_address (bus
, dev
, func
, 2);
471 if (grub_pci_read (addr
) >> 24 == 0x3)
475 addr
= grub_pci_make_address (bus
, dev
, func
, 4);
476 for (i
= 0; i
< 6; i
++, addr
+= 4)
478 grub_uint32_t base
, type
;
480 base
= grub_pci_read (addr
);
482 if ((base
== 0) || (base
== 0xffffffff) ||
483 (base
& GRUB_PCI_ADDR_SPACE_IO
))
486 type
= base
& GRUB_PCI_ADDR_MEM_TYPE_MASK
;
487 if (! (addr
& GRUB_PCI_ADDR_MEM_PREFETCH
))
489 if (type
== GRUB_PCI_ADDR_MEM_TYPE_64
)
497 base
&= GRUB_PCI_ADDR_MEM_MASK
;
498 if (type
== GRUB_PCI_ADDR_MEM_TYPE_64
)
503 video_base
= grub_pci_read (addr
+ 4);
516 static grub_efi_guid_t uga_draw_guid
= GRUB_EFI_UGA_DRAW_GUID
;
519 grub_linux_setup_video (struct linux_kernel_params
*params
)
521 grub_efi_uga_draw_protocol_t
*c
;
522 grub_uint32_t width
, height
, depth
, rate
;
524 c
= grub_efi_locate_protocol (&uga_draw_guid
, 0);
528 if (efi_call_5 (c
->get_mode
, c
, &width
, &height
, &depth
, &rate
))
531 grub_printf ("Video mode: %ux%u-%u@%u\n", width
, height
, depth
, rate
);
534 grub_pci_iterate (grub_find_video_card
);
538 grub_printf ("Can\'t find frame buffer address\n");
542 grub_printf ("Video frame buffer: %llx\n", (unsigned long long) video_base
);
544 params
->lfb_width
= width
;
545 params
->lfb_height
= height
;
546 params
->lfb_depth
= depth
;
548 /* FIXME: shouldn't use fixed value. */
549 params
->lfb_line_len
= 8192;
551 params
->lfb_base
= video_base
;
552 params
->lfb_size
= (params
->lfb_line_len
* params
->lfb_height
+ 65535) >> 16;
554 params
->red_mask_size
= 8;
555 params
->red_field_pos
= 16;
556 params
->green_mask_size
= 8;
557 params
->green_field_pos
= 8;
558 params
->blue_mask_size
= 8;
559 params
->blue_field_pos
= 0;
560 params
->reserved_mask_size
= 8;
561 params
->reserved_field_pos
= 24;
567 grub_rescue_cmd_linux (int argc
, char *argv
[])
569 grub_file_t file
= 0;
570 struct linux_kernel_header lh
;
571 struct linux_kernel_params
*params
;
572 grub_uint8_t setup_sects
;
573 grub_size_t real_size
, prot_size
;
579 grub_dl_ref (my_mod
);
583 grub_error (GRUB_ERR_BAD_ARGUMENT
, "no kernel specified");
587 file
= grub_file_open (argv
[0]);
591 if (grub_file_read (file
, (char *) &lh
, sizeof (lh
)) != sizeof (lh
))
593 grub_error (GRUB_ERR_READ_ERROR
, "cannot read the linux header");
597 if (lh
.boot_flag
!= grub_cpu_to_le16 (0xaa55))
599 grub_error (GRUB_ERR_BAD_OS
, "invalid magic number");
603 if (lh
.setup_sects
> GRUB_LINUX_MAX_SETUP_SECTS
)
605 grub_error (GRUB_ERR_BAD_OS
, "too many setup sectors");
609 /* EFI support is quite new, so reject old versions. */
610 if (lh
.header
!= grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE
)
611 || grub_le_to_cpu16 (lh
.version
) < 0x0203)
613 grub_error (GRUB_ERR_BAD_OS
, "too old version");
617 /* I'm not sure how to support zImage on EFI. */
618 if (! (lh
.loadflags
& GRUB_LINUX_FLAG_BIG_KERNEL
))
620 grub_error (GRUB_ERR_BAD_OS
, "zImage is not supported");
624 setup_sects
= lh
.setup_sects
;
626 /* If SETUP_SECTS is not set, set it to the default (4). */
628 setup_sects
= GRUB_LINUX_DEFAULT_SETUP_SECTS
;
630 real_size
= setup_sects
<< GRUB_DISK_SECTOR_BITS
;
631 prot_size
= grub_file_size (file
) - real_size
- GRUB_DISK_SECTOR_SIZE
;
633 if (! allocate_pages (prot_size
))
636 params
= (struct linux_kernel_params
*) real_mode_mem
;
637 grub_memset (params
, 0, GRUB_LINUX_CL_END_OFFSET
);
638 grub_memcpy (¶ms
->setup_sects
, &lh
.setup_sects
, sizeof (lh
) - 0x1F1);
640 params
->ps_mouse
= params
->padding10
= 0;
642 len
= 0x400 - sizeof (lh
);
643 if (grub_file_read (file
, (char *) real_mode_mem
+ sizeof (lh
), len
) != len
)
645 grub_error (GRUB_ERR_FILE_READ_ERROR
, "Couldn't read file");
649 /* XXX Linux assumes that only elilo can boot Linux on EFI!!! */
650 params
->type_of_loader
= (LINUX_LOADER_ID_ELILO
<< 4);
652 params
->cl_magic
= GRUB_LINUX_CL_MAGIC
;
653 params
->cl_offset
= 0x1000;
654 params
->cmd_line_ptr
= (unsigned long) real_mode_mem
+ 0x1000;
655 params
->ramdisk_image
= 0;
656 params
->ramdisk_size
= 0;
658 params
->heap_end_ptr
= GRUB_LINUX_HEAP_END_OFFSET
;
659 params
->loadflags
|= GRUB_LINUX_FLAG_CAN_USE_HEAP
;
661 /* These are not needed to be precise, because Linux uses these values
662 only to raise an error when the decompression code cannot find good
664 params
->ext_mem
= ((32 * 0x100000) >> 10);
665 params
->alt_mem
= ((32 * 0x100000) >> 10);
667 params
->video_cursor_x
= grub_getxy () >> 8;
668 params
->video_cursor_y
= grub_getxy () & 0xff;
669 params
->video_page
= 0; /* ??? */
670 params
->video_mode
= grub_efi_system_table
->con_out
->mode
->mode
;
671 params
->video_width
= (grub_getwh () >> 8);
672 params
->video_ega_bx
= 0;
673 params
->video_height
= (grub_getwh () & 0xff);
674 params
->have_vga
= 0;
675 params
->font_size
= 16; /* XXX */
677 if (grub_le_to_cpu16 (params
->version
) >= 0x0206)
679 params
->v0206
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE
;
680 params
->v0206
.efi_system_table
= (grub_uint32_t
) (unsigned long) grub_efi_system_table
;
682 params
->v0206
.efi_system_table_hi
= (grub_uint32_t
) ((grub_uint64_t
) grub_efi_system_table
>> 32);
685 else if (grub_le_to_cpu16 (params
->version
) >= 0x0204)
687 params
->v0204
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE_0204
;
688 params
->v0204
.efi_system_table
= (grub_uint32_t
) (unsigned long) grub_efi_system_table
;
692 /* The structure is zeroed already. */
695 params
->lfb_width
= 0;
696 params
->lfb_height
= 0;
697 params
->lfb_depth
= 0;
698 params
->lfb_base
= 0;
699 params
->lfb_size
= 0;
700 params
->lfb_line_len
= 0;
701 params
->red_mask_size
= 0;
702 params
->red_field_pos
= 0;
703 params
->green_mask_size
= 0;
704 params
->green_field_pos
= 0;
705 params
->blue_mask_size
= 0;
706 params
->blue_field_pos
= 0;
707 params
->reserved_mask_size
= 0;
708 params
->reserved_field_pos
= 0;
709 params
->vesapm_segment
= 0;
710 params
->vesapm_offset
= 0;
711 params
->lfb_pages
= 0;
712 params
->vesa_attrib
= 0;
715 params
->apm_version
= 0;
716 params
->apm_code_segment
= 0;
717 params
->apm_entry
= 0;
718 params
->apm_16bit_code_segment
= 0;
719 params
->apm_data_segment
= 0;
720 params
->apm_flags
= 0;
721 params
->apm_code_len
= 0;
722 params
->apm_data_len
= 0;
724 /* XXX is there any way to use SpeedStep on EFI? */
725 params
->ist_signature
= 0;
726 params
->ist_command
= 0;
727 params
->ist_event
= 0;
728 params
->ist_perf_level
= 0;
730 /* Let the kernel probe the information. */
731 grub_memset (params
->hd0_drive_info
, 0, sizeof (params
->hd0_drive_info
));
732 grub_memset (params
->hd1_drive_info
, 0, sizeof (params
->hd1_drive_info
));
735 params
->rom_config_len
= 0;
737 /* No need to fake the BIOS's memory map. */
738 params
->mmap_size
= 0;
740 /* Let the kernel probe the information. */
741 params
->ps_mouse
= 0;
743 /* Clear padding for future compatibility. */
744 grub_memset (params
->padding1
, 0, sizeof (params
->padding1
));
745 grub_memset (params
->padding2
, 0, sizeof (params
->padding2
));
746 grub_memset (params
->padding3
, 0, sizeof (params
->padding3
));
747 grub_memset (params
->padding4
, 0, sizeof (params
->padding4
));
748 grub_memset (params
->padding5
, 0, sizeof (params
->padding5
));
749 grub_memset (params
->padding6
, 0, sizeof (params
->padding6
));
750 grub_memset (params
->padding7
, 0, sizeof (params
->padding7
));
751 grub_memset (params
->padding8
, 0, sizeof (params
->padding8
));
752 grub_memset (params
->padding9
, 0, sizeof (params
->padding9
));
756 /* The other EFI parameters are filled when booting. */
758 grub_file_seek (file
, real_size
+ GRUB_DISK_SECTOR_SIZE
);
760 /* XXX there is no way to know if the kernel really supports EFI. */
761 grub_printf (" [Linux-bzImage, setup=0x%x, size=0x%x]\n",
762 (unsigned) real_size
, (unsigned) prot_size
);
764 /* Detect explicitly specified memory size, if any. */
767 for (i
= 1; i
< argc
; i
++)
768 if (grub_memcmp (argv
[i
], "mem=", 4) == 0)
770 char *val
= argv
[i
] + 4;
772 linux_mem_size
= grub_strtoul (val
, &val
, 0);
776 grub_errno
= GRUB_ERR_NONE
;
783 switch (grub_tolower (val
[0]))
795 /* Check an overflow. */
796 if (linux_mem_size
> (~0UL >> shift
))
799 linux_mem_size
<<= shift
;
802 else if (grub_memcmp (argv
[i
], "video=", 6) == 0)
804 if (grub_memcmp (&argv
[i
][6], "vesafb", 6) == 0)
805 video_type
= GRUB_VIDEO_TYPE_VLFB
;
806 else if (grub_memcmp (&argv
[i
][6], "efifb", 5) == 0)
807 video_type
= GRUB_VIDEO_TYPE_EFI
;
812 if (! grub_linux_setup_video (params
))
813 params
->have_vga
= video_type
;
816 /* Specify the boot file. */
817 dest
= grub_stpcpy ((char *) real_mode_mem
+ GRUB_LINUX_CL_OFFSET
,
819 dest
= grub_stpcpy (dest
, argv
[0]);
821 /* Copy kernel parameters. */
824 && dest
+ grub_strlen (argv
[i
]) + 1 < ((char *) real_mode_mem
825 + GRUB_LINUX_CL_END_OFFSET
);
829 dest
= grub_stpcpy (dest
, argv
[i
]);
833 if (grub_file_read (file
, (char *) GRUB_LINUX_BZIMAGE_ADDR
, len
) != len
)
834 grub_error (GRUB_ERR_FILE_READ_ERROR
, "Couldn't read file");
836 if (grub_errno
== GRUB_ERR_NONE
)
838 grub_loader_set (grub_linux_boot
, grub_linux_unload
, 1);
845 grub_file_close (file
);
847 if (grub_errno
!= GRUB_ERR_NONE
)
849 grub_dl_unref (my_mod
);
855 grub_rescue_cmd_initrd (int argc
, char *argv
[])
857 grub_file_t file
= 0;
859 grub_addr_t addr_min
, addr_max
;
861 grub_efi_uintn_t mmap_size
;
862 grub_efi_memory_descriptor_t
*desc
;
863 grub_efi_uintn_t desc_size
;
864 struct linux_kernel_header
*lh
;
868 grub_error (GRUB_ERR_BAD_ARGUMENT
, "No module specified");
874 grub_error (GRUB_ERR_BAD_ARGUMENT
, "You need to load the kernel first.");
878 file
= grub_file_open (argv
[0]);
882 size
= grub_file_size (file
);
883 initrd_pages
= (page_align (size
) >> 12);
885 lh
= (struct linux_kernel_header
*) real_mode_mem
;
887 addr_max
= (grub_cpu_to_le32 (lh
->initrd_addr_max
) << 10);
888 if (linux_mem_size
!= 0 && linux_mem_size
< addr_max
)
889 addr_max
= linux_mem_size
;
891 /* Linux 2.3.xx has a bug in the memory range check, so avoid
893 Linux 2.2.xx has a bug in the memory range check, which is
894 worse than that of Linux 2.3.xx, so avoid the last 64kb. */
897 /* Usually, the compression ratio is about 50%. */
898 addr_min
= (grub_addr_t
) prot_mode_mem
+ ((prot_mode_pages
* 3) << 12)
901 /* Find the highest address to put the initrd. */
902 mmap_size
= find_mmap_size ();
903 if (grub_efi_get_memory_map (&mmap_size
, mmap_buf
, 0, &desc_size
, 0) <= 0)
904 grub_fatal ("cannot get memory map");
907 for (desc
= mmap_buf
;
908 desc
< NEXT_MEMORY_DESCRIPTOR (mmap_buf
, mmap_size
);
909 desc
= NEXT_MEMORY_DESCRIPTOR (desc
, desc_size
))
911 if (desc
->type
== GRUB_EFI_CONVENTIONAL_MEMORY
912 && desc
->num_pages
>= initrd_pages
)
914 grub_efi_physical_address_t physical_end
;
916 physical_end
= desc
->physical_start
+ (desc
->num_pages
<< 12);
917 if (physical_end
> addr_max
)
918 physical_end
= addr_max
;
920 if (physical_end
< addr_min
)
923 if (physical_end
> addr
)
924 addr
= physical_end
- page_align (size
);
930 grub_error (GRUB_ERR_OUT_OF_MEMORY
, "no free pages available");
934 initrd_mem
= grub_efi_allocate_pages (addr
, initrd_pages
);
936 grub_fatal ("cannot allocate pages");
938 if (grub_file_read (file
, initrd_mem
, size
) != size
)
940 grub_error (GRUB_ERR_FILE_READ_ERROR
, "Couldn't read file");
944 grub_printf (" [Initrd, addr=0x%x, size=0x%x]\n",
945 (unsigned) addr
, (unsigned) size
);
947 lh
->ramdisk_image
= addr
;
948 lh
->ramdisk_size
= size
;
949 lh
->root_dev
= 0x0100; /* XXX */
953 grub_file_close (file
);
959 grub_rescue_register_command ("linux",
960 grub_rescue_cmd_linux
,
962 grub_rescue_register_command ("initrd",
963 grub_rescue_cmd_initrd
,
970 grub_rescue_unregister_command ("linux");
971 grub_rescue_unregister_command ("initrd");