1 /* linux.c - boot Linux */
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2004,2005,2007,2009,2010,2017 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/efi/api.h>
21 #include <grub/efi/efi.h>
23 #include <grub/elfload.h>
24 #include <grub/loader.h>
27 #include <grub/misc.h>
28 #include <grub/command.h>
29 #include <grub/cpu/relocator.h>
30 #include <grub/machine/loongson.h>
31 #include <grub/memory.h>
32 #include <grub/i18n.h>
33 #include <grub/lib/cmdline.h>
34 #include <grub/linux.h>
35 #include <grub/term.h>
39 GRUB_MOD_LICENSE ("GPLv3+");
41 #define _ull unsigned long long
42 #pragma GCC diagnostic ignored "-Wcast-align"
44 typedef unsigned long size_t;
46 static grub_dl_t my_mod
;
50 static grub_uint32_t tmp_index
= 0;
51 static grub_size_t linux_size
;
53 static struct grub_relocator
*relocator
;
54 static grub_addr_t target_addr
, entry_addr
;
55 static int linux_argc
;
56 static grub_uint8_t
*linux_args_addr
;
57 static grub_off_t rd_addr_arg_off
, rd_size_arg_off
;
58 static int initrd_loaded
= 0;
61 static grub_uint32_t j
= 0;
62 static grub_uint32_t t
= 0;
63 grub_uint64_t tempMemsize
= 0;
64 grub_uint32_t free_index
= 0;
65 grub_uint32_t reserve_index
= 0;
66 grub_uint32_t acpi_table_index
= 0;
67 grub_uint32_t acpi_nvs_index
= 0;
69 #define LINUX_MAX_ARGC 1024
70 static int ventoy_debug
= 0;
71 static int ventoy_initrd_called
= 0;
72 static int ventoy_linux_argc
= 0;
73 static char **ventoy_linux_args
= NULL
;
74 static int ventoy_extra_initrd_num
= 0;
75 static char *ventoy_extra_initrd_list
[256];
77 grub_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
78 int argc
, char *argv
[]);
82 static inline grub_size_t
83 page_align (grub_size_t size
)
85 return (size
+ (1 << 12) - 1) & (~((1 << 12) - 1));
88 /* Find the optimal number of pages for the memory map. Is it better to
89 move this code to efi/mm.c? */
90 static grub_efi_uintn_t
93 static grub_efi_uintn_t mmap_size
= 0;
98 mmap_size
= (1 << 12);
102 grub_efi_memory_descriptor_t
*mmap
;
103 grub_efi_uintn_t desc_size
;
105 mmap
= grub_malloc (mmap_size
);
109 ret
= grub_efi_get_memory_map (&mmap_size
, mmap
, 0, &desc_size
, 0);
114 grub_error (GRUB_ERR_IO
, "cannot get memory map");
120 mmap_size
+= (1 << 12);
124 /* Increase the size a bit for safety, because GRUB allocates more on
125 later, and EFI itself may allocate more. */
126 mmap_size
+= (1 << 12);
128 return page_align (mmap_size
);
132 static void ventoy_debug_pause(void)
136 if (0 == ventoy_debug
)
141 grub_printf("press Enter to continue ......\n");
145 if (key
== '\n' || key
== '\r')
152 static int ventoy_preboot(void)
160 grub_printf("ventoy_preboot %d %d\n", ventoy_linux_argc
, ventoy_initrd_called
);
161 ventoy_debug_pause();
164 if (ventoy_linux_argc
== 0)
169 if (ventoy_initrd_called
)
171 ventoy_initrd_called
= 0;
175 grub_snprintf(buf
, sizeof(buf
), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
177 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(buf
);
179 file
= grub_env_get("vtoy_img_part_file");
182 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(file
);
187 grub_printf("========== initrd list ==========\n");
188 for (i
= 0; i
< ventoy_extra_initrd_num
; i
++)
190 grub_printf("%s\n", ventoy_extra_initrd_list
[i
]);
192 grub_printf("=================================\n");
194 ventoy_debug_pause();
197 grub_cmd_initrd(NULL
, ventoy_extra_initrd_num
, ventoy_extra_initrd_list
);
202 static int ventoy_boot_opt_filter(char *opt
)
204 if (grub_strcmp(opt
, "noinitrd") == 0)
209 if (grub_strcmp(opt
, "vga=current") == 0)
214 if (grub_strncmp(opt
, "rdinit=", 7) == 0)
216 if (grub_strcmp(opt
, "rdinit=/vtoy/vtoy") != 0)
224 if (grub_strncmp(opt
, "init=", 5) == 0)
233 if (grub_strcmp(opt
, "quiet") == 0)
238 if (grub_strncmp(opt
, "loglevel=", 9) == 0)
243 if (grub_strcmp(opt
, "splash") == 0)
252 static int ventoy_bootopt_hook(int argc
, char *argv
[])
261 //grub_printf("ventoy_bootopt_hook: %d %d\n", argc, ventoy_linux_argc);
263 if (ventoy_linux_argc
== 0)
268 /* the 1st parameter is BOOT_IMAGE=xxxx */
269 if (argc
> 0 && 0 == ventoy_boot_opt_filter(argv
[0]))
271 ventoy_linux_args
[count
++] = grub_strdup(argv
[0]);
274 for (i
= 0; i
< ventoy_linux_argc
; i
++)
276 ventoy_linux_args
[count
] = ventoy_linux_args
[i
+ (LINUX_MAX_ARGC
/ 2)];
277 ventoy_linux_args
[i
+ (LINUX_MAX_ARGC
/ 2)] = NULL
;
279 if (ventoy_linux_args
[count
][0] == '@')
281 env
= grub_env_get(ventoy_linux_args
[count
] + 1);
284 grub_free(ventoy_linux_args
[count
]);
286 newenv
= grub_strdup(env
);
293 if (*last
!= ' ' && *last
!= '\t')
305 for (pos
= last
; *pos
; pos
++)
307 if (*pos
== ' ' || *pos
== '\t')
311 if (0 == ventoy_boot_opt_filter(last
))
313 ventoy_linux_args
[count
++] = grub_strdup(last
);
322 if (0 == ventoy_boot_opt_filter(last
))
324 ventoy_linux_args
[count
++] = grub_strdup(last
);
343 /* We have processed the 1st parameter before, so start from 1 */
344 for (i
= 1; i
< argc
; i
++)
346 if (ventoy_boot_opt_filter(argv
[i
]))
351 ventoy_linux_args
[count
++] = grub_strdup(argv
[i
]);
356 ventoy_linux_args
[count
++] = grub_strdup("loglevel=7");
359 ventoy_linux_argc
= count
;
363 grub_printf("========== bootoption ==========\n");
364 for (i
= 0; i
< count
; i
++)
366 grub_printf("%s ", ventoy_linux_args
[i
]);
368 grub_printf("\n================================\n");
375 grub_cmd_set_boot_opt (grub_command_t cmd
__attribute__ ((unused
)),
376 int argc
, char *argv
[])
381 for (i
= 0; i
< argc
; i
++)
383 ventoy_linux_args
[ventoy_linux_argc
+ (LINUX_MAX_ARGC
/ 2) ] = grub_strdup(argv
[i
]);
387 vtdebug
= grub_env_get("vtdebug_flag");
388 if (vtdebug
&& vtdebug
[0])
393 if (ventoy_debug
) grub_printf("ventoy set boot opt %d\n", ventoy_linux_argc
);
399 grub_cmd_unset_boot_opt (grub_command_t cmd
__attribute__ ((unused
)),
400 int argc
, char *argv
[])
407 for (i
= 0; i
< LINUX_MAX_ARGC
; i
++)
409 if (ventoy_linux_args
[i
])
411 grub_free(ventoy_linux_args
[i
]);
416 ventoy_linux_argc
= 0;
417 ventoy_initrd_called
= 0;
418 grub_memset(ventoy_linux_args
, 0, sizeof(char *) * LINUX_MAX_ARGC
);
423 grub_cmd_extra_initrd_append (grub_command_t cmd
__attribute__ ((unused
)),
424 int argc
, char *argv
[])
436 for (pos
= argv
[0]; *pos
; pos
++)
446 /* grub2 newc bug workaround */
447 newclen
= (int)grub_strlen(end
+ 1);
448 if ((110 + newclen
) % 4 == 0)
450 grub_snprintf(buf
, sizeof(buf
), "newc:.%s:%s", end
+ 1, argv
[0]);
454 grub_snprintf(buf
, sizeof(buf
), "newc:%s:%s", end
+ 1, argv
[0]);
457 if (ventoy_extra_initrd_num
< 256)
459 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(buf
);
467 grub_cmd_extra_initrd_reset (grub_command_t cmd
__attribute__ ((unused
)),
468 int argc
, char *argv
[])
475 for (i
= 0; i
< ventoy_extra_initrd_num
; i
++)
477 if (ventoy_extra_initrd_list
[i
])
479 grub_free(ventoy_extra_initrd_list
[i
]);
483 grub_memset(ventoy_extra_initrd_list
, 0, sizeof(ventoy_extra_initrd_list
));
490 grub_linux_boot (void)
492 struct grub_relocator64_state state
;
493 grub_int8_t checksum
= 0;
494 grub_efi_memory_descriptor_t
* lsdesc
= NULL
;
498 grub_memset (&state
, 0, sizeof (state
));
500 /* Boot the kernel. */
501 state
.gpr
[1] = entry_addr
;
502 grub_dprintf("loongson", "entry_addr is 0x%llx\n", (_ull
)state
.gpr
[1]);
503 state
.gpr
[4] = linux_argc
;
504 grub_dprintf("loongson", "linux_argc is %lld\n", (_ull
)state
.gpr
[4]);
505 state
.gpr
[5] = (grub_addr_t
) linux_args_addr
;
506 grub_dprintf("loongson", "args_addr is 0x%llx\n", (_ull
)state
.gpr
[5]);
508 if(grub_efi_is_loongson ())
510 grub_efi_uintn_t mmap_size
;
511 grub_efi_uintn_t desc_size
;
512 grub_efi_memory_descriptor_t
*mmap_buf
;
514 struct bootparamsinterface
* boot_params
;
515 void * tmp_boot_params
= NULL
;
516 grub_efi_uint8_t new_interface_flag
= 0;
517 mem_map
* new_interface_mem
= NULL
;
520 struct memmap reserve_mem
[GRUB_EFI_LOONGSON_MMAP_MAX
];
521 struct memmap free_mem
[GRUB_EFI_LOONGSON_MMAP_MAX
];
522 struct memmap acpi_table_mem
[GRUB_EFI_LOONGSON_MMAP_MAX
];
523 struct memmap acpi_nvs_mem
[GRUB_EFI_LOONGSON_MMAP_MAX
];
525 grub_memset(reserve_mem
, 0, sizeof(struct memmap
) * GRUB_EFI_LOONGSON_MMAP_MAX
);
526 grub_memset(free_mem
, 0, sizeof(struct memmap
) * GRUB_EFI_LOONGSON_MMAP_MAX
);
527 grub_memset(acpi_table_mem
, 0, sizeof(struct memmap
) * GRUB_EFI_LOONGSON_MMAP_MAX
);
528 grub_memset(acpi_nvs_mem
, 0, sizeof(struct memmap
) * GRUB_EFI_LOONGSON_MMAP_MAX
);
530 tmp_boot_params
= grub_efi_loongson_get_boot_params();
531 if(tmp_boot_params
== NULL
)
533 grub_printf("not find param\n");
537 boot_params
= (struct bootparamsinterface
*)tmp_boot_params
;
538 p
= (char *)&(boot_params
->signature
);
539 if(grub_strncmp(p
, "BPI", 3) == 0)
541 /* Check extlist headers */
542 ext_list
* listpointer
= NULL
;
543 listpointer
= boot_params
->extlist
;
544 for( ;listpointer
!= NULL
; listpointer
= listpointer
->next
)
546 char *pl
= (char *)&(listpointer
->signature
);
547 if(grub_strncmp(pl
, "MEM", 3) == 0)
549 new_interface_mem
= (mem_map
*)listpointer
;
553 new_interface_flag
= 1;
554 grub_dprintf("loongson", "get new parameter interface\n");
556 new_interface_flag
= 0;
557 grub_dprintf("loongson", "get old parameter interface\n");
560 state
.gpr
[6] = (grub_uint64_t
)tmp_boot_params
;
561 grub_dprintf("loongson", "boot_params is 0x%llx\n", (_ull
)state
.gpr
[6]);
563 mmap_size
= find_mmap_size ();
566 mmap_buf
= grub_efi_allocate_any_pages (page_align (mmap_size
) >> 12);
568 return grub_error (GRUB_ERR_IO
, "cannot allocate memory map");
569 err
= grub_efi_finish_boot_services (&mmap_size
, mmap_buf
, NULL
,
571 //grub_printf("%s-%d\n", __func__, __LINE__);
575 if(new_interface_flag
)
577 if (!mmap_buf
|| !mmap_size
|| !desc_size
)
580 tmp_index
= new_interface_mem
-> mapcount
;
581 //grub_printf("%s-%d mapcount %d\n", __func__, __LINE__, tmp_index);
584 According to UEFI SPEC,mmap_buf is the accurate Memory Map array \
585 now we can fill platform specific memory structure.
587 for(lsdesc
= mmap_buf
; lsdesc
< (grub_efi_memory_descriptor_t
*)((char *)mmap_buf
+ mmap_size
); lsdesc
= (grub_efi_memory_descriptor_t
*)((char *)lsdesc
+ desc_size
))
590 if((lsdesc
->type
!= GRUB_EFI_ACPI_RECLAIM_MEMORY
) && \
591 (lsdesc
->type
!= GRUB_EFI_ACPI_MEMORY_NVS
) && \
592 (lsdesc
->type
!= GRUB_EFI_RUNTIME_SERVICES_DATA
) && \
593 (lsdesc
->type
!= GRUB_EFI_RUNTIME_SERVICES_CODE
) && \
594 (lsdesc
->type
!= GRUB_EFI_RESERVED_MEMORY_TYPE
) && \
595 (lsdesc
->type
!= GRUB_EFI_PAL_CODE
))
598 free_mem
[free_index
].memtype
= GRUB_EFI_LOONGSON_SYSTEM_RAM_LOW
;
599 free_mem
[free_index
].memstart
= (lsdesc
->physical_start
) & 0xffffffffffff;
600 free_mem
[free_index
].memsize
= lsdesc
->num_pages
* 4096;
603 }else if((lsdesc
->type
== GRUB_EFI_ACPI_RECLAIM_MEMORY
)){
604 acpi_table_mem
[acpi_table_index
].memtype
= GRUB_EFI_LOONGSON_ACPI_TABLE
;
605 acpi_table_mem
[acpi_table_index
].memstart
= (lsdesc
->physical_start
) & 0xffffffffffff;
606 acpi_table_mem
[acpi_table_index
].memsize
= lsdesc
->num_pages
* 4096;
609 }else if((lsdesc
->type
== GRUB_EFI_ACPI_MEMORY_NVS
)){
610 acpi_nvs_mem
[acpi_nvs_index
].memtype
= GRUB_EFI_LOONGSON_ACPI_NVS
;
611 acpi_nvs_mem
[acpi_nvs_index
].memstart
= (lsdesc
->physical_start
) & 0xffffffffffff;
612 acpi_nvs_mem
[acpi_nvs_index
].memsize
= lsdesc
->num_pages
* 4096;
617 reserve_mem
[reserve_index
].memtype
= GRUB_EFI_LOONGSON_MEMORY_RESERVED
;
618 reserve_mem
[reserve_index
].memstart
= (lsdesc
->physical_start
) & 0xffffffffffff;
619 reserve_mem
[reserve_index
].memsize
= lsdesc
->num_pages
* 4096;
625 for(j
= 0; j
< free_index
;)
627 tempMemsize
= free_mem
[j
].memsize
;
628 for(t
= j
+ 1; t
< free_index
; t
++)
630 if((free_mem
[j
].memstart
+ tempMemsize
== free_mem
[t
].memstart
) && (free_mem
[j
].memtype
== free_mem
[t
].memtype
))
632 tempMemsize
+= free_mem
[t
].memsize
;
637 if(free_mem
[j
].memstart
>= 0x10000000) /*HIGH MEM*/
638 new_interface_mem
->map
[tmp_index
].memtype
= GRUB_EFI_LOONGSON_SYSTEM_RAM_HIGH
;
640 new_interface_mem
->map
[tmp_index
].memtype
= GRUB_EFI_LOONGSON_SYSTEM_RAM_LOW
;
641 new_interface_mem
->map
[tmp_index
].memstart
= free_mem
[j
].memstart
;
642 new_interface_mem
->map
[tmp_index
].memsize
= tempMemsize
;
643 grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n",
645 new_interface_mem
->map
[tmp_index
].memtype
,
646 (_ull
)new_interface_mem
->map
[tmp_index
].memstart
,
647 (_ull
)new_interface_mem
->map
[tmp_index
].memstart
+ new_interface_mem
->map
[tmp_index
].memsize
654 tmp_index
= grub_efi_loongson_memmap_sort(acpi_table_mem
, acpi_table_index
, new_interface_mem
, tmp_index
, GRUB_EFI_LOONGSON_ACPI_TABLE
);
655 tmp_index
= grub_efi_loongson_memmap_sort(acpi_nvs_mem
, acpi_nvs_index
, new_interface_mem
, tmp_index
, GRUB_EFI_LOONGSON_ACPI_NVS
);
657 tmp_index
= grub_efi_loongson_memmap_sort(reserve_mem
, reserve_index
, new_interface_mem
, tmp_index
, GRUB_EFI_LOONGSON_MEMORY_RESERVED
);
659 new_interface_mem
->mapcount
= tmp_index
;
660 new_interface_mem
->header
.checksum
= 0;
661 //grub_printf("%s-%d mapcount %d\n", __func__, __LINE__, tmp_index);
663 checksum
= grub_efi_loongson_grub_calculatechecksum8((grub_uint8_t
*)new_interface_mem
, new_interface_mem
->header
.length
);
664 new_interface_mem
->header
.checksum
= checksum
;
669 grub_relocator64_boot (relocator
, state
);
671 return GRUB_ERR_NONE
;
675 grub_linux_unload (void)
677 grub_relocator_unload (relocator
);
678 grub_dl_unref (my_mod
);
682 return GRUB_ERR_NONE
;
686 grub_linux_load32 (grub_elf_t elf
, const char *filename
)
690 grub_uint8_t
*playground
;
692 /* Linux's entry point incorrectly contains a virtual address. */
693 entry_addr
= elf
->ehdr
.ehdr32
.e_entry
;
695 linux_size
= grub_elf32_size (elf
, &base
, 0);
699 linux_size
= ALIGN_UP (base
+ linux_size
- base
, 8);
701 relocator
= grub_relocator_new ();
706 grub_relocator_chunk_t ch
;
707 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
708 grub_vtop ((void *) target_addr
),
712 playground
= get_virtual_current_address (ch
);
715 /* Now load the segments into the area we claimed. */
716 return grub_elf32_load (elf
, filename
, playground
- base
, GRUB_ELF_LOAD_FLAGS_NONE
, 0, 0);
720 grub_linux_load64 (grub_elf_t elf
, const char *filename
)
724 grub_uint8_t
*playground
;
726 /* Linux's entry point incorrectly contains a virtual address. */
727 entry_addr
= elf
->ehdr
.ehdr64
.e_entry
;
728 grub_dprintf("loongson", "entry address = 0x%llx\n", (_ull
)entry_addr
);
730 linux_size
= grub_elf64_size (elf
, &base
, 0);
731 grub_dprintf("loongson", "base = 0x%llx\n", (_ull
)base
);
736 linux_size
= ALIGN_UP (base
+ linux_size
- base
, 8);
738 relocator
= grub_relocator_new ();
743 grub_relocator_chunk_t ch
;
744 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
745 grub_vtop ((void *) target_addr
),
749 playground
= get_virtual_current_address (ch
);
750 //playground = 0xffffffff81ee0000; //½«ÄÚºËÖ±½Óloadµ½elfÍ·Ö¸¶¨Äڴ棬¶ø·Çgrub·ÖÅäµÄ¿Õ¼ä
751 //playground = 0xffffffff80200000;
754 grub_printf("playground:0x%llx\n", (_ull
)playground
);
756 /* Now load the segments into the area we claimed. */
757 return grub_elf64_load (elf
, filename
, playground
- base
, GRUB_ELF_LOAD_FLAGS_NONE
, 0, 0);
761 grub_cmd_linux (grub_command_t cmd
__attribute__ ((unused
)),
762 int argc
, char *argv
[])
767 grub_uint32_t
*linux_argv
;
772 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
774 if (ventoy_linux_argc
)
776 ventoy_bootopt_hook(argc
, argv
);
777 argc
= ventoy_linux_argc
;
778 argv
= ventoy_linux_args
;
781 elf
= grub_elf_open (argv
[0], GRUB_FILE_TYPE_LINUX_KERNEL
);
785 if (elf
->ehdr
.ehdr32
.e_type
!= ET_EXEC
)
787 grub_elf_close (elf
);
788 return grub_error (GRUB_ERR_UNKNOWN_OS
,
789 N_("this ELF file is not of the right type"));
792 /* Release the previously used memory. */
793 grub_loader_unset ();
798 /* Main arguments. */
799 size
= (linux_argc
) * sizeof (grub_uint32_t
);
800 /* Initrd address and size. */
801 size
+= 2 * sizeof (grub_uint32_t
);
802 /* NULL terminator. */
803 size
+= sizeof (grub_uint32_t
);
804 /* First argument is always "a0". */
805 size
+= ALIGN_UP (sizeof ("a0"), 4);
806 /* Normal arguments. */
807 for (i
= 1; i
< argc
; i
++)
808 size
+= ALIGN_UP (grub_strlen (argv
[i
]) + 1, 4);
811 size
+= ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
812 size
+= ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
814 size
= ALIGN_UP (size
, 8);
816 if (grub_elf_is_elf32 (elf
))
817 err
= grub_linux_load32 (elf
, argv
[0]);
819 if (grub_elf_is_elf64 (elf
))
820 err
= grub_linux_load64 (elf
, argv
[0]);
822 err
= grub_error (GRUB_ERR_BAD_OS
, N_("invalid arch-dependent ELF magic"));
824 grub_elf_close (elf
);
830 grub_relocator_chunk_t ch
;
831 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
832 0, (0xffffffff - size
) + 1,
834 GRUB_RELOCATOR_PREFERENCE_HIGH
, 0);
837 linux_args_addr
= get_virtual_current_address (ch
);
840 linux_argv
= (grub_uint32_t
*) linux_args_addr
;
841 linux_args
= (char *) (linux_argv
+ (linux_argc
+ 1 + 2));
843 grub_memcpy (linux_args
, "a0", sizeof ("a0"));
844 *linux_argv
= (grub_uint32_t
) (grub_addr_t
) linux_args
;
846 linux_args
+= ALIGN_UP (sizeof ("a0"), 4);
848 for (i
= 1; i
< argc
; i
++)
850 grub_memcpy (linux_args
, argv
[i
], grub_strlen (argv
[i
]) + 1);
851 *linux_argv
= (grub_uint32_t
) (grub_addr_t
) linux_args
;
853 linux_args
+= ALIGN_UP (grub_strlen (argv
[i
]) + 1, 4);
856 /* Reserve space for rd arguments. */
857 rd_addr_arg_off
= (grub_uint8_t
*) linux_args
- linux_args_addr
;
858 linux_args
+= ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
862 rd_size_arg_off
= (grub_uint8_t
*) linux_args
- linux_args_addr
;
863 linux_args
+= ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
869 //wake up other cores
872 "dli $8, 0x900000003ff01000\n\t"
883 grub_loader_set (grub_linux_boot
, grub_linux_unload
, 0);
886 grub_dl_ref (my_mod
);
888 return GRUB_ERR_NONE
;
892 grub_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
893 int argc
, char *argv
[])
895 grub_size_t size
= 0;
898 struct grub_linux_initrd_context initrd_ctx
= { 0, 0, 0 };
901 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
904 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("you need to load the kernel first"));
907 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "only one initrd command can be issued.");
909 if (grub_initrd_init (argc
, argv
, &initrd_ctx
))
912 size
= grub_get_initrd_size (&initrd_ctx
);
915 grub_relocator_chunk_t ch
;
916 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
917 0, (0xffffffff - size
) + 1,
919 GRUB_RELOCATOR_PREFERENCE_HIGH
, 0);
923 initrd_dest
= get_virtual_current_address (ch
);
926 if (grub_initrd_load (&initrd_ctx
, argv
, initrd_dest
))
929 grub_snprintf ((char *) linux_args_addr
+ rd_addr_arg_off
,
930 sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%lx",
931 (grub_uint64_t
) initrd_dest
);
932 ((grub_uint32_t
*) linux_args_addr
)[linux_argc
]
933 = (grub_uint32_t
) ((grub_addr_t
) linux_args_addr
+ rd_addr_arg_off
);
936 grub_snprintf ((char *) linux_args_addr
+ rd_size_arg_off
,
937 sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx",
938 (grub_uint64_t
) size
);
939 ((grub_uint32_t
*) linux_args_addr
)[linux_argc
]
940 = (grub_uint32_t
) ((grub_addr_t
) linux_args_addr
+ rd_size_arg_off
);
946 grub_initrd_close (&initrd_ctx
);
952 ventoy_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
953 int argc
, char *argv
[])
959 if (ventoy_debug
) grub_printf("ventoy_cmd_initrd %d\n", ventoy_linux_argc
);
961 if (ventoy_linux_argc
== 0)
963 return grub_cmd_initrd(cmd
, argc
, argv
);
966 grub_snprintf(buf
, sizeof(buf
), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
968 if (ventoy_debug
) grub_printf("membuf=%s\n", buf
);
970 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(buf
);
972 file
= grub_env_get("vtoy_img_part_file");
975 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(file
);
978 for (i
= 0; i
< argc
; i
++)
980 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(argv
[i
]);
983 ventoy_initrd_called
= 1;
987 grub_printf("========== initrd list ==========\n");
988 for (i
= 0; i
< ventoy_extra_initrd_num
; i
++)
990 grub_printf("%s\n", ventoy_extra_initrd_list
[i
]);
992 grub_printf("=================================\n");
995 return grub_cmd_initrd(cmd
, ventoy_extra_initrd_num
, ventoy_extra_initrd_list
);
998 static grub_command_t cmd_linux
, cmd_initrd
;
999 static grub_command_t cmd_set_bootopt
, cmd_unset_bootopt
, cmd_extra_initrd_append
, cmd_extra_initrd_reset
;
1001 GRUB_MOD_INIT(linux
)
1003 cmd_linux
= grub_register_command ("linux", grub_cmd_linux
,
1004 0, N_("Load Linux."));
1005 cmd_initrd
= grub_register_command ("initrd", ventoy_cmd_initrd
,
1006 0, N_("Load initrd."));
1008 cmd_set_bootopt
= grub_register_command ("vt_set_boot_opt", grub_cmd_set_boot_opt
, 0, N_("set ext boot opt"));
1009 cmd_unset_bootopt
= grub_register_command ("vt_unset_boot_opt", grub_cmd_unset_boot_opt
, 0, N_("unset ext boot opt"));
1011 cmd_extra_initrd_append
= grub_register_command ("vt_img_extra_initrd_append", grub_cmd_extra_initrd_append
, 0, N_(""));
1012 cmd_extra_initrd_reset
= grub_register_command ("vt_img_extra_initrd_reset", grub_cmd_extra_initrd_reset
, 0, N_(""));
1014 ventoy_linux_args
= grub_zalloc(sizeof(char *) * LINUX_MAX_ARGC
);
1019 GRUB_MOD_FINI(linux
)
1021 grub_unregister_command (cmd_linux
);
1022 grub_unregister_command (cmd_initrd
);