]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/loader/i386/linux.c
6601d5de1fe0b37f7de7145a8843e240d9aaf232
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / loader / i386 / linux.c
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc.
4 *
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.
9 *
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.
14 *
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/>.
17 */
18
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>
24 #include <grub/err.h>
25 #include <grub/misc.h>
26 #include <grub/types.h>
27 #include <grub/dl.h>
28 #include <grub/mm.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>
39
40 GRUB_MOD_LICENSE ("GPLv3+");
41
42 #ifdef GRUB_MACHINE_PCBIOS
43 #include <grub/i386/pc/vesa_modes_table.h>
44 #endif
45
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
56 #else
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
62 #endif
63
64 static grub_dl_t my_mod;
65
66 static grub_size_t linux_mem_size;
67 static int loaded;
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;
80 #else
81 static const grub_size_t efi_mmap_size = 0;
82 #endif
83
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 grub_err_t
90 grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]);
91
92 /* FIXME */
93 #if 0
94 struct idt_descriptor
95 {
96 grub_uint16_t limit;
97 void *base;
98 } GRUB_PACKED;
99
100 static struct idt_descriptor idt_desc =
101 {
102 0,
103 0
104 };
105 #endif
106
107 static inline grub_size_t
108 page_align (grub_size_t size)
109 {
110 return (size + (1 << 12) - 1) & (~((1 << 12) - 1));
111 }
112
113 /* Helper for find_mmap_size. */
114 static int
115 count_hook (grub_uint64_t addr __attribute__ ((unused)),
116 grub_uint64_t size __attribute__ ((unused)),
117 grub_memory_type_t type __attribute__ ((unused)), void *data)
118 {
119 grub_size_t *count = data;
120
121 (*count)++;
122 return 0;
123 }
124
125 /* Find the optimal number of pages for the memory map. */
126 static grub_size_t
127 find_mmap_size (void)
128 {
129 grub_size_t count = 0, mmap_size;
130
131 grub_mmap_iterate (count_hook, &count);
132
133 mmap_size = count * sizeof (struct grub_e820_mmap);
134
135 /* Increase the size a bit for safety, because GRUB allocates more on
136 later. */
137 mmap_size += (1 << 12);
138
139 return page_align (mmap_size);
140 }
141
142 static void
143 free_pages (void)
144 {
145 grub_relocator_unload (relocator);
146 relocator = NULL;
147 prot_mode_mem = initrd_mem = 0;
148 prot_mode_target = initrd_mem_target = 0;
149 }
150
151 /* Allocate pages for the real mode code and the protected mode code
152 for linux as well as a memory map buffer. */
153 static grub_err_t
154 allocate_pages (grub_size_t prot_size, grub_size_t *align,
155 grub_size_t min_align, int relocatable,
156 grub_uint64_t preferred_address)
157 {
158 grub_err_t err;
159
160 if (prot_size == 0)
161 prot_size = 1;
162
163 prot_size = page_align (prot_size);
164
165 /* Initialize the memory pointers with NULL for convenience. */
166 free_pages ();
167
168 relocator = grub_relocator_new ();
169 if (!relocator)
170 {
171 err = grub_errno;
172 goto fail;
173 }
174
175 /* FIXME: Should request low memory from the heap when this feature is
176 implemented. */
177
178 {
179 grub_relocator_chunk_t ch;
180 if (relocatable)
181 {
182 err = grub_relocator_alloc_chunk_align (relocator, &ch,
183 preferred_address,
184 preferred_address,
185 prot_size, 1,
186 GRUB_RELOCATOR_PREFERENCE_LOW,
187 1);
188 for (; err && *align + 1 > min_align; (*align)--)
189 {
190 grub_errno = GRUB_ERR_NONE;
191 err = grub_relocator_alloc_chunk_align (relocator, &ch,
192 0x1000000,
193 0xffffffff & ~prot_size,
194 prot_size, 1 << *align,
195 GRUB_RELOCATOR_PREFERENCE_LOW,
196 1);
197 }
198 if (err)
199 goto fail;
200 }
201 else
202 err = grub_relocator_alloc_chunk_addr (relocator, &ch,
203 preferred_address,
204 prot_size);
205 if (err)
206 goto fail;
207 prot_mode_mem = get_virtual_current_address (ch);
208 prot_mode_target = get_physical_target_address (ch);
209 }
210
211 grub_dprintf ("linux", "prot_mode_mem = %p, prot_mode_target = %lx, prot_size = %x\n",
212 prot_mode_mem, (unsigned long) prot_mode_target,
213 (unsigned) prot_size);
214 return GRUB_ERR_NONE;
215
216 fail:
217 free_pages ();
218 return err;
219 }
220
221 static grub_err_t
222 grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num,
223 grub_uint64_t start, grub_uint64_t size,
224 grub_uint32_t type)
225 {
226 int n = *e820_num;
227
228 if ((n > 0) && (e820_map[n - 1].addr + e820_map[n - 1].size == start) &&
229 (e820_map[n - 1].type == type))
230 e820_map[n - 1].size += size;
231 else
232 {
233 e820_map[n].addr = start;
234 e820_map[n].size = size;
235 e820_map[n].type = type;
236 (*e820_num)++;
237 }
238 return GRUB_ERR_NONE;
239 }
240
241 static grub_err_t
242 grub_linux_setup_video (struct linux_kernel_params *params)
243 {
244 struct grub_video_mode_info mode_info;
245 void *framebuffer;
246 grub_err_t err;
247 grub_video_driver_id_t driver_id;
248 const char *gfxlfbvar = grub_env_get ("gfxpayloadforcelfb");
249
250 driver_id = grub_video_get_driver_id ();
251
252 if (driver_id == GRUB_VIDEO_DRIVER_NONE)
253 return 1;
254
255 err = grub_video_get_info_and_fini (&mode_info, &framebuffer);
256
257 if (err)
258 {
259 grub_errno = GRUB_ERR_NONE;
260 return 1;
261 }
262
263 params->lfb_width = mode_info.width;
264 params->lfb_height = mode_info.height;
265 params->lfb_depth = mode_info.bpp;
266 params->lfb_line_len = mode_info.pitch;
267
268 params->lfb_base = (grub_size_t) framebuffer;
269
270 #if defined (GRUB_MACHINE_EFI) && defined (__x86_64__)
271 params->ext_lfb_base = (grub_size_t) (((grub_uint64_t)(grub_size_t) framebuffer) >> 32);
272 params->capabilities |= VIDEO_CAPABILITY_64BIT_BASE;
273 #endif
274
275 params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, 65536);
276
277 params->red_mask_size = mode_info.red_mask_size;
278 params->red_field_pos = mode_info.red_field_pos;
279 params->green_mask_size = mode_info.green_mask_size;
280 params->green_field_pos = mode_info.green_field_pos;
281 params->blue_mask_size = mode_info.blue_mask_size;
282 params->blue_field_pos = mode_info.blue_field_pos;
283 params->reserved_mask_size = mode_info.reserved_mask_size;
284 params->reserved_field_pos = mode_info.reserved_field_pos;
285
286 if (gfxlfbvar && (gfxlfbvar[0] == '1' || gfxlfbvar[0] == 'y'))
287 params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
288 else
289 {
290 switch (driver_id)
291 {
292 case GRUB_VIDEO_DRIVER_VBE:
293 params->lfb_size >>= 16;
294 params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA;
295 break;
296
297 case GRUB_VIDEO_DRIVER_EFI_UGA:
298 case GRUB_VIDEO_DRIVER_EFI_GOP:
299 params->have_vga = GRUB_VIDEO_LINUX_TYPE_EFIFB;
300 break;
301
302 /* FIXME: check if better id is available. */
303 case GRUB_VIDEO_DRIVER_SM712:
304 case GRUB_VIDEO_DRIVER_SIS315PRO:
305 case GRUB_VIDEO_DRIVER_VGA:
306 case GRUB_VIDEO_DRIVER_CIRRUS:
307 case GRUB_VIDEO_DRIVER_BOCHS:
308 case GRUB_VIDEO_DRIVER_RADEON_FULOONG2E:
309 case GRUB_VIDEO_DRIVER_RADEON_YEELOONG3A:
310 case GRUB_VIDEO_DRIVER_IEEE1275:
311 case GRUB_VIDEO_DRIVER_COREBOOT:
312 /* Make gcc happy. */
313 case GRUB_VIDEO_DRIVER_XEN:
314 case GRUB_VIDEO_DRIVER_SDL:
315 case GRUB_VIDEO_DRIVER_NONE:
316 case GRUB_VIDEO_ADAPTER_CAPTURE:
317 params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE;
318 break;
319 }
320 }
321
322 #ifdef GRUB_MACHINE_PCBIOS
323 /* VESA packed modes may come with zeroed mask sizes, which need
324 to be set here according to DAC Palette width. If we don't,
325 this results in Linux displaying a black screen. */
326 if (driver_id == GRUB_VIDEO_DRIVER_VBE && mode_info.bpp <= 8)
327 {
328 struct grub_vbe_info_block controller_info;
329 int status;
330 int width = 8;
331
332 status = grub_vbe_bios_get_controller_info (&controller_info);
333
334 if (status == GRUB_VBE_STATUS_OK &&
335 (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH))
336 status = grub_vbe_bios_set_dac_palette_width (&width);
337
338 if (status != GRUB_VBE_STATUS_OK)
339 /* 6 is default after mode reset. */
340 width = 6;
341
342 params->red_mask_size = params->green_mask_size
343 = params->blue_mask_size = width;
344 params->reserved_mask_size = 0;
345 }
346 #endif
347
348 return GRUB_ERR_NONE;
349 }
350
351 /* Context for grub_linux_boot. */
352 struct grub_linux_boot_ctx
353 {
354 grub_addr_t real_mode_target;
355 grub_size_t real_size;
356 struct linux_kernel_params *params;
357 int e820_num;
358 };
359
360 /* Helper for grub_linux_boot. */
361 static int
362 grub_linux_boot_mmap_find (grub_uint64_t addr, grub_uint64_t size,
363 grub_memory_type_t type, void *data)
364 {
365 struct grub_linux_boot_ctx *ctx = data;
366
367 /* We must put real mode code in the traditional space. */
368 if (type != GRUB_MEMORY_AVAILABLE || addr > 0x90000)
369 return 0;
370
371 if (addr + size < 0x10000)
372 return 0;
373
374 if (addr < 0x10000)
375 {
376 size += addr - 0x10000;
377 addr = 0x10000;
378 }
379
380 if (addr + size > 0x90000)
381 size = 0x90000 - addr;
382
383 if (ctx->real_size + efi_mmap_size > size)
384 return 0;
385
386 grub_dprintf ("linux", "addr = %lx, size = %x, need_size = %x\n",
387 (unsigned long) addr,
388 (unsigned) size,
389 (unsigned) (ctx->real_size + efi_mmap_size));
390 ctx->real_mode_target = ((addr + size) - (ctx->real_size + efi_mmap_size));
391 return 1;
392 }
393
394 /* GRUB types conveniently match E820 types. */
395 static int
396 grub_linux_boot_mmap_fill (grub_uint64_t addr, grub_uint64_t size,
397 grub_memory_type_t type, void *data)
398 {
399 struct grub_linux_boot_ctx *ctx = data;
400
401 if (grub_e820_add_region (ctx->params->e820_map, &ctx->e820_num,
402 addr, size, type))
403 return 1;
404
405 return 0;
406 }
407
408 static void ventoy_debug_pause(void)
409 {
410 char key;
411
412 if (0 == ventoy_debug)
413 {
414 return;
415 }
416
417 grub_printf("press Enter to continue ......\n");
418 while (1)
419 {
420 key = grub_getkey();
421 if (key == '\n' || key == '\r')
422 {
423 break;
424 }
425 }
426 }
427
428 static int ventoy_preboot(void)
429 {
430 char buf[128];
431 char *argv[2];
432
433 if (ventoy_debug)
434 {
435 grub_printf("ventoy_preboot %d %d\n", ventoy_linux_argc, ventoy_initrd_called);
436 ventoy_debug_pause();
437 }
438
439 if (ventoy_linux_argc == 0)
440 {
441 return 0;
442 }
443
444 if (ventoy_initrd_called)
445 {
446 ventoy_initrd_called = 0;
447 return 0;
448 }
449
450 grub_snprintf(buf, sizeof(buf), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
451
452 argv[0] = buf;
453 argv[1] = NULL;
454 grub_cmd_initrd(NULL, 1, argv);
455
456 if (ventoy_debug)
457 {
458 grub_printf("add initrd %s\n", buf);
459 ventoy_debug_pause();
460 }
461
462 return 0;
463 }
464
465 static int ventoy_boot_opt_filter(char *opt)
466 {
467 if (grub_strcmp(opt, "noinitrd") == 0)
468 {
469 return 1;
470 }
471
472 if (grub_strncmp(opt, "rdinit=", 7) == 0)
473 {
474 if (grub_strcmp(opt, "rdinit=/vtoy/vtoy") != 0)
475 {
476 opt[0] = 'v';
477 opt[1] = 't';
478 }
479 return 0;
480 }
481
482 if (ventoy_debug)
483 {
484 if (grub_strcmp(opt, "quiet") == 0)
485 {
486 return 1;
487 }
488
489 if (grub_strncmp(opt, "loglevel=", 9) == 0)
490 {
491 return 1;
492 }
493
494 if (grub_strcmp(opt, "splash") == 0)
495 {
496 return 1;
497 }
498 }
499
500 return 0;
501 }
502
503 static int ventoy_bootopt_hook(int argc, char *argv[])
504 {
505 int i;
506 int count = 0;
507 const char *env;
508 char c;
509 char *newenv;
510 char *last, *pos;
511
512 //grub_printf("ventoy_bootopt_hook: %d %d\n", argc, ventoy_linux_argc);
513
514 if (ventoy_linux_argc == 0)
515 {
516 return 0;
517 }
518
519 for (i = 0; i < argc; i++)
520 {
521 if (ventoy_boot_opt_filter(argv[i]))
522 {
523 continue;
524 }
525
526 ventoy_linux_args[count++] = grub_strdup(argv[i]);
527 }
528
529 for (i = 0; i < ventoy_linux_argc; i++)
530 {
531 ventoy_linux_args[count] = ventoy_linux_args[i + (LINUX_MAX_ARGC / 2)];
532 ventoy_linux_args[i + (LINUX_MAX_ARGC / 2)] = NULL;
533
534 if (ventoy_linux_args[count][0] == '@')
535 {
536 env = grub_env_get(ventoy_linux_args[count] + 1);
537 if (env)
538 {
539 grub_free(ventoy_linux_args[count]);
540
541 newenv = grub_strdup(env);
542 last = newenv;
543
544 while (*last)
545 {
546 while (*last)
547 {
548 if (*last != ' ' && *last != '\t')
549 {
550 break;
551 }
552 last++;
553 }
554
555 if (*last == 0)
556 {
557 break;
558 }
559
560 for (pos = last; *pos; pos++)
561 {
562 if (*pos == ' ' || *pos == '\t')
563 {
564 c = *pos;
565 *pos = 0;
566 if (0 == ventoy_boot_opt_filter(last))
567 {
568 ventoy_linux_args[count++] = grub_strdup(last);
569 }
570 *pos = c;
571 break;
572 }
573 }
574
575 if (*pos == 0)
576 {
577 if (0 == ventoy_boot_opt_filter(last))
578 {
579 ventoy_linux_args[count++] = grub_strdup(last);
580 }
581 break;
582 }
583
584 last = pos + 1;
585 }
586 }
587 else
588 {
589 count++;
590 }
591 }
592 else
593 {
594 count++;
595 }
596 }
597
598 if (ventoy_debug)
599 {
600 ventoy_linux_args[count++] = grub_strdup("loglevel=10");
601 }
602
603 ventoy_linux_argc = count;
604
605 if (ventoy_debug)
606 {
607 grub_printf("========== bootoption ==========\n");
608 for (i = 0; i < count; i++)
609 {
610 grub_printf("%s ", ventoy_linux_args[i]);
611 }
612 grub_printf("\n================================\n");
613 }
614
615 return 0;
616 }
617
618 static grub_err_t
619 grub_cmd_set_boot_opt (grub_command_t cmd __attribute__ ((unused)),
620 int argc, char *argv[])
621 {
622 int i;
623 const char *vtdebug;
624
625 for (i = 0; i < argc; i++)
626 {
627 ventoy_linux_args[ventoy_linux_argc + (LINUX_MAX_ARGC / 2) ] = grub_strdup(argv[i]);
628 ventoy_linux_argc++;
629 }
630
631 vtdebug = grub_env_get("vtdebug_flag");
632 if (vtdebug && vtdebug[0])
633 {
634 ventoy_debug = 1;
635 }
636
637 if (ventoy_debug) grub_printf("ventoy set boot opt %d\n", ventoy_linux_argc);
638
639 return 0;
640 }
641
642 static grub_err_t
643 grub_cmd_unset_boot_opt (grub_command_t cmd __attribute__ ((unused)),
644 int argc, char *argv[])
645 {
646 int i;
647
648 (void)argc;
649 (void)argv;
650
651 for (i = 0; i < LINUX_MAX_ARGC; i++)
652 {
653 if (ventoy_linux_args[i])
654 {
655 grub_free(ventoy_linux_args[i]);
656 }
657 }
658
659 ventoy_debug = 0;
660 ventoy_linux_argc = 0;
661 ventoy_initrd_called = 0;
662 grub_memset(ventoy_linux_args, 0, sizeof(char *) * LINUX_MAX_ARGC);
663 return 0;
664 }
665
666
667 static grub_err_t
668 grub_linux_boot (void)
669 {
670 grub_err_t err = 0;
671 const char *modevar;
672 char *tmp;
673 struct grub_relocator32_state state;
674 void *real_mode_mem;
675 struct grub_linux_boot_ctx ctx = {
676 .real_mode_target = 0
677 };
678 grub_size_t mmap_size;
679 grub_size_t cl_offset;
680
681 ventoy_preboot();
682
683 #ifdef GRUB_MACHINE_IEEE1275
684 {
685 const char *bootpath;
686 grub_ssize_t len;
687
688 bootpath = grub_env_get ("root");
689 if (bootpath)
690 grub_ieee1275_set_property (grub_ieee1275_chosen,
691 "bootpath", bootpath,
692 grub_strlen (bootpath) + 1,
693 &len);
694 linux_params.ofw_signature = GRUB_LINUX_OFW_SIGNATURE;
695 linux_params.ofw_num_items = 1;
696 linux_params.ofw_cif_handler = (grub_uint32_t) grub_ieee1275_entry_fn;
697 linux_params.ofw_idt = 0;
698 }
699 #endif
700
701 modevar = grub_env_get ("gfxpayload");
702
703 /* Now all graphical modes are acceptable.
704 May change in future if we have modes without framebuffer. */
705 if (modevar && *modevar != 0)
706 {
707 tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar);
708 if (! tmp)
709 return grub_errno;
710 #if ACCEPTS_PURE_TEXT
711 err = grub_video_set_mode (tmp, 0, 0);
712 #else
713 err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
714 #endif
715 grub_free (tmp);
716 }
717 else /* We can't go back to text mode from coreboot fb. */
718 #ifdef GRUB_MACHINE_COREBOOT
719 if (grub_video_get_driver_id () == GRUB_VIDEO_DRIVER_COREBOOT)
720 err = GRUB_ERR_NONE;
721 else
722 #endif
723 {
724 #if ACCEPTS_PURE_TEXT
725 err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0);
726 #else
727 err = grub_video_set_mode (DEFAULT_VIDEO_MODE,
728 GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
729 #endif
730 }
731
732 if (err)
733 {
734 grub_print_error ();
735 grub_puts_ (N_("Booting in blind mode"));
736 grub_errno = GRUB_ERR_NONE;
737 }
738
739 if (grub_linux_setup_video (&linux_params))
740 {
741 #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
742 linux_params.have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT;
743 linux_params.video_mode = 0x3;
744 #else
745 linux_params.have_vga = 0;
746 linux_params.video_mode = 0;
747 linux_params.video_width = 0;
748 linux_params.video_height = 0;
749 #endif
750 }
751
752
753 #ifndef GRUB_MACHINE_IEEE1275
754 if (linux_params.have_vga == GRUB_VIDEO_LINUX_TYPE_TEXT)
755 #endif
756 {
757 grub_term_output_t term;
758 int found = 0;
759 FOR_ACTIVE_TERM_OUTPUTS(term)
760 if (grub_strcmp (term->name, "vga_text") == 0
761 || grub_strcmp (term->name, "console") == 0
762 || grub_strcmp (term->name, "ofconsole") == 0)
763 {
764 struct grub_term_coordinate pos = grub_term_getxy (term);
765 linux_params.video_cursor_x = pos.x;
766 linux_params.video_cursor_y = pos.y;
767 linux_params.video_width = grub_term_width (term);
768 linux_params.video_height = grub_term_height (term);
769 found = 1;
770 break;
771 }
772 if (!found)
773 {
774 linux_params.video_cursor_x = 0;
775 linux_params.video_cursor_y = 0;
776 linux_params.video_width = 80;
777 linux_params.video_height = 25;
778 }
779 }
780
781 #ifdef GRUB_KERNEL_USE_RSDP_ADDR
782 linux_params.acpi_rsdp_addr = grub_le_to_cpu64 (grub_rsdp_addr);
783 #endif
784
785 mmap_size = find_mmap_size ();
786 /* Make sure that each size is aligned to a page boundary. */
787 cl_offset = ALIGN_UP (mmap_size + sizeof (linux_params), 4096);
788 if (cl_offset < ((grub_size_t) linux_params.setup_sects << GRUB_DISK_SECTOR_BITS))
789 cl_offset = ALIGN_UP ((grub_size_t) (linux_params.setup_sects
790 << GRUB_DISK_SECTOR_BITS), 4096);
791 ctx.real_size = ALIGN_UP (cl_offset + maximal_cmdline_size, 4096);
792
793 #ifdef GRUB_MACHINE_EFI
794 efi_mmap_size = grub_efi_find_mmap_size ();
795 if (efi_mmap_size == 0)
796 return grub_errno;
797 #endif
798
799 grub_dprintf ("linux", "real_size = %x, mmap_size = %x\n",
800 (unsigned) ctx.real_size, (unsigned) mmap_size);
801
802 #ifdef GRUB_MACHINE_EFI
803 grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 1);
804 if (! ctx.real_mode_target)
805 grub_efi_mmap_iterate (grub_linux_boot_mmap_find, &ctx, 0);
806 #else
807 grub_mmap_iterate (grub_linux_boot_mmap_find, &ctx);
808 #endif
809 grub_dprintf ("linux", "real_mode_target = %lx, real_size = %x, efi_mmap_size = %x\n",
810 (unsigned long) ctx.real_mode_target,
811 (unsigned) ctx.real_size,
812 (unsigned) efi_mmap_size);
813
814 if (! ctx.real_mode_target)
815 return grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate real mode pages");
816
817 {
818 grub_relocator_chunk_t ch;
819 err = grub_relocator_alloc_chunk_addr (relocator, &ch,
820 ctx.real_mode_target,
821 (ctx.real_size + efi_mmap_size));
822 if (err)
823 return err;
824 real_mode_mem = get_virtual_current_address (ch);
825 }
826 efi_mmap_buf = (grub_uint8_t *) real_mode_mem + ctx.real_size;
827
828 grub_dprintf ("linux", "real_mode_mem = %p\n",
829 real_mode_mem);
830
831 ctx.params = real_mode_mem;
832
833 *ctx.params = linux_params;
834 ctx.params->cmd_line_ptr = ctx.real_mode_target + cl_offset;
835 grub_memcpy ((char *) ctx.params + cl_offset, linux_cmdline,
836 maximal_cmdline_size);
837
838 grub_dprintf ("linux", "code32_start = %x\n",
839 (unsigned) ctx.params->code32_start);
840
841 ctx.e820_num = 0;
842 if (grub_mmap_iterate (grub_linux_boot_mmap_fill, &ctx))
843 return grub_errno;
844 ctx.params->mmap_size = ctx.e820_num;
845
846 #ifdef GRUB_MACHINE_EFI
847 {
848 grub_efi_uintn_t efi_desc_size;
849 grub_size_t efi_mmap_target;
850 grub_efi_uint32_t efi_desc_version;
851 err = grub_efi_finish_boot_services (&efi_mmap_size, efi_mmap_buf, NULL,
852 &efi_desc_size, &efi_desc_version);
853 if (err)
854 return err;
855
856 /* Note that no boot services are available from here. */
857 efi_mmap_target = ctx.real_mode_target
858 + ((grub_uint8_t *) efi_mmap_buf - (grub_uint8_t *) real_mode_mem);
859 /* Pass EFI parameters. */
860 if (grub_le_to_cpu16 (ctx.params->version) >= 0x0208)
861 {
862 ctx.params->v0208.efi_mem_desc_size = efi_desc_size;
863 ctx.params->v0208.efi_mem_desc_version = efi_desc_version;
864 ctx.params->v0208.efi_mmap = efi_mmap_target;
865 ctx.params->v0208.efi_mmap_size = efi_mmap_size;
866
867 #ifdef __x86_64__
868 ctx.params->v0208.efi_mmap_hi = (efi_mmap_target >> 32);
869 #endif
870 }
871 else if (grub_le_to_cpu16 (ctx.params->version) >= 0x0206)
872 {
873 ctx.params->v0206.efi_mem_desc_size = efi_desc_size;
874 ctx.params->v0206.efi_mem_desc_version = efi_desc_version;
875 ctx.params->v0206.efi_mmap = efi_mmap_target;
876 ctx.params->v0206.efi_mmap_size = efi_mmap_size;
877 }
878 else if (grub_le_to_cpu16 (ctx.params->version) >= 0x0204)
879 {
880 ctx.params->v0204.efi_mem_desc_size = efi_desc_size;
881 ctx.params->v0204.efi_mem_desc_version = efi_desc_version;
882 ctx.params->v0204.efi_mmap = efi_mmap_target;
883 ctx.params->v0204.efi_mmap_size = efi_mmap_size;
884 }
885 }
886 #endif
887
888 /* FIXME. */
889 /* asm volatile ("lidt %0" : : "m" (idt_desc)); */
890 state.ebp = state.edi = state.ebx = 0;
891 state.esi = ctx.real_mode_target;
892 state.esp = ctx.real_mode_target;
893 state.eip = ctx.params->code32_start;
894 return grub_relocator32_boot (relocator, state, 0);
895 }
896
897 static grub_err_t
898 grub_linux_unload (void)
899 {
900 grub_dl_unref (my_mod);
901 loaded = 0;
902 grub_free (linux_cmdline);
903 linux_cmdline = 0;
904 return GRUB_ERR_NONE;
905 }
906
907 static grub_err_t
908 grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
909 int argc, char *argv[])
910 {
911 grub_file_t file = 0;
912 struct linux_i386_kernel_header lh;
913 grub_uint8_t setup_sects;
914 grub_size_t real_size, prot_size, prot_file_size;
915 grub_ssize_t len;
916 int i;
917 grub_size_t align, min_align;
918 int relocatable;
919 grub_uint64_t preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
920
921 grub_dl_ref (my_mod);
922
923 if (argc == 0)
924 {
925 grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
926 goto fail;
927 }
928
929 file = grub_file_open (argv[0], GRUB_FILE_TYPE_LINUX_KERNEL);
930 if (! file)
931 goto fail;
932
933 if (ventoy_linux_argc)
934 {
935 const char *tip = grub_env_get("ventoy_loading_tip");
936 if (tip)
937 {
938 grub_printf("%s\n", tip);
939 grub_refresh();
940 }
941 }
942
943 if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh))
944 {
945 if (!grub_errno)
946 grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
947 argv[0]);
948 goto fail;
949 }
950
951 if (lh.boot_flag != grub_cpu_to_le16_compile_time (0xaa55))
952 {
953 grub_error (GRUB_ERR_BAD_OS, "invalid magic number");
954 goto fail;
955 }
956
957 if (lh.setup_sects > GRUB_LINUX_MAX_SETUP_SECTS)
958 {
959 grub_error (GRUB_ERR_BAD_OS, "too many setup sectors");
960 goto fail;
961 }
962
963 /* FIXME: 2.03 is not always good enough (Linux 2.4 can be 2.03 and
964 still not support 32-bit boot. */
965 if (lh.header != grub_cpu_to_le32_compile_time (GRUB_LINUX_I386_MAGIC_SIGNATURE)
966 || grub_le_to_cpu16 (lh.version) < 0x0203)
967 {
968 grub_error (GRUB_ERR_BAD_OS, "version too old for 32-bit boot"
969 #ifdef GRUB_MACHINE_PCBIOS
970 " (try with `linux16')"
971 #endif
972 );
973 goto fail;
974 }
975
976 if (! (lh.loadflags & GRUB_LINUX_FLAG_BIG_KERNEL))
977 {
978 grub_error (GRUB_ERR_BAD_OS, "zImage doesn't support 32-bit boot"
979 #ifdef GRUB_MACHINE_PCBIOS
980 " (try with `linux16')"
981 #endif
982 );
983 goto fail;
984 }
985
986 if (grub_le_to_cpu16 (lh.version) >= 0x0206)
987 maximal_cmdline_size = grub_le_to_cpu32 (lh.cmdline_size) + 1;
988 else
989 maximal_cmdline_size = 256;
990
991 if (maximal_cmdline_size < 128)
992 maximal_cmdline_size = 128;
993
994 setup_sects = lh.setup_sects;
995
996 /* If SETUP_SECTS is not set, set it to the default (4). */
997 if (! setup_sects)
998 setup_sects = GRUB_LINUX_DEFAULT_SETUP_SECTS;
999
1000 real_size = setup_sects << GRUB_DISK_SECTOR_BITS;
1001 prot_file_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE;
1002
1003 if (grub_le_to_cpu16 (lh.version) >= 0x205
1004 && lh.kernel_alignment != 0
1005 && ((lh.kernel_alignment - 1) & lh.kernel_alignment) == 0)
1006 {
1007 for (align = 0; align < 32; align++)
1008 if (grub_le_to_cpu32 (lh.kernel_alignment) & (1 << align))
1009 break;
1010 relocatable = grub_le_to_cpu32 (lh.relocatable);
1011 }
1012 else
1013 {
1014 align = 0;
1015 relocatable = 0;
1016 }
1017
1018 if (grub_le_to_cpu16 (lh.version) >= 0x020a)
1019 {
1020 min_align = lh.min_alignment;
1021 prot_size = grub_le_to_cpu32 (lh.init_size);
1022 prot_init_space = page_align (prot_size);
1023 if (relocatable)
1024 preferred_address = grub_le_to_cpu64 (lh.pref_address);
1025 else
1026 preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
1027 }
1028 else
1029 {
1030 min_align = align;
1031 prot_size = prot_file_size;
1032 preferred_address = GRUB_LINUX_BZIMAGE_ADDR;
1033 /* Usually, the compression ratio is about 50%. */
1034 prot_init_space = page_align (prot_size) * 3;
1035 }
1036
1037 if (allocate_pages (prot_size, &align,
1038 min_align, relocatable,
1039 preferred_address))
1040 goto fail;
1041
1042 grub_memset (&linux_params, 0, sizeof (linux_params));
1043 grub_memcpy (&linux_params.setup_sects, &lh.setup_sects, sizeof (lh) - 0x1F1);
1044
1045 linux_params.code32_start = prot_mode_target + lh.code32_start - GRUB_LINUX_BZIMAGE_ADDR;
1046 linux_params.kernel_alignment = (1 << align);
1047 linux_params.ps_mouse = linux_params.padding10 = 0;
1048
1049 /*
1050 * The Linux 32-bit boot protocol defines the setup header end
1051 * to be at 0x202 + the byte value at 0x201.
1052 */
1053 len = 0x202 + *((char *) &linux_params.jump + 1);
1054
1055 /* Verify the struct is big enough so we do not write past the end. */
1056 if (len > (char *) &linux_params.edd_mbr_sig_buffer - (char *) &linux_params) {
1057 grub_error (GRUB_ERR_BAD_OS, "Linux setup header too big");
1058 goto fail;
1059 }
1060
1061 /* We've already read lh so there is no need to read it second time. */
1062 len -= sizeof(lh);
1063
1064 if (grub_file_read (file, (char *) &linux_params + sizeof (lh), len) != len)
1065 {
1066 if (!grub_errno)
1067 grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
1068 argv[0]);
1069 goto fail;
1070 }
1071
1072 linux_params.type_of_loader = GRUB_LINUX_BOOT_LOADER_TYPE;
1073
1074 /* These two are used (instead of cmd_line_ptr) by older versions of Linux,
1075 and otherwise ignored. */
1076 linux_params.cl_magic = GRUB_LINUX_CL_MAGIC;
1077 linux_params.cl_offset = 0x1000;
1078
1079 linux_params.ramdisk_image = 0;
1080 linux_params.ramdisk_size = 0;
1081
1082 linux_params.heap_end_ptr = GRUB_LINUX_HEAP_END_OFFSET;
1083 linux_params.loadflags |= GRUB_LINUX_FLAG_CAN_USE_HEAP;
1084
1085 /* These are not needed to be precise, because Linux uses these values
1086 only to raise an error when the decompression code cannot find good
1087 space. */
1088 linux_params.ext_mem = ((32 * 0x100000) >> 10);
1089 linux_params.alt_mem = ((32 * 0x100000) >> 10);
1090
1091 /* Ignored by Linux. */
1092 linux_params.video_page = 0;
1093
1094 /* Only used when `video_mode == 0x7', otherwise ignored. */
1095 linux_params.video_ega_bx = 0;
1096
1097 linux_params.font_size = 16; /* XXX */
1098
1099 #ifdef GRUB_MACHINE_EFI
1100 #ifdef __x86_64__
1101 if (grub_le_to_cpu16 (linux_params.version) < 0x0208 &&
1102 ((grub_addr_t) grub_efi_system_table >> 32) != 0)
1103 return grub_error(GRUB_ERR_BAD_OS,
1104 "kernel does not support 64-bit addressing");
1105 #endif
1106
1107 if (grub_le_to_cpu16 (linux_params.version) >= 0x0208)
1108 {
1109 linux_params.v0208.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
1110 linux_params.v0208.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
1111 #ifdef __x86_64__
1112 linux_params.v0208.efi_system_table_hi = (grub_uint32_t) ((grub_uint64_t) grub_efi_system_table >> 32);
1113 #endif
1114 }
1115 else if (grub_le_to_cpu16 (linux_params.version) >= 0x0206)
1116 {
1117 linux_params.v0206.efi_signature = GRUB_LINUX_EFI_SIGNATURE;
1118 linux_params.v0206.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
1119 }
1120 else if (grub_le_to_cpu16 (linux_params.version) >= 0x0204)
1121 {
1122 linux_params.v0204.efi_signature = GRUB_LINUX_EFI_SIGNATURE_0204;
1123 linux_params.v0204.efi_system_table = (grub_uint32_t) (grub_addr_t) grub_efi_system_table;
1124 }
1125 #endif
1126
1127 /* The other parameters are filled when booting. */
1128
1129 grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE);
1130
1131 grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n",
1132 (unsigned) real_size, (unsigned) prot_size);
1133
1134 /* Look for memory size and video mode specified on the command line. */
1135 linux_mem_size = 0;
1136 for (i = 1; i < argc; i++)
1137 #ifdef GRUB_MACHINE_PCBIOS
1138 if (grub_memcmp (argv[i], "vga=", 4) == 0)
1139 {
1140 /* Video mode selection support. */
1141 char *val = argv[i] + 4;
1142 unsigned vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
1143 struct grub_vesa_mode_table_entry *linux_mode;
1144 grub_err_t err;
1145 char *buf;
1146
1147 grub_dl_load ("vbe");
1148
1149 if (grub_strcmp (val, "normal") == 0)
1150 vid_mode = GRUB_LINUX_VID_MODE_NORMAL;
1151 else if (grub_strcmp (val, "ext") == 0)
1152 vid_mode = GRUB_LINUX_VID_MODE_EXTENDED;
1153 else if (grub_strcmp (val, "ask") == 0)
1154 {
1155 grub_puts_ (N_("Legacy `ask' parameter no longer supported."));
1156
1157 /* We usually would never do this in a loader, but "vga=ask" means user
1158 requested interaction, so it can't hurt to request keyboard input. */
1159 grub_wait_after_message ();
1160
1161 goto fail;
1162 }
1163 else
1164 vid_mode = (grub_uint16_t) grub_strtoul (val, 0, 0);
1165
1166 switch (vid_mode)
1167 {
1168 case 0:
1169 case GRUB_LINUX_VID_MODE_NORMAL:
1170 grub_env_set ("gfxpayload", "text");
1171 grub_printf_ (N_("%s is deprecated. "
1172 "Use set gfxpayload=%s before "
1173 "linux command instead.\n"),
1174 argv[i], "text");
1175 break;
1176
1177 case 1:
1178 case GRUB_LINUX_VID_MODE_EXTENDED:
1179 /* FIXME: support 80x50 text. */
1180 grub_env_set ("gfxpayload", "text");
1181 grub_printf_ (N_("%s is deprecated. "
1182 "Use set gfxpayload=%s before "
1183 "linux command instead.\n"),
1184 argv[i], "text");
1185 break;
1186 default:
1187 /* Ignore invalid values. */
1188 if (vid_mode < GRUB_VESA_MODE_TABLE_START ||
1189 vid_mode > GRUB_VESA_MODE_TABLE_END)
1190 {
1191 grub_env_set ("gfxpayload", "text");
1192 /* TRANSLATORS: "x" has to be entered in, like an identifier,
1193 so please don't use better Unicode codepoints. */
1194 grub_printf_ (N_("%s is deprecated. VGA mode %d isn't recognized. "
1195 "Use set gfxpayload=WIDTHxHEIGHT[xDEPTH] "
1196 "before linux command instead.\n"),
1197 argv[i], vid_mode);
1198 break;
1199 }
1200
1201 linux_mode = &grub_vesa_mode_table[vid_mode
1202 - GRUB_VESA_MODE_TABLE_START];
1203
1204 buf = grub_xasprintf ("%ux%ux%u,%ux%u",
1205 linux_mode->width, linux_mode->height,
1206 linux_mode->depth,
1207 linux_mode->width, linux_mode->height);
1208 if (! buf)
1209 goto fail;
1210
1211 grub_printf_ (N_("%s is deprecated. "
1212 "Use set gfxpayload=%s before "
1213 "linux command instead.\n"),
1214 argv[i], buf);
1215 err = grub_env_set ("gfxpayload", buf);
1216 grub_free (buf);
1217 if (err)
1218 goto fail;
1219 }
1220 }
1221 else
1222 #endif /* GRUB_MACHINE_PCBIOS */
1223 if (grub_memcmp (argv[i], "mem=", 4) == 0)
1224 {
1225 char *val = argv[i] + 4;
1226
1227 linux_mem_size = grub_strtoul (val, &val, 0);
1228
1229 if (grub_errno)
1230 {
1231 grub_errno = GRUB_ERR_NONE;
1232 linux_mem_size = 0;
1233 }
1234 else
1235 {
1236 int shift = 0;
1237
1238 switch (grub_tolower (val[0]))
1239 {
1240 case 'g':
1241 shift += 10;
1242 /* FALLTHROUGH */
1243 case 'm':
1244 shift += 10;
1245 /* FALLTHROUGH */
1246 case 'k':
1247 shift += 10;
1248 /* FALLTHROUGH */
1249 default:
1250 break;
1251 }
1252
1253 /* Check an overflow. */
1254 if (linux_mem_size > (~0UL >> shift))
1255 linux_mem_size = 0;
1256 else
1257 linux_mem_size <<= shift;
1258 }
1259 }
1260 else if (grub_memcmp (argv[i], "quiet", sizeof ("quiet") - 1) == 0)
1261 {
1262 linux_params.loadflags |= GRUB_LINUX_FLAG_QUIET;
1263 }
1264
1265 /* Create kernel command line. */
1266 linux_cmdline = grub_zalloc (maximal_cmdline_size + 1);
1267 if (!linux_cmdline)
1268 goto fail;
1269 grub_memcpy (linux_cmdline, LINUX_IMAGE, sizeof (LINUX_IMAGE));
1270 {
1271 grub_err_t err;
1272
1273 if (ventoy_linux_argc)
1274 {
1275 ventoy_bootopt_hook(argc, argv);
1276 err = grub_create_loader_cmdline (ventoy_linux_argc, ventoy_linux_args,
1277 linux_cmdline
1278 + sizeof (LINUX_IMAGE) - 1,
1279 maximal_cmdline_size
1280 - (sizeof (LINUX_IMAGE) - 1),
1281 GRUB_VERIFY_KERNEL_CMDLINE);
1282 }
1283 else
1284 {
1285 err = grub_create_loader_cmdline (argc, argv,
1286 linux_cmdline
1287 + sizeof (LINUX_IMAGE) - 1,
1288 maximal_cmdline_size
1289 - (sizeof (LINUX_IMAGE) - 1),
1290 GRUB_VERIFY_KERNEL_CMDLINE);
1291 }
1292
1293 if (err)
1294 goto fail;
1295 }
1296
1297 len = prot_file_size;
1298 if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno)
1299 grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
1300 argv[0]);
1301
1302 if (grub_errno == GRUB_ERR_NONE)
1303 {
1304 grub_loader_set (grub_linux_boot, grub_linux_unload,
1305 0 /* set noreturn=0 in order to avoid grub_console_fini() */);
1306 loaded = 1;
1307 }
1308
1309 fail:
1310
1311 if (file)
1312 grub_file_close (file);
1313
1314 if (grub_errno != GRUB_ERR_NONE)
1315 {
1316 grub_dl_unref (my_mod);
1317 loaded = 0;
1318 }
1319
1320 return grub_errno;
1321 }
1322
1323 static grub_err_t
1324 grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
1325 int argc, char *argv[])
1326 {
1327 grub_size_t size = 0, aligned_size = 0;
1328 grub_addr_t addr_min, addr_max;
1329 grub_addr_t addr;
1330 grub_err_t err;
1331 struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
1332
1333 if (argc == 0)
1334 {
1335 grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
1336 goto fail;
1337 }
1338
1339 if (! loaded)
1340 {
1341 grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first"));
1342 goto fail;
1343 }
1344
1345 if (grub_initrd_init (argc, argv, &initrd_ctx))
1346 goto fail;
1347
1348 size = grub_get_initrd_size (&initrd_ctx);
1349 aligned_size = ALIGN_UP (size, 4096);
1350
1351 /* Get the highest address available for the initrd. */
1352 if (grub_le_to_cpu16 (linux_params.version) >= 0x0203)
1353 {
1354 addr_max = grub_cpu_to_le32 (linux_params.initrd_addr_max);
1355
1356 /* XXX in reality, Linux specifies a bogus value, so
1357 it is necessary to make sure that ADDR_MAX does not exceed
1358 0x3fffffff. */
1359 if (addr_max > GRUB_LINUX_INITRD_MAX_ADDRESS)
1360 addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
1361 }
1362 else
1363 addr_max = GRUB_LINUX_INITRD_MAX_ADDRESS;
1364
1365 if (linux_mem_size != 0 && linux_mem_size < addr_max)
1366 addr_max = linux_mem_size;
1367
1368 /* Linux 2.3.xx has a bug in the memory range check, so avoid
1369 the last page.
1370 Linux 2.2.xx has a bug in the memory range check, which is
1371 worse than that of Linux 2.3.xx, so avoid the last 64kb. */
1372 addr_max -= 0x10000;
1373
1374 addr_min = (grub_addr_t) prot_mode_target + prot_init_space;
1375
1376 /* Put the initrd as high as possible, 4KiB aligned. */
1377 addr = (addr_max - aligned_size) & ~0xFFF;
1378
1379 if (addr < addr_min)
1380 {
1381 grub_error (GRUB_ERR_OUT_OF_RANGE, "the initrd is too big");
1382 goto fail;
1383 }
1384
1385 {
1386 grub_relocator_chunk_t ch;
1387 err = grub_relocator_alloc_chunk_align (relocator, &ch,
1388 addr_min, addr, aligned_size,
1389 0x1000,
1390 GRUB_RELOCATOR_PREFERENCE_HIGH,
1391 1);
1392 if (err)
1393 return err;
1394 initrd_mem = get_virtual_current_address (ch);
1395 initrd_mem_target = get_physical_target_address (ch);
1396 }
1397
1398 if (grub_initrd_load (&initrd_ctx, argv, initrd_mem))
1399 goto fail;
1400
1401 grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n",
1402 (unsigned) addr, (unsigned) size);
1403
1404 linux_params.ramdisk_image = initrd_mem_target;
1405 linux_params.ramdisk_size = size;
1406 linux_params.root_dev = 0x0100; /* XXX */
1407
1408 fail:
1409 grub_initrd_close (&initrd_ctx);
1410
1411 return grub_errno;
1412 }
1413
1414 static grub_err_t
1415 ventoy_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
1416 int argc, char *argv[])
1417 {
1418 int i;
1419 char buf[64];
1420 char *newargv[32] = {NULL};
1421
1422 if (ventoy_debug) grub_printf("ventoy_cmd_initrd %d\n", ventoy_linux_argc);
1423
1424 if (ventoy_linux_argc == 0)
1425 {
1426 return grub_cmd_initrd(cmd, argc, argv);
1427 }
1428
1429 grub_snprintf(buf, sizeof(buf), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
1430
1431 if (ventoy_debug) grub_printf("membuf=%s\n", buf);
1432
1433 newargv[0] = buf;
1434 for (i = 0; i < argc; i++)
1435 {
1436 newargv[i + 1] = argv[i];
1437 }
1438
1439 ventoy_initrd_called = 1;
1440
1441 return grub_cmd_initrd(cmd, argc + 1, newargv);
1442 }
1443
1444
1445 static grub_command_t cmd_linux, cmd_initrd, cmd_linuxefi, cmd_initrdefi, cmd_set_bootopt, cmd_unset_bootopt;
1446
1447 GRUB_MOD_INIT(linux)
1448 {
1449 cmd_linux = grub_register_command ("linux", grub_cmd_linux,
1450 0, N_("Load Linux."));
1451 cmd_initrd = grub_register_command ("initrd", ventoy_cmd_initrd,
1452 0, N_("Load initrd."));
1453
1454 cmd_linuxefi = grub_register_command ("linuxefi", grub_cmd_linux,
1455 0, N_("Load Linux."));
1456 cmd_initrdefi = grub_register_command ("initrdefi", ventoy_cmd_initrd,
1457 0, N_("Load initrd."));
1458 cmd_set_bootopt = grub_register_command ("vt_set_boot_opt", grub_cmd_set_boot_opt, 0, N_("set ext boot opt"));
1459 cmd_unset_bootopt = grub_register_command ("vt_unset_boot_opt", grub_cmd_unset_boot_opt, 0, N_("unset ext boot opt"));
1460
1461 ventoy_linux_args = grub_zalloc(sizeof(char *) * LINUX_MAX_ARGC);
1462
1463 my_mod = mod;
1464 }
1465
1466 GRUB_MOD_FINI(linux)
1467 {
1468 grub_unregister_command (cmd_linux);
1469 grub_unregister_command (cmd_initrd);
1470 }