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 int g_img_max_search_level
= -1;
78 img_iterator_node g_img_iterator_head
;
79 img_iterator_node
*g_img_iterator_tail
= NULL
;
81 grub_uint8_t g_ventoy_break_level
= 0;
82 grub_uint8_t g_ventoy_debug_level
= 0;
83 grub_uint8_t g_ventoy_chain_type
= 0;
85 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
86 grub_uint32_t g_ventoy_cpio_size
= 0;
87 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
88 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
90 int g_plugin_image_list
= 0;
92 ventoy_grub_param
*g_grub_param
= NULL
;
94 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
96 ventoy_img_chunk_list g_img_chunk_list
;
98 int g_wimboot_enable
= 0;
99 ventoy_img_chunk_list g_wimiso_chunk_list
;
100 char *g_wimiso_path
= NULL
;
102 int g_vhdboot_enable
= 0;
104 grub_uint64_t g_conf_replace_offset
= 0;
105 grub_uint64_t g_svd_replace_offset
= 0;
106 conf_replace
*g_conf_replace_node
= NULL
;
107 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
108 int g_conf_replace_new_len
= 0;
109 int g_conf_replace_new_len_align
= 0;
111 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
112 grub_uint64_t g_ventoy_disk_size
= 0;
114 static char *g_tree_script_buf
= NULL
;
115 static int g_tree_script_pos
= 0;
117 static char *g_list_script_buf
= NULL
;
118 static int g_list_script_pos
= 0;
120 static char *g_part_list_buf
= NULL
;
121 static int g_part_list_pos
= 0;
123 static int g_video_mode_max
= 0;
124 static int g_video_mode_num
= 0;
125 static ventoy_video_mode
*g_video_mode_list
= NULL
;
127 static int g_enumerate_time_checked
= 0;
128 static grub_uint64_t g_enumerate_start_time_ms
;
129 static grub_uint64_t g_enumerate_finish_time_ms
;
130 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
132 static const char *g_menu_class
[] =
134 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
137 static const char *g_menu_prefix
[] =
139 "iso", "wim", "efi", "img", "vhd", "vtoy"
142 void ventoy_debug(const char *fmt
, ...)
146 va_start (args
, fmt
);
147 grub_vprintf (fmt
, args
);
151 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
161 for (i
= 0; i
< 16; i
++)
163 grub_printf("%02x ", guid
[i
]);
168 int ventoy_is_efi_os(void)
172 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
178 static int ventoy_get_fs_type(const char *fs
)
182 return ventoy_fs_max
;
184 else if (grub_strncmp(fs
, "exfat", 5) == 0)
186 return ventoy_fs_exfat
;
188 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
190 return ventoy_fs_ntfs
;
192 else if (grub_strncmp(fs
, "ext", 3) == 0)
194 return ventoy_fs_ext
;
196 else if (grub_strncmp(fs
, "xfs", 3) == 0)
198 return ventoy_fs_xfs
;
200 else if (grub_strncmp(fs
, "udf", 3) == 0)
202 return ventoy_fs_udf
;
204 else if (grub_strncmp(fs
, "fat", 3) == 0)
206 return ventoy_fs_fat
;
209 return ventoy_fs_max
;
212 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
231 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
233 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
237 static int ventoy_control_get_flag(const char *key
)
239 const char *val
= ventoy_get_env(key
);
241 if (val
&& val
[0] == '1' && val
[1] == 0)
248 static grub_err_t
ventoy_fs_close(grub_file_t file
)
250 grub_file_close(g_old_file
);
251 grub_free(file
->data
);
259 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
265 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
270 for (i
= 0; i
< g_video_mode_num
; i
++)
272 if (g_video_mode_list
[i
].width
== info
->width
&&
273 g_video_mode_list
[i
].height
== info
->height
&&
274 g_video_mode_list
[i
].bpp
== info
->bpp
)
280 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
281 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
282 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
285 if (g_video_mode_num
== g_video_mode_max
)
287 g_video_mode_max
*= 2;
288 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
294 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
296 if (v1
->bpp
== v2
->bpp
)
298 if (v1
->width
== v2
->width
)
300 if (v1
->height
== v2
->height
)
306 return (v1
->height
< v2
->height
) ? -1 : 1;
311 return (v1
->width
< v2
->width
) ? -1 : 1;
316 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
320 static int ventoy_enum_video_mode(void)
323 grub_video_adapter_t adapter
;
324 grub_video_driver_id_t id
;
325 ventoy_video_mode mode
;
327 g_video_mode_num
= 0;
328 g_video_mode_max
= 1024;
329 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
330 if (!g_video_mode_list
)
335 #ifdef GRUB_MACHINE_PCBIOS
336 grub_dl_load ("vbe");
339 id
= grub_video_get_driver_id ();
341 FOR_VIDEO_ADAPTERS (adapter
)
343 if (!adapter
->iterate
||
344 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
345 adapter
->init() != GRUB_ERR_NONE
)))
350 adapter
->iterate(ventoy_video_hook
, NULL
);
352 if (adapter
->id
!= id
)
358 /* sort video mode */
359 for (i
= 0; i
< g_video_mode_num
; i
++)
360 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
362 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
364 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
365 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
366 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
370 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
373 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
377 static struct grub_fs vtoy_fs
=
382 .fs_read
= ventoy_fs_read
,
383 .fs_close
= ventoy_fs_close
,
393 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
399 file
->data
= grub_malloc(rawFile
->size
+ 4096);
405 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
406 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
408 g_old_file
= rawFile
;
410 file
->size
= rawFile
->size
+ len
;
411 file
->device
= rawFile
->device
;
413 file
->not_easily_seekable
= 1;
418 static int ventoy_check_decimal_var(const char *name
, long *value
)
420 const char *value_str
= NULL
;
422 value_str
= grub_env_get(name
);
423 if (NULL
== value_str
)
425 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
428 if (!ventoy_is_decimal(value_str
))
430 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
433 *value
= grub_strtol(value_str
, NULL
, 10);
435 return GRUB_ERR_NONE
;
438 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
442 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
445 if (0 == grub_strcmp(args
[0], "on"))
448 grub_env_set("vtdebug_flag", "debug");
453 grub_env_set("vtdebug_flag", "");
456 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
459 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
463 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
465 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
466 grub_printf(" level:\r\n");
467 grub_printf(" 01/11: busybox / (+cat log)\r\n");
468 grub_printf(" 02/12: initrd / (+cat log)\r\n");
469 grub_printf(" 03/13: hook / (+cat log)\r\n");
471 grub_printf(" debug:\r\n");
472 grub_printf(" 0: debug is off\r\n");
473 grub_printf(" 1: debug is on\r\n");
475 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
478 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
480 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
482 g_ventoy_debug_level
= 1;
485 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
488 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
497 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
500 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
532 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
537 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
539 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
542 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
547 value_long
+= grub_strtol(args
[1], NULL
, 10);
549 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
550 grub_env_set(args
[0], buf
);
552 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
555 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
557 ulonglong value1
= 0;
558 ulonglong value2
= 0;
563 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
566 value1
= grub_strtoull(args
[0], NULL
, 10);
567 value2
= grub_strtoull(args
[1], NULL
, 10);
569 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
570 grub_env_set(args
[2], buf
);
572 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
575 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
590 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
593 debug("failed to open file <%s> for udf check\n", args
[0]);
597 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
599 grub_env_set(args
[1], buf
);
601 grub_file_close(file
);
607 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
615 g_wimboot_enable
= 0;
616 grub_check_free(g_wimiso_path
);
617 grub_check_free(g_wimiso_chunk_list
.chunk
);
619 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
625 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
626 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
627 if (NULL
== g_wimiso_chunk_list
.chunk
)
629 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
632 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
633 g_wimiso_chunk_list
.cur_chunk
= 0;
635 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
637 g_wimboot_enable
= 1;
638 g_wimiso_path
= grub_strdup(args
[0]);
640 grub_file_close(file
);
645 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
651 grub_uint32_t offset
;
653 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
656 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
660 len
= (int)file
->size
;
662 data
= (char *)grub_malloc(file
->size
);
668 grub_file_read(file
, data
, file
->size
);
669 grub_file_close(file
);
671 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
672 grub_script_execute_sourcecode(exec
);
674 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
675 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
676 grub_file_close(file
);
678 grub_script_execute_sourcecode("loopback -d efiboot");
682 *direntoff
= offset
+ 2;
687 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
697 ventoy_iso9660_override
*dirent
;
706 totlen
= sizeof(ventoy_chain_head
);
708 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
710 debug("failed to load efiboot template %d\n", len
);
716 debug("efiboot template len:%d offset:%d\n", len
, offset
);
718 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
721 debug("failed to open file <%s>\n", args
[0]);
725 totlen
+= ventoy_align_2k(file
->size
);
727 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
728 dirent
->first_sector
= len
/ 2048;
729 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
730 dirent
->size
= (grub_uint32_t
)file
->size
;
731 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
733 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
735 #ifdef GRUB_MACHINE_EFI
736 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
738 data
= (char *)grub_malloc(totlen
);
741 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
743 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
744 grub_check_free(buf
);
746 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
747 grub_file_close(file
);
749 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
750 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
751 grub_env_set(name
, value
);
753 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
754 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
755 grub_env_set(name
, value
);
760 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
777 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
780 debug("failed to open file <%s>\n", args
[0]);
784 #ifdef GRUB_MACHINE_EFI
785 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
787 buf
= (char *)grub_malloc(file
->size
);
790 grub_file_read(file
, buf
, file
->size
);
792 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
793 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
794 grub_env_set(name
, value
);
796 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
797 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
798 grub_env_set(name
, value
);
800 grub_file_close(file
);
806 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
824 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
827 debug("failed to open file <%s> for udf check\n", args
[0]);
831 headlen
= sizeof(ventoy_chain_head
);
833 #ifdef GRUB_MACHINE_EFI
834 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
836 buf
= (char *)grub_malloc(headlen
+ file
->size
);
839 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
841 grub_file_read(file
, buf
+ headlen
, file
->size
);
843 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
844 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
845 grub_env_set(name
, value
);
847 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
848 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
849 grub_env_set(name
, value
);
851 grub_file_close(file
);
857 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
866 if (args
[0][0] == '1')
868 grub_iso9660_set_nojoliet(1);
872 grub_iso9660_set_nojoliet(0);
878 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
883 grub_uint8_t buf
[32];
894 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
897 debug("failed to open file <%s> for udf check\n", args
[0]);
901 for (i
= 16; i
< 32; i
++)
903 grub_file_seek(file
, i
* 2048);
904 grub_file_read(file
, buf
, sizeof(buf
));
912 grub_file_seek(file
, i
* 2048);
913 grub_file_read(file
, buf
, sizeof(buf
));
915 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
918 grub_file_seek(file
, i
* 2048);
919 grub_file_read(file
, buf
, sizeof(buf
));
921 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
922 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
928 grub_file_close(file
);
930 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
935 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
937 long value_long1
= 0;
938 long value_long2
= 0;
940 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
942 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
945 value_long1
= grub_strtol(args
[0], NULL
, 10);
946 value_long2
= grub_strtol(args
[2], NULL
, 10);
948 if (0 == grub_strcmp(args
[1], "eq"))
950 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
952 else if (0 == grub_strcmp(args
[1], "ne"))
954 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
956 else if (0 == grub_strcmp(args
[1], "gt"))
958 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
960 else if (0 == grub_strcmp(args
[1], "lt"))
962 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
964 else if (0 == grub_strcmp(args
[1], "ge"))
966 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
968 else if (0 == grub_strcmp(args
[1], "le"))
970 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
974 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
980 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
987 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
990 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
991 pos
= grub_strstr(buf
, ",");
997 grub_env_set(args
[1], buf
);
999 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1002 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1008 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1014 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1017 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1019 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1020 if (0 == grub_script_execute_sourcecode(buf
))
1022 debug("file %s exist, ventoy_compatible YES\n", buf
);
1023 grub_env_set("ventoy_compatible", "YES");
1024 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1028 debug("file %s NOT exist\n", buf
);
1032 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1033 pos
= grub_strstr(buf
, ")");
1039 disk
= grub_disk_open(buf
);
1042 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1043 grub_disk_close(disk
);
1045 g_img_swap_tmp_buf
[703] = 0;
1046 for (i
= 318; i
< 703; i
++)
1048 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1049 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1051 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1052 grub_env_set("ventoy_compatible", "YES");
1053 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1059 debug("failed to open disk <%s>\n", buf
);
1062 grub_env_set("ventoy_compatible", "NO");
1063 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1066 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1072 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1074 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1077 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1082 if (0 == g_sort_case_sensitive
)
1084 if (grub_islower(c1
))
1086 c1
= c1
- 'a' + 'A';
1089 if (grub_islower(c2
))
1091 c2
= c2
- 'a' + 'A';
1104 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1110 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1112 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1115 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1120 if (0 == g_sort_case_sensitive
)
1122 if (grub_islower(c1
))
1124 c1
= c1
- 'a' + 'A';
1127 if (grub_islower(c2
))
1129 c2
= c2
- 'a' + 'A';
1142 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1144 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1146 grub_memcpy(img1
, img2
, sizeof(img_info
));
1147 img1
->next
= g_img_swap_tmp
.next
;
1148 img1
->prev
= g_img_swap_tmp
.prev
;
1150 g_img_swap_tmp
.next
= img2
->next
;
1151 g_img_swap_tmp
.prev
= img2
->prev
;
1152 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1155 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1159 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1167 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1171 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1181 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1190 img_iterator_node
*tmp
;
1191 img_iterator_node
*new_node
;
1192 img_iterator_node
*node
= (img_iterator_node
*)data
;
1194 if (g_enumerate_time_checked
== 0)
1196 g_enumerate_finish_time_ms
= grub_get_time_ms();
1197 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1200 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1202 g_enumerate_time_checked
= 1;
1206 len
= grub_strlen(filename
);
1210 if (node
->level
+ 1 > g_img_max_search_level
)
1215 if ((len
== 1 && filename
[0] == '.') ||
1216 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1221 if (!ventoy_img_name_valid(filename
, len
))
1226 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1231 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1233 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1234 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1237 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1242 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1245 new_node
->level
= node
->level
+ 1;
1246 new_node
->plugin_list_index
= index
;
1247 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1249 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1252 debug("Directory %s ignored...\n", new_node
->dir
);
1253 grub_free(new_node
);
1257 new_node
->tail
= node
->tail
;
1259 new_node
->parent
= node
;
1260 if (!node
->firstchild
)
1262 node
->firstchild
= new_node
;
1265 if (g_img_iterator_tail
)
1267 g_img_iterator_tail
->next
= new_node
;
1268 g_img_iterator_tail
= new_node
;
1272 g_img_iterator_head
.next
= new_node
;
1273 g_img_iterator_tail
= new_node
;
1279 debug("Find a file %s\n", filename
);
1285 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1287 type
= img_type_iso
;
1289 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1291 type
= img_type_wim
;
1293 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1294 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1296 type
= img_type_vhd
;
1298 #ifdef GRUB_MACHINE_EFI
1299 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1301 type
= img_type_efi
;
1304 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1306 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1308 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1309 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1314 type
= img_type_img
;
1316 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1318 type
= img_type_vtoy
;
1320 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1322 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1324 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1325 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1334 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1339 if (g_plugin_image_list
)
1341 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1342 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1343 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1345 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1348 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1350 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1355 img
= grub_zalloc(sizeof(img_info
));
1359 img
->plugin_list_index
= index
;
1360 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1362 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1364 img
->size
= info
->size
;
1367 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1370 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1372 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1377 if (g_ventoy_img_list
)
1379 tail
= *(node
->tail
);
1385 g_ventoy_img_list
= img
;
1388 img
->id
= g_ventoy_img_count
;
1390 if (node
&& NULL
== node
->firstiso
)
1392 node
->firstiso
= img
;
1403 *((img_info
**)(node
->tail
)) = img
;
1404 g_ventoy_img_count
++;
1406 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1407 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1410 img
->class = g_menu_class
[type
];
1412 img
->menu_prefix
= g_menu_prefix
[type
];
1414 if (img_type_iso
== type
)
1416 if (ventoy_plugin_check_memdisk(img
->path
))
1418 img
->menu_prefix
= "miso";
1422 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1429 static int ventoy_arch_mode_init(void)
1431 #ifdef GRUB_MACHINE_EFI
1432 if (grub_strcmp(GRUB_TARGET_CPU
, "i386") == 0)
1434 g_ventoy_plat_data
= VTOY_PLAT_I386_UEFI
;
1435 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "ia32");
1437 else if (grub_strcmp(GRUB_TARGET_CPU
, "arm64") == 0)
1439 g_ventoy_plat_data
= VTOY_PLAT_ARM64_UEFI
;
1440 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "aa64");
1442 else if (grub_strcmp(GRUB_TARGET_CPU
, "mips64el") == 0)
1444 g_ventoy_plat_data
= VTOY_PLAT_MIPS_UEFI
;
1445 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "mips");
1449 g_ventoy_plat_data
= VTOY_PLAT_X86_64_UEFI
;
1450 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "uefi");
1453 g_ventoy_plat_data
= VTOY_PLAT_X86_LEGACY
;
1454 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "legacy");
1460 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1462 int len
= GRUB_UINT_MAX
;
1463 const char *value
= NULL
;
1464 char name
[32] = {0};
1465 char plat
[32] = {0};
1466 char guidstr
[32] = {0};
1467 ventoy_guid guid
= VENTOY_GUID
;
1468 const char *fmt1
= NULL
;
1469 const char *fmt2
= NULL
;
1470 const char *fmt3
= NULL
;
1471 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1472 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1473 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1474 const char fmtcode
[]={
1475 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1476 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1477 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1478 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1479 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1480 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1483 grub_memset(name
, 0, sizeof(name
));
1484 puint
[0] = grub_swap_bytes32(0x56454e54);
1485 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1486 puint
[2] = grub_swap_bytes32(0x45525349);
1487 puint
[1] = grub_swap_bytes32(0x4f595f56);
1488 value
= ventoy_get_env(name
);
1490 grub_memset(name
, 0, sizeof(name
));
1491 puint
[1] = grub_swap_bytes32(0x5f544f50);
1492 puint
[0] = grub_swap_bytes32(0x56544c45);
1493 fmt1
= ventoy_get_env(name
);
1499 grub_memset(name
, 0, sizeof(name
));
1500 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1501 puint
[0] = grub_swap_bytes32(0x56544c45);
1502 fmt2
= ventoy_get_env(name
);
1504 grub_memset(name
, 0, sizeof(name
));
1505 puint
[1] = grub_swap_bytes32(0x5f434c52);
1506 puint
[0] = grub_swap_bytes32(0x56544c45);
1507 fmt3
= ventoy_get_env(name
);
1509 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1511 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1513 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1514 #pragma GCC diagnostic push
1515 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1516 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1517 fmt1
? fmt1
: fmtdata
,
1518 fmt2
? fmt2
: fmtdata
+ 4,
1519 value
? value
: "", plat
, guidstr
,
1520 fmt3
? fmt3
: fmtdata
+ 6);
1521 #pragma GCC diagnostic pop
1523 grub_memset(name
, 0, sizeof(name
));
1524 puint
[0] = grub_swap_bytes32(0x76746f79);
1525 puint
[2] = grub_swap_bytes32(0x656e7365);
1526 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1527 ventoy_set_env(name
, guidstr
);
1532 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1536 grub_uint8_t md5
[16];
1540 grub_memset(input
, 0, sizeof(input
));
1542 grub_printf("Enter password: ");
1545 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1547 grub_password_get(input
, 128);
1548 if (grub_strcmp(pwd
->text
, input
) == 0)
1553 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1555 grub_password_get(input
, 128);
1556 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1557 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1562 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1564 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1565 grub_password_get(input
+ offset
, 128);
1567 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1568 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1574 grub_printf("Invalid password!\n\n");
1581 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1583 img_info
*minimg
= NULL
;
1584 img_info
*img
= (img_info
*)(node
->firstiso
);
1586 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1588 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1603 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1605 img_iterator_node
*Minchild
= NULL
;
1606 img_iterator_node
*child
= node
->firstchild
;
1608 while (child
&& child
->parent
== node
)
1610 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1614 child
= child
->next
;
1619 Minchild
->select
= 1;
1625 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1628 img_info
*img
= NULL
;
1629 const char *dir_class
= NULL
;
1630 const char *dir_alias
= NULL
;
1631 img_iterator_node
*child
= NULL
;
1633 if (node
->isocnt
== 0 || node
->done
== 1)
1638 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1640 offset
= node
->parent
->dirlen
;
1643 if (node
== &g_img_iterator_head
)
1645 if (g_default_menu_mode
== 0)
1647 if (g_tree_view_menu_style
== 0)
1649 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1650 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1651 " echo 'return ...' \n"
1656 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1657 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1665 node
->dir
[node
->dirlen
- 1] = 0;
1666 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1669 dir_class
= "vtoydir";
1672 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1675 if (g_tree_view_menu_style
== 0)
1677 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1678 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1679 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1683 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1684 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1685 dir_alias
, dir_class
, node
->dir
+ offset
);
1690 dir_alias
= node
->dir
+ offset
;
1692 if (g_tree_view_menu_style
== 0)
1694 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1695 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1696 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1700 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1701 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1702 dir_alias
, dir_class
, node
->dir
+ offset
);
1706 if (g_tree_view_menu_style
== 0)
1708 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1709 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1710 " echo 'return ...' \n"
1715 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1716 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1722 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1724 ventoy_dynamic_tree_menu(child
);
1727 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1729 if (g_tree_view_menu_style
== 0)
1731 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1732 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1735 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1736 img
->unsupport
? "[***********] " : "",
1737 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1739 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1743 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1744 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1747 img
->unsupport
? "[***********] " : "",
1748 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1750 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1754 if (node
!= &g_img_iterator_head
)
1756 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1763 int ventoy_check_device_result(int ret
)
1767 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1768 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1769 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1773 grub_printf(VTOY_WARNING
"\n");
1774 grub_printf(VTOY_WARNING
"\n");
1775 grub_printf(VTOY_WARNING
"\n\n\n");
1777 grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret
);
1778 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1780 grub_printf("\n\nWill exit after 10 seconds ...... ");
1788 int ventoy_check_device(grub_device_t dev
)
1792 grub_uint64_t offset
;
1797 struct grub_partition
*partition
;
1799 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1801 return ventoy_check_device_result(1 | 0x1000);
1804 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1805 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1806 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1808 #ifndef GRUB_MACHINE_EFI
1809 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1810 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
1811 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1813 return ventoy_check_device_result(2 | 0x1000);
1822 /* We must have partition 2 */
1825 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
1829 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1833 return ventoy_check_device_result(3 | 0x1000);
1836 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1838 grub_file_close(file
);
1839 return ventoy_check_device_result(4 | 0x1000);
1842 partition
= dev
->disk
->partition
;
1843 if (partition
->number
!= 0 || partition
->start
!= 2048)
1845 return ventoy_check_device_result(5);
1850 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
1852 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
1853 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
1854 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
1856 grub_file_close(file
);
1857 return ventoy_check_device_result(6);
1862 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
1863 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
1864 PartTbl
[1].SectorCount
!= 65536)
1866 grub_file_close(file
);
1867 return ventoy_check_device_result(6);
1873 offset
= partition
->start
+ partition
->len
;
1874 partition
= file
->device
->disk
->partition
;
1875 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1877 grub_file_close(file
);
1878 return ventoy_check_device_result(7);
1882 grub_file_close(file
);
1884 if (workaround
== 0)
1886 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1887 dev2
= grub_device_open(devname
);
1890 return ventoy_check_device_result(8);
1893 fs
= grub_fs_probe(dev2
);
1896 grub_device_close(dev2
);
1897 return ventoy_check_device_result(9);
1900 fs
->fs_label(dev2
, &label
);
1901 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1903 grub_device_close(dev2
);
1904 return ventoy_check_device_result(10);
1907 grub_device_close(dev2
);
1910 return ventoy_check_device_result(0);
1913 static int ventoy_set_default_menu(void)
1919 const char *strdata
= NULL
;
1920 img_info
*cur
= NULL
;
1921 img_info
*default_node
= NULL
;
1922 const char *default_image
= NULL
;
1924 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1925 if (default_image
&& default_image
[0] == '/')
1927 img_len
= grub_strlen(default_image
);
1929 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1931 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1943 if (0 == g_default_menu_mode
)
1945 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1949 def
= grub_strdup(default_image
);
1955 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1957 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1958 if (strdata
&& strdata
[0] == '/')
1960 pos
= def
+ grub_strlen(strdata
);
1971 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1974 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1978 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1986 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1990 grub_device_t dev
= NULL
;
1991 img_info
*cur
= NULL
;
1992 img_info
*tail
= NULL
;
1993 const char *strdata
= NULL
;
1994 char *device_name
= NULL
;
1996 img_iterator_node
*node
= NULL
;
1997 img_iterator_node
*tmp
= NULL
;
2003 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2006 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2008 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2011 g_enumerate_time_checked
= 0;
2012 g_enumerate_start_time_ms
= grub_get_time_ms();
2014 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2015 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2017 g_filt_dot_underscore_file
= 1;
2020 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2021 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2023 g_sort_case_sensitive
= 1;
2026 device_name
= grub_file_get_device_name(args
[0]);
2032 g_enum_dev
= dev
= grub_device_open(device_name
);
2038 g_enum_fs
= fs
= grub_fs_probe(dev
);
2044 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2046 debug("unsupported fs:<%s>\n", fs
->name
);
2047 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2051 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2053 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2054 if (strdata
&& strdata
[0] == '1')
2056 g_default_menu_mode
= 1;
2059 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2061 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2063 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2064 if (strdata
&& strdata
[0] == '/')
2066 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2067 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2069 g_img_iterator_head
.dir
[len
++] = '/';
2071 g_img_iterator_head
.dirlen
= len
;
2075 g_img_iterator_head
.dirlen
= 1;
2076 grub_strcpy(g_img_iterator_head
.dir
, "/");
2079 g_img_iterator_head
.tail
= &tail
;
2081 if (g_img_max_search_level
< 0)
2083 g_img_max_search_level
= GRUB_INT_MAX
;
2084 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2085 if (strdata
&& ventoy_is_decimal(strdata
))
2087 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2091 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2092 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2093 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2094 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2095 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2096 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2098 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2100 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2103 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2104 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2106 g_tree_view_menu_style
= 1;
2109 ventoy_set_default_menu();
2111 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2113 ventoy_dynamic_tree_menu(node
);
2117 node
= g_img_iterator_head
.next
;
2125 /* sort image list by image name */
2126 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2128 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2130 if (ventoy_cmp_img(cur
, tail
) > 0)
2132 ventoy_swap_img(cur
, tail
);
2137 if (g_default_menu_mode
== 1)
2139 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2140 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2141 " echo 'return ...' \n"
2145 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2147 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2148 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2151 cur
->unsupport
? "[***********] " : "",
2152 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2154 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2157 g_tree_script_buf
[g_tree_script_pos
] = 0;
2158 g_list_script_buf
[g_list_script_pos
] = 0;
2160 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2161 grub_env_set(args
[1], buf
);
2165 check_free(device_name
, grub_free
);
2166 check_free(dev
, grub_device_close
);
2168 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2172 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2174 img_info
*next
= NULL
;
2175 img_info
*cur
= g_ventoy_img_list
;
2188 g_ventoy_img_list
= NULL
;
2189 g_ventoy_img_count
= 0;
2191 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2194 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2197 img_info
*cur
= g_ventoy_img_list
;
2201 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2203 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2206 img_id
= grub_strtol(args
[0], NULL
, 10);
2207 if (img_id
>= g_ventoy_img_count
)
2209 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2212 debug("Find image %ld name \n", img_id
);
2214 while (cur
&& img_id
> 0)
2222 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2225 debug("image name is %s\n", cur
->name
);
2227 grub_env_set(args
[1], cur
->name
);
2229 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2232 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2236 img_info
*cur
= g_ventoy_img_list
;
2242 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2245 len
= (int)grub_strlen(args
[0]);
2249 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2258 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2261 grub_snprintf(id
, sizeof(id
), "VID_%d", cur
->id
);
2262 grub_env_set("chosen", id
);
2263 grub_env_export("chosen");
2265 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2268 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2273 const char *id
= NULL
;
2274 img_info
*cur
= g_ventoy_img_list
;
2278 if (argc
< 1 || argc
> 2)
2280 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2283 id
= grub_env_get("chosen");
2285 pos
= grub_strstr(id
, "VID_");
2288 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2292 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2297 if (img_id
== cur
->id
)
2306 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2309 grub_env_set(args
[0], cur
->path
);
2313 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2314 grub_env_set(args
[1], value
);
2317 g_svd_replace_offset
= 0;
2319 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2322 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2329 device_name
= grub_file_get_device_name(filename
);
2341 pos2
= grub_strstr(pos
, ",");
2344 pos2
= grub_strstr(pos
, ")");
2352 disk
= grub_disk_open(pos
);
2355 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2356 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2357 grub_disk_close(disk
);
2364 grub_free(device_name
);
2368 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2370 eltorito_descriptor desc
;
2372 grub_memset(&desc
, 0, sizeof(desc
));
2373 grub_file_seek(file
, 17 * 2048);
2374 grub_file_read(file
, &desc
, sizeof(desc
));
2376 if (desc
.type
!= 0 || desc
.version
!= 1)
2381 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2382 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2390 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2394 grub_uint8_t buf
[512];
2395 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2397 grub_file_seek(file
, sector
* 2048);
2398 grub_file_read(file
, buf
, sizeof(buf
));
2400 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2402 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2406 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2411 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2413 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2415 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2419 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2421 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2426 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2428 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2430 if (buf
[36] == parttype
[i
])
2432 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2438 debug("%s does not contain efi eltorito\n", file
->name
);
2442 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2445 const char *fs
= NULL
;
2446 const char *cdprompt
= NULL
;
2448 grub_uint8_t chksum
= 0;
2451 disk
= file
->device
->disk
;
2452 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2454 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2455 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2456 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2458 pos
= grub_strstr(file
->name
, "/");
2464 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2466 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2468 param
->vtoy_img_size
= file
->size
;
2470 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2471 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2473 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2475 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2476 param
->vtoy_reserved
[4] = 0;
2477 if (g_ventoy_chain_type
== 1) /* Windows */
2479 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2480 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2482 param
->vtoy_reserved
[4] = 1;
2486 fs
= ventoy_get_env("ventoy_fs_probe");
2487 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2489 param
->vtoy_reserved
[3] = 1;
2492 /* calculate checksum */
2493 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2495 chksum
+= *((grub_uint8_t
*)param
+ i
);
2497 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2502 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2504 grub_uint32_t i
= 0;
2505 grub_uint64_t total
= 0;
2506 grub_uint64_t fileblk
= 0;
2507 ventoy_img_chunk
*chunk
= NULL
;
2509 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2511 chunk
= chunklist
->chunk
+ i
;
2513 if (chunk
->disk_start_sector
<= start
)
2515 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2519 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2522 fileblk
= (file
->size
+ 511) / 512;
2524 if (total
!= fileblk
)
2526 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2527 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2529 debug("maybe img file to be processed.\n");
2539 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2543 grub_uint32_t i
= 0;
2544 grub_uint32_t sector
= 0;
2545 grub_uint32_t count
= 0;
2546 grub_off_t size
= 0;
2547 grub_off_t read
= 0;
2549 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2550 if (fs_type
== ventoy_fs_exfat
)
2552 grub_fat_get_file_chunk(start
, file
, chunklist
);
2554 else if (fs_type
== ventoy_fs_ext
)
2556 grub_ext_get_file_chunk(start
, file
, chunklist
);
2560 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2561 file
->read_hook_data
= chunklist
;
2563 for (size
= file
->size
; size
> 0; size
-= read
)
2565 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2566 grub_file_read(file
, NULL
, read
);
2569 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2571 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2572 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2575 if (ventoy_fs_udf
== fs_type
)
2577 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2579 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2580 chunklist
->chunk
[i
].img_start_sector
= sector
;
2581 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2587 len
= (int)grub_strlen(file
->name
);
2588 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2589 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2590 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2591 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2593 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2595 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2605 chunklist
->chunk
[i
].img_start_sector
= sector
;
2606 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2614 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2618 grub_disk_addr_t start
;
2623 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2626 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2629 g_conf_replace_node
= NULL
;
2630 g_conf_replace_offset
= 0;
2632 if (g_img_chunk_list
.chunk
)
2634 grub_free(g_img_chunk_list
.chunk
);
2637 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2639 grub_file_close(file
);
2640 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2643 /* get image chunk data */
2644 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2645 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2646 if (NULL
== g_img_chunk_list
.chunk
)
2648 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2651 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2652 g_img_chunk_list
.cur_chunk
= 0;
2654 start
= file
->device
->disk
->partition
->start
;
2656 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2658 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2659 grub_file_close(file
);
2663 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2666 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2667 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2670 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2672 grub_uint64_t offset
= 0;
2673 grub_uint32_t align
= 0;
2674 grub_file_t file
= NULL
;
2675 conf_replace
*node
= NULL
;
2681 debug("select conf replace argc:%d\n", argc
);
2688 node
= ventoy_plugin_find_conf_replace(args
[1]);
2691 debug("Conf replace not found for %s\n", args
[1]);
2695 debug("Find conf replace for %s\n", args
[1]);
2697 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2700 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2704 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2705 grub_file_close(file
);
2707 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2710 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2714 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2716 if (align
> vtoy_max_replace_file_size
)
2718 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2722 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2723 g_conf_replace_new_len
= (int)file
->size
;
2724 g_conf_replace_new_len_align
= align
;
2726 g_conf_replace_node
= node
;
2727 g_conf_replace_offset
= offset
+ 2;
2729 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2734 grub_file_close(file
);
2736 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2739 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2744 char configfile
[128];
2745 install_template
*node
= NULL
;
2751 debug("select auto installation argc:%d\n", argc
);
2758 node
= ventoy_plugin_find_install_template(args
[0]);
2761 debug("Auto install template not found for %s\n", args
[0]);
2765 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2767 node
->cursel
= node
->autosel
- 1;
2768 debug("Auto install template auto select %d\n", node
->autosel
);
2772 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2778 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2779 " echo %s\n}\n", "123");
2781 for (i
= 0; i
< node
->templatenum
; i
++)
2783 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2785 node
->templatepath
[i
].path
);
2788 g_ventoy_menu_esc
= 1;
2789 g_ventoy_suppress_esc
= 1;
2791 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2792 grub_script_execute_sourcecode(configfile
);
2794 g_ventoy_menu_esc
= 0;
2795 g_ventoy_suppress_esc
= 0;
2799 node
->cursel
= g_ventoy_last_entry
- 1;
2801 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2804 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2809 char configfile
[128];
2810 persistence_config
*node
;
2816 debug("select persistence argc:%d\n", argc
);
2823 node
= ventoy_plugin_find_persistent(args
[0]);
2826 debug("Persistence image not found for %s\n", args
[0]);
2830 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2832 node
->cursel
= node
->autosel
- 1;
2833 debug("Persistence image auto select %d\n", node
->autosel
);
2837 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2843 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2844 " echo %s\n}\n", "123");
2846 for (i
= 0; i
< node
->backendnum
; i
++)
2848 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2850 node
->backendpath
[i
].path
);
2854 g_ventoy_menu_esc
= 1;
2855 g_ventoy_suppress_esc
= 1;
2857 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2858 grub_script_execute_sourcecode(configfile
);
2860 g_ventoy_menu_esc
= 0;
2861 g_ventoy_suppress_esc
= 0;
2865 node
->cursel
= g_ventoy_last_entry
- 1;
2867 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2870 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2873 ventoy_img_chunk
*cur
;
2879 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2881 cur
= g_img_chunk_list
.chunk
+ i
;
2882 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2883 cur
->img_start_sector
, cur
->img_end_sector
,
2884 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2888 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2891 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2895 ventoy_img_chunk_list chunklist
;
2900 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2903 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2906 /* get image chunk data */
2907 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2908 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2909 if (NULL
== chunklist
.chunk
)
2911 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2914 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2915 chunklist
.cur_chunk
= 0;
2917 ventoy_get_block_list(file
, &chunklist
, 0);
2919 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2921 grub_printf("########## UNSUPPORTED ###############\n");
2924 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2926 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2928 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2929 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2932 grub_printf("\n==================================\n");
2934 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2936 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2937 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2938 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2939 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2940 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2944 grub_free(chunklist
.chunk
);
2945 grub_file_close(file
);
2947 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2950 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2953 ventoy_grub_param_file_replace
*replace
= NULL
;
2961 replace
= &(g_grub_param
->file_replace
);
2962 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2964 replace
->old_name_cnt
= 0;
2965 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2967 replace
->old_name_cnt
++;
2968 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2971 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2974 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2977 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2985 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2986 grub_printf("%s", g_list_script_buf
);
2990 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2991 grub_printf("%s", g_tree_script_buf
);
2997 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2999 img_info
*cur
= g_ventoy_img_list
;
3007 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3008 grub_printf("name:<%s>\n\n", cur
->name
);
3015 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3021 ventoy_plugin_dump_injection();
3026 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3032 ventoy_plugin_dump_auto_install();
3037 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3043 ventoy_plugin_dump_persistence();
3048 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3059 if (args
[0][0] == '0')
3061 return g_ventoy_memdisk_mode
? 0 : 1;
3063 else if (args
[0][0] == '1')
3065 return g_ventoy_iso_raw
? 0 : 1;
3067 else if (args
[0][0] == '2')
3069 return g_ventoy_iso_uefi_drv
? 0 : 1;
3071 else if (args
[0][0] == '3')
3073 return g_ventoy_grub2_mode
? 0 : 1;
3079 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3081 static int configfile_mode
= 0;
3082 char memfile
[128] = {0};
3089 * args[0]: 0:normal 1:configfile
3090 * args[1]: 0:list_buf 1:tree_buf
3095 debug("Invalid argc %d\n", argc
);
3099 if (args
[0][0] == '0')
3101 if (args
[1][0] == '0')
3103 grub_script_execute_sourcecode(g_list_script_buf
);
3107 grub_script_execute_sourcecode(g_tree_script_buf
);
3112 if (configfile_mode
)
3114 debug("Now already in F3 mode %d\n", configfile_mode
);
3118 if (args
[1][0] == '0')
3120 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3121 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3125 g_ventoy_last_entry
= -1;
3126 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3127 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3130 configfile_mode
= 1;
3131 grub_script_execute_sourcecode(memfile
);
3132 configfile_mode
= 0;
3138 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3149 g_ventoy_case_insensitive
= 1;
3150 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3151 g_ventoy_case_insensitive
= 0;
3157 grub_file_close(file
);
3163 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3168 const char *isopath
= NULL
;
3170 ventoy_mbr_head mbr
;
3177 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3180 isopath
= grub_env_get("vtoy_iso_part");
3183 debug("isopath is null %p\n", isopath
);
3187 debug("isopath is %s\n", isopath
);
3189 for (id
= 0; id
< 30 && (find
== 0); id
++)
3191 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3192 if (grub_strstr(isopath
, hdname
))
3194 debug("skip %s ...\n", hdname
);
3198 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3200 disk
= grub_disk_open(hdname
);
3203 debug("%s not exist\n", hdname
);
3207 grub_memset(&mbr
, 0, sizeof(mbr
));
3208 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3210 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3212 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3213 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3216 grub_env_set(args
[0], hdname
);
3220 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3224 debug("read %s failed\n", hdname
);
3227 grub_disk_close(disk
);
3233 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3244 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3247 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3250 debug("failed to open file %s\n", args
[0]);
3254 buf
= grub_malloc(len
);
3261 grub_file_read(file
, buf
, len
- 1);
3263 ventoy_get_line(buf
);
3264 ventoy_set_env(args
[1], buf
);
3268 grub_check_free(buf
);
3269 grub_file_close(file
);
3274 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3279 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3280 "0 %llu linear /dev/ventoy %llu\n",
3281 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3286 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3288 char *device_name
= NULL
;
3289 grub_device_t dev
= NULL
;
3294 g_part_list_pos
= 0;
3295 grub_env_unset("vtoy_img_part_file");
3302 device_name
= grub_file_get_device_name(args
[0]);
3305 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3309 dev
= grub_device_open(device_name
);
3312 debug("grub_device_open failed, %s\n", device_name
);
3316 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3318 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3319 grub_env_set("vtoy_img_part_file", buf
);
3323 check_free(device_name
, grub_free
);
3324 check_free(dev
, grub_device_close
);
3330 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3341 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3344 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3347 debug("failed to open file %s\n", args
[0]);
3351 buf
= grub_malloc(file
->size
+ 1);
3357 buf
[file
->size
] = 0;
3358 grub_file_read(file
, buf
, file
->size
);
3360 if (grub_strstr(buf
, args
[1]))
3367 grub_check_free(buf
);
3368 grub_file_close(file
);
3373 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3379 ventoy_iso9660_vd pvd
;
3386 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3389 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3392 debug("failed to open file %s\n", args
[0]);
3396 grub_file_seek(file
, 16 * 2048);
3397 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3398 if (len
!= sizeof(pvd
))
3400 debug("failed to read pvd %d\n", len
);
3404 grub_memset(buf
, 0, sizeof(buf
));
3405 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3406 ventoy_set_env(args
[1], buf
);
3408 grub_memset(buf
, 0, sizeof(buf
));
3409 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3410 ventoy_set_env(args
[2], buf
);
3414 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3415 ventoy_set_env(args
[3], buf
);
3418 grub_file_close(file
);
3423 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3434 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3437 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3440 debug("failed to open file %s\n", args
[0]);
3444 grub_memset(buf
, 0, sizeof(buf
));
3445 grub_file_seek(file
, 16 * 2048 + 813);
3446 len
= (int)grub_file_read(file
, buf
, 17);
3449 debug("failed to read create date %d\n", len
);
3453 ventoy_set_env(args
[1], buf
);
3456 grub_file_close(file
);
3461 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3467 ventoy_env_hook_root(1);
3472 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3478 ventoy_env_hook_root(0);
3483 #ifdef GRUB_MACHINE_EFI
3484 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3489 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3495 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3496 if (var
&& *var
== 1)
3504 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3513 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3518 grub_uint64_t FileSectors
= 0;
3519 ventoy_gpt_info
*gpt
= NULL
;
3520 ventoy_part_table
*pt
= NULL
;
3521 grub_uint8_t zeroguid
[16] = {0};
3526 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3529 debug("failed to open file %s\n", args
[0]);
3533 if (file
->size
% 512)
3535 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3539 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3545 FileSectors
= file
->size
/ 512;
3547 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3548 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3550 debug("This is EFI partition table\n");
3552 for (i
= 0; i
< 128; i
++)
3554 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3556 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3558 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3559 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3567 debug("This is MBR partition table\n");
3569 for (i
= 0; i
< 4; i
++)
3571 pt
= gpt
->MBR
.PartTbl
+ i
;
3572 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3574 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3575 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3576 (ulonglong
)FileSectors
);
3585 grub_file_close(file
);
3586 grub_check_free(gpt
);
3587 grub_errno
= GRUB_ERR_NONE
;
3591 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3600 for (i
= 0; i
< 500; i
++)
3602 ret
= grub_getkey_noblock();
3603 if (ret
== GRUB_TERM_NO_KEY
)
3612 grub_printf("\n\n Still have key input after clear.\n");
3620 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3627 int image_sector_size
;
3629 ventoy_chain_head
*chain
;
3630 ventoy_img_chunk
*chunk
;
3631 ventoy_os_param
*osparam
;
3632 ventoy_image_location
*location
;
3633 ventoy_image_disk_region
*region
;
3634 struct grub_acpi_table_header
*acpi
;
3643 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3645 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3651 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3653 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3655 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3659 img_chunk_num
= chain
->img_chunk_num
;
3661 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3662 datalen
= sizeof(ventoy_os_param
) + loclen
;
3664 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3665 acpi
= grub_zalloc(buflen
);
3671 /* Step1: Fill acpi table header */
3672 grub_memcpy(acpi
->signature
, "VTOY", 4);
3673 acpi
->length
= buflen
;
3675 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3676 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3678 acpi
->creator_id
[0] = 1;
3679 acpi
->creator_rev
= 1;
3681 /* Step2: Fill data */
3682 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3683 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3684 osparam
->vtoy_img_location_addr
= 0;
3685 osparam
->vtoy_img_location_len
= loclen
;
3686 osparam
->chksum
= 0;
3687 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3689 location
= (ventoy_image_location
*)(osparam
+ 1);
3690 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3691 location
->image_sector_size
= image_sector_size
;
3692 location
->disk_sector_size
= chain
->disk_sector_size
;
3693 location
->region_count
= img_chunk_num
;
3695 region
= location
->regions
;
3696 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3697 if (512 == image_sector_size
)
3699 for (i
= 0; i
< img_chunk_num
; i
++)
3701 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3702 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3703 region
->disk_start_sector
= chunk
->disk_start_sector
;
3710 for (i
= 0; i
< img_chunk_num
; i
++)
3712 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3713 region
->image_start_sector
= chunk
->img_start_sector
;
3714 region
->disk_start_sector
= chunk
->disk_start_sector
;
3720 /* Step3: Fill acpi checksum */
3722 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3724 /* load acpi table */
3725 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3726 grub_script_execute_sourcecode(cmd
);
3730 VENTOY_CMD_RETURN(0);
3733 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3739 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3740 g_ventoy_last_entry
= -1;
3745 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3751 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3756 grub_uint64_t
ventoy_get_part1_size(ventoy_gpt_info
*gpt
)
3758 grub_uint64_t sectors
;
3760 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3762 sectors
= gpt
->PartTbl
[0].LastLBA
+ 1 - gpt
->PartTbl
[0].StartLBA
;
3766 sectors
= gpt
->MBR
.PartTbl
[0].SectorCount
;
3769 return sectors
* 512;
3772 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3774 const char *pos
= filename
+ 1;
3782 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3784 grub_strncpy((char *)data
, filename
, 128);
3795 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3798 char *device_name
= NULL
;
3799 grub_device_t dev
= NULL
;
3800 grub_fs_t fs
= NULL
;
3801 char buf
[128] = {0};
3807 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3811 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3813 device_name
= grub_file_get_device_name(args
[0]);
3816 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3820 dev
= grub_device_open(device_name
);
3823 debug("grub_device_open failed, %s\n", device_name
);
3827 fs
= grub_fs_probe(dev
);
3830 debug("grub_fs_probe failed, %s\n", device_name
);
3834 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3838 ventoy_set_env(args
[2], buf
);
3845 check_free(device_name
, grub_free
);
3846 check_free(dev
, grub_device_close
);
3851 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3861 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3862 if (!g_ventoy_part_info
)
3867 disk
= grub_disk_open(args
[0]);
3870 debug("Failed to open disk %s\n", args
[0]);
3874 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
3876 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3877 grub_disk_close(disk
);
3879 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3880 dev
= grub_device_open(name
);
3883 /* make sure that we are running in a correct Ventoy device */
3884 ret
= ventoy_check_device(dev
);
3885 grub_device_close(dev
);
3896 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3899 const char *vcfg
= NULL
;
3904 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
3907 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
3908 grub_env_set(args
[1], vcfg
);
3913 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
3921 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3924 grub_uint8_t zeroguid
[16] = {0};
3929 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3932 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3934 if (id
>= 1 && id
<= 128)
3936 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3944 if (id
>= 1 && id
<= 4)
3946 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3956 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3959 char *device_name
= NULL
;
3960 grub_device_t dev
= NULL
;
3961 grub_fs_t fs
= NULL
;
3966 debug("get fs label for %s\n", args
[0]);
3970 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3974 device_name
= grub_file_get_device_name(args
[0]);
3977 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3981 dev
= grub_device_open(device_name
);
3984 debug("grub_device_open failed, %s\n", device_name
);
3988 fs
= grub_fs_probe(dev
);
3989 if (NULL
== fs
|| NULL
== fs
->fs_label
)
3991 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
3995 fs
->fs_label(dev
, &label
);
3998 debug("label=<%s>\n", label
);
3999 ventoy_set_env(args
[1], label
);
4007 check_free(device_name
, grub_free
);
4008 check_free(dev
, grub_device_close
);
4013 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4017 grub_snprintf((char *)data
, 256, "%s", filename
);
4025 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4028 char *device_name
= NULL
;
4029 grub_device_t dev
= NULL
;
4030 grub_fs_t fs
= NULL
;
4031 char name
[256] ={0};
4037 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
4041 device_name
= grub_file_get_device_name(args
[0]);
4044 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4048 dev
= grub_device_open(device_name
);
4051 debug("grub_device_open failed, %s\n", device_name
);
4055 fs
= grub_fs_probe(dev
);
4058 debug("grub_fs_probe failed, %s\n", device_name
);
4062 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
4065 ventoy_set_env(args
[2], name
);
4072 check_free(device_name
, grub_free
);
4073 check_free(dev
, grub_device_close
);
4078 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4088 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4092 for (pos
= args
[0]; *pos
; pos
++)
4106 grub_env_set(args
[1], args
[0]);
4116 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4126 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4131 len
= (int)grub_strlen(buf
);
4132 for (i
= len
; i
> 0; i
--)
4134 if (buf
[i
- 1] == '/')
4136 grub_env_set(args
[1], buf
+ i
);
4141 grub_env_set(args
[1], buf
);
4146 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4148 struct grub_video_mode_info info
;
4155 if (!g_video_mode_list
)
4157 ventoy_enum_video_mode();
4160 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4162 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4166 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4169 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4171 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4172 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4174 VENTOY_CMD_RETURN(0);
4177 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4179 struct grub_video_mode_info info
;
4186 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4188 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4192 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4195 grub_env_set(args
[0], buf
);
4197 VENTOY_CMD_RETURN(0);
4200 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4208 if (!g_video_mode_list
)
4213 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4214 if (id
< g_video_mode_num
)
4216 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4217 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4220 grub_env_set(args
[1], buf
);
4222 VENTOY_CMD_RETURN(0);
4225 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
4227 grub_uint64_t size
= 0;
4230 char fullpath
[256] = {0};
4233 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4236 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
4239 debug("grub_file_open failed <%s>\n", fullpath
);
4245 grub_file_close(file
);
4249 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
4253 char fullpath
[256] = {0};
4256 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4259 file
= grub_file_open(fullpath
, type
);
4262 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
4269 int ventoy_is_file_exist(const char *fmt
, ...)
4274 char buf
[256] = {0};
4276 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
4280 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4283 grub_strncpy(pos
+ len
, "\" ]", 3);
4285 debug("script exec %s\n", buf
);
4287 if (0 == grub_script_execute_sourcecode(buf
))
4295 int ventoy_is_dir_exist(const char *fmt
, ...)
4300 char buf
[256] = {0};
4302 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
4306 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4309 grub_strncpy(pos
+ len
, "\" ]", 3);
4311 debug("script exec %s\n", buf
);
4313 if (0 == grub_script_execute_sourcecode(buf
))
4321 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
4324 grub_uint8_t
*outbuf
;
4325 grub_uint8_t gzHdr
[10] =
4327 0x1F, 0x8B, /* magic */
4330 0,0,0,0, /* mtime */
4335 grub_memset(&s
, 0, sizeof(mz_stream
));
4337 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
4339 outbuf
= (grub_uint8_t
*)mem_out
;
4341 mem_out_len
-= sizeof(gzHdr
) + 8;
4342 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
4343 outbuf
+= sizeof(gzHdr
);
4345 s
.avail_in
= mem_in_len
;
4348 s
.avail_out
= mem_out_len
;
4349 s
.next_out
= outbuf
;
4351 mz_deflate(&s
, MZ_FINISH
);
4355 outbuf
+= s
.total_out
;
4356 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
4357 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
4359 return s
.total_out
+ sizeof(gzHdr
) + 8;
4362 static int ventoy_env_init(void)
4366 grub_env_set("vtdebug_flag", "");
4368 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4369 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4370 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4371 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4373 ventoy_filt_register(0, ventoy_wrapper_open
);
4375 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4378 g_grub_param
->grub_env_get
= grub_env_get
;
4379 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4380 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4381 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4382 grub_env_set("env_param", buf
);
4383 grub_env_set("ventoy_env_param", buf
);
4385 grub_env_export("env_param");
4386 grub_env_export("ventoy_env_param");
4392 static cmd_para ventoy_cmds
[] =
4394 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4395 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4396 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4397 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4398 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4399 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4400 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4401 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4402 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4403 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4404 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4405 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4406 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4407 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4408 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4409 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4410 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4411 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4412 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4413 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4414 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4415 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4416 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4417 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4419 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4420 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4421 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4422 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4423 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4424 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4425 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4427 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4428 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4429 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4430 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4431 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4432 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4433 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4434 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4435 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4438 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4439 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4440 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4441 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4442 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4443 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4444 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4445 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4446 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4447 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4448 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4450 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4451 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4452 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4453 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4454 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4455 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4457 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4458 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4459 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4460 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4461 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4462 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4463 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4464 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4465 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4466 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4468 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4469 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4470 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4471 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4472 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4473 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4474 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4475 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4477 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4478 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4479 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4482 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4483 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4484 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4486 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4487 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4488 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4491 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4492 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4493 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4494 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4495 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
4496 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4497 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4498 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4499 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4500 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4501 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4503 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4504 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4505 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4506 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4507 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
4508 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
4514 GRUB_MOD_INIT(ventoy
)
4517 cmd_para
*cur
= NULL
;
4521 ventoy_arch_mode_init();
4523 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4525 cur
= ventoy_cmds
+ i
;
4526 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4527 cur
->summary
, cur
->description
, cur
->parser
);
4531 GRUB_MOD_FINI(ventoy
)
4535 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4537 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);