1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 int g_ventoy_debug
= 0;
55 static int g_efi_os
= 0xFF;
56 initrd_info
*g_initrd_img_list
= NULL
;
57 initrd_info
*g_initrd_img_tail
= NULL
;
58 int g_initrd_img_count
= 0;
59 int g_valid_initrd_count
= 0;
60 int g_default_menu_mode
= 0;
61 int g_filt_dot_underscore_file
= 0;
62 int g_sort_case_sensitive
= 0;
63 int g_tree_view_menu_style
= 0;
64 static grub_file_t g_old_file
;
65 static int g_ventoy_last_entry_back
;
66 static grub_uint32_t g_ventoy_plat_data
;
69 char g_img_swap_tmp_buf
[1024];
70 img_info g_img_swap_tmp
;
71 img_info
*g_ventoy_img_list
= NULL
;
73 int g_ventoy_img_count
= 0;
75 grub_device_t g_enum_dev
= NULL
;
76 grub_fs_t g_enum_fs
= NULL
;
77 img_iterator_node g_img_iterator_head
;
78 img_iterator_node
*g_img_iterator_tail
= NULL
;
80 grub_uint8_t g_ventoy_break_level
= 0;
81 grub_uint8_t g_ventoy_debug_level
= 0;
82 grub_uint8_t g_ventoy_chain_type
= 0;
84 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
85 grub_uint32_t g_ventoy_cpio_size
= 0;
86 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
87 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
89 int g_plugin_image_list
= 0;
91 ventoy_grub_param
*g_grub_param
= NULL
;
93 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
95 ventoy_img_chunk_list g_img_chunk_list
;
97 int g_wimboot_enable
= 0;
98 ventoy_img_chunk_list g_wimiso_chunk_list
;
99 char *g_wimiso_path
= NULL
;
101 int g_vhdboot_enable
= 0;
103 grub_uint64_t g_conf_replace_offset
= 0;
104 grub_uint64_t g_svd_replace_offset
= 0;
105 conf_replace
*g_conf_replace_node
= NULL
;
106 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
107 int g_conf_replace_new_len
= 0;
108 int g_conf_replace_new_len_align
= 0;
110 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
111 grub_uint64_t g_ventoy_disk_size
= 0;
113 static char *g_tree_script_buf
= NULL
;
114 static int g_tree_script_pos
= 0;
116 static char *g_list_script_buf
= NULL
;
117 static int g_list_script_pos
= 0;
119 static char *g_part_list_buf
= NULL
;
120 static int g_part_list_pos
= 0;
122 static int g_video_mode_max
= 0;
123 static int g_video_mode_num
= 0;
124 static ventoy_video_mode
*g_video_mode_list
= NULL
;
126 static int g_enumerate_time_checked
= 0;
127 static grub_uint64_t g_enumerate_start_time_ms
;
128 static grub_uint64_t g_enumerate_finish_time_ms
;
130 static const char *g_menu_class
[] =
132 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
135 static const char *g_menu_prefix
[] =
137 "iso", "wim", "efi", "img", "vhd", "vtoy"
140 void ventoy_debug(const char *fmt
, ...)
144 va_start (args
, fmt
);
145 grub_vprintf (fmt
, args
);
149 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
159 for (i
= 0; i
< 16; i
++)
161 grub_printf("%02x ", guid
[i
]);
166 int ventoy_is_efi_os(void)
170 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
176 static int ventoy_get_fs_type(const char *fs
)
180 return ventoy_fs_max
;
182 else if (grub_strncmp(fs
, "exfat", 5) == 0)
184 return ventoy_fs_exfat
;
186 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
188 return ventoy_fs_ntfs
;
190 else if (grub_strncmp(fs
, "ext", 3) == 0)
192 return ventoy_fs_ext
;
194 else if (grub_strncmp(fs
, "xfs", 3) == 0)
196 return ventoy_fs_xfs
;
198 else if (grub_strncmp(fs
, "udf", 3) == 0)
200 return ventoy_fs_udf
;
202 else if (grub_strncmp(fs
, "fat", 3) == 0)
204 return ventoy_fs_fat
;
207 return ventoy_fs_max
;
210 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
229 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
231 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
235 static grub_err_t
ventoy_fs_close(grub_file_t file
)
237 grub_file_close(g_old_file
);
238 grub_free(file
->data
);
246 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
252 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
257 for (i
= 0; i
< g_video_mode_num
; i
++)
259 if (g_video_mode_list
[i
].width
== info
->width
&&
260 g_video_mode_list
[i
].height
== info
->height
&&
261 g_video_mode_list
[i
].bpp
== info
->bpp
)
267 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
268 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
269 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
272 if (g_video_mode_num
== g_video_mode_max
)
274 g_video_mode_max
*= 2;
275 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
281 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
283 if (v1
->bpp
== v2
->bpp
)
285 if (v1
->width
== v2
->width
)
287 if (v1
->height
== v2
->height
)
293 return (v1
->height
< v2
->height
) ? -1 : 1;
298 return (v1
->width
< v2
->width
) ? -1 : 1;
303 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
307 static int ventoy_enum_video_mode(void)
310 grub_video_adapter_t adapter
;
311 grub_video_driver_id_t id
;
312 ventoy_video_mode mode
;
314 g_video_mode_num
= 0;
315 g_video_mode_max
= 1024;
316 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
317 if (!g_video_mode_list
)
322 #ifdef GRUB_MACHINE_PCBIOS
323 grub_dl_load ("vbe");
326 id
= grub_video_get_driver_id ();
328 FOR_VIDEO_ADAPTERS (adapter
)
330 if (!adapter
->iterate
||
331 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
332 adapter
->init() != GRUB_ERR_NONE
)))
337 adapter
->iterate(ventoy_video_hook
, NULL
);
339 if (adapter
->id
!= id
)
345 /* sort video mode */
346 for (i
= 0; i
< g_video_mode_num
; i
++)
347 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
349 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
351 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
352 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
353 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
357 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
360 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
364 static struct grub_fs vtoy_fs
=
369 .fs_read
= ventoy_fs_read
,
370 .fs_close
= ventoy_fs_close
,
380 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
386 file
->data
= grub_malloc(rawFile
->size
+ 4096);
392 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
393 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
395 g_old_file
= rawFile
;
397 file
->size
= rawFile
->size
+ len
;
398 file
->device
= rawFile
->device
;
400 file
->not_easily_seekable
= 1;
405 static int ventoy_check_decimal_var(const char *name
, long *value
)
407 const char *value_str
= NULL
;
409 value_str
= grub_env_get(name
);
410 if (NULL
== value_str
)
412 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
415 if (!ventoy_is_decimal(value_str
))
417 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
420 *value
= grub_strtol(value_str
, NULL
, 10);
422 return GRUB_ERR_NONE
;
425 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
429 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
432 if (0 == grub_strcmp(args
[0], "on"))
435 grub_env_set("vtdebug_flag", "debug");
440 grub_env_set("vtdebug_flag", "");
443 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
446 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
450 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
452 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
453 grub_printf(" level:\r\n");
454 grub_printf(" 01/11: busybox / (+cat log)\r\n");
455 grub_printf(" 02/12: initrd / (+cat log)\r\n");
456 grub_printf(" 03/13: hook / (+cat log)\r\n");
458 grub_printf(" debug:\r\n");
459 grub_printf(" 0: debug is off\r\n");
460 grub_printf(" 1: debug is on\r\n");
462 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
465 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
467 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
469 g_ventoy_debug_level
= 1;
472 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
475 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
484 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
487 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
519 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
524 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
526 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
529 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
534 value_long
+= grub_strtol(args
[1], NULL
, 10);
536 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
537 grub_env_set(args
[0], buf
);
539 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
542 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
550 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
553 value1
= grub_strtol(args
[0], NULL
, 10);
554 value2
= grub_strtol(args
[1], NULL
, 10);
556 grub_snprintf(buf
, sizeof(buf
), "%ld", (value1
% value2
));
557 grub_env_set(args
[2], buf
);
559 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
562 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
577 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
580 debug("failed to open file <%s> for udf check\n", args
[0]);
584 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
586 grub_env_set(args
[1], buf
);
588 grub_file_close(file
);
594 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
602 g_wimboot_enable
= 0;
603 grub_check_free(g_wimiso_path
);
604 grub_check_free(g_wimiso_chunk_list
.chunk
);
606 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
612 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
613 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
614 if (NULL
== g_wimiso_chunk_list
.chunk
)
616 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
619 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
620 g_wimiso_chunk_list
.cur_chunk
= 0;
622 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
624 g_wimboot_enable
= 1;
625 g_wimiso_path
= grub_strdup(args
[0]);
627 grub_file_close(file
);
632 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
638 grub_uint32_t offset
;
640 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
643 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
647 len
= (int)file
->size
;
649 data
= (char *)grub_malloc(file
->size
);
655 grub_file_read(file
, data
, file
->size
);
656 grub_file_close(file
);
658 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
659 grub_script_execute_sourcecode(exec
);
661 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
662 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
663 grub_file_close(file
);
665 grub_script_execute_sourcecode("loopback -d efiboot");
669 *direntoff
= offset
+ 2;
674 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
684 ventoy_iso9660_override
*dirent
;
693 totlen
= sizeof(ventoy_chain_head
);
695 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
697 debug("failed to load efiboot template %d\n", len
);
703 debug("efiboot template len:%d offset:%d\n", len
, offset
);
705 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
708 debug("failed to open file <%s>\n", args
[0]);
712 totlen
+= ventoy_align_2k(file
->size
);
714 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
715 dirent
->first_sector
= len
/ 2048;
716 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
717 dirent
->size
= (grub_uint32_t
)file
->size
;
718 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
720 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
722 #ifdef GRUB_MACHINE_EFI
723 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
725 data
= (char *)grub_malloc(totlen
);
728 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
730 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
731 grub_check_free(buf
);
733 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
734 grub_file_close(file
);
736 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
737 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
738 grub_env_set(name
, value
);
740 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
741 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
742 grub_env_set(name
, value
);
747 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
764 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
767 debug("failed to open file <%s>\n", args
[0]);
771 #ifdef GRUB_MACHINE_EFI
772 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
774 buf
= (char *)grub_malloc(file
->size
);
777 grub_file_read(file
, buf
, file
->size
);
779 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
780 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
781 grub_env_set(name
, value
);
783 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
784 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
785 grub_env_set(name
, value
);
787 grub_file_close(file
);
793 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
811 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
814 debug("failed to open file <%s> for udf check\n", args
[0]);
818 headlen
= sizeof(ventoy_chain_head
);
820 #ifdef GRUB_MACHINE_EFI
821 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
823 buf
= (char *)grub_malloc(headlen
+ file
->size
);
826 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
828 grub_file_read(file
, buf
+ headlen
, file
->size
);
830 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
831 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
832 grub_env_set(name
, value
);
834 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
835 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
836 grub_env_set(name
, value
);
838 grub_file_close(file
);
844 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
853 if (args
[0][0] == '1')
855 grub_iso9660_set_nojoliet(1);
859 grub_iso9660_set_nojoliet(0);
865 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
870 grub_uint8_t buf
[32];
881 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
884 debug("failed to open file <%s> for udf check\n", args
[0]);
888 for (i
= 16; i
< 32; i
++)
890 grub_file_seek(file
, i
* 2048);
891 grub_file_read(file
, buf
, sizeof(buf
));
899 grub_file_seek(file
, i
* 2048);
900 grub_file_read(file
, buf
, sizeof(buf
));
902 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
905 grub_file_seek(file
, i
* 2048);
906 grub_file_read(file
, buf
, sizeof(buf
));
908 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
909 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
915 grub_file_close(file
);
917 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
922 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
924 long value_long1
= 0;
925 long value_long2
= 0;
927 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
929 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
932 value_long1
= grub_strtol(args
[0], NULL
, 10);
933 value_long2
= grub_strtol(args
[2], NULL
, 10);
935 if (0 == grub_strcmp(args
[1], "eq"))
937 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
939 else if (0 == grub_strcmp(args
[1], "ne"))
941 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
943 else if (0 == grub_strcmp(args
[1], "gt"))
945 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
947 else if (0 == grub_strcmp(args
[1], "lt"))
949 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
951 else if (0 == grub_strcmp(args
[1], "ge"))
953 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
955 else if (0 == grub_strcmp(args
[1], "le"))
957 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
961 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
967 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
974 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
977 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
978 pos
= grub_strstr(buf
, ",");
984 grub_env_set(args
[1], buf
);
986 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
989 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
995 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1001 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1004 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1006 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1007 if (0 == grub_script_execute_sourcecode(buf
))
1009 debug("file %s exist, ventoy_compatible YES\n", buf
);
1010 grub_env_set("ventoy_compatible", "YES");
1011 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1015 debug("file %s NOT exist\n", buf
);
1019 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1020 pos
= grub_strstr(buf
, ")");
1026 disk
= grub_disk_open(buf
);
1029 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1030 grub_disk_close(disk
);
1032 g_img_swap_tmp_buf
[703] = 0;
1033 for (i
= 318; i
< 703; i
++)
1035 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1036 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1038 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1039 grub_env_set("ventoy_compatible", "YES");
1040 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1046 debug("failed to open disk <%s>\n", buf
);
1049 grub_env_set("ventoy_compatible", "NO");
1050 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1053 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1059 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1061 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1064 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1069 if (0 == g_sort_case_sensitive
)
1071 if (grub_islower(c1
))
1073 c1
= c1
- 'a' + 'A';
1076 if (grub_islower(c2
))
1078 c2
= c2
- 'a' + 'A';
1091 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1097 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1099 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1102 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1107 if (0 == g_sort_case_sensitive
)
1109 if (grub_islower(c1
))
1111 c1
= c1
- 'a' + 'A';
1114 if (grub_islower(c2
))
1116 c2
= c2
- 'a' + 'A';
1129 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1131 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1133 grub_memcpy(img1
, img2
, sizeof(img_info
));
1134 img1
->next
= g_img_swap_tmp
.next
;
1135 img1
->prev
= g_img_swap_tmp
.prev
;
1137 g_img_swap_tmp
.next
= img2
->next
;
1138 g_img_swap_tmp
.prev
= img2
->prev
;
1139 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1142 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1146 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1154 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1158 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1168 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1177 img_iterator_node
*tmp
;
1178 img_iterator_node
*new_node
;
1179 img_iterator_node
*node
= (img_iterator_node
*)data
;
1181 if (g_enumerate_time_checked
== 0)
1183 g_enumerate_finish_time_ms
= grub_get_time_ms();
1184 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1187 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1189 g_enumerate_time_checked
= 1;
1193 len
= grub_strlen(filename
);
1197 if ((len
== 1 && filename
[0] == '.') ||
1198 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1203 if (!ventoy_img_name_valid(filename
, len
))
1208 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1213 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1215 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1216 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1219 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1224 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1227 new_node
->plugin_list_index
= index
;
1228 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1230 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1233 debug("Directory %s ignored...\n", new_node
->dir
);
1234 grub_free(new_node
);
1238 new_node
->tail
= node
->tail
;
1240 new_node
->parent
= node
;
1241 if (!node
->firstchild
)
1243 node
->firstchild
= new_node
;
1246 if (g_img_iterator_tail
)
1248 g_img_iterator_tail
->next
= new_node
;
1249 g_img_iterator_tail
= new_node
;
1253 g_img_iterator_head
.next
= new_node
;
1254 g_img_iterator_tail
= new_node
;
1260 debug("Find a file %s\n", filename
);
1266 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1268 type
= img_type_iso
;
1270 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1272 type
= img_type_wim
;
1274 else if (g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1275 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1277 type
= img_type_vhd
;
1279 #ifdef GRUB_MACHINE_EFI
1280 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1282 type
= img_type_efi
;
1285 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1287 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1289 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1290 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1295 type
= img_type_img
;
1297 else if (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1299 type
= img_type_vtoy
;
1301 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1303 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1305 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1306 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1315 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1320 if (g_plugin_image_list
)
1322 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1323 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1324 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1326 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1329 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1331 debug("File %s found in image_blacklist plugin config...\n", g_img_swap_tmp_buf
);
1336 img
= grub_zalloc(sizeof(img_info
));
1340 img
->plugin_list_index
= index
;
1341 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1343 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1345 img
->size
= info
->size
;
1348 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1351 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1353 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1358 if (g_ventoy_img_list
)
1360 tail
= *(node
->tail
);
1366 g_ventoy_img_list
= img
;
1369 img
->id
= g_ventoy_img_count
;
1371 if (node
&& NULL
== node
->firstiso
)
1373 node
->firstiso
= img
;
1384 *((img_info
**)(node
->tail
)) = img
;
1385 g_ventoy_img_count
++;
1387 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1388 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1391 img
->class = g_menu_class
[type
];
1393 img
->menu_prefix
= g_menu_prefix
[type
];
1395 if (img_type_iso
== type
)
1397 if (ventoy_plugin_check_memdisk(img
->path
))
1399 img
->menu_prefix
= "miso";
1403 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1410 static int ventoy_arch_mode_init(void)
1412 #ifdef GRUB_MACHINE_EFI
1413 if (grub_strcmp(GRUB_TARGET_CPU
, "i386") == 0)
1415 g_ventoy_plat_data
= VTOY_PLAT_I386_UEFI
;
1416 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "ia32");
1418 else if (grub_strcmp(GRUB_TARGET_CPU
, "arm64") == 0)
1420 g_ventoy_plat_data
= VTOY_PLAT_ARM64_UEFI
;
1421 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "aa64");
1425 g_ventoy_plat_data
= VTOY_PLAT_X86_64_UEFI
;
1426 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "uefi");
1429 g_ventoy_plat_data
= VTOY_PLAT_X86_LEGACY
;
1430 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "legacy");
1436 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1438 int len
= GRUB_UINT_MAX
;
1439 const char *value
= NULL
;
1440 char name
[32] = {0};
1441 char plat
[32] = {0};
1442 char guidstr
[32] = {0};
1443 ventoy_guid guid
= VENTOY_GUID
;
1444 const char *fmt1
= NULL
;
1445 const char *fmt2
= NULL
;
1446 const char *fmt3
= NULL
;
1447 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1448 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1449 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1450 const char fmtcode
[]={
1451 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1452 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1453 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1454 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1455 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1456 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1459 grub_memset(name
, 0, sizeof(name
));
1460 puint
[0] = grub_swap_bytes32(0x56454e54);
1461 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1462 puint
[2] = grub_swap_bytes32(0x45525349);
1463 puint
[1] = grub_swap_bytes32(0x4f595f56);
1464 value
= ventoy_get_env(name
);
1466 grub_memset(name
, 0, sizeof(name
));
1467 puint
[1] = grub_swap_bytes32(0x5f544f50);
1468 puint
[0] = grub_swap_bytes32(0x56544c45);
1469 fmt1
= ventoy_get_env(name
);
1475 grub_memset(name
, 0, sizeof(name
));
1476 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1477 puint
[0] = grub_swap_bytes32(0x56544c45);
1478 fmt2
= ventoy_get_env(name
);
1480 grub_memset(name
, 0, sizeof(name
));
1481 puint
[1] = grub_swap_bytes32(0x5f434c52);
1482 puint
[0] = grub_swap_bytes32(0x56544c45);
1483 fmt3
= ventoy_get_env(name
);
1485 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1487 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1489 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1490 #pragma GCC diagnostic push
1491 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1492 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1493 fmt1
? fmt1
: fmtdata
,
1494 fmt2
? fmt2
: fmtdata
+ 4,
1495 value
? value
: "", plat
, guidstr
,
1496 fmt3
? fmt3
: fmtdata
+ 6);
1497 #pragma GCC diagnostic pop
1499 grub_memset(name
, 0, sizeof(name
));
1500 puint
[0] = grub_swap_bytes32(0x76746f79);
1501 puint
[2] = grub_swap_bytes32(0x656e7365);
1502 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1503 ventoy_set_env(name
, guidstr
);
1508 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1512 grub_uint8_t md5
[16];
1516 grub_memset(input
, 0, sizeof(input
));
1518 grub_printf("Enter password: ");
1521 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1523 grub_password_get(input
, 128);
1524 if (grub_strcmp(pwd
->text
, input
) == 0)
1529 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1531 grub_password_get(input
, 128);
1532 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1533 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1538 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1540 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1541 grub_password_get(input
+ offset
, 128);
1543 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1544 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1550 grub_printf("Invalid password!\n\n");
1557 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1559 img_info
*minimg
= NULL
;
1560 img_info
*img
= (img_info
*)(node
->firstiso
);
1562 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1564 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1579 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1581 img_iterator_node
*Minchild
= NULL
;
1582 img_iterator_node
*child
= node
->firstchild
;
1584 while (child
&& child
->parent
== node
)
1586 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1590 child
= child
->next
;
1595 Minchild
->select
= 1;
1601 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1604 img_info
*img
= NULL
;
1605 const char *dir_class
= NULL
;
1606 const char *dir_alias
= NULL
;
1607 img_iterator_node
*child
= NULL
;
1609 if (node
->isocnt
== 0 || node
->done
== 1)
1614 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1616 offset
= node
->parent
->dirlen
;
1619 if (node
== &g_img_iterator_head
)
1621 if (g_default_menu_mode
== 0)
1623 if (g_tree_view_menu_style
== 0)
1625 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1626 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1627 " echo 'return ...' \n"
1632 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1633 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1641 node
->dir
[node
->dirlen
- 1] = 0;
1642 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1645 dir_class
= "vtoydir";
1648 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1651 if (g_tree_view_menu_style
== 0)
1653 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1654 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1655 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1659 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1660 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1661 dir_alias
, dir_class
, node
->dir
+ offset
);
1666 dir_alias
= node
->dir
+ offset
;
1668 if (g_tree_view_menu_style
== 0)
1670 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1671 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1672 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1676 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1677 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1678 dir_alias
, dir_class
, node
->dir
+ offset
);
1682 if (g_tree_view_menu_style
== 0)
1684 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1685 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1686 " echo 'return ...' \n"
1691 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1692 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1698 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1700 ventoy_dynamic_tree_menu(child
);
1703 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1705 if (g_tree_view_menu_style
== 0)
1707 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1708 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1711 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1712 img
->unsupport
? "[***********] " : "",
1713 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1715 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1719 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1720 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1723 img
->unsupport
? "[***********] " : "",
1724 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1726 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1730 if (node
!= &g_img_iterator_head
)
1732 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1739 int ventoy_check_device_result(int ret
)
1743 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1744 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1745 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1749 grub_printf(VTOY_WARNING
"\n");
1750 grub_printf(VTOY_WARNING
"\n");
1751 grub_printf(VTOY_WARNING
"\n\n\n");
1753 grub_printf("This is NOT a standard Ventoy device and is NOT supported.\n\n");
1754 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1756 grub_printf("\n\nWill exit after 10 seconds ...... ");
1764 int ventoy_check_device(grub_device_t dev
)
1768 grub_uint64_t offset
;
1773 struct grub_partition
*partition
;
1775 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1777 return ventoy_check_device_result(1 | 0x1000);
1780 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1781 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1782 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1784 #ifndef GRUB_MACHINE_EFI
1785 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1786 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
1787 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1789 return ventoy_check_device_result(2 | 0x1000);
1798 /* We must have partition 2 */
1801 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
1805 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1809 return ventoy_check_device_result(3 | 0x1000);
1812 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1814 grub_file_close(file
);
1815 return ventoy_check_device_result(4 | 0x1000);
1818 partition
= dev
->disk
->partition
;
1819 if (partition
->number
!= 0 || partition
->start
!= 2048)
1821 return ventoy_check_device_result(5);
1826 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
1828 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
1829 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
1830 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
1832 grub_file_close(file
);
1833 return ventoy_check_device_result(6);
1838 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
1839 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
1840 PartTbl
[1].SectorCount
!= 65536)
1842 grub_file_close(file
);
1843 return ventoy_check_device_result(6);
1849 offset
= partition
->start
+ partition
->len
;
1850 partition
= file
->device
->disk
->partition
;
1851 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1853 grub_file_close(file
);
1854 return ventoy_check_device_result(7);
1858 grub_file_close(file
);
1860 if (workaround
== 0)
1862 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1863 dev2
= grub_device_open(devname
);
1866 return ventoy_check_device_result(8);
1869 fs
= grub_fs_probe(dev2
);
1872 grub_device_close(dev2
);
1873 return ventoy_check_device_result(9);
1876 fs
->fs_label(dev2
, &label
);
1877 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1879 grub_device_close(dev2
);
1880 return ventoy_check_device_result(10);
1883 grub_device_close(dev2
);
1886 return ventoy_check_device_result(0);
1889 static int ventoy_set_default_menu(void)
1895 const char *strdata
= NULL
;
1896 img_info
*cur
= NULL
;
1897 img_info
*default_node
= NULL
;
1898 const char *default_image
= NULL
;
1900 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1901 if (default_image
&& default_image
[0] == '/')
1903 img_len
= grub_strlen(default_image
);
1905 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1907 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1919 if (0 == g_default_menu_mode
)
1921 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1925 def
= grub_strdup(default_image
);
1931 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1933 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1934 if (strdata
&& strdata
[0] == '/')
1936 pos
= def
+ grub_strlen(strdata
);
1947 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1950 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1954 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1962 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1966 grub_device_t dev
= NULL
;
1967 img_info
*cur
= NULL
;
1968 img_info
*tail
= NULL
;
1969 const char *strdata
= NULL
;
1970 char *device_name
= NULL
;
1972 img_iterator_node
*node
= NULL
;
1973 img_iterator_node
*tmp
= NULL
;
1979 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1982 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1984 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1987 g_enumerate_start_time_ms
= grub_get_time_ms();
1989 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1990 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1992 g_filt_dot_underscore_file
= 1;
1995 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
1996 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1998 g_sort_case_sensitive
= 1;
2001 device_name
= grub_file_get_device_name(args
[0]);
2007 g_enum_dev
= dev
= grub_device_open(device_name
);
2013 g_enum_fs
= fs
= grub_fs_probe(dev
);
2019 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2021 debug("unsupported fs:<%s>\n", fs
->name
);
2022 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2026 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2028 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2029 if (strdata
&& strdata
[0] == '1')
2031 g_default_menu_mode
= 1;
2034 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2036 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2038 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2039 if (strdata
&& strdata
[0] == '/')
2041 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2042 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2044 g_img_iterator_head
.dir
[len
++] = '/';
2046 g_img_iterator_head
.dirlen
= len
;
2050 g_img_iterator_head
.dirlen
= 1;
2051 grub_strcpy(g_img_iterator_head
.dir
, "/");
2054 g_img_iterator_head
.tail
= &tail
;
2056 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2058 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2061 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2062 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2064 g_tree_view_menu_style
= 1;
2067 ventoy_set_default_menu();
2069 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2071 ventoy_dynamic_tree_menu(node
);
2075 node
= g_img_iterator_head
.next
;
2083 /* sort image list by image name */
2084 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2086 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2088 if (ventoy_cmp_img(cur
, tail
) > 0)
2090 ventoy_swap_img(cur
, tail
);
2095 if (g_default_menu_mode
== 1)
2097 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2098 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2099 " echo 'return ...' \n"
2103 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2105 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2106 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2109 cur
->unsupport
? "[***********] " : "",
2110 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2112 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2115 g_tree_script_buf
[g_tree_script_pos
] = 0;
2116 g_list_script_buf
[g_list_script_pos
] = 0;
2118 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2119 grub_env_set(args
[1], buf
);
2123 check_free(device_name
, grub_free
);
2124 check_free(dev
, grub_device_close
);
2126 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2130 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2132 img_info
*next
= NULL
;
2133 img_info
*cur
= g_ventoy_img_list
;
2146 g_ventoy_img_list
= NULL
;
2147 g_ventoy_img_count
= 0;
2149 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2152 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2155 img_info
*cur
= g_ventoy_img_list
;
2159 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2161 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2164 img_id
= grub_strtol(args
[0], NULL
, 10);
2165 if (img_id
>= g_ventoy_img_count
)
2167 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2170 debug("Find image %ld name \n", img_id
);
2172 while (cur
&& img_id
> 0)
2180 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2183 debug("image name is %s\n", cur
->name
);
2185 grub_env_set(args
[1], cur
->name
);
2187 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2190 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2195 const char *id
= NULL
;
2196 img_info
*cur
= g_ventoy_img_list
;
2200 if (argc
< 1 || argc
> 2)
2202 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2205 id
= grub_env_get("chosen");
2207 pos
= grub_strstr(id
, "VID_");
2210 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2214 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2219 if (img_id
== cur
->id
)
2228 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2231 grub_env_set(args
[0], cur
->path
);
2235 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2236 grub_env_set(args
[1], value
);
2239 g_svd_replace_offset
= 0;
2241 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2244 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2251 device_name
= grub_file_get_device_name(filename
);
2263 pos2
= grub_strstr(pos
, ",");
2266 pos2
= grub_strstr(pos
, ")");
2274 disk
= grub_disk_open(pos
);
2277 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2278 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2279 grub_disk_close(disk
);
2286 grub_free(device_name
);
2290 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2292 eltorito_descriptor desc
;
2294 grub_memset(&desc
, 0, sizeof(desc
));
2295 grub_file_seek(file
, 17 * 2048);
2296 grub_file_read(file
, &desc
, sizeof(desc
));
2298 if (desc
.type
!= 0 || desc
.version
!= 1)
2303 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2304 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2312 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2316 grub_uint8_t buf
[512];
2317 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2319 grub_file_seek(file
, sector
* 2048);
2320 grub_file_read(file
, buf
, sizeof(buf
));
2322 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2324 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2328 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2333 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2335 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2337 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2341 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2343 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2348 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2350 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2352 if (buf
[36] == parttype
[i
])
2354 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2360 debug("%s does not contain efi eltorito\n", file
->name
);
2364 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2367 const char *fs
= NULL
;
2368 const char *cdprompt
= NULL
;
2370 grub_uint8_t chksum
= 0;
2373 disk
= file
->device
->disk
;
2374 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2376 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2377 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2378 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2380 pos
= grub_strstr(file
->name
, "/");
2386 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2388 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2390 param
->vtoy_img_size
= file
->size
;
2392 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2393 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2395 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2397 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2398 param
->vtoy_reserved
[4] = 0;
2399 if (g_ventoy_chain_type
== 1) /* Windows */
2401 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2402 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2404 param
->vtoy_reserved
[4] = 1;
2408 fs
= ventoy_get_env("ventoy_fs_probe");
2409 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2411 param
->vtoy_reserved
[3] = 1;
2414 /* calculate checksum */
2415 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2417 chksum
+= *((grub_uint8_t
*)param
+ i
);
2419 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2424 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2426 grub_uint32_t i
= 0;
2427 grub_uint64_t total
= 0;
2428 ventoy_img_chunk
*chunk
= NULL
;
2430 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2432 chunk
= chunklist
->chunk
+ i
;
2434 if (chunk
->disk_start_sector
<= start
)
2436 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2440 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2443 if (total
!= ((file
->size
+ 511) / 512))
2445 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2452 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2456 grub_uint32_t i
= 0;
2457 grub_uint32_t sector
= 0;
2458 grub_uint32_t count
= 0;
2459 grub_off_t size
= 0;
2460 grub_off_t read
= 0;
2462 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2463 if (fs_type
== ventoy_fs_exfat
)
2465 grub_fat_get_file_chunk(start
, file
, chunklist
);
2467 else if (fs_type
== ventoy_fs_ext
)
2469 grub_ext_get_file_chunk(start
, file
, chunklist
);
2473 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2474 file
->read_hook_data
= chunklist
;
2476 for (size
= file
->size
; size
> 0; size
-= read
)
2478 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2479 grub_file_read(file
, NULL
, read
);
2482 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2484 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2485 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2488 if (ventoy_fs_udf
== fs_type
)
2490 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2492 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2493 chunklist
->chunk
[i
].img_start_sector
= sector
;
2494 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2500 len
= (int)grub_strlen(file
->name
);
2501 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2502 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2503 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2504 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2506 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2508 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2518 chunklist
->chunk
[i
].img_start_sector
= sector
;
2519 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2527 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2531 grub_disk_addr_t start
;
2536 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2539 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2542 g_conf_replace_node
= NULL
;
2543 g_conf_replace_offset
= 0;
2545 if (g_img_chunk_list
.chunk
)
2547 grub_free(g_img_chunk_list
.chunk
);
2550 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2552 grub_file_close(file
);
2553 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2556 /* get image chunk data */
2557 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2558 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2559 if (NULL
== g_img_chunk_list
.chunk
)
2561 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2564 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2565 g_img_chunk_list
.cur_chunk
= 0;
2567 start
= file
->device
->disk
->partition
->start
;
2569 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2571 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2572 grub_file_close(file
);
2576 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2579 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2580 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2583 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2585 grub_uint64_t offset
= 0;
2586 grub_uint32_t align
= 0;
2587 grub_file_t file
= NULL
;
2588 conf_replace
*node
= NULL
;
2594 debug("select conf replace argc:%d\n", argc
);
2601 node
= ventoy_plugin_find_conf_replace(args
[1]);
2604 debug("Conf replace not found for %s\n", args
[1]);
2608 debug("Find conf replace for %s\n", args
[1]);
2610 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2613 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2617 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2618 grub_file_close(file
);
2620 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2623 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2627 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2629 if (align
> vtoy_max_replace_file_size
)
2631 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2635 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2636 g_conf_replace_new_len
= (int)file
->size
;
2637 g_conf_replace_new_len_align
= align
;
2639 g_conf_replace_node
= node
;
2640 g_conf_replace_offset
= offset
+ 2;
2642 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2647 grub_file_close(file
);
2649 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2652 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2657 char configfile
[128];
2658 install_template
*node
= NULL
;
2664 debug("select auto installation argc:%d\n", argc
);
2671 node
= ventoy_plugin_find_install_template(args
[0]);
2674 debug("Auto install template not found for %s\n", args
[0]);
2678 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2680 node
->cursel
= node
->autosel
- 1;
2681 debug("Auto install template auto select %d\n", node
->autosel
);
2685 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2691 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2692 " echo %s\n}\n", "123");
2694 for (i
= 0; i
< node
->templatenum
; i
++)
2696 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2698 node
->templatepath
[i
].path
);
2701 g_ventoy_menu_esc
= 1;
2702 g_ventoy_suppress_esc
= 1;
2704 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2705 grub_script_execute_sourcecode(configfile
);
2707 g_ventoy_menu_esc
= 0;
2708 g_ventoy_suppress_esc
= 0;
2712 node
->cursel
= g_ventoy_last_entry
- 1;
2714 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2717 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2722 char configfile
[128];
2723 persistence_config
*node
;
2729 debug("select persistence argc:%d\n", argc
);
2736 node
= ventoy_plugin_find_persistent(args
[0]);
2739 debug("Persistence image not found for %s\n", args
[0]);
2743 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2745 node
->cursel
= node
->autosel
- 1;
2746 debug("Persistence image auto select %d\n", node
->autosel
);
2750 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2756 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2757 " echo %s\n}\n", "123");
2759 for (i
= 0; i
< node
->backendnum
; i
++)
2761 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2763 node
->backendpath
[i
].path
);
2767 g_ventoy_menu_esc
= 1;
2768 g_ventoy_suppress_esc
= 1;
2770 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2771 grub_script_execute_sourcecode(configfile
);
2773 g_ventoy_menu_esc
= 0;
2774 g_ventoy_suppress_esc
= 0;
2778 node
->cursel
= g_ventoy_last_entry
- 1;
2780 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2783 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2786 ventoy_img_chunk
*cur
;
2792 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2794 cur
= g_img_chunk_list
.chunk
+ i
;
2795 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2796 cur
->img_start_sector
, cur
->img_end_sector
,
2797 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2801 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2804 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2808 ventoy_img_chunk_list chunklist
;
2813 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2816 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2819 /* get image chunk data */
2820 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2821 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2822 if (NULL
== chunklist
.chunk
)
2824 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2827 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2828 chunklist
.cur_chunk
= 0;
2830 ventoy_get_block_list(file
, &chunklist
, 0);
2832 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2834 grub_printf("########## UNSUPPORTED ###############\n");
2837 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2839 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2841 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2842 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2845 grub_printf("\n==================================\n");
2847 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2849 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2850 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2851 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2852 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2853 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2857 grub_free(chunklist
.chunk
);
2858 grub_file_close(file
);
2860 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2863 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2866 ventoy_grub_param_file_replace
*replace
= NULL
;
2874 replace
= &(g_grub_param
->file_replace
);
2875 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2877 replace
->old_name_cnt
= 0;
2878 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2880 replace
->old_name_cnt
++;
2881 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2884 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2887 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2890 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2898 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2899 grub_printf("%s", g_list_script_buf
);
2903 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2904 grub_printf("%s", g_tree_script_buf
);
2910 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2912 img_info
*cur
= g_ventoy_img_list
;
2920 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
2921 grub_printf("name:<%s>\n\n", cur
->name
);
2928 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2934 ventoy_plugin_dump_injection();
2939 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2945 ventoy_plugin_dump_auto_install();
2950 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2956 ventoy_plugin_dump_persistence();
2961 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2972 if (args
[0][0] == '0')
2974 return g_ventoy_memdisk_mode
? 0 : 1;
2976 else if (args
[0][0] == '1')
2978 return g_ventoy_iso_raw
? 0 : 1;
2980 else if (args
[0][0] == '2')
2982 return g_ventoy_iso_uefi_drv
? 0 : 1;
2988 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2990 static int configfile_mode
= 0;
2991 char memfile
[128] = {0};
2998 * args[0]: 0:normal 1:configfile
2999 * args[1]: 0:list_buf 1:tree_buf
3004 debug("Invalid argc %d\n", argc
);
3008 if (args
[0][0] == '0')
3010 if (args
[1][0] == '0')
3012 grub_script_execute_sourcecode(g_list_script_buf
);
3016 grub_script_execute_sourcecode(g_tree_script_buf
);
3021 if (configfile_mode
)
3023 debug("Now already in F3 mode %d\n", configfile_mode
);
3027 if (args
[1][0] == '0')
3029 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3030 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3034 g_ventoy_last_entry
= -1;
3035 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3036 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3039 configfile_mode
= 1;
3040 grub_script_execute_sourcecode(memfile
);
3041 configfile_mode
= 0;
3047 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3058 g_ventoy_case_insensitive
= 1;
3059 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3060 g_ventoy_case_insensitive
= 0;
3066 grub_file_close(file
);
3072 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3077 const char *isopath
= NULL
;
3079 ventoy_mbr_head mbr
;
3086 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3089 isopath
= grub_env_get("vtoy_iso_part");
3092 debug("isopath is null %p\n", isopath
);
3096 debug("isopath is %s\n", isopath
);
3098 for (id
= 0; id
< 30 && (find
== 0); id
++)
3100 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3101 if (grub_strstr(isopath
, hdname
))
3103 debug("skip %s ...\n", hdname
);
3107 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3109 disk
= grub_disk_open(hdname
);
3112 debug("%s not exist\n", hdname
);
3116 grub_memset(&mbr
, 0, sizeof(mbr
));
3117 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3119 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3121 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3122 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3125 grub_env_set(args
[0], hdname
);
3129 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3133 debug("read %s failed\n", hdname
);
3136 grub_disk_close(disk
);
3142 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3153 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3156 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3159 debug("failed to open file %s\n", args
[0]);
3163 buf
= grub_malloc(len
);
3170 grub_file_read(file
, buf
, len
- 1);
3172 ventoy_get_line(buf
);
3173 ventoy_set_env(args
[1], buf
);
3177 grub_check_free(buf
);
3178 grub_file_close(file
);
3183 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3188 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3189 "0 %llu linear /dev/ventoy %llu\n",
3190 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3195 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3197 char *device_name
= NULL
;
3198 grub_device_t dev
= NULL
;
3203 g_part_list_pos
= 0;
3204 grub_env_unset("vtoy_img_part_file");
3211 device_name
= grub_file_get_device_name(args
[0]);
3214 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3218 dev
= grub_device_open(device_name
);
3221 debug("grub_device_open failed, %s\n", device_name
);
3225 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3227 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3228 grub_env_set("vtoy_img_part_file", buf
);
3232 check_free(device_name
, grub_free
);
3233 check_free(dev
, grub_device_close
);
3239 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3250 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3253 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3256 debug("failed to open file %s\n", args
[0]);
3260 buf
= grub_malloc(file
->size
+ 1);
3266 buf
[file
->size
] = 0;
3267 grub_file_read(file
, buf
, file
->size
);
3269 if (grub_strstr(buf
, args
[1]))
3276 grub_check_free(buf
);
3277 grub_file_close(file
);
3282 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3288 ventoy_iso9660_vd pvd
;
3295 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3298 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3301 debug("failed to open file %s\n", args
[0]);
3305 grub_file_seek(file
, 16 * 2048);
3306 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3307 if (len
!= sizeof(pvd
))
3309 debug("failed to read pvd %d\n", len
);
3313 grub_memset(buf
, 0, sizeof(buf
));
3314 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3315 ventoy_set_env(args
[1], buf
);
3317 grub_memset(buf
, 0, sizeof(buf
));
3318 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3319 ventoy_set_env(args
[2], buf
);
3323 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3324 ventoy_set_env(args
[3], buf
);
3327 grub_file_close(file
);
3332 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3343 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3346 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3349 debug("failed to open file %s\n", args
[0]);
3353 grub_memset(buf
, 0, sizeof(buf
));
3354 grub_file_seek(file
, 16 * 2048 + 813);
3355 len
= (int)grub_file_read(file
, buf
, 17);
3358 debug("failed to read create date %d\n", len
);
3362 ventoy_set_env(args
[1], buf
);
3365 grub_file_close(file
);
3370 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3376 ventoy_env_hook_root(1);
3381 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3387 ventoy_env_hook_root(0);
3392 #ifdef GRUB_MACHINE_EFI
3393 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3398 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3404 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3405 if (var
&& *var
== 1)
3413 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3422 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3429 int image_sector_size
;
3431 ventoy_chain_head
*chain
;
3432 ventoy_img_chunk
*chunk
;
3433 ventoy_os_param
*osparam
;
3434 ventoy_image_location
*location
;
3435 ventoy_image_disk_region
*region
;
3436 struct grub_acpi_table_header
*acpi
;
3445 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3447 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3453 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3455 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3457 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3461 img_chunk_num
= chain
->img_chunk_num
;
3463 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3464 datalen
= sizeof(ventoy_os_param
) + loclen
;
3466 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3467 acpi
= grub_zalloc(buflen
);
3473 /* Step1: Fill acpi table header */
3474 grub_memcpy(acpi
->signature
, "VTOY", 4);
3475 acpi
->length
= buflen
;
3477 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3478 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3480 acpi
->creator_id
[0] = 1;
3481 acpi
->creator_rev
= 1;
3483 /* Step2: Fill data */
3484 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3485 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3486 osparam
->vtoy_img_location_addr
= 0;
3487 osparam
->vtoy_img_location_len
= loclen
;
3488 osparam
->chksum
= 0;
3489 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3491 location
= (ventoy_image_location
*)(osparam
+ 1);
3492 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3493 location
->image_sector_size
= image_sector_size
;
3494 location
->disk_sector_size
= chain
->disk_sector_size
;
3495 location
->region_count
= img_chunk_num
;
3497 region
= location
->regions
;
3498 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3499 if (512 == image_sector_size
)
3501 for (i
= 0; i
< img_chunk_num
; i
++)
3503 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3504 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3505 region
->disk_start_sector
= chunk
->disk_start_sector
;
3512 for (i
= 0; i
< img_chunk_num
; i
++)
3514 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3515 region
->image_start_sector
= chunk
->img_start_sector
;
3516 region
->disk_start_sector
= chunk
->disk_start_sector
;
3522 /* Step3: Fill acpi checksum */
3524 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3526 /* load acpi table */
3527 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3528 grub_script_execute_sourcecode(cmd
);
3532 VENTOY_CMD_RETURN(0);
3535 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3541 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3542 g_ventoy_last_entry
= -1;
3547 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3553 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3558 grub_uint64_t
ventoy_get_part1_size(ventoy_gpt_info
*gpt
)
3560 grub_uint64_t sectors
;
3562 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3564 sectors
= gpt
->PartTbl
[0].LastLBA
+ 1 - gpt
->PartTbl
[0].StartLBA
;
3568 sectors
= gpt
->MBR
.PartTbl
[0].SectorCount
;
3571 return sectors
* 512;
3574 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3576 const char *pos
= filename
+ 1;
3584 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3586 grub_strncpy((char *)data
, filename
, 128);
3597 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3600 char *device_name
= NULL
;
3601 grub_device_t dev
= NULL
;
3602 grub_fs_t fs
= NULL
;
3603 char buf
[128] = {0};
3609 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3613 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3615 device_name
= grub_file_get_device_name(args
[0]);
3618 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3622 dev
= grub_device_open(device_name
);
3625 debug("grub_device_open failed, %s\n", device_name
);
3629 fs
= grub_fs_probe(dev
);
3632 debug("grub_fs_probe failed, %s\n", device_name
);
3636 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3640 ventoy_set_env(args
[2], buf
);
3647 check_free(device_name
, grub_free
);
3648 check_free(dev
, grub_device_close
);
3653 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3663 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3664 if (!g_ventoy_part_info
)
3669 disk
= grub_disk_open(args
[0]);
3672 debug("Failed to open disk %s\n", args
[0]);
3676 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
3678 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3679 grub_disk_close(disk
);
3681 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3682 dev
= grub_device_open(name
);
3685 /* make sure that we are running in a correct Ventoy device */
3686 ret
= ventoy_check_device(dev
);
3687 grub_device_close(dev
);
3698 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3701 const char *vcfg
= NULL
;
3706 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
3709 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
3710 grub_env_set(args
[1], vcfg
);
3715 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
3723 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3726 grub_uint8_t zeroguid
[16] = {0};
3731 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3734 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3736 if (id
>= 1 && id
<= 128)
3738 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3746 if (id
>= 1 && id
<= 4)
3748 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3758 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3761 char *device_name
= NULL
;
3762 grub_device_t dev
= NULL
;
3763 grub_fs_t fs
= NULL
;
3770 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3774 device_name
= grub_file_get_device_name(args
[0]);
3777 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3781 dev
= grub_device_open(device_name
);
3784 debug("grub_device_open failed, %s\n", device_name
);
3788 fs
= grub_fs_probe(dev
);
3791 debug("grub_fs_probe failed, %s\n", device_name
);
3795 fs
->fs_label(dev
, &label
);
3798 ventoy_set_env(args
[1], label
);
3806 check_free(device_name
, grub_free
);
3807 check_free(dev
, grub_device_close
);
3812 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3816 grub_snprintf((char *)data
, 256, "%s", filename
);
3824 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3827 char *device_name
= NULL
;
3828 grub_device_t dev
= NULL
;
3829 grub_fs_t fs
= NULL
;
3830 char name
[256] ={0};
3836 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3840 device_name
= grub_file_get_device_name(args
[0]);
3843 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3847 dev
= grub_device_open(device_name
);
3850 debug("grub_device_open failed, %s\n", device_name
);
3854 fs
= grub_fs_probe(dev
);
3857 debug("grub_fs_probe failed, %s\n", device_name
);
3861 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3864 ventoy_set_env(args
[2], name
);
3871 check_free(device_name
, grub_free
);
3872 check_free(dev
, grub_device_close
);
3877 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3887 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3891 for (pos
= args
[0]; *pos
; pos
++)
3905 grub_env_set(args
[1], args
[0]);
3915 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3925 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
3930 len
= (int)grub_strlen(buf
);
3931 for (i
= len
; i
> 0; i
--)
3933 if (buf
[i
- 1] == '/')
3935 grub_env_set(args
[1], buf
+ i
);
3940 grub_env_set(args
[1], buf
);
3945 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3947 struct grub_video_mode_info info
;
3954 if (!g_video_mode_list
)
3956 ventoy_enum_video_mode();
3959 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3961 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3965 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3968 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3970 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3971 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3973 VENTOY_CMD_RETURN(0);
3976 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3978 struct grub_video_mode_info info
;
3985 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3987 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3991 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3994 grub_env_set(args
[0], buf
);
3996 VENTOY_CMD_RETURN(0);
3999 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4007 if (!g_video_mode_list
)
4012 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4013 if (id
< g_video_mode_num
)
4015 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4016 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4019 grub_env_set(args
[1], buf
);
4021 VENTOY_CMD_RETURN(0);
4024 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
4026 grub_uint64_t size
= 0;
4029 char fullpath
[256] = {0};
4032 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4035 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
4038 debug("grub_file_open failed <%s>\n", fullpath
);
4044 grub_file_close(file
);
4048 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
4052 char fullpath
[256] = {0};
4055 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4058 file
= grub_file_open(fullpath
, type
);
4061 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
4068 int ventoy_is_file_exist(const char *fmt
, ...)
4073 char buf
[256] = {0};
4075 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
4079 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4082 grub_strncpy(pos
+ len
, "\" ]", 3);
4084 debug("script exec %s\n", buf
);
4086 if (0 == grub_script_execute_sourcecode(buf
))
4094 int ventoy_is_dir_exist(const char *fmt
, ...)
4099 char buf
[256] = {0};
4101 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
4105 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4108 grub_strncpy(pos
+ len
, "\" ]", 3);
4110 debug("script exec %s\n", buf
);
4112 if (0 == grub_script_execute_sourcecode(buf
))
4120 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
4123 grub_uint8_t
*outbuf
;
4124 grub_uint8_t gzHdr
[10] =
4126 0x1F, 0x8B, /* magic */
4129 0,0,0,0, /* mtime */
4134 grub_memset(&s
, 0, sizeof(mz_stream
));
4136 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
4138 outbuf
= (grub_uint8_t
*)mem_out
;
4140 mem_out_len
-= sizeof(gzHdr
) + 8;
4141 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
4142 outbuf
+= sizeof(gzHdr
);
4144 s
.avail_in
= mem_in_len
;
4147 s
.avail_out
= mem_out_len
;
4148 s
.next_out
= outbuf
;
4150 mz_deflate(&s
, MZ_FINISH
);
4154 outbuf
+= s
.total_out
;
4155 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
4156 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
4158 return s
.total_out
+ sizeof(gzHdr
) + 8;
4161 static int ventoy_env_init(void)
4165 grub_env_set("vtdebug_flag", "");
4167 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4168 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4169 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4170 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4172 ventoy_filt_register(0, ventoy_wrapper_open
);
4174 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4177 g_grub_param
->grub_env_get
= grub_env_get
;
4178 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4179 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4180 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4181 grub_env_set("env_param", buf
);
4182 grub_env_set("ventoy_env_param", buf
);
4183 grub_env_export("ventoy_env_param");
4189 static cmd_para ventoy_cmds
[] =
4191 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4192 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4193 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4194 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4195 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4196 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4197 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4198 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4199 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4200 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4201 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4202 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4203 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4204 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4205 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4206 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4207 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4208 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4209 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4210 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4211 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4212 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4213 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4215 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4216 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4217 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4218 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4219 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4220 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4221 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4223 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4224 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4225 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4226 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4227 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4228 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4229 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4230 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4231 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4234 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4235 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4236 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4237 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4238 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4239 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4240 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4241 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4242 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4243 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4244 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4246 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4247 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4248 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4249 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4250 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4251 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4253 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4254 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4255 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4256 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4257 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4258 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4259 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4260 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4261 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4262 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4264 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4265 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4266 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4267 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4268 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4269 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4270 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4271 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4273 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4274 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4275 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4278 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4279 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4280 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4282 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4283 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4284 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4287 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4288 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4289 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4290 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4291 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4292 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4293 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4294 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4295 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4296 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4298 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4299 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4300 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4301 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4307 GRUB_MOD_INIT(ventoy
)
4310 cmd_para
*cur
= NULL
;
4314 ventoy_arch_mode_init();
4316 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4318 cur
= ventoy_cmds
+ i
;
4319 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4320 cur
->summary
, cur
->description
, cur
->parser
);
4324 GRUB_MOD_FINI(ventoy
)
4328 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4330 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);