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/loader.h>
21 #include <grub/file.h>
22 #include <grub/disk.h>
24 #include <grub/misc.h>
25 #include <grub/types.h>
28 #include <grub/term.h>
29 #include <grub/cpu/linux.h>
30 #include <grub/efi/api.h>
31 #include <grub/efi/efi.h>
32 #include <grub/efi/uga_draw.h>
34 #include <grub/command.h>
35 #include <grub/memory.h>
36 #include <grub/i18n.h>
38 #define GRUB_LINUX_CL_OFFSET 0x1000
39 #define GRUB_LINUX_CL_END_OFFSET 0x2000
41 #define NEXT_MEMORY_DESCRIPTOR(desc, size) \
42 ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size)))
44 static grub_dl_t my_mod
;
46 static grub_size_t linux_mem_size
;
48 static void *real_mode_mem
;
49 static void *prot_mode_mem
;
50 static void *initrd_mem
;
51 static grub_efi_uintn_t real_mode_pages
;
52 static grub_efi_uintn_t prot_mode_pages
;
53 static grub_efi_uintn_t initrd_pages
;
54 static void *mmap_buf
;
56 static grub_uint8_t gdt
[] __attribute__ ((aligned(16))) =
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x9A, 0xCF, 0x00,
65 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x92, 0xCF, 0x00
72 } __attribute__ ((packed
));
74 static struct gdt_descriptor gdt_desc
=
84 } __attribute__ ((packed
));
86 static struct idt_descriptor idt_desc
=
92 static inline grub_size_t
93 page_align (grub_size_t size
)
95 return (size
+ (1 << 12) - 1) & (~((1 << 12) - 1));
98 /* Find the optimal number of pages for the memory map. Is it better to
99 move this code to efi/mm.c? */
100 static grub_efi_uintn_t
101 find_mmap_size (void)
103 static grub_efi_uintn_t mmap_size
= 0;
108 mmap_size
= (1 << 12);
112 grub_efi_memory_descriptor_t
*mmap
;
113 grub_efi_uintn_t desc_size
;
115 mmap
= grub_malloc (mmap_size
);
119 ret
= grub_efi_get_memory_map (&mmap_size
, mmap
, 0, &desc_size
, 0);
123 grub_fatal ("cannot get memory map");
127 mmap_size
+= (1 << 12);
130 /* Increase the size a bit for safety, because GRUB allocates more on
131 later, and EFI itself may allocate more. */
132 mmap_size
+= (1 << 12);
134 return page_align (mmap_size
);
142 grub_efi_free_pages ((grub_addr_t
) real_mode_mem
, real_mode_pages
);
148 grub_efi_free_pages ((grub_addr_t
) prot_mode_mem
, prot_mode_pages
);
154 grub_efi_free_pages ((grub_addr_t
) initrd_mem
, initrd_pages
);
159 /* Allocate pages for the real mode code and the protected mode code
160 for linux as well as a memory map buffer. */
162 allocate_pages (grub_size_t prot_size
)
164 grub_efi_uintn_t desc_size
;
165 grub_efi_memory_descriptor_t
*mmap
, *mmap_end
;
166 grub_efi_uintn_t mmap_size
, tmp_mmap_size
;
167 grub_efi_memory_descriptor_t
*desc
;
168 grub_size_t real_size
;
170 /* Make sure that each size is aligned to a page boundary. */
171 real_size
= GRUB_LINUX_CL_END_OFFSET
;
172 prot_size
= page_align (prot_size
);
173 mmap_size
= find_mmap_size ();
175 grub_dprintf ("linux", "real_size = %x, prot_size = %x, mmap_size = %x\n",
176 (unsigned) real_size
, (unsigned) prot_size
, (unsigned) mmap_size
);
178 /* Calculate the number of pages; Combine the real mode code with
179 the memory map buffer for simplicity. */
180 real_mode_pages
= ((real_size
+ mmap_size
) >> 12);
181 prot_mode_pages
= (prot_size
>> 12);
183 /* Initialize the memory pointers with NULL for convenience. */
187 /* Read the memory map temporarily, to find free space. */
188 mmap
= grub_malloc (mmap_size
);
192 tmp_mmap_size
= mmap_size
;
193 if (grub_efi_get_memory_map (&tmp_mmap_size
, mmap
, 0, &desc_size
, 0) <= 0)
194 grub_fatal ("cannot get memory map");
196 mmap_end
= NEXT_MEMORY_DESCRIPTOR (mmap
, tmp_mmap_size
);
198 /* First, find free pages for the real mode code
199 and the memory map buffer. */
202 desc
= NEXT_MEMORY_DESCRIPTOR (desc
, desc_size
))
204 /* Probably it is better to put the real mode code in the traditional
206 if (desc
->type
== GRUB_EFI_CONVENTIONAL_MEMORY
207 && desc
->physical_start
<= 0x90000
208 && desc
->num_pages
>= real_mode_pages
)
210 grub_efi_physical_address_t physical_end
;
211 grub_efi_physical_address_t addr
;
213 physical_end
= desc
->physical_start
+ (desc
->num_pages
<< 12);
214 if (physical_end
> 0x90000)
215 physical_end
= 0x90000;
217 grub_dprintf ("linux", "physical_start = %x, physical_end = %x\n",
218 (unsigned) desc
->physical_start
,
219 (unsigned) physical_end
);
220 addr
= physical_end
- real_size
- mmap_size
;
224 grub_dprintf ("linux", "trying to allocate %u pages at %lx\n",
225 (unsigned) real_mode_pages
, (unsigned long) addr
);
226 real_mode_mem
= grub_efi_allocate_pages (addr
, real_mode_pages
);
228 grub_fatal ("cannot allocate pages");
230 desc
->num_pages
-= real_mode_pages
;
237 grub_error (GRUB_ERR_OUT_OF_MEMORY
, "cannot allocate real mode pages");
241 mmap_buf
= (void *) ((char *) real_mode_mem
+ real_size
);
243 /* Next, find free pages for the protected mode code. */
244 /* XXX what happens if anything is using this address? */
245 prot_mode_mem
= grub_efi_allocate_pages (0x100000, prot_mode_pages
+ 1);
248 grub_error (GRUB_ERR_OUT_OF_MEMORY
,
249 "cannot allocate protected mode pages");
253 grub_dprintf ("linux", "real_mode_mem = %lx, real_mode_pages = %x, "
254 "prot_mode_mem = %lx, prot_mode_pages = %x\n",
255 (unsigned long) real_mode_mem
, (unsigned) real_mode_pages
,
256 (unsigned long) prot_mode_mem
, (unsigned) prot_mode_pages
);
268 grub_e820_add_region (struct grub_e820_mmap
*e820_map
, int *e820_num
,
269 grub_uint64_t start
, grub_uint64_t size
,
274 if (n
>= GRUB_E820_MAX_ENTRY
)
275 grub_fatal ("Too many e820 memory map entries");
277 if ((n
> 0) && (e820_map
[n
- 1].addr
+ e820_map
[n
- 1].size
== start
) &&
278 (e820_map
[n
- 1].type
== type
))
279 e820_map
[n
- 1].size
+= size
;
282 e820_map
[n
].addr
= start
;
283 e820_map
[n
].size
= size
;
284 e820_map
[n
].type
= type
;
290 extern grub_uint8_t grub_linux_trampoline_start
[];
291 extern grub_uint8_t grub_linux_trampoline_end
[];
295 grub_linux_boot (void)
297 struct linux_kernel_params
*params
;
298 grub_efi_uintn_t mmap_size
;
299 grub_efi_uintn_t map_key
;
300 grub_efi_uintn_t desc_size
;
301 grub_efi_uint32_t desc_version
;
304 params
= real_mode_mem
;
306 grub_dprintf ("linux", "code32_start = %x, idt_desc = %lx, gdt_desc = %lx\n",
307 (unsigned) params
->code32_start
,
308 (unsigned long) &(idt_desc
.limit
),
309 (unsigned long) &(gdt_desc
.limit
));
310 grub_dprintf ("linux", "idt = %x:%lx, gdt = %x:%lx\n",
311 (unsigned) idt_desc
.limit
, (unsigned long) idt_desc
.base
,
312 (unsigned) gdt_desc
.limit
, (unsigned long) gdt_desc
.base
);
314 auto int NESTED_FUNC_ATTR
hook (grub_uint64_t
, grub_uint64_t
, grub_uint32_t
);
315 int NESTED_FUNC_ATTR
hook (grub_uint64_t addr
, grub_uint64_t size
, grub_uint32_t type
)
319 case GRUB_MACHINE_MEMORY_AVAILABLE
:
320 grub_e820_add_region (params
->e820_map
, &e820_num
,
321 addr
, size
, GRUB_E820_RAM
);
324 #ifdef GRUB_MACHINE_MEMORY_ACPI
325 case GRUB_MACHINE_MEMORY_ACPI
:
326 grub_e820_add_region (params
->e820_map
, &e820_num
,
327 addr
, size
, GRUB_E820_ACPI
);
331 #ifdef GRUB_MACHINE_MEMORY_NVS
332 case GRUB_MACHINE_MEMORY_NVS
:
333 grub_e820_add_region (params
->e820_map
, &e820_num
,
334 addr
, size
, GRUB_E820_NVS
);
338 #ifdef GRUB_MACHINE_MEMORY_CODE
339 case GRUB_MACHINE_MEMORY_CODE
:
340 grub_e820_add_region (params
->e820_map
, &e820_num
,
341 addr
, size
, GRUB_E820_EXEC_CODE
);
346 grub_e820_add_region (params
->e820_map
, &e820_num
,
347 addr
, size
, GRUB_E820_RESERVED
);
353 grub_mmap_iterate (hook
);
354 params
->mmap_size
= e820_num
;
356 mmap_size
= find_mmap_size ();
357 if (grub_efi_get_memory_map (&mmap_size
, mmap_buf
, &map_key
,
358 &desc_size
, &desc_version
) <= 0)
359 grub_fatal ("cannot get memory map");
361 if (! grub_efi_exit_boot_services (map_key
))
362 grub_fatal ("cannot exit boot services");
364 /* Note that no boot services are available from here. */
366 /* Pass EFI parameters. */
367 if (grub_le_to_cpu16 (params
->version
) >= 0x0206)
369 params
->v0206
.efi_mem_desc_size
= desc_size
;
370 params
->v0206
.efi_mem_desc_version
= desc_version
;
371 params
->v0206
.efi_mmap
= (grub_uint32_t
) (unsigned long) mmap_buf
;
372 params
->v0206
.efi_mmap_size
= mmap_size
;
374 params
->v0206
.efi_mmap_hi
= (grub_uint32_t
) ((grub_uint64_t
) mmap_buf
>> 32);
377 else if (grub_le_to_cpu16 (params
->version
) >= 0x0204)
379 params
->v0204
.efi_mem_desc_size
= desc_size
;
380 params
->v0204
.efi_mem_desc_version
= desc_version
;
381 params
->v0204
.efi_mmap
= (grub_uint32_t
) (unsigned long) mmap_buf
;
382 params
->v0204
.efi_mmap_size
= mmap_size
;
387 grub_memcpy ((char *) prot_mode_mem
+ (prot_mode_pages
<< 12),
388 grub_linux_trampoline_start
,
389 grub_linux_trampoline_end
- grub_linux_trampoline_start
);
391 ((void (*) (unsigned long, void *)) ((char *) prot_mode_mem
392 + (prot_mode_pages
<< 12)))
393 (params
->code32_start
, real_mode_mem
);
397 /* Hardware interrupts are not safe any longer. */
398 asm volatile ("cli" : : );
400 /* Load the IDT and the GDT for the bootstrap. */
401 asm volatile ("lidt %0" : : "m" (idt_desc
));
402 asm volatile ("lgdt %0" : : "m" (gdt_desc
));
404 /* Pass parameters. */
405 asm volatile ("movl %0, %%ecx" : : "m" (params
->code32_start
));
406 asm volatile ("movl %0, %%esi" : : "m" (real_mode_mem
));
408 asm volatile ("xorl %%ebx, %%ebx" : : );
411 asm volatile ("jmp *%%ecx" : : );
415 /* Never reach here. */
416 return GRUB_ERR_NONE
;
420 grub_linux_unload (void)
423 grub_dl_unref (my_mod
);
425 return GRUB_ERR_NONE
;
428 static grub_efi_guid_t uga_draw_guid
= GRUB_EFI_UGA_DRAW_GUID
;
431 #define RGB_MASK 0xffffff
432 #define RGB_MAGIC 0x121314
434 #define LINE_MAX 4096
435 #define FBTEST_STEP (0x10000 >> 2)
436 #define FBTEST_COUNT 8
439 find_line_len (grub_uint32_t
*fb_base
, grub_uint32_t
*line_len
)
441 grub_uint32_t
*base
= (grub_uint32_t
*) (grub_target_addr_t
) *fb_base
;
444 for (i
= 0; i
< FBTEST_COUNT
; i
++, base
+= FBTEST_STEP
)
446 if ((*base
& RGB_MASK
) == RGB_MAGIC
)
450 for (j
= LINE_MIN
; j
<= LINE_MAX
; j
++)
452 if ((base
[j
] & RGB_MASK
) == RGB_MAGIC
)
454 *fb_base
= (grub_uint32_t
) (grub_target_addr_t
) base
;
469 find_framebuf (grub_uint32_t
*fb_base
, grub_uint32_t
*line_len
)
473 auto int NESTED_FUNC_ATTR
find_card (grub_pci_device_t dev
,
474 grub_pci_id_t pciid
);
476 int NESTED_FUNC_ATTR
find_card (grub_pci_device_t dev
,
479 grub_pci_address_t addr
;
481 addr
= grub_pci_make_address (dev
, GRUB_PCI_REG_CLASS
);
482 if (grub_pci_read (addr
) >> 24 == 0x3)
486 grub_printf ("Display controller: %d:%d.%d\nDevice id: %x\n",
487 grub_pci_get_bus (dev
), grub_pci_get_device (dev
),
488 grub_pci_get_function (dev
), pciid
);
490 for (i
= 0; i
< 6; i
++, addr
+= 4)
492 grub_uint32_t old_bar1
, old_bar2
, type
;
493 grub_uint64_t base64
;
495 old_bar1
= grub_pci_read (addr
);
496 if ((! old_bar1
) || (old_bar1
& GRUB_PCI_ADDR_SPACE_IO
))
499 type
= old_bar1
& GRUB_PCI_ADDR_MEM_TYPE_MASK
;
500 if (type
== GRUB_PCI_ADDR_MEM_TYPE_64
)
505 old_bar2
= grub_pci_read (addr
+ 4);
512 base64
|= (old_bar1
& GRUB_PCI_ADDR_MEM_MASK
);
514 grub_printf ("%s(%d): 0x%llx\n",
515 ((old_bar1
& GRUB_PCI_ADDR_MEM_PREFETCH
) ?
517 (unsigned long long) base64
);
519 if ((old_bar1
& GRUB_PCI_ADDR_MEM_PREFETCH
) && (! found
))
522 if (find_line_len (fb_base
, line_len
))
526 if (type
== GRUB_PCI_ADDR_MEM_TYPE_64
)
537 grub_pci_iterate (find_card
);
542 grub_linux_setup_video (struct linux_kernel_params
*params
)
544 grub_efi_uga_draw_protocol_t
*c
;
545 grub_uint32_t width
, height
, depth
, rate
, pixel
, fb_base
, line_len
;
548 c
= grub_efi_locate_protocol (&uga_draw_guid
, 0);
552 if (efi_call_5 (c
->get_mode
, c
, &width
, &height
, &depth
, &rate
))
555 grub_printf ("Video mode: %ux%u-%u@%u\n", width
, height
, depth
, rate
);
557 grub_efi_set_text_mode (0);
559 efi_call_10 (c
->blt
, c
, (struct grub_efi_uga_pixel
*) &pixel
,
560 GRUB_EFI_UGA_VIDEO_FILL
, 0, 0, 0, 0, 1, height
, 0);
561 ret
= find_framebuf (&fb_base
, &line_len
);
562 grub_efi_set_text_mode (1);
566 grub_printf ("Can\'t find frame buffer address\n");
570 grub_printf ("Frame buffer base: 0x%x\n", fb_base
);
571 grub_printf ("Video line length: %d\n", line_len
);
573 params
->lfb_width
= width
;
574 params
->lfb_height
= height
;
575 params
->lfb_depth
= depth
;
576 params
->lfb_line_len
= line_len
;
578 params
->lfb_base
= fb_base
;
579 params
->lfb_size
= ALIGN_UP (line_len
* params
->lfb_height
, 65536);
581 params
->red_mask_size
= 8;
582 params
->red_field_pos
= 16;
583 params
->green_mask_size
= 8;
584 params
->green_field_pos
= 8;
585 params
->blue_mask_size
= 8;
586 params
->blue_field_pos
= 0;
587 params
->reserved_mask_size
= 8;
588 params
->reserved_field_pos
= 24;
590 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_VESA
;
591 params
->vid_mode
= 0x338; /* 1024x768x32 */
597 grub_cmd_linux (grub_command_t cmd
__attribute__ ((unused
)),
598 int argc
, char *argv
[])
600 grub_file_t file
= 0;
601 struct linux_kernel_header lh
;
602 struct linux_kernel_params
*params
;
603 grub_uint8_t setup_sects
;
604 grub_size_t real_size
, prot_size
;
609 grub_dl_ref (my_mod
);
613 grub_error (GRUB_ERR_BAD_ARGUMENT
, "no kernel specified");
617 file
= grub_file_open (argv
[0]);
621 if (grub_file_read (file
, &lh
, sizeof (lh
)) != sizeof (lh
))
623 grub_error (GRUB_ERR_READ_ERROR
, "cannot read the Linux header");
627 if (lh
.boot_flag
!= grub_cpu_to_le16 (0xaa55))
629 grub_error (GRUB_ERR_BAD_OS
, "invalid magic number");
633 if (lh
.setup_sects
> GRUB_LINUX_MAX_SETUP_SECTS
)
635 grub_error (GRUB_ERR_BAD_OS
, "too many setup sectors");
639 /* EFI support is quite new, so reject old versions. */
640 if (lh
.header
!= grub_cpu_to_le32 (GRUB_LINUX_MAGIC_SIGNATURE
)
641 || grub_le_to_cpu16 (lh
.version
) < 0x0203)
643 grub_error (GRUB_ERR_BAD_OS
, "too old version");
647 /* I'm not sure how to support zImage on EFI. */
648 if (! (lh
.loadflags
& GRUB_LINUX_FLAG_BIG_KERNEL
))
650 grub_error (GRUB_ERR_BAD_OS
, "zImage is not supported");
654 setup_sects
= lh
.setup_sects
;
656 /* If SETUP_SECTS is not set, set it to the default (4). */
658 setup_sects
= GRUB_LINUX_DEFAULT_SETUP_SECTS
;
660 real_size
= setup_sects
<< GRUB_DISK_SECTOR_BITS
;
661 prot_size
= grub_file_size (file
) - real_size
- GRUB_DISK_SECTOR_SIZE
;
663 if (! allocate_pages (prot_size
))
666 params
= (struct linux_kernel_params
*) real_mode_mem
;
667 grub_memset (params
, 0, GRUB_LINUX_CL_END_OFFSET
);
668 grub_memcpy (¶ms
->setup_sects
, &lh
.setup_sects
, sizeof (lh
) - 0x1F1);
670 params
->ps_mouse
= params
->padding10
= 0;
672 len
= 0x400 - sizeof (lh
);
673 if (grub_file_read (file
, (char *) real_mode_mem
+ sizeof (lh
), len
) != len
)
675 grub_error (GRUB_ERR_FILE_READ_ERROR
, "couldn't read file");
679 params
->type_of_loader
= (LINUX_LOADER_ID_GRUB
<< 4);
681 params
->cl_magic
= GRUB_LINUX_CL_MAGIC
;
682 params
->cl_offset
= 0x1000;
683 params
->cmd_line_ptr
= (unsigned long) real_mode_mem
+ 0x1000;
684 params
->ramdisk_image
= 0;
685 params
->ramdisk_size
= 0;
687 params
->heap_end_ptr
= GRUB_LINUX_HEAP_END_OFFSET
;
688 params
->loadflags
|= GRUB_LINUX_FLAG_CAN_USE_HEAP
;
690 /* These are not needed to be precise, because Linux uses these values
691 only to raise an error when the decompression code cannot find good
693 params
->ext_mem
= ((32 * 0x100000) >> 10);
694 params
->alt_mem
= ((32 * 0x100000) >> 10);
697 grub_term_output_t term
;
699 FOR_ACTIVE_TERM_OUTPUTS(term
)
700 if (grub_strcmp (term
->name
, "vga_text") == 0
701 || grub_strcmp (term
->name
, "console") == 0)
703 grub_uint16_t pos
= grub_term_getxy (term
);
704 params
->video_cursor_x
= pos
>> 8;
705 params
->video_cursor_y
= pos
& 0xff;
706 params
->video_width
= grub_term_width (term
);
707 params
->video_height
= grub_term_height (term
);
713 params
->video_cursor_x
= 0;
714 params
->video_cursor_y
= 0;
715 params
->video_width
= 80;
716 params
->video_height
= 25;
719 params
->video_page
= 0; /* ??? */
720 params
->video_mode
= grub_efi_system_table
->con_out
->mode
->mode
;
721 params
->video_ega_bx
= 0;
722 params
->have_vga
= 0;
723 params
->font_size
= 16; /* XXX */
725 if (grub_le_to_cpu16 (params
->version
) >= 0x0206)
727 params
->v0206
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE
;
728 params
->v0206
.efi_system_table
= (grub_uint32_t
) (unsigned long) grub_efi_system_table
;
730 params
->v0206
.efi_system_table_hi
= (grub_uint32_t
) ((grub_uint64_t
) grub_efi_system_table
>> 32);
733 else if (grub_le_to_cpu16 (params
->version
) >= 0x0204)
735 params
->v0204
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE_0204
;
736 params
->v0204
.efi_system_table
= (grub_uint32_t
) (unsigned long) grub_efi_system_table
;
740 /* The structure is zeroed already. */
743 params
->lfb_width
= 0;
744 params
->lfb_height
= 0;
745 params
->lfb_depth
= 0;
746 params
->lfb_base
= 0;
747 params
->lfb_size
= 0;
748 params
->lfb_line_len
= 0;
749 params
->red_mask_size
= 0;
750 params
->red_field_pos
= 0;
751 params
->green_mask_size
= 0;
752 params
->green_field_pos
= 0;
753 params
->blue_mask_size
= 0;
754 params
->blue_field_pos
= 0;
755 params
->reserved_mask_size
= 0;
756 params
->reserved_field_pos
= 0;
757 params
->vesapm_segment
= 0;
758 params
->vesapm_offset
= 0;
759 params
->lfb_pages
= 0;
760 params
->vesa_attrib
= 0;
763 params
->apm_version
= 0;
764 params
->apm_code_segment
= 0;
765 params
->apm_entry
= 0;
766 params
->apm_16bit_code_segment
= 0;
767 params
->apm_data_segment
= 0;
768 params
->apm_flags
= 0;
769 params
->apm_code_len
= 0;
770 params
->apm_data_len
= 0;
772 /* XXX is there any way to use SpeedStep on EFI? */
773 params
->ist_signature
= 0;
774 params
->ist_command
= 0;
775 params
->ist_event
= 0;
776 params
->ist_perf_level
= 0;
778 /* Let the kernel probe the information. */
779 grub_memset (params
->hd0_drive_info
, 0, sizeof (params
->hd0_drive_info
));
780 grub_memset (params
->hd1_drive_info
, 0, sizeof (params
->hd1_drive_info
));
783 params
->rom_config_len
= 0;
785 /* No need to fake the BIOS's memory map. */
786 params
->mmap_size
= 0;
788 /* Let the kernel probe the information. */
789 params
->ps_mouse
= 0;
791 /* Clear padding for future compatibility. */
792 grub_memset (params
->padding1
, 0, sizeof (params
->padding1
));
793 grub_memset (params
->padding2
, 0, sizeof (params
->padding2
));
794 grub_memset (params
->padding3
, 0, sizeof (params
->padding3
));
795 grub_memset (params
->padding4
, 0, sizeof (params
->padding4
));
796 grub_memset (params
->padding5
, 0, sizeof (params
->padding5
));
797 grub_memset (params
->padding6
, 0, sizeof (params
->padding6
));
798 grub_memset (params
->padding7
, 0, sizeof (params
->padding7
));
799 grub_memset (params
->padding8
, 0, sizeof (params
->padding8
));
800 grub_memset (params
->padding9
, 0, sizeof (params
->padding9
));
804 /* The other EFI parameters are filled when booting. */
806 grub_file_seek (file
, real_size
+ GRUB_DISK_SECTOR_SIZE
);
808 /* XXX there is no way to know if the kernel really supports EFI. */
809 grub_printf (" [Linux-bzImage, setup=0x%x, size=0x%x]\n",
810 (unsigned) real_size
, (unsigned) prot_size
);
812 grub_linux_setup_video (params
);
814 /* Detect explicitly specified memory size, if any. */
816 for (i
= 1; i
< argc
; i
++)
817 if (grub_memcmp (argv
[i
], "mem=", 4) == 0)
819 char *val
= argv
[i
] + 4;
821 linux_mem_size
= grub_strtoul (val
, &val
, 0);
825 grub_errno
= GRUB_ERR_NONE
;
832 switch (grub_tolower (val
[0]))
844 /* Check an overflow. */
845 if (linux_mem_size
> (~0UL >> shift
))
848 linux_mem_size
<<= shift
;
851 else if (grub_memcmp (argv
[i
], "video=efifb", 11) == 0)
853 if (params
->have_vga
)
854 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_SIMPLE
;
857 /* Specify the boot file. */
858 dest
= grub_stpcpy ((char *) real_mode_mem
+ GRUB_LINUX_CL_OFFSET
,
860 dest
= grub_stpcpy (dest
, argv
[0]);
862 /* Copy kernel parameters. */
865 && dest
+ grub_strlen (argv
[i
]) + 1 < ((char *) real_mode_mem
866 + GRUB_LINUX_CL_END_OFFSET
);
870 dest
= grub_stpcpy (dest
, argv
[i
]);
874 if (grub_file_read (file
, (void *) GRUB_LINUX_BZIMAGE_ADDR
, len
) != len
)
875 grub_error (GRUB_ERR_FILE_READ_ERROR
, "couldn't read file");
877 if (grub_errno
== GRUB_ERR_NONE
)
879 grub_loader_set (grub_linux_boot
, grub_linux_unload
, 1);
886 grub_file_close (file
);
888 if (grub_errno
!= GRUB_ERR_NONE
)
890 grub_dl_unref (my_mod
);
898 grub_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
899 int argc
, char *argv
[])
901 grub_file_t file
= 0;
903 grub_addr_t addr_min
, addr_max
;
905 grub_efi_uintn_t mmap_size
;
906 grub_efi_memory_descriptor_t
*desc
;
907 grub_efi_uintn_t desc_size
;
908 struct linux_kernel_header
*lh
;
912 grub_error (GRUB_ERR_BAD_ARGUMENT
, "no module specified");
918 grub_error (GRUB_ERR_BAD_ARGUMENT
, "you need to load the kernel first");
922 file
= grub_file_open (argv
[0]);
926 size
= grub_file_size (file
);
927 initrd_pages
= (page_align (size
) >> 12);
929 lh
= (struct linux_kernel_header
*) real_mode_mem
;
931 addr_max
= (grub_cpu_to_le32 (lh
->initrd_addr_max
) << 10);
932 if (linux_mem_size
!= 0 && linux_mem_size
< addr_max
)
933 addr_max
= linux_mem_size
;
935 /* Linux 2.3.xx has a bug in the memory range check, so avoid
937 Linux 2.2.xx has a bug in the memory range check, which is
938 worse than that of Linux 2.3.xx, so avoid the last 64kb. */
941 /* Usually, the compression ratio is about 50%. */
942 addr_min
= (grub_addr_t
) prot_mode_mem
+ ((prot_mode_pages
* 3) << 12)
945 /* Find the highest address to put the initrd. */
946 mmap_size
= find_mmap_size ();
947 if (grub_efi_get_memory_map (&mmap_size
, mmap_buf
, 0, &desc_size
, 0) <= 0)
948 grub_fatal ("cannot get memory map");
951 for (desc
= mmap_buf
;
952 desc
< NEXT_MEMORY_DESCRIPTOR (mmap_buf
, mmap_size
);
953 desc
= NEXT_MEMORY_DESCRIPTOR (desc
, desc_size
))
955 if (desc
->type
== GRUB_EFI_CONVENTIONAL_MEMORY
956 && desc
->num_pages
>= initrd_pages
)
958 grub_efi_physical_address_t physical_end
;
960 physical_end
= desc
->physical_start
+ (desc
->num_pages
<< 12);
961 if (physical_end
> addr_max
)
962 physical_end
= addr_max
;
964 if (physical_end
< page_align (size
))
967 physical_end
-= page_align (size
);
969 if ((physical_end
>= addr_min
) &&
970 (physical_end
>= desc
->physical_start
) &&
971 (physical_end
> addr
))
978 grub_error (GRUB_ERR_OUT_OF_MEMORY
, "no free pages available");
982 initrd_mem
= grub_efi_allocate_pages (addr
, initrd_pages
);
984 grub_fatal ("cannot allocate pages");
986 if (grub_file_read (file
, initrd_mem
, size
) != size
)
988 grub_error (GRUB_ERR_FILE_READ_ERROR
, "couldn't read file");
992 grub_printf (" [Initrd, addr=0x%x, size=0x%x]\n",
993 (unsigned) addr
, (unsigned) size
);
995 lh
->ramdisk_image
= addr
;
996 lh
->ramdisk_size
= size
;
997 lh
->root_dev
= 0x0100; /* XXX */
1001 grub_file_close (file
);
1006 static grub_command_t cmd_linux
, cmd_initrd
;
1008 GRUB_MOD_INIT(linux
)
1010 cmd_linux
= grub_register_command ("linux", grub_cmd_linux
,
1011 0, N_("Load Linux."));
1012 cmd_initrd
= grub_register_command ("initrd", grub_cmd_initrd
,
1013 0, N_("Load initrd."));
1017 GRUB_MOD_FINI(linux
)
1019 grub_unregister_command (cmd_linux
);
1020 grub_unregister_command (cmd_initrd
);