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>
37 #include <grub/linux.h>
38 #include <grub/machine/kernel.h>
40 GRUB_MOD_LICENSE ("GPLv3+");
42 #ifdef GRUB_MACHINE_PCBIOS
43 #include <grub/i386/pc/vesa_modes_table.h>
46 #ifdef GRUB_MACHINE_EFI
47 #include <grub/efi/efi.h>
48 #define HAS_VGA_TEXT 0
49 #define DEFAULT_VIDEO_MODE "auto"
50 #define ACCEPTS_PURE_TEXT 0
51 #elif defined (GRUB_MACHINE_IEEE1275)
52 #include <grub/ieee1275/ieee1275.h>
53 #define HAS_VGA_TEXT 0
54 #define DEFAULT_VIDEO_MODE "text"
55 #define ACCEPTS_PURE_TEXT 1
57 #include <grub/i386/pc/vbe.h>
58 #include <grub/i386/pc/console.h>
59 #define HAS_VGA_TEXT 1
60 #define DEFAULT_VIDEO_MODE "text"
61 #define ACCEPTS_PURE_TEXT 1
64 static grub_dl_t my_mod
;
66 static grub_size_t linux_mem_size
;
68 static void *prot_mode_mem
;
69 static grub_addr_t prot_mode_target
;
70 static void *initrd_mem
;
71 static grub_addr_t initrd_mem_target
;
72 static grub_size_t prot_init_space
;
73 static struct grub_relocator
*relocator
= NULL
;
74 static void *efi_mmap_buf
;
75 static grub_size_t maximal_cmdline_size
;
76 static struct linux_kernel_params linux_params
;
77 static char *linux_cmdline
;
78 #ifdef GRUB_MACHINE_EFI
79 static grub_efi_uintn_t efi_mmap_size
;
81 static const grub_size_t efi_mmap_size
= 0;
84 #define LINUX_MAX_ARGC 1024
85 static int ventoy_debug
= 0;
86 static int ventoy_initrd_called
= 0;
87 static int ventoy_linux_argc
= 0;
88 static char **ventoy_linux_args
= NULL
;
89 static int ventoy_extra_initrd_num
= 0;
90 static char *ventoy_extra_initrd_list
[256];
92 grub_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)), int argc
, char *argv
[]);
102 static struct idt_descriptor idt_desc
=
109 static inline grub_size_t
110 page_align (grub_size_t size
)
112 return (size
+ (1 << 12) - 1) & (~((1 << 12) - 1));
115 /* Helper for find_mmap_size. */
117 count_hook (grub_uint64_t addr
__attribute__ ((unused
)),
118 grub_uint64_t size
__attribute__ ((unused
)),
119 grub_memory_type_t type
__attribute__ ((unused
)), void *data
)
121 grub_size_t
*count
= data
;
127 /* Find the optimal number of pages for the memory map. */
129 find_mmap_size (void)
131 grub_size_t count
= 0, mmap_size
;
133 grub_mmap_iterate (count_hook
, &count
);
135 mmap_size
= count
* sizeof (struct grub_e820_mmap
);
137 /* Increase the size a bit for safety, because GRUB allocates more on
139 mmap_size
+= (1 << 12);
141 return page_align (mmap_size
);
147 grub_relocator_unload (relocator
);
149 prot_mode_mem
= initrd_mem
= 0;
150 prot_mode_target
= initrd_mem_target
= 0;
153 /* Allocate pages for the real mode code and the protected mode code
154 for linux as well as a memory map buffer. */
156 allocate_pages (grub_size_t prot_size
, grub_size_t
*align
,
157 grub_size_t min_align
, int relocatable
,
158 grub_uint64_t preferred_address
)
165 prot_size
= page_align (prot_size
);
167 /* Initialize the memory pointers with NULL for convenience. */
170 relocator
= grub_relocator_new ();
177 /* FIXME: Should request low memory from the heap when this feature is
181 grub_relocator_chunk_t ch
;
184 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
188 GRUB_RELOCATOR_PREFERENCE_LOW
,
190 for (; err
&& *align
+ 1 > min_align
; (*align
)--)
192 grub_errno
= GRUB_ERR_NONE
;
193 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
195 0xffffffff & ~prot_size
,
196 prot_size
, 1 << *align
,
197 GRUB_RELOCATOR_PREFERENCE_LOW
,
204 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
209 prot_mode_mem
= get_virtual_current_address (ch
);
210 prot_mode_target
= get_physical_target_address (ch
);
213 grub_dprintf ("linux", "prot_mode_mem = %p, prot_mode_target = %lx, prot_size = %x\n",
214 prot_mode_mem
, (unsigned long) prot_mode_target
,
215 (unsigned) prot_size
);
216 return GRUB_ERR_NONE
;
224 grub_e820_add_region (struct grub_e820_mmap
*e820_map
, int *e820_num
,
225 grub_uint64_t start
, grub_uint64_t size
,
230 if ((n
> 0) && (e820_map
[n
- 1].addr
+ e820_map
[n
- 1].size
== start
) &&
231 (e820_map
[n
- 1].type
== type
))
232 e820_map
[n
- 1].size
+= size
;
235 e820_map
[n
].addr
= start
;
236 e820_map
[n
].size
= size
;
237 e820_map
[n
].type
= type
;
240 return GRUB_ERR_NONE
;
244 grub_linux_setup_video (struct linux_kernel_params
*params
)
246 struct grub_video_mode_info mode_info
;
249 grub_video_driver_id_t driver_id
;
250 const char *gfxlfbvar
= grub_env_get ("gfxpayloadforcelfb");
252 driver_id
= grub_video_get_driver_id ();
254 if (driver_id
== GRUB_VIDEO_DRIVER_NONE
)
257 err
= grub_video_get_info_and_fini (&mode_info
, &framebuffer
);
261 grub_errno
= GRUB_ERR_NONE
;
265 params
->lfb_width
= mode_info
.width
;
266 params
->lfb_height
= mode_info
.height
;
267 params
->lfb_depth
= mode_info
.bpp
;
268 params
->lfb_line_len
= mode_info
.pitch
;
270 params
->lfb_base
= (grub_size_t
) framebuffer
;
272 #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
273 params
->ext_lfb_base
= (grub_size_t
) (((grub_uint64_t
)(grub_size_t
) framebuffer
) >> 32);
274 params
->capabilities
|= VIDEO_CAPABILITY_64BIT_BASE
;
277 params
->lfb_size
= ALIGN_UP (params
->lfb_line_len
* params
->lfb_height
, 65536);
279 params
->red_mask_size
= mode_info
.red_mask_size
;
280 params
->red_field_pos
= mode_info
.red_field_pos
;
281 params
->green_mask_size
= mode_info
.green_mask_size
;
282 params
->green_field_pos
= mode_info
.green_field_pos
;
283 params
->blue_mask_size
= mode_info
.blue_mask_size
;
284 params
->blue_field_pos
= mode_info
.blue_field_pos
;
285 params
->reserved_mask_size
= mode_info
.reserved_mask_size
;
286 params
->reserved_field_pos
= mode_info
.reserved_field_pos
;
288 if (gfxlfbvar
&& (gfxlfbvar
[0] == '1' || gfxlfbvar
[0] == 'y'))
289 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_SIMPLE
;
294 case GRUB_VIDEO_DRIVER_VBE
:
295 params
->lfb_size
>>= 16;
296 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_VESA
;
299 case GRUB_VIDEO_DRIVER_EFI_UGA
:
300 case GRUB_VIDEO_DRIVER_EFI_GOP
:
301 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_EFIFB
;
304 /* FIXME: check if better id is available. */
305 case GRUB_VIDEO_DRIVER_SM712
:
306 case GRUB_VIDEO_DRIVER_SIS315PRO
:
307 case GRUB_VIDEO_DRIVER_VGA
:
308 case GRUB_VIDEO_DRIVER_CIRRUS
:
309 case GRUB_VIDEO_DRIVER_BOCHS
:
310 case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E
:
311 case GRUB_VIDEO_DRIVER_RADEON_YEELOONG3A
:
312 case GRUB_VIDEO_DRIVER_IEEE1275
:
313 case GRUB_VIDEO_DRIVER_COREBOOT
:
314 /* Make gcc happy. */
315 case GRUB_VIDEO_DRIVER_XEN
:
316 case GRUB_VIDEO_DRIVER_SDL
:
317 case GRUB_VIDEO_DRIVER_NONE
:
318 case GRUB_VIDEO_ADAPTER_CAPTURE
:
319 params
->have_vga
= GRUB_VIDEO_LINUX_TYPE_SIMPLE
;
324 #ifdef GRUB_MACHINE_PCBIOS
325 /* VESA packed modes may come with zeroed mask sizes, which need
326 to be set here according to DAC Palette width. If we don't,
327 this results in Linux displaying a black screen. */
328 if (driver_id
== GRUB_VIDEO_DRIVER_VBE
&& mode_info
.bpp
<= 8)
330 struct grub_vbe_info_block controller_info
;
334 status
= grub_vbe_bios_get_controller_info (&controller_info
);
336 if (status
== GRUB_VBE_STATUS_OK
&&
337 (controller_info
.capabilities
& GRUB_VBE_CAPABILITY_DACWIDTH
))
338 status
= grub_vbe_bios_set_dac_palette_width (&width
);
340 if (status
!= GRUB_VBE_STATUS_OK
)
341 /* 6 is default after mode reset. */
344 params
->red_mask_size
= params
->green_mask_size
345 = params
->blue_mask_size
= width
;
346 params
->reserved_mask_size
= 0;
350 return GRUB_ERR_NONE
;
353 /* Context for grub_linux_boot. */
354 struct grub_linux_boot_ctx
356 grub_addr_t real_mode_target
;
357 grub_size_t real_size
;
358 struct linux_kernel_params
*params
;
362 /* Helper for grub_linux_boot. */
364 grub_linux_boot_mmap_find (grub_uint64_t addr
, grub_uint64_t size
,
365 grub_memory_type_t type
, void *data
)
367 struct grub_linux_boot_ctx
*ctx
= data
;
369 /* We must put real mode code in the traditional space. */
370 if (type
!= GRUB_MEMORY_AVAILABLE
|| addr
> 0x90000)
373 if (addr
+ size
< 0x10000)
378 size
+= addr
- 0x10000;
382 if (addr
+ size
> 0x90000)
383 size
= 0x90000 - addr
;
385 if (ctx
->real_size
+ efi_mmap_size
> size
)
388 grub_dprintf ("linux", "addr = %lx, size = %x, need_size = %x\n",
389 (unsigned long) addr
,
391 (unsigned) (ctx
->real_size
+ efi_mmap_size
));
392 ctx
->real_mode_target
= ((addr
+ size
) - (ctx
->real_size
+ efi_mmap_size
));
396 /* GRUB types conveniently match E820 types. */
398 grub_linux_boot_mmap_fill (grub_uint64_t addr
, grub_uint64_t size
,
399 grub_memory_type_t type
, void *data
)
401 struct grub_linux_boot_ctx
*ctx
= data
;
403 if (grub_e820_add_region (ctx
->params
->e820_map
, &ctx
->e820_num
,
410 static void ventoy_debug_pause(void)
414 if (0 == ventoy_debug
)
419 grub_printf("press Enter to continue ......\n");
423 if (key
== '\n' || key
== '\r')
430 static int ventoy_preboot(void)
438 grub_printf("ventoy_preboot %d %d\n", ventoy_linux_argc
, ventoy_initrd_called
);
439 ventoy_debug_pause();
442 if (ventoy_linux_argc
== 0)
447 if (ventoy_initrd_called
)
449 ventoy_initrd_called
= 0;
453 grub_snprintf(buf
, sizeof(buf
), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
455 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(buf
);
457 file
= grub_env_get("vtoy_img_part_file");
460 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(file
);
465 grub_printf("========== initrd list ==========\n");
466 for (i
= 0; i
< ventoy_extra_initrd_num
; i
++)
468 grub_printf("%s\n", ventoy_extra_initrd_list
[i
]);
470 grub_printf("=================================\n");
472 ventoy_debug_pause();
475 grub_cmd_initrd(NULL
, ventoy_extra_initrd_num
, ventoy_extra_initrd_list
);
480 static int ventoy_boot_opt_filter(char *opt
)
482 if (grub_strcmp(opt
, "noinitrd") == 0)
487 if (grub_strcmp(opt
, "vga=current") == 0)
492 if (grub_strncmp(opt
, "rdinit=", 7) == 0)
494 if (grub_strcmp(opt
, "rdinit=/vtoy/vtoy") != 0)
502 if (grub_strncmp(opt
, "init=", 5) == 0)
509 if (grub_strncmp(opt
, "dm=", 3) == 0)
518 if (grub_strcmp(opt
, "quiet") == 0)
523 if (grub_strncmp(opt
, "loglevel=", 9) == 0)
528 if (grub_strcmp(opt
, "splash") == 0)
537 static int ventoy_bootopt_hook(int argc
, char *argv
[])
547 //grub_printf("ventoy_bootopt_hook: %d %d\n", argc, ventoy_linux_argc);
549 if (ventoy_linux_argc
== 0)
554 /* To avoid --- parameter, we split two parts */
555 for (TmpIdx
= 0; TmpIdx
< argc
; TmpIdx
++)
557 if (ventoy_boot_opt_filter(argv
[TmpIdx
]))
562 if (grub_strncmp(argv
[TmpIdx
], "--", 2) == 0)
567 ventoy_linux_args
[count
++] = grub_strdup(argv
[TmpIdx
]);
570 for (i
= 0; i
< ventoy_linux_argc
; i
++)
572 ventoy_linux_args
[count
] = ventoy_linux_args
[i
+ (LINUX_MAX_ARGC
/ 2)];
573 ventoy_linux_args
[i
+ (LINUX_MAX_ARGC
/ 2)] = NULL
;
575 if (ventoy_linux_args
[count
][0] == '@')
577 env
= grub_env_get(ventoy_linux_args
[count
] + 1);
580 grub_free(ventoy_linux_args
[count
]);
582 newenv
= grub_strdup(env
);
589 if (*last
!= ' ' && *last
!= '\t')
601 for (pos
= last
; *pos
; pos
++)
603 if (*pos
== ' ' || *pos
== '\t')
607 if (0 == ventoy_boot_opt_filter(last
))
609 ventoy_linux_args
[count
++] = grub_strdup(last
);
618 if (0 == ventoy_boot_opt_filter(last
))
620 ventoy_linux_args
[count
++] = grub_strdup(last
);
639 while (TmpIdx
< argc
)
641 if (ventoy_boot_opt_filter(argv
[TmpIdx
]))
646 ventoy_linux_args
[count
++] = grub_strdup(argv
[TmpIdx
]);
652 ventoy_linux_args
[count
++] = grub_strdup("loglevel=7");
655 ventoy_linux_argc
= count
;
659 grub_printf("========== bootoption ==========\n");
660 for (i
= 0; i
< count
; i
++)
662 grub_printf("%s ", ventoy_linux_args
[i
]);
664 grub_printf("\n================================\n");
671 grub_cmd_set_boot_opt (grub_command_t cmd
__attribute__ ((unused
)),
672 int argc
, char *argv
[])
677 for (i
= 0; i
< argc
; i
++)
679 ventoy_linux_args
[ventoy_linux_argc
+ (LINUX_MAX_ARGC
/ 2) ] = grub_strdup(argv
[i
]);
683 vtdebug
= grub_env_get("vtdebug_flag");
684 if (vtdebug
&& vtdebug
[0])
689 if (ventoy_debug
) grub_printf("ventoy set boot opt %d\n", ventoy_linux_argc
);
695 grub_cmd_unset_boot_opt (grub_command_t cmd
__attribute__ ((unused
)),
696 int argc
, char *argv
[])
703 for (i
= 0; i
< LINUX_MAX_ARGC
; i
++)
705 if (ventoy_linux_args
[i
])
707 grub_free(ventoy_linux_args
[i
]);
712 ventoy_linux_argc
= 0;
713 ventoy_initrd_called
= 0;
714 grub_memset(ventoy_linux_args
, 0, sizeof(char *) * LINUX_MAX_ARGC
);
719 grub_cmd_extra_initrd_append (grub_command_t cmd
__attribute__ ((unused
)),
720 int argc
, char *argv
[])
732 for (pos
= argv
[0]; *pos
; pos
++)
742 /* grub2 newc bug workaround */
743 newclen
= (int)grub_strlen(end
+ 1);
744 if ((110 + newclen
) % 4 == 0)
746 grub_snprintf(buf
, sizeof(buf
), "newc:.%s:%s", end
+ 1, argv
[0]);
750 grub_snprintf(buf
, sizeof(buf
), "newc:%s:%s", end
+ 1, argv
[0]);
753 if (ventoy_extra_initrd_num
< 256)
755 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(buf
);
763 grub_cmd_extra_initrd_reset (grub_command_t cmd
__attribute__ ((unused
)),
764 int argc
, char *argv
[])
771 for (i
= 0; i
< ventoy_extra_initrd_num
; i
++)
773 if (ventoy_extra_initrd_list
[i
])
775 grub_free(ventoy_extra_initrd_list
[i
]);
779 grub_memset(ventoy_extra_initrd_list
, 0, sizeof(ventoy_extra_initrd_list
));
786 grub_linux_boot (void)
791 struct grub_relocator32_state state
;
793 struct grub_linux_boot_ctx ctx
= {
794 .real_mode_target
= 0
796 grub_size_t mmap_size
;
797 grub_size_t cl_offset
;
801 #ifdef GRUB_MACHINE_IEEE1275
803 const char *bootpath
;
806 bootpath
= grub_env_get ("root");
808 grub_ieee1275_set_property (grub_ieee1275_chosen
,
809 "bootpath", bootpath
,
810 grub_strlen (bootpath
) + 1,
812 linux_params
.ofw_signature
= GRUB_LINUX_OFW_SIGNATURE
;
813 linux_params
.ofw_num_items
= 1;
814 linux_params
.ofw_cif_handler
= (grub_uint32_t
) grub_ieee1275_entry_fn
;
815 linux_params
.ofw_idt
= 0;
819 modevar
= grub_env_get ("gfxpayload");
821 /* Now all graphical modes are acceptable.
822 May change in future if we have modes without framebuffer. */
823 if (modevar
&& *modevar
!= 0)
825 tmp
= grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE
, modevar
);
828 #if ACCEPTS_PURE_TEXT
829 err
= grub_video_set_mode (tmp
, 0, 0);
831 err
= grub_video_set_mode (tmp
, GRUB_VIDEO_MODE_TYPE_PURE_TEXT
, 0);
835 else /* We can't go back to text mode from coreboot fb. */
836 #ifdef GRUB_MACHINE_COREBOOT
837 if (grub_video_get_driver_id () == GRUB_VIDEO_DRIVER_COREBOOT
)
842 #if ACCEPTS_PURE_TEXT
843 err
= grub_video_set_mode (DEFAULT_VIDEO_MODE
, 0, 0);
845 err
= grub_video_set_mode (DEFAULT_VIDEO_MODE
,
846 GRUB_VIDEO_MODE_TYPE_PURE_TEXT
, 0);
853 grub_puts_ (N_("Booting in blind mode"));
854 grub_errno
= GRUB_ERR_NONE
;
857 if (grub_linux_setup_video (&linux_params
))
859 #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
860 linux_params
.have_vga
= GRUB_VIDEO_LINUX_TYPE_TEXT
;
861 linux_params
.video_mode
= 0x3;
863 linux_params
.have_vga
= 0;
864 linux_params
.video_mode
= 0;
865 linux_params
.video_width
= 0;
866 linux_params
.video_height
= 0;
871 #ifndef GRUB_MACHINE_IEEE1275
872 if (linux_params
.have_vga
== GRUB_VIDEO_LINUX_TYPE_TEXT
)
875 grub_term_output_t term
;
877 FOR_ACTIVE_TERM_OUTPUTS(term
)
878 if (grub_strcmp (term
->name
, "vga_text") == 0
879 || grub_strcmp (term
->name
, "console") == 0
880 || grub_strcmp (term
->name
, "ofconsole") == 0)
882 struct grub_term_coordinate pos
= grub_term_getxy (term
);
883 linux_params
.video_cursor_x
= pos
.x
;
884 linux_params
.video_cursor_y
= pos
.y
;
885 linux_params
.video_width
= grub_term_width (term
);
886 linux_params
.video_height
= grub_term_height (term
);
892 linux_params
.video_cursor_x
= 0;
893 linux_params
.video_cursor_y
= 0;
894 linux_params
.video_width
= 80;
895 linux_params
.video_height
= 25;
899 #ifdef GRUB_KERNEL_USE_RSDP_ADDR
900 linux_params
.acpi_rsdp_addr
= grub_le_to_cpu64 (grub_rsdp_addr
);
903 mmap_size
= find_mmap_size ();
904 /* Make sure that each size is aligned to a page boundary. */
905 cl_offset
= ALIGN_UP (mmap_size
+ sizeof (linux_params
), 4096);
906 if (cl_offset
< ((grub_size_t
) linux_params
.setup_sects
<< GRUB_DISK_SECTOR_BITS
))
907 cl_offset
= ALIGN_UP ((grub_size_t
) (linux_params
.setup_sects
908 << GRUB_DISK_SECTOR_BITS
), 4096);
909 ctx
.real_size
= ALIGN_UP (cl_offset
+ maximal_cmdline_size
, 4096);
911 #ifdef GRUB_MACHINE_EFI
912 efi_mmap_size
= grub_efi_find_mmap_size ();
913 if (efi_mmap_size
== 0)
917 grub_dprintf ("linux", "real_size = %x, mmap_size = %x\n",
918 (unsigned) ctx
.real_size
, (unsigned) mmap_size
);
920 #ifdef GRUB_MACHINE_EFI
921 grub_efi_mmap_iterate (grub_linux_boot_mmap_find
, &ctx
, 1);
922 if (! ctx
.real_mode_target
)
923 grub_efi_mmap_iterate (grub_linux_boot_mmap_find
, &ctx
, 0);
925 grub_mmap_iterate (grub_linux_boot_mmap_find
, &ctx
);
927 grub_dprintf ("linux", "real_mode_target = %lx, real_size = %x, efi_mmap_size = %x\n",
928 (unsigned long) ctx
.real_mode_target
,
929 (unsigned) ctx
.real_size
,
930 (unsigned) efi_mmap_size
);
932 if (! ctx
.real_mode_target
)
933 return grub_error (GRUB_ERR_OUT_OF_MEMORY
, "cannot allocate real mode pages");
936 grub_relocator_chunk_t ch
;
937 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
938 ctx
.real_mode_target
,
939 (ctx
.real_size
+ efi_mmap_size
));
942 real_mode_mem
= get_virtual_current_address (ch
);
944 efi_mmap_buf
= (grub_uint8_t
*) real_mode_mem
+ ctx
.real_size
;
946 grub_dprintf ("linux", "real_mode_mem = %p\n",
949 ctx
.params
= real_mode_mem
;
951 *ctx
.params
= linux_params
;
952 ctx
.params
->cmd_line_ptr
= ctx
.real_mode_target
+ cl_offset
;
953 grub_memcpy ((char *) ctx
.params
+ cl_offset
, linux_cmdline
,
954 maximal_cmdline_size
);
956 grub_dprintf ("linux", "code32_start = %x\n",
957 (unsigned) ctx
.params
->code32_start
);
960 if (grub_mmap_iterate (grub_linux_boot_mmap_fill
, &ctx
))
962 ctx
.params
->mmap_size
= ctx
.e820_num
;
964 #ifdef GRUB_MACHINE_EFI
966 grub_efi_uintn_t efi_desc_size
;
967 grub_size_t efi_mmap_target
;
968 grub_efi_uint32_t efi_desc_version
;
969 err
= grub_efi_finish_boot_services (&efi_mmap_size
, efi_mmap_buf
, NULL
,
970 &efi_desc_size
, &efi_desc_version
);
974 /* Note that no boot services are available from here. */
975 efi_mmap_target
= ctx
.real_mode_target
976 + ((grub_uint8_t
*) efi_mmap_buf
- (grub_uint8_t
*) real_mode_mem
);
977 /* Pass EFI parameters. */
978 if (grub_le_to_cpu16 (ctx
.params
->version
) >= 0x0208)
980 ctx
.params
->v0208
.efi_mem_desc_size
= efi_desc_size
;
981 ctx
.params
->v0208
.efi_mem_desc_version
= efi_desc_version
;
982 ctx
.params
->v0208
.efi_mmap
= efi_mmap_target
;
983 ctx
.params
->v0208
.efi_mmap_size
= efi_mmap_size
;
986 ctx
.params
->v0208
.efi_mmap_hi
= (efi_mmap_target
>> 32);
989 else if (grub_le_to_cpu16 (ctx
.params
->version
) >= 0x0206)
991 ctx
.params
->v0206
.efi_mem_desc_size
= efi_desc_size
;
992 ctx
.params
->v0206
.efi_mem_desc_version
= efi_desc_version
;
993 ctx
.params
->v0206
.efi_mmap
= efi_mmap_target
;
994 ctx
.params
->v0206
.efi_mmap_size
= efi_mmap_size
;
996 else if (grub_le_to_cpu16 (ctx
.params
->version
) >= 0x0204)
998 ctx
.params
->v0204
.efi_mem_desc_size
= efi_desc_size
;
999 ctx
.params
->v0204
.efi_mem_desc_version
= efi_desc_version
;
1000 ctx
.params
->v0204
.efi_mmap
= efi_mmap_target
;
1001 ctx
.params
->v0204
.efi_mmap_size
= efi_mmap_size
;
1007 /* asm volatile ("lidt %0" : : "m" (idt_desc)); */
1008 state
.ebp
= state
.edi
= state
.ebx
= 0;
1009 state
.esi
= ctx
.real_mode_target
;
1010 state
.esp
= ctx
.real_mode_target
;
1011 state
.eip
= ctx
.params
->code32_start
;
1012 return grub_relocator32_boot (relocator
, state
, 0);
1016 grub_linux_unload (void)
1018 grub_dl_unref (my_mod
);
1020 grub_free (linux_cmdline
);
1022 return GRUB_ERR_NONE
;
1026 grub_cmd_linux (grub_command_t cmd
__attribute__ ((unused
)),
1027 int argc
, char *argv
[])
1029 grub_file_t file
= 0;
1030 struct linux_i386_kernel_header lh
;
1031 grub_uint8_t setup_sects
;
1032 grub_size_t real_size
, prot_size
, prot_file_size
;
1035 grub_size_t align
, min_align
;
1037 grub_uint64_t preferred_address
= GRUB_LINUX_BZIMAGE_ADDR
;
1039 grub_dl_ref (my_mod
);
1043 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
1047 file
= grub_file_open (argv
[0], GRUB_FILE_TYPE_LINUX_KERNEL
);
1051 if (ventoy_linux_argc
)
1053 const char *tip
= grub_env_get("ventoy_loading_tip");
1056 grub_printf("%s\n", tip
);
1061 if (grub_file_read (file
, &lh
, sizeof (lh
)) != sizeof (lh
))
1064 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
1069 if (lh
.boot_flag
!= grub_cpu_to_le16_compile_time (0xaa55))
1071 grub_error (GRUB_ERR_BAD_OS
, "invalid magic number");
1075 if (lh
.setup_sects
> GRUB_LINUX_MAX_SETUP_SECTS
)
1077 grub_error (GRUB_ERR_BAD_OS
, "too many setup sectors");
1081 /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
1082 still not support 32-bit boot. */
1083 if (lh
.header
!= grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE
)
1084 || grub_le_to_cpu16 (lh
.version
) < 0x0203)
1086 grub_error (GRUB_ERR_BAD_OS
, "version too old for 32-bit boot"
1087 #ifdef GRUB_MACHINE_PCBIOS
1088 " (try with `linux16')"
1094 if (! (lh
.loadflags
& GRUB_LINUX_FLAG_BIG_KERNEL
))
1096 grub_error (GRUB_ERR_BAD_OS
, "zImage doesn't support 32-bit boot"
1097 #ifdef GRUB_MACHINE_PCBIOS
1098 " (try with `linux16')"
1104 if (grub_le_to_cpu16 (lh
.version
) >= 0x0206)
1105 maximal_cmdline_size
= grub_le_to_cpu32 (lh
.cmdline_size
) + 1;
1107 maximal_cmdline_size
= 256;
1109 if (maximal_cmdline_size
< 128)
1110 maximal_cmdline_size
= 128;
1112 setup_sects
= lh
.setup_sects
;
1114 /* If SETUP_SECTS is not set, set it to the default (4). */
1116 setup_sects
= GRUB_LINUX_DEFAULT_SETUP_SECTS
;
1118 real_size
= setup_sects
<< GRUB_DISK_SECTOR_BITS
;
1119 prot_file_size
= grub_file_size (file
) - real_size
- GRUB_DISK_SECTOR_SIZE
;
1121 if (grub_le_to_cpu16 (lh
.version
) >= 0x205
1122 && lh
.kernel_alignment
!= 0
1123 && ((lh
.kernel_alignment
- 1) & lh
.kernel_alignment
) == 0)
1125 for (align
= 0; align
< 32; align
++)
1126 if (grub_le_to_cpu32 (lh
.kernel_alignment
) & (1 << align
))
1128 relocatable
= grub_le_to_cpu32 (lh
.relocatable
);
1136 if (grub_le_to_cpu16 (lh
.version
) >= 0x020a)
1138 min_align
= lh
.min_alignment
;
1139 prot_size
= grub_le_to_cpu32 (lh
.init_size
);
1140 prot_init_space
= page_align (prot_size
);
1142 preferred_address
= grub_le_to_cpu64 (lh
.pref_address
);
1144 preferred_address
= GRUB_LINUX_BZIMAGE_ADDR
;
1149 prot_size
= prot_file_size
;
1150 preferred_address
= GRUB_LINUX_BZIMAGE_ADDR
;
1151 /* Usually, the compression ratio is about 50%. */
1152 prot_init_space
= page_align (prot_size
) * 3;
1155 if (allocate_pages (prot_size
, &align
,
1156 min_align
, relocatable
,
1160 grub_memset (&linux_params
, 0, sizeof (linux_params
));
1161 grub_memcpy (&linux_params
.setup_sects
, &lh
.setup_sects
, sizeof (lh
) - 0x1F1);
1163 linux_params
.code32_start
= prot_mode_target
+ lh
.code32_start
- GRUB_LINUX_BZIMAGE_ADDR
;
1164 linux_params
.kernel_alignment
= (1 << align
);
1165 linux_params
.ps_mouse
= linux_params
.padding10
= 0;
1168 * The Linux 32-bit boot protocol defines the setup header end
1169 * to be at 0x202 + the byte value at 0x201.
1171 len
= 0x202 + *((char *) &linux_params
.jump
+ 1);
1173 /* Verify the struct is big enough so we do not write past the end. */
1174 if (len
> (char *) &linux_params
.edd_mbr_sig_buffer
- (char *) &linux_params
) {
1175 grub_error (GRUB_ERR_BAD_OS
, "Linux setup header too big");
1179 /* We've already read lh so there is no need to read it second time. */
1182 if (grub_file_read (file
, (char *) &linux_params
+ sizeof (lh
), len
) != len
)
1185 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
1190 linux_params
.type_of_loader
= GRUB_LINUX_BOOT_LOADER_TYPE
;
1192 /* These two are used (instead of cmd_line_ptr) by older versions of Linux,
1193 and otherwise ignored. */
1194 linux_params
.cl_magic
= GRUB_LINUX_CL_MAGIC
;
1195 linux_params
.cl_offset
= 0x1000;
1197 linux_params
.ramdisk_image
= 0;
1198 linux_params
.ramdisk_size
= 0;
1200 linux_params
.heap_end_ptr
= GRUB_LINUX_HEAP_END_OFFSET
;
1201 linux_params
.loadflags
|= GRUB_LINUX_FLAG_CAN_USE_HEAP
;
1203 /* These are not needed to be precise, because Linux uses these values
1204 only to raise an error when the decompression code cannot find good
1206 linux_params
.ext_mem
= ((32 * 0x100000) >> 10);
1207 linux_params
.alt_mem
= ((32 * 0x100000) >> 10);
1209 /* Ignored by Linux. */
1210 linux_params
.video_page
= 0;
1212 /* Only used when `video_mode == 0x7', otherwise ignored. */
1213 linux_params
.video_ega_bx
= 0;
1215 linux_params
.font_size
= 16; /* XXX */
1217 #ifdef GRUB_MACHINE_EFI
1219 if (grub_le_to_cpu16 (linux_params
.version
) < 0x0208 &&
1220 ((grub_addr_t
) grub_efi_system_table
>> 32) != 0)
1221 return grub_error(GRUB_ERR_BAD_OS
,
1222 "kernel does not support 64-bit addressing");
1225 if (grub_le_to_cpu16 (linux_params
.version
) >= 0x0208)
1227 linux_params
.v0208
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE
;
1228 linux_params
.v0208
.efi_system_table
= (grub_uint32_t
) (grub_addr_t
) grub_efi_system_table
;
1230 linux_params
.v0208
.efi_system_table_hi
= (grub_uint32_t
) ((grub_uint64_t
) grub_efi_system_table
>> 32);
1233 else if (grub_le_to_cpu16 (linux_params
.version
) >= 0x0206)
1235 linux_params
.v0206
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE
;
1236 linux_params
.v0206
.efi_system_table
= (grub_uint32_t
) (grub_addr_t
) grub_efi_system_table
;
1238 else if (grub_le_to_cpu16 (linux_params
.version
) >= 0x0204)
1240 linux_params
.v0204
.efi_signature
= GRUB_LINUX_EFI_SIGNATURE_0204
;
1241 linux_params
.v0204
.efi_system_table
= (grub_uint32_t
) (grub_addr_t
) grub_efi_system_table
;
1245 /* The other parameters are filled when booting. */
1247 grub_file_seek (file
, real_size
+ GRUB_DISK_SECTOR_SIZE
);
1249 grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
1250 (unsigned) real_size
, (unsigned) prot_size
);
1252 /* Look for memory size and video mode specified on the command line. */
1254 for (i
= 1; i
< argc
; i
++)
1255 #ifdef GRUB_MACHINE_PCBIOS
1256 if (grub_memcmp (argv
[i
], "vga=", 4) == 0 && (grub_memcmp (argv
[i
], "vga=current", 11) != 0))
1258 /* Video mode selection support. */
1259 char *val
= argv
[i
] + 4;
1260 unsigned vid_mode
= GRUB_LINUX_VID_MODE_NORMAL
;
1261 struct grub_vesa_mode_table_entry
*linux_mode
;
1265 grub_dl_load ("vbe");
1267 if (grub_strcmp (val
, "normal") == 0)
1268 vid_mode
= GRUB_LINUX_VID_MODE_NORMAL
;
1269 else if (grub_strcmp (val
, "ext") == 0)
1270 vid_mode
= GRUB_LINUX_VID_MODE_EXTENDED
;
1271 else if (grub_strcmp (val
, "ask") == 0)
1273 grub_puts_ (N_("Legacy `ask' parameter no longer supported."));
1275 /* We usually would never do this in a loader, but "vga=ask" means user
1276 requested interaction, so it can't hurt to request keyboard input. */
1277 grub_wait_after_message ();
1282 vid_mode
= (grub_uint16_t
) grub_strtoul (val
, 0, 0);
1287 case GRUB_LINUX_VID_MODE_NORMAL
:
1288 grub_env_set ("gfxpayload", "text");
1289 grub_printf_ (N_("%s is deprecated. "
1290 "Use set gfxpayload=%s before "
1291 "linux command instead.\n"),
1296 case GRUB_LINUX_VID_MODE_EXTENDED
:
1297 /* FIXME: support 80x50 text. */
1298 grub_env_set ("gfxpayload", "text");
1299 grub_printf_ (N_("%s is deprecated. "
1300 "Use set gfxpayload=%s before "
1301 "linux command instead.\n"),
1305 /* Ignore invalid values. */
1306 if (vid_mode
< GRUB_VESA_MODE_TABLE_START
||
1307 vid_mode
> GRUB_VESA_MODE_TABLE_END
)
1309 grub_env_set ("gfxpayload", "text");
1310 /* TRANSLATORS: "x" has to be entered in, like an identifier,
1311 so please don't use better Unicode codepoints. */
1312 grub_printf_ (N_("%s is deprecated. VGA mode %d isn't recognized. "
1313 "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] "
1314 "before linux command instead.\n"),
1319 linux_mode
= &grub_vesa_mode_table
[vid_mode
1320 - GRUB_VESA_MODE_TABLE_START
];
1322 buf
= grub_xasprintf ("%ux%ux%u,%ux%u",
1323 linux_mode
->width
, linux_mode
->height
,
1325 linux_mode
->width
, linux_mode
->height
);
1329 grub_printf_ (N_("%s is deprecated. "
1330 "Use set gfxpayload=%s before "
1331 "linux command instead.\n"),
1333 err
= grub_env_set ("gfxpayload", buf
);
1340 #endif /* GRUB_MACHINE_PCBIOS */
1341 if (grub_memcmp (argv
[i
], "mem=", 4) == 0)
1343 char *val
= argv
[i
] + 4;
1345 linux_mem_size
= grub_strtoul (val
, &val
, 0);
1349 grub_errno
= GRUB_ERR_NONE
;
1356 switch (grub_tolower (val
[0]))
1371 /* Check an overflow. */
1372 if (linux_mem_size
> (~0UL >> shift
))
1375 linux_mem_size
<<= shift
;
1378 else if (grub_memcmp (argv
[i
], "quiet", sizeof ("quiet") - 1) == 0)
1380 linux_params
.loadflags
|= GRUB_LINUX_FLAG_QUIET
;
1383 /* Create kernel command line. */
1384 linux_cmdline
= grub_zalloc (maximal_cmdline_size
+ 1);
1387 grub_memcpy (linux_cmdline
, LINUX_IMAGE
, sizeof (LINUX_IMAGE
));
1391 if (ventoy_linux_argc
)
1393 ventoy_bootopt_hook(argc
, argv
);
1394 err
= grub_create_loader_cmdline (ventoy_linux_argc
, ventoy_linux_args
,
1396 + sizeof (LINUX_IMAGE
) - 1,
1397 maximal_cmdline_size
1398 - (sizeof (LINUX_IMAGE
) - 1),
1399 GRUB_VERIFY_KERNEL_CMDLINE
);
1403 err
= grub_create_loader_cmdline (argc
, argv
,
1405 + sizeof (LINUX_IMAGE
) - 1,
1406 maximal_cmdline_size
1407 - (sizeof (LINUX_IMAGE
) - 1),
1408 GRUB_VERIFY_KERNEL_CMDLINE
);
1415 len
= prot_file_size
;
1416 if (grub_file_read (file
, prot_mode_mem
, len
) != len
&& !grub_errno
)
1417 grub_error (GRUB_ERR_BAD_OS
, N_("premature end of file %s"),
1420 if (grub_errno
== GRUB_ERR_NONE
)
1422 grub_loader_set (grub_linux_boot
, grub_linux_unload
,
1423 0 /* set noreturn=0 in order to avoid grub_console_fini() */);
1430 grub_file_close (file
);
1432 if (grub_errno
!= GRUB_ERR_NONE
)
1434 grub_dl_unref (my_mod
);
1442 grub_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
1443 int argc
, char *argv
[])
1445 grub_size_t size
= 0, aligned_size
= 0;
1446 grub_addr_t addr_min
, addr_max
;
1449 struct grub_linux_initrd_context initrd_ctx
= { 0, 0, 0 };
1453 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
1459 grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("you need to load the kernel first"));
1463 if (grub_initrd_init (argc
, argv
, &initrd_ctx
))
1466 size
= grub_get_initrd_size (&initrd_ctx
);
1467 aligned_size
= ALIGN_UP (size
, 4096);
1469 /* Get the highest address available for the initrd. */
1470 if (grub_le_to_cpu16 (linux_params
.version
) >= 0x0203)
1472 addr_max
= grub_cpu_to_le32 (linux_params
.initrd_addr_max
);
1474 /* XXX in reality, Linux specifies a bogus value, so
1475 it is necessary to make sure that ADDR_MAX does not exceed
1477 if (addr_max
> GRUB_LINUX_INITRD_MAX_ADDRESS
)
1478 addr_max
= GRUB_LINUX_INITRD_MAX_ADDRESS
;
1481 addr_max
= GRUB_LINUX_INITRD_MAX_ADDRESS
;
1483 if (linux_mem_size
!= 0 && linux_mem_size
< addr_max
)
1484 addr_max
= linux_mem_size
;
1486 /* Linux 2.3.xx has a bug in the memory range check, so avoid
1488 Linux 2.2.xx has a bug in the memory range check, which is
1489 worse than that of Linux 2.3.xx, so avoid the last 64kb. */
1490 addr_max
-= 0x10000;
1492 addr_min
= (grub_addr_t
) prot_mode_target
+ prot_init_space
;
1494 /* Put the initrd as high as possible, 4KiB aligned. */
1495 addr
= (addr_max
- aligned_size
) & ~0xFFF;
1497 if (addr
< addr_min
)
1499 grub_error (GRUB_ERR_OUT_OF_RANGE
, "the initrd is too big");
1504 grub_relocator_chunk_t ch
;
1505 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
1506 addr_min
, addr
, aligned_size
,
1508 GRUB_RELOCATOR_PREFERENCE_HIGH
,
1512 initrd_mem
= get_virtual_current_address (ch
);
1513 initrd_mem_target
= get_physical_target_address (ch
);
1516 if (grub_initrd_load (&initrd_ctx
, argv
, initrd_mem
))
1519 grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
1520 (unsigned) addr
, (unsigned) size
);
1522 linux_params
.ramdisk_image
= initrd_mem_target
;
1523 linux_params
.ramdisk_size
= size
;
1524 linux_params
.root_dev
= 0x0100; /* XXX */
1527 grub_initrd_close (&initrd_ctx
);
1533 ventoy_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
1534 int argc
, char *argv
[])
1540 if (ventoy_debug
) grub_printf("ventoy_cmd_initrd %d\n", ventoy_linux_argc
);
1542 if (ventoy_linux_argc
== 0)
1544 return grub_cmd_initrd(cmd
, argc
, argv
);
1547 grub_snprintf(buf
, sizeof(buf
), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
1549 if (ventoy_debug
) grub_printf("membuf=%s\n", buf
);
1551 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(buf
);
1553 file
= grub_env_get("vtoy_img_part_file");
1556 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(file
);
1559 for (i
= 0; i
< argc
; i
++)
1561 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(argv
[i
]);
1564 ventoy_initrd_called
= 1;
1568 grub_printf("========== initrd list ==========\n");
1569 for (i
= 0; i
< ventoy_extra_initrd_num
; i
++)
1571 grub_printf("%s\n", ventoy_extra_initrd_list
[i
]);
1573 grub_printf("=================================\n");
1576 return grub_cmd_initrd(cmd
, ventoy_extra_initrd_num
, ventoy_extra_initrd_list
);
1580 static grub_command_t cmd_linux
, cmd_initrd
, cmd_linuxefi
, cmd_initrdefi
;
1581 static grub_command_t cmd_set_bootopt
, cmd_unset_bootopt
, cmd_extra_initrd_append
, cmd_extra_initrd_reset
;
1583 GRUB_MOD_INIT(linux
)
1585 cmd_linux
= grub_register_command ("linux", grub_cmd_linux
,
1586 0, N_("Load Linux."));
1587 cmd_initrd
= grub_register_command ("initrd", ventoy_cmd_initrd
,
1588 0, N_("Load initrd."));
1590 cmd_linuxefi
= grub_register_command ("linuxefi", grub_cmd_linux
,
1591 0, N_("Load Linux."));
1592 cmd_initrdefi
= grub_register_command ("initrdefi", ventoy_cmd_initrd
,
1593 0, N_("Load initrd."));
1594 cmd_set_bootopt
= grub_register_command ("vt_set_boot_opt", grub_cmd_set_boot_opt
, 0, N_("set ext boot opt"));
1595 cmd_unset_bootopt
= grub_register_command ("vt_unset_boot_opt", grub_cmd_unset_boot_opt
, 0, N_("unset ext boot opt"));
1597 cmd_extra_initrd_append
= grub_register_command ("vt_img_extra_initrd_append", grub_cmd_extra_initrd_append
, 0, N_(""));
1598 cmd_extra_initrd_reset
= grub_register_command ("vt_img_extra_initrd_reset", grub_cmd_extra_initrd_reset
, 0, N_(""));
1600 ventoy_linux_args
= grub_zalloc(sizeof(char *) * LINUX_MAX_ARGC
);
1605 GRUB_MOD_FINI(linux
)
1607 grub_unregister_command (cmd_linux
);
1608 grub_unregister_command (cmd_initrd
);