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
[])
262 //grub_printf("ventoy_bootopt_hook: %d %d\n", argc, ventoy_linux_argc);
264 if (ventoy_linux_argc
== 0)
269 /* To avoid --- parameter, we split two parts */
270 for (TmpIdx
= 0; TmpIdx
< argc
; TmpIdx
++)
272 if (ventoy_boot_opt_filter(argv
[TmpIdx
]))
277 if (grub_strncmp(argv
[TmpIdx
], "--", 2) == 0)
282 ventoy_linux_args
[count
++] = grub_strdup(argv
[TmpIdx
]);
285 for (i
= 0; i
< ventoy_linux_argc
; i
++)
287 ventoy_linux_args
[count
] = ventoy_linux_args
[i
+ (LINUX_MAX_ARGC
/ 2)];
288 ventoy_linux_args
[i
+ (LINUX_MAX_ARGC
/ 2)] = NULL
;
290 if (ventoy_linux_args
[count
][0] == '@')
292 env
= grub_env_get(ventoy_linux_args
[count
] + 1);
295 grub_free(ventoy_linux_args
[count
]);
297 newenv
= grub_strdup(env
);
304 if (*last
!= ' ' && *last
!= '\t')
316 for (pos
= last
; *pos
; pos
++)
318 if (*pos
== ' ' || *pos
== '\t')
322 if (0 == ventoy_boot_opt_filter(last
))
324 ventoy_linux_args
[count
++] = grub_strdup(last
);
333 if (0 == ventoy_boot_opt_filter(last
))
335 ventoy_linux_args
[count
++] = grub_strdup(last
);
354 while (TmpIdx
< argc
)
356 if (ventoy_boot_opt_filter(argv
[TmpIdx
]))
361 ventoy_linux_args
[count
++] = grub_strdup(argv
[TmpIdx
]);
367 ventoy_linux_args
[count
++] = grub_strdup("loglevel=7");
370 ventoy_linux_argc
= count
;
374 grub_printf("========== bootoption ==========\n");
375 for (i
= 0; i
< count
; i
++)
377 grub_printf("%s ", ventoy_linux_args
[i
]);
379 grub_printf("\n================================\n");
386 grub_cmd_set_boot_opt (grub_command_t cmd
__attribute__ ((unused
)),
387 int argc
, char *argv
[])
392 for (i
= 0; i
< argc
; i
++)
394 ventoy_linux_args
[ventoy_linux_argc
+ (LINUX_MAX_ARGC
/ 2) ] = grub_strdup(argv
[i
]);
398 vtdebug
= grub_env_get("vtdebug_flag");
399 if (vtdebug
&& vtdebug
[0])
404 if (ventoy_debug
) grub_printf("ventoy set boot opt %d\n", ventoy_linux_argc
);
410 grub_cmd_unset_boot_opt (grub_command_t cmd
__attribute__ ((unused
)),
411 int argc
, char *argv
[])
418 for (i
= 0; i
< LINUX_MAX_ARGC
; i
++)
420 if (ventoy_linux_args
[i
])
422 grub_free(ventoy_linux_args
[i
]);
427 ventoy_linux_argc
= 0;
428 ventoy_initrd_called
= 0;
429 grub_memset(ventoy_linux_args
, 0, sizeof(char *) * LINUX_MAX_ARGC
);
434 grub_cmd_extra_initrd_append (grub_command_t cmd
__attribute__ ((unused
)),
435 int argc
, char *argv
[])
447 for (pos
= argv
[0]; *pos
; pos
++)
457 /* grub2 newc bug workaround */
458 newclen
= (int)grub_strlen(end
+ 1);
459 if ((110 + newclen
) % 4 == 0)
461 grub_snprintf(buf
, sizeof(buf
), "newc:.%s:%s", end
+ 1, argv
[0]);
465 grub_snprintf(buf
, sizeof(buf
), "newc:%s:%s", end
+ 1, argv
[0]);
468 if (ventoy_extra_initrd_num
< 256)
470 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(buf
);
478 grub_cmd_extra_initrd_reset (grub_command_t cmd
__attribute__ ((unused
)),
479 int argc
, char *argv
[])
486 for (i
= 0; i
< ventoy_extra_initrd_num
; i
++)
488 if (ventoy_extra_initrd_list
[i
])
490 grub_free(ventoy_extra_initrd_list
[i
]);
494 grub_memset(ventoy_extra_initrd_list
, 0, sizeof(ventoy_extra_initrd_list
));
501 grub_linux_boot (void)
503 struct grub_relocator64_state state
;
504 grub_int8_t checksum
= 0;
505 grub_efi_memory_descriptor_t
* lsdesc
= NULL
;
509 grub_memset (&state
, 0, sizeof (state
));
511 /* Boot the kernel. */
512 state
.gpr
[1] = entry_addr
;
513 grub_dprintf("loongson", "entry_addr is 0x%llx\n", (_ull
)state
.gpr
[1]);
514 state
.gpr
[4] = linux_argc
;
515 grub_dprintf("loongson", "linux_argc is %lld\n", (_ull
)state
.gpr
[4]);
516 state
.gpr
[5] = (grub_addr_t
) linux_args_addr
;
517 grub_dprintf("loongson", "args_addr is 0x%llx\n", (_ull
)state
.gpr
[5]);
519 if(grub_efi_is_loongson ())
521 grub_efi_uintn_t mmap_size
;
522 grub_efi_uintn_t desc_size
;
523 grub_efi_memory_descriptor_t
*mmap_buf
;
525 struct bootparamsinterface
* boot_params
;
526 void * tmp_boot_params
= NULL
;
527 grub_efi_uint8_t new_interface_flag
= 0;
528 mem_map
* new_interface_mem
= NULL
;
531 struct memmap reserve_mem
[GRUB_EFI_LOONGSON_MMAP_MAX
];
532 struct memmap free_mem
[GRUB_EFI_LOONGSON_MMAP_MAX
];
533 struct memmap acpi_table_mem
[GRUB_EFI_LOONGSON_MMAP_MAX
];
534 struct memmap acpi_nvs_mem
[GRUB_EFI_LOONGSON_MMAP_MAX
];
536 grub_memset(reserve_mem
, 0, sizeof(struct memmap
) * GRUB_EFI_LOONGSON_MMAP_MAX
);
537 grub_memset(free_mem
, 0, sizeof(struct memmap
) * GRUB_EFI_LOONGSON_MMAP_MAX
);
538 grub_memset(acpi_table_mem
, 0, sizeof(struct memmap
) * GRUB_EFI_LOONGSON_MMAP_MAX
);
539 grub_memset(acpi_nvs_mem
, 0, sizeof(struct memmap
) * GRUB_EFI_LOONGSON_MMAP_MAX
);
541 tmp_boot_params
= grub_efi_loongson_get_boot_params();
542 if(tmp_boot_params
== NULL
)
544 grub_printf("not find param\n");
548 boot_params
= (struct bootparamsinterface
*)tmp_boot_params
;
549 p
= (char *)&(boot_params
->signature
);
550 if(grub_strncmp(p
, "BPI", 3) == 0)
552 /* Check extlist headers */
553 ext_list
* listpointer
= NULL
;
554 listpointer
= boot_params
->extlist
;
555 for( ;listpointer
!= NULL
; listpointer
= listpointer
->next
)
557 char *pl
= (char *)&(listpointer
->signature
);
558 if(grub_strncmp(pl
, "MEM", 3) == 0)
560 new_interface_mem
= (mem_map
*)listpointer
;
564 new_interface_flag
= 1;
565 grub_dprintf("loongson", "get new parameter interface\n");
567 new_interface_flag
= 0;
568 grub_dprintf("loongson", "get old parameter interface\n");
571 state
.gpr
[6] = (grub_uint64_t
)tmp_boot_params
;
572 grub_dprintf("loongson", "boot_params is 0x%llx\n", (_ull
)state
.gpr
[6]);
574 mmap_size
= find_mmap_size ();
577 mmap_buf
= grub_efi_allocate_any_pages (page_align (mmap_size
) >> 12);
579 return grub_error (GRUB_ERR_IO
, "cannot allocate memory map");
580 err
= grub_efi_finish_boot_services (&mmap_size
, mmap_buf
, NULL
,
582 //grub_printf("%s-%d\n", __func__, __LINE__);
586 if(new_interface_flag
)
588 if (!mmap_buf
|| !mmap_size
|| !desc_size
)
591 tmp_index
= new_interface_mem
-> mapcount
;
592 //grub_printf("%s-%d mapcount %d\n", __func__, __LINE__, tmp_index);
595 According to UEFI SPEC,mmap_buf is the accurate Memory Map array \
596 now we can fill platform specific memory structure.
598 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
))
601 if((lsdesc
->type
!= GRUB_EFI_ACPI_RECLAIM_MEMORY
) && \
602 (lsdesc
->type
!= GRUB_EFI_ACPI_MEMORY_NVS
) && \
603 (lsdesc
->type
!= GRUB_EFI_RUNTIME_SERVICES_DATA
) && \
604 (lsdesc
->type
!= GRUB_EFI_RUNTIME_SERVICES_CODE
) && \
605 (lsdesc
->type
!= GRUB_EFI_RESERVED_MEMORY_TYPE
) && \
606 (lsdesc
->type
!= GRUB_EFI_PAL_CODE
))
609 free_mem
[free_index
].memtype
= GRUB_EFI_LOONGSON_SYSTEM_RAM_LOW
;
610 free_mem
[free_index
].memstart
= (lsdesc
->physical_start
) & 0xffffffffffff;
611 free_mem
[free_index
].memsize
= lsdesc
->num_pages
* 4096;
614 }else if((lsdesc
->type
== GRUB_EFI_ACPI_RECLAIM_MEMORY
)){
615 acpi_table_mem
[acpi_table_index
].memtype
= GRUB_EFI_LOONGSON_ACPI_TABLE
;
616 acpi_table_mem
[acpi_table_index
].memstart
= (lsdesc
->physical_start
) & 0xffffffffffff;
617 acpi_table_mem
[acpi_table_index
].memsize
= lsdesc
->num_pages
* 4096;
620 }else if((lsdesc
->type
== GRUB_EFI_ACPI_MEMORY_NVS
)){
621 acpi_nvs_mem
[acpi_nvs_index
].memtype
= GRUB_EFI_LOONGSON_ACPI_NVS
;
622 acpi_nvs_mem
[acpi_nvs_index
].memstart
= (lsdesc
->physical_start
) & 0xffffffffffff;
623 acpi_nvs_mem
[acpi_nvs_index
].memsize
= lsdesc
->num_pages
* 4096;
628 reserve_mem
[reserve_index
].memtype
= GRUB_EFI_LOONGSON_MEMORY_RESERVED
;
629 reserve_mem
[reserve_index
].memstart
= (lsdesc
->physical_start
) & 0xffffffffffff;
630 reserve_mem
[reserve_index
].memsize
= lsdesc
->num_pages
* 4096;
636 for(j
= 0; j
< free_index
;)
638 tempMemsize
= free_mem
[j
].memsize
;
639 for(t
= j
+ 1; t
< free_index
; t
++)
641 if((free_mem
[j
].memstart
+ tempMemsize
== free_mem
[t
].memstart
) && (free_mem
[j
].memtype
== free_mem
[t
].memtype
))
643 tempMemsize
+= free_mem
[t
].memsize
;
648 if(free_mem
[j
].memstart
>= 0x10000000) /*HIGH MEM*/
649 new_interface_mem
->map
[tmp_index
].memtype
= GRUB_EFI_LOONGSON_SYSTEM_RAM_HIGH
;
651 new_interface_mem
->map
[tmp_index
].memtype
= GRUB_EFI_LOONGSON_SYSTEM_RAM_LOW
;
652 new_interface_mem
->map
[tmp_index
].memstart
= free_mem
[j
].memstart
;
653 new_interface_mem
->map
[tmp_index
].memsize
= tempMemsize
;
654 grub_dprintf("loongson", "map[%d]:type %x, start 0x%llx, end 0x%llx\n",
656 new_interface_mem
->map
[tmp_index
].memtype
,
657 (_ull
)new_interface_mem
->map
[tmp_index
].memstart
,
658 (_ull
)new_interface_mem
->map
[tmp_index
].memstart
+ new_interface_mem
->map
[tmp_index
].memsize
665 tmp_index
= grub_efi_loongson_memmap_sort(acpi_table_mem
, acpi_table_index
, new_interface_mem
, tmp_index
, GRUB_EFI_LOONGSON_ACPI_TABLE
);
666 tmp_index
= grub_efi_loongson_memmap_sort(acpi_nvs_mem
, acpi_nvs_index
, new_interface_mem
, tmp_index
, GRUB_EFI_LOONGSON_ACPI_NVS
);
668 tmp_index
= grub_efi_loongson_memmap_sort(reserve_mem
, reserve_index
, new_interface_mem
, tmp_index
, GRUB_EFI_LOONGSON_MEMORY_RESERVED
);
670 new_interface_mem
->mapcount
= tmp_index
;
671 new_interface_mem
->header
.checksum
= 0;
672 //grub_printf("%s-%d mapcount %d\n", __func__, __LINE__, tmp_index);
674 checksum
= grub_efi_loongson_grub_calculatechecksum8((grub_uint8_t
*)new_interface_mem
, new_interface_mem
->header
.length
);
675 new_interface_mem
->header
.checksum
= checksum
;
680 grub_relocator64_boot (relocator
, state
);
682 return GRUB_ERR_NONE
;
686 grub_linux_unload (void)
688 grub_relocator_unload (relocator
);
689 grub_dl_unref (my_mod
);
693 return GRUB_ERR_NONE
;
697 grub_linux_load32 (grub_elf_t elf
, const char *filename
)
701 grub_uint8_t
*playground
;
703 /* Linux's entry point incorrectly contains a virtual address. */
704 entry_addr
= elf
->ehdr
.ehdr32
.e_entry
;
706 linux_size
= grub_elf32_size (elf
, &base
, 0);
710 linux_size
= ALIGN_UP (base
+ linux_size
- base
, 8);
712 relocator
= grub_relocator_new ();
717 grub_relocator_chunk_t ch
;
718 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
719 grub_vtop ((void *) target_addr
),
723 playground
= get_virtual_current_address (ch
);
726 /* Now load the segments into the area we claimed. */
727 return grub_elf32_load (elf
, filename
, playground
- base
, GRUB_ELF_LOAD_FLAGS_NONE
, 0, 0);
731 grub_linux_load64 (grub_elf_t elf
, const char *filename
)
735 grub_uint8_t
*playground
;
737 /* Linux's entry point incorrectly contains a virtual address. */
738 entry_addr
= elf
->ehdr
.ehdr64
.e_entry
;
739 grub_dprintf("loongson", "entry address = 0x%llx\n", (_ull
)entry_addr
);
741 linux_size
= grub_elf64_size (elf
, &base
, 0);
742 grub_dprintf("loongson", "base = 0x%llx\n", (_ull
)base
);
747 linux_size
= ALIGN_UP (base
+ linux_size
- base
, 8);
749 relocator
= grub_relocator_new ();
754 grub_relocator_chunk_t ch
;
755 err
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
756 grub_vtop ((void *) target_addr
),
760 playground
= get_virtual_current_address (ch
);
761 //playground = 0xffffffff81ee0000; //½«ÄÚºËÖ±½Óloadµ½elfÍ·Ö¸¶¨Äڴ棬¶ø·Çgrub·ÖÅäµÄ¿Õ¼ä
762 //playground = 0xffffffff80200000;
765 grub_printf("playground:0x%llx\n", (_ull
)playground
);
767 /* Now load the segments into the area we claimed. */
768 return grub_elf64_load (elf
, filename
, playground
- base
, GRUB_ELF_LOAD_FLAGS_NONE
, 0, 0);
772 grub_cmd_linux (grub_command_t cmd
__attribute__ ((unused
)),
773 int argc
, char *argv
[])
778 grub_uint32_t
*linux_argv
;
783 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
785 if (ventoy_linux_argc
)
787 ventoy_bootopt_hook(argc
, argv
);
788 argc
= ventoy_linux_argc
;
789 argv
= ventoy_linux_args
;
792 elf
= grub_elf_open (argv
[0], GRUB_FILE_TYPE_LINUX_KERNEL
);
796 if (elf
->ehdr
.ehdr32
.e_type
!= ET_EXEC
)
798 grub_elf_close (elf
);
799 return grub_error (GRUB_ERR_UNKNOWN_OS
,
800 N_("this ELF file is not of the right type"));
803 /* Release the previously used memory. */
804 grub_loader_unset ();
809 /* Main arguments. */
810 size
= (linux_argc
) * sizeof (grub_uint32_t
);
811 /* Initrd address and size. */
812 size
+= 2 * sizeof (grub_uint32_t
);
813 /* NULL terminator. */
814 size
+= sizeof (grub_uint32_t
);
815 /* First argument is always "a0". */
816 size
+= ALIGN_UP (sizeof ("a0"), 4);
817 /* Normal arguments. */
818 for (i
= 1; i
< argc
; i
++)
819 size
+= ALIGN_UP (grub_strlen (argv
[i
]) + 1, 4);
822 size
+= ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
823 size
+= ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
825 size
= ALIGN_UP (size
, 8);
827 if (grub_elf_is_elf32 (elf
))
828 err
= grub_linux_load32 (elf
, argv
[0]);
830 if (grub_elf_is_elf64 (elf
))
831 err
= grub_linux_load64 (elf
, argv
[0]);
833 err
= grub_error (GRUB_ERR_BAD_OS
, N_("invalid arch-dependent ELF magic"));
835 grub_elf_close (elf
);
841 grub_relocator_chunk_t ch
;
842 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
843 0, (0xffffffff - size
) + 1,
845 GRUB_RELOCATOR_PREFERENCE_HIGH
, 0);
848 linux_args_addr
= get_virtual_current_address (ch
);
851 linux_argv
= (grub_uint32_t
*) linux_args_addr
;
852 linux_args
= (char *) (linux_argv
+ (linux_argc
+ 1 + 2));
854 grub_memcpy (linux_args
, "a0", sizeof ("a0"));
855 *linux_argv
= (grub_uint32_t
) (grub_addr_t
) linux_args
;
857 linux_args
+= ALIGN_UP (sizeof ("a0"), 4);
859 for (i
= 1; i
< argc
; i
++)
861 grub_memcpy (linux_args
, argv
[i
], grub_strlen (argv
[i
]) + 1);
862 *linux_argv
= (grub_uint32_t
) (grub_addr_t
) linux_args
;
864 linux_args
+= ALIGN_UP (grub_strlen (argv
[i
]) + 1, 4);
867 /* Reserve space for rd arguments. */
868 rd_addr_arg_off
= (grub_uint8_t
*) linux_args
- linux_args_addr
;
869 linux_args
+= ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4);
873 rd_size_arg_off
= (grub_uint8_t
*) linux_args
- linux_args_addr
;
874 linux_args
+= ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4);
880 //wake up other cores
883 "dli $8, 0x900000003ff01000\n\t"
894 grub_loader_set (grub_linux_boot
, grub_linux_unload
, 0);
897 grub_dl_ref (my_mod
);
899 return GRUB_ERR_NONE
;
903 grub_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
904 int argc
, char *argv
[])
906 grub_size_t size
= 0;
909 struct grub_linux_initrd_context initrd_ctx
= { 0, 0, 0 };
912 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("filename expected"));
915 return grub_error (GRUB_ERR_BAD_ARGUMENT
, N_("you need to load the kernel first"));
918 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "only one initrd command can be issued.");
920 if (grub_initrd_init (argc
, argv
, &initrd_ctx
))
923 size
= grub_get_initrd_size (&initrd_ctx
);
926 grub_relocator_chunk_t ch
;
927 err
= grub_relocator_alloc_chunk_align (relocator
, &ch
,
928 0, (0xffffffff - size
) + 1,
930 GRUB_RELOCATOR_PREFERENCE_HIGH
, 0);
934 initrd_dest
= get_virtual_current_address (ch
);
937 if (grub_initrd_load (&initrd_ctx
, argv
, initrd_dest
))
940 grub_snprintf ((char *) linux_args_addr
+ rd_addr_arg_off
,
941 sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%lx",
942 (grub_uint64_t
) initrd_dest
);
943 ((grub_uint32_t
*) linux_args_addr
)[linux_argc
]
944 = (grub_uint32_t
) ((grub_addr_t
) linux_args_addr
+ rd_addr_arg_off
);
947 grub_snprintf ((char *) linux_args_addr
+ rd_size_arg_off
,
948 sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%lx",
949 (grub_uint64_t
) size
);
950 ((grub_uint32_t
*) linux_args_addr
)[linux_argc
]
951 = (grub_uint32_t
) ((grub_addr_t
) linux_args_addr
+ rd_size_arg_off
);
957 grub_initrd_close (&initrd_ctx
);
963 ventoy_cmd_initrd (grub_command_t cmd
__attribute__ ((unused
)),
964 int argc
, char *argv
[])
970 if (ventoy_debug
) grub_printf("ventoy_cmd_initrd %d\n", ventoy_linux_argc
);
972 if (ventoy_linux_argc
== 0)
974 return grub_cmd_initrd(cmd
, argc
, argv
);
977 grub_snprintf(buf
, sizeof(buf
), "mem:%s:size:%s", grub_env_get("ventoy_cpio_addr"), grub_env_get("ventoy_cpio_size"));
979 if (ventoy_debug
) grub_printf("membuf=%s\n", buf
);
981 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(buf
);
983 file
= grub_env_get("vtoy_img_part_file");
986 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(file
);
989 for (i
= 0; i
< argc
; i
++)
991 ventoy_extra_initrd_list
[ventoy_extra_initrd_num
++] = grub_strdup(argv
[i
]);
994 ventoy_initrd_called
= 1;
998 grub_printf("========== initrd list ==========\n");
999 for (i
= 0; i
< ventoy_extra_initrd_num
; i
++)
1001 grub_printf("%s\n", ventoy_extra_initrd_list
[i
]);
1003 grub_printf("=================================\n");
1006 return grub_cmd_initrd(cmd
, ventoy_extra_initrd_num
, ventoy_extra_initrd_list
);
1009 static grub_command_t cmd_linux
, cmd_initrd
;
1010 static grub_command_t cmd_set_bootopt
, cmd_unset_bootopt
, cmd_extra_initrd_append
, cmd_extra_initrd_reset
;
1012 GRUB_MOD_INIT(linux
)
1014 cmd_linux
= grub_register_command ("linux", grub_cmd_linux
,
1015 0, N_("Load Linux."));
1016 cmd_initrd
= grub_register_command ("initrd", ventoy_cmd_initrd
,
1017 0, N_("Load initrd."));
1019 cmd_set_bootopt
= grub_register_command ("vt_set_boot_opt", grub_cmd_set_boot_opt
, 0, N_("set ext boot opt"));
1020 cmd_unset_bootopt
= grub_register_command ("vt_unset_boot_opt", grub_cmd_unset_boot_opt
, 0, N_("unset ext boot opt"));
1022 cmd_extra_initrd_append
= grub_register_command ("vt_img_extra_initrd_append", grub_cmd_extra_initrd_append
, 0, N_(""));
1023 cmd_extra_initrd_reset
= grub_register_command ("vt_img_extra_initrd_reset", grub_cmd_extra_initrd_reset
, 0, N_(""));
1025 ventoy_linux_args
= grub_zalloc(sizeof(char *) * LINUX_MAX_ARGC
);
1030 GRUB_MOD_FINI(linux
)
1032 grub_unregister_command (cmd_linux
);
1033 grub_unregister_command (cmd_initrd
);