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 int ventoy_strcmp(const char *pattern
, const char *str
)
153 while (*pattern
&& *str
)
155 if ((*pattern
!= *str
) && (*pattern
!= '*'))
162 return (int)(grub_uint8_t
)*pattern
- (int)(grub_uint8_t
)*str
;
165 int ventoy_strncmp (const char *pattern
, const char *str
, grub_size_t n
)
170 while (*pattern
&& *str
&& --n
)
172 if ((*pattern
!= *str
) && (*pattern
!= '*'))
179 return (int)(grub_uint8_t
)*pattern
- (int)(grub_uint8_t
)*str
;
183 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
193 for (i
= 0; i
< 16; i
++)
195 grub_printf("%02x ", guid
[i
]);
200 int ventoy_is_efi_os(void)
204 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
210 static int ventoy_get_fs_type(const char *fs
)
214 return ventoy_fs_max
;
216 else if (grub_strncmp(fs
, "exfat", 5) == 0)
218 return ventoy_fs_exfat
;
220 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
222 return ventoy_fs_ntfs
;
224 else if (grub_strncmp(fs
, "ext", 3) == 0)
226 return ventoy_fs_ext
;
228 else if (grub_strncmp(fs
, "xfs", 3) == 0)
230 return ventoy_fs_xfs
;
232 else if (grub_strncmp(fs
, "udf", 3) == 0)
234 return ventoy_fs_udf
;
236 else if (grub_strncmp(fs
, "fat", 3) == 0)
238 return ventoy_fs_fat
;
241 return ventoy_fs_max
;
244 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
263 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
265 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
269 static int ventoy_control_get_flag(const char *key
)
271 const char *val
= ventoy_get_env(key
);
273 if (val
&& val
[0] == '1' && val
[1] == 0)
280 static grub_err_t
ventoy_fs_close(grub_file_t file
)
282 grub_file_close(g_old_file
);
283 grub_free(file
->data
);
291 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
297 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
302 for (i
= 0; i
< g_video_mode_num
; i
++)
304 if (g_video_mode_list
[i
].width
== info
->width
&&
305 g_video_mode_list
[i
].height
== info
->height
&&
306 g_video_mode_list
[i
].bpp
== info
->bpp
)
312 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
313 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
314 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
317 if (g_video_mode_num
== g_video_mode_max
)
319 g_video_mode_max
*= 2;
320 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
326 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
328 if (v1
->bpp
== v2
->bpp
)
330 if (v1
->width
== v2
->width
)
332 if (v1
->height
== v2
->height
)
338 return (v1
->height
< v2
->height
) ? -1 : 1;
343 return (v1
->width
< v2
->width
) ? -1 : 1;
348 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
352 static int ventoy_enum_video_mode(void)
355 grub_video_adapter_t adapter
;
356 grub_video_driver_id_t id
;
357 ventoy_video_mode mode
;
359 g_video_mode_num
= 0;
360 g_video_mode_max
= 1024;
361 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
362 if (!g_video_mode_list
)
367 #ifdef GRUB_MACHINE_PCBIOS
368 grub_dl_load ("vbe");
371 id
= grub_video_get_driver_id ();
373 FOR_VIDEO_ADAPTERS (adapter
)
375 if (!adapter
->iterate
||
376 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
377 adapter
->init() != GRUB_ERR_NONE
)))
382 adapter
->iterate(ventoy_video_hook
, NULL
);
384 if (adapter
->id
!= id
)
390 /* sort video mode */
391 for (i
= 0; i
< g_video_mode_num
; i
++)
392 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
394 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
396 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
397 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
398 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
402 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
405 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
409 static struct grub_fs vtoy_fs
=
414 .fs_read
= ventoy_fs_read
,
415 .fs_close
= ventoy_fs_close
,
425 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
431 file
->data
= grub_malloc(rawFile
->size
+ 4096);
437 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
438 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
440 g_old_file
= rawFile
;
442 file
->size
= rawFile
->size
+ len
;
443 file
->device
= rawFile
->device
;
445 file
->not_easily_seekable
= 1;
450 static int ventoy_check_decimal_var(const char *name
, long *value
)
452 const char *value_str
= NULL
;
454 value_str
= grub_env_get(name
);
455 if (NULL
== value_str
)
457 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
460 if (!ventoy_is_decimal(value_str
))
462 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
465 *value
= grub_strtol(value_str
, NULL
, 10);
467 return GRUB_ERR_NONE
;
470 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
474 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
477 if (0 == grub_strcmp(args
[0], "on"))
480 grub_env_set("vtdebug_flag", "debug");
485 grub_env_set("vtdebug_flag", "");
488 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
491 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
495 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
497 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
498 grub_printf(" level:\r\n");
499 grub_printf(" 01/11: busybox / (+cat log)\r\n");
500 grub_printf(" 02/12: initrd / (+cat log)\r\n");
501 grub_printf(" 03/13: hook / (+cat log)\r\n");
503 grub_printf(" debug:\r\n");
504 grub_printf(" 0: debug is off\r\n");
505 grub_printf(" 1: debug is on\r\n");
507 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
510 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
512 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
514 g_ventoy_debug_level
= 1;
517 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
520 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
529 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
532 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
564 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
569 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
571 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
574 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
579 value_long
+= grub_strtol(args
[1], NULL
, 10);
581 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
582 grub_env_set(args
[0], buf
);
584 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
587 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
589 ulonglong value1
= 0;
590 ulonglong value2
= 0;
595 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
598 value1
= grub_strtoull(args
[0], NULL
, 10);
599 value2
= grub_strtoull(args
[1], NULL
, 10);
601 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
602 grub_env_set(args
[2], buf
);
604 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
607 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
622 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
625 debug("failed to open file <%s> for udf check\n", args
[0]);
629 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
631 grub_env_set(args
[1], buf
);
633 grub_file_close(file
);
639 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
647 g_wimboot_enable
= 0;
648 grub_check_free(g_wimiso_path
);
649 grub_check_free(g_wimiso_chunk_list
.chunk
);
651 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
657 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
658 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
659 if (NULL
== g_wimiso_chunk_list
.chunk
)
661 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
664 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
665 g_wimiso_chunk_list
.cur_chunk
= 0;
667 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
669 g_wimboot_enable
= 1;
670 g_wimiso_path
= grub_strdup(args
[0]);
672 grub_file_close(file
);
677 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
683 grub_uint32_t offset
;
685 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
688 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
692 len
= (int)file
->size
;
694 data
= (char *)grub_malloc(file
->size
);
700 grub_file_read(file
, data
, file
->size
);
701 grub_file_close(file
);
703 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
704 grub_script_execute_sourcecode(exec
);
706 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
707 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
708 grub_file_close(file
);
710 grub_script_execute_sourcecode("loopback -d efiboot");
714 *direntoff
= offset
+ 2;
719 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
729 ventoy_iso9660_override
*dirent
;
738 totlen
= sizeof(ventoy_chain_head
);
740 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
742 debug("failed to load efiboot template %d\n", len
);
748 debug("efiboot template len:%d offset:%d\n", len
, offset
);
750 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
753 debug("failed to open file <%s>\n", args
[0]);
757 totlen
+= ventoy_align_2k(file
->size
);
759 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
760 dirent
->first_sector
= len
/ 2048;
761 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
762 dirent
->size
= (grub_uint32_t
)file
->size
;
763 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
765 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
767 #ifdef GRUB_MACHINE_EFI
768 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
770 data
= (char *)grub_malloc(totlen
);
773 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
775 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
776 grub_check_free(buf
);
778 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
779 grub_file_close(file
);
781 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
782 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
783 grub_env_set(name
, value
);
785 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
786 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
787 grub_env_set(name
, value
);
792 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
809 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
812 debug("failed to open file <%s>\n", args
[0]);
816 #ifdef GRUB_MACHINE_EFI
817 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
819 buf
= (char *)grub_malloc(file
->size
);
822 grub_file_read(file
, buf
, file
->size
);
824 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
825 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
826 grub_env_set(name
, value
);
828 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
829 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
830 grub_env_set(name
, value
);
832 grub_file_close(file
);
838 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
856 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
859 debug("failed to open file <%s> for udf check\n", args
[0]);
863 headlen
= sizeof(ventoy_chain_head
);
865 #ifdef GRUB_MACHINE_EFI
866 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
868 buf
= (char *)grub_malloc(headlen
+ file
->size
);
871 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
873 grub_file_read(file
, buf
+ headlen
, file
->size
);
875 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
876 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
877 grub_env_set(name
, value
);
879 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
880 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
881 grub_env_set(name
, value
);
883 grub_file_close(file
);
889 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
898 if (args
[0][0] == '1')
900 grub_iso9660_set_nojoliet(1);
904 grub_iso9660_set_nojoliet(0);
910 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
915 grub_uint8_t buf
[32];
926 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
929 debug("failed to open file <%s> for udf check\n", args
[0]);
933 for (i
= 16; i
< 32; i
++)
935 grub_file_seek(file
, i
* 2048);
936 grub_file_read(file
, buf
, sizeof(buf
));
944 grub_file_seek(file
, i
* 2048);
945 grub_file_read(file
, buf
, sizeof(buf
));
947 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
950 grub_file_seek(file
, i
* 2048);
951 grub_file_read(file
, buf
, sizeof(buf
));
953 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
954 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
960 grub_file_close(file
);
962 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
967 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
969 long value_long1
= 0;
970 long value_long2
= 0;
972 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
974 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
977 value_long1
= grub_strtol(args
[0], NULL
, 10);
978 value_long2
= grub_strtol(args
[2], NULL
, 10);
980 if (0 == grub_strcmp(args
[1], "eq"))
982 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
984 else if (0 == grub_strcmp(args
[1], "ne"))
986 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
988 else if (0 == grub_strcmp(args
[1], "gt"))
990 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
992 else if (0 == grub_strcmp(args
[1], "lt"))
994 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
996 else if (0 == grub_strcmp(args
[1], "ge"))
998 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1000 else if (0 == grub_strcmp(args
[1], "le"))
1002 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1006 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1012 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1015 char buf
[128] = {0};
1019 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1022 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1023 pos
= grub_strstr(buf
, ",");
1029 grub_env_set(args
[1], buf
);
1031 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1034 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1040 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1046 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1049 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1051 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1052 if (0 == grub_script_execute_sourcecode(buf
))
1054 debug("file %s exist, ventoy_compatible YES\n", buf
);
1055 grub_env_set("ventoy_compatible", "YES");
1056 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1060 debug("file %s NOT exist\n", buf
);
1064 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1065 pos
= grub_strstr(buf
, ")");
1071 disk
= grub_disk_open(buf
);
1074 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1075 grub_disk_close(disk
);
1077 g_img_swap_tmp_buf
[703] = 0;
1078 for (i
= 318; i
< 703; i
++)
1080 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1081 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1083 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1084 grub_env_set("ventoy_compatible", "YES");
1085 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1091 debug("failed to open disk <%s>\n", buf
);
1094 grub_env_set("ventoy_compatible", "NO");
1095 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1098 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1104 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1106 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1109 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1114 if (0 == g_sort_case_sensitive
)
1116 if (grub_islower(c1
))
1118 c1
= c1
- 'a' + 'A';
1121 if (grub_islower(c2
))
1123 c2
= c2
- 'a' + 'A';
1136 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1142 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1144 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1147 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1152 if (0 == g_sort_case_sensitive
)
1154 if (grub_islower(c1
))
1156 c1
= c1
- 'a' + 'A';
1159 if (grub_islower(c2
))
1161 c2
= c2
- 'a' + 'A';
1174 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1176 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1178 grub_memcpy(img1
, img2
, sizeof(img_info
));
1179 img1
->next
= g_img_swap_tmp
.next
;
1180 img1
->prev
= g_img_swap_tmp
.prev
;
1182 g_img_swap_tmp
.next
= img2
->next
;
1183 g_img_swap_tmp
.prev
= img2
->prev
;
1184 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1187 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1191 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1199 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1203 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1213 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1222 img_iterator_node
*tmp
;
1223 img_iterator_node
*new_node
;
1224 img_iterator_node
*node
= (img_iterator_node
*)data
;
1226 if (g_enumerate_time_checked
== 0)
1228 g_enumerate_finish_time_ms
= grub_get_time_ms();
1229 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1232 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1234 g_enumerate_time_checked
= 1;
1238 len
= grub_strlen(filename
);
1242 if (node
->level
+ 1 > g_img_max_search_level
)
1247 if ((len
== 1 && filename
[0] == '.') ||
1248 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1253 if (!ventoy_img_name_valid(filename
, len
))
1258 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1263 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1265 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1266 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1269 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1274 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1277 new_node
->level
= node
->level
+ 1;
1278 new_node
->plugin_list_index
= index
;
1279 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1281 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1284 debug("Directory %s ignored...\n", new_node
->dir
);
1285 grub_free(new_node
);
1289 new_node
->tail
= node
->tail
;
1291 new_node
->parent
= node
;
1292 if (!node
->firstchild
)
1294 node
->firstchild
= new_node
;
1297 if (g_img_iterator_tail
)
1299 g_img_iterator_tail
->next
= new_node
;
1300 g_img_iterator_tail
= new_node
;
1304 g_img_iterator_head
.next
= new_node
;
1305 g_img_iterator_tail
= new_node
;
1311 debug("Find a file %s\n", filename
);
1317 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1319 type
= img_type_iso
;
1321 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1323 type
= img_type_wim
;
1325 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1326 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1328 type
= img_type_vhd
;
1330 #ifdef GRUB_MACHINE_EFI
1331 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1333 type
= img_type_efi
;
1336 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1338 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1340 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1341 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1346 type
= img_type_img
;
1348 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1350 type
= img_type_vtoy
;
1352 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1354 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1356 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1357 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1366 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1371 if (g_plugin_image_list
)
1373 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1374 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1375 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1377 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1380 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1382 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1387 img
= grub_zalloc(sizeof(img_info
));
1391 img
->plugin_list_index
= index
;
1392 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1394 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1396 img
->size
= info
->size
;
1399 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1402 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1404 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1409 if (g_ventoy_img_list
)
1411 tail
= *(node
->tail
);
1417 g_ventoy_img_list
= img
;
1420 img
->id
= g_ventoy_img_count
;
1422 if (node
&& NULL
== node
->firstiso
)
1424 node
->firstiso
= img
;
1435 *((img_info
**)(node
->tail
)) = img
;
1436 g_ventoy_img_count
++;
1438 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1439 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1442 img
->class = g_menu_class
[type
];
1444 img
->menu_prefix
= g_menu_prefix
[type
];
1446 if (img_type_iso
== type
)
1448 if (ventoy_plugin_check_memdisk(img
->path
))
1450 img
->menu_prefix
= "miso";
1454 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1461 static int ventoy_arch_mode_init(void)
1463 #ifdef GRUB_MACHINE_EFI
1464 if (grub_strcmp(GRUB_TARGET_CPU
, "i386") == 0)
1466 g_ventoy_plat_data
= VTOY_PLAT_I386_UEFI
;
1467 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "ia32");
1469 else if (grub_strcmp(GRUB_TARGET_CPU
, "arm64") == 0)
1471 g_ventoy_plat_data
= VTOY_PLAT_ARM64_UEFI
;
1472 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "aa64");
1474 else if (grub_strcmp(GRUB_TARGET_CPU
, "mips64el") == 0)
1476 g_ventoy_plat_data
= VTOY_PLAT_MIPS_UEFI
;
1477 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "mips");
1481 g_ventoy_plat_data
= VTOY_PLAT_X86_64_UEFI
;
1482 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "uefi");
1485 g_ventoy_plat_data
= VTOY_PLAT_X86_LEGACY
;
1486 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "legacy");
1492 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1494 int len
= GRUB_UINT_MAX
;
1495 const char *value
= NULL
;
1496 char name
[32] = {0};
1497 char plat
[32] = {0};
1498 char guidstr
[32] = {0};
1499 ventoy_guid guid
= VENTOY_GUID
;
1500 const char *fmt1
= NULL
;
1501 const char *fmt2
= NULL
;
1502 const char *fmt3
= NULL
;
1503 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1504 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1505 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1506 const char fmtcode
[]={
1507 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1508 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1509 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1510 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1511 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1512 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1515 grub_memset(name
, 0, sizeof(name
));
1516 puint
[0] = grub_swap_bytes32(0x56454e54);
1517 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1518 puint
[2] = grub_swap_bytes32(0x45525349);
1519 puint
[1] = grub_swap_bytes32(0x4f595f56);
1520 value
= ventoy_get_env(name
);
1522 grub_memset(name
, 0, sizeof(name
));
1523 puint
[1] = grub_swap_bytes32(0x5f544f50);
1524 puint
[0] = grub_swap_bytes32(0x56544c45);
1525 fmt1
= ventoy_get_env(name
);
1531 grub_memset(name
, 0, sizeof(name
));
1532 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1533 puint
[0] = grub_swap_bytes32(0x56544c45);
1534 fmt2
= ventoy_get_env(name
);
1536 grub_memset(name
, 0, sizeof(name
));
1537 puint
[1] = grub_swap_bytes32(0x5f434c52);
1538 puint
[0] = grub_swap_bytes32(0x56544c45);
1539 fmt3
= ventoy_get_env(name
);
1541 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1543 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1545 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1546 #pragma GCC diagnostic push
1547 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1548 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1549 fmt1
? fmt1
: fmtdata
,
1550 fmt2
? fmt2
: fmtdata
+ 4,
1551 value
? value
: "", plat
, guidstr
,
1552 fmt3
? fmt3
: fmtdata
+ 6);
1553 #pragma GCC diagnostic pop
1555 grub_memset(name
, 0, sizeof(name
));
1556 puint
[0] = grub_swap_bytes32(0x76746f79);
1557 puint
[2] = grub_swap_bytes32(0x656e7365);
1558 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1559 ventoy_set_env(name
, guidstr
);
1564 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1568 grub_uint8_t md5
[16];
1572 grub_memset(input
, 0, sizeof(input
));
1574 grub_printf("Enter password: ");
1577 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1579 grub_password_get(input
, 128);
1580 if (grub_strcmp(pwd
->text
, input
) == 0)
1585 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1587 grub_password_get(input
, 128);
1588 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1589 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1594 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1596 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1597 grub_password_get(input
+ offset
, 128);
1599 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1600 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1606 grub_printf("Invalid password!\n\n");
1613 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1615 img_info
*minimg
= NULL
;
1616 img_info
*img
= (img_info
*)(node
->firstiso
);
1618 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1620 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1635 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1637 img_iterator_node
*Minchild
= NULL
;
1638 img_iterator_node
*child
= node
->firstchild
;
1640 while (child
&& child
->parent
== node
)
1642 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1646 child
= child
->next
;
1651 Minchild
->select
= 1;
1657 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1660 img_info
*img
= NULL
;
1661 const char *dir_class
= NULL
;
1662 const char *dir_alias
= NULL
;
1663 img_iterator_node
*child
= NULL
;
1665 if (node
->isocnt
== 0 || node
->done
== 1)
1670 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1672 offset
= node
->parent
->dirlen
;
1675 if (node
== &g_img_iterator_head
)
1677 if (g_default_menu_mode
== 0)
1679 if (g_tree_view_menu_style
== 0)
1681 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1682 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1683 " echo 'return ...' \n"
1688 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1689 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1697 node
->dir
[node
->dirlen
- 1] = 0;
1698 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1701 dir_class
= "vtoydir";
1704 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1707 if (g_tree_view_menu_style
== 0)
1709 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1710 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1711 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1715 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1716 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1717 dir_alias
, dir_class
, node
->dir
+ offset
);
1722 dir_alias
= node
->dir
+ offset
;
1724 if (g_tree_view_menu_style
== 0)
1726 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1727 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1728 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1732 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1733 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1734 dir_alias
, dir_class
, node
->dir
+ offset
);
1738 if (g_tree_view_menu_style
== 0)
1740 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1741 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1742 " echo 'return ...' \n"
1747 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1748 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1754 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1756 ventoy_dynamic_tree_menu(child
);
1759 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1761 if (g_tree_view_menu_style
== 0)
1763 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1764 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1767 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1768 img
->unsupport
? "[***********] " : "",
1769 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1771 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1775 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1776 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1779 img
->unsupport
? "[***********] " : "",
1780 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1782 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1786 if (node
!= &g_img_iterator_head
)
1788 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1795 int ventoy_check_device_result(int ret
)
1799 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1800 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1801 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1805 grub_printf(VTOY_WARNING
"\n");
1806 grub_printf(VTOY_WARNING
"\n");
1807 grub_printf(VTOY_WARNING
"\n\n\n");
1809 grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret
);
1810 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1812 grub_printf("\n\nWill exit after 10 seconds ...... ");
1820 int ventoy_check_device(grub_device_t dev
)
1824 grub_uint64_t offset
;
1829 struct grub_partition
*partition
;
1831 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1833 return ventoy_check_device_result(1 | 0x1000);
1836 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1837 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1838 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1840 #ifndef GRUB_MACHINE_EFI
1841 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1842 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
1843 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1845 return ventoy_check_device_result(2 | 0x1000);
1854 /* We must have partition 2 */
1857 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
1861 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1865 return ventoy_check_device_result(3 | 0x1000);
1868 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1870 grub_file_close(file
);
1871 return ventoy_check_device_result(4 | 0x1000);
1874 partition
= dev
->disk
->partition
;
1875 if (partition
->number
!= 0 || partition
->start
!= 2048)
1877 return ventoy_check_device_result(5);
1882 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
1884 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
1885 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
1886 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
1888 grub_file_close(file
);
1889 return ventoy_check_device_result(6);
1894 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
1895 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
1896 PartTbl
[1].SectorCount
!= 65536)
1898 grub_file_close(file
);
1899 return ventoy_check_device_result(6);
1905 offset
= partition
->start
+ partition
->len
;
1906 partition
= file
->device
->disk
->partition
;
1907 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1909 grub_file_close(file
);
1910 return ventoy_check_device_result(7);
1914 grub_file_close(file
);
1916 if (workaround
== 0)
1918 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1919 dev2
= grub_device_open(devname
);
1922 return ventoy_check_device_result(8);
1925 fs
= grub_fs_probe(dev2
);
1928 grub_device_close(dev2
);
1929 return ventoy_check_device_result(9);
1932 fs
->fs_label(dev2
, &label
);
1933 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1935 grub_device_close(dev2
);
1936 return ventoy_check_device_result(10);
1939 grub_device_close(dev2
);
1942 return ventoy_check_device_result(0);
1945 static int ventoy_set_default_menu(void)
1951 const char *strdata
= NULL
;
1952 img_info
*cur
= NULL
;
1953 img_info
*default_node
= NULL
;
1954 const char *default_image
= NULL
;
1956 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1957 if (default_image
&& default_image
[0] == '/')
1959 img_len
= grub_strlen(default_image
);
1961 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1963 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1975 if (0 == g_default_menu_mode
)
1977 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1981 def
= grub_strdup(default_image
);
1987 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1989 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1990 if (strdata
&& strdata
[0] == '/')
1992 pos
= def
+ grub_strlen(strdata
);
2003 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2006 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2010 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
2018 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2022 grub_device_t dev
= NULL
;
2023 img_info
*cur
= NULL
;
2024 img_info
*tail
= NULL
;
2025 const char *strdata
= NULL
;
2026 char *device_name
= NULL
;
2028 img_iterator_node
*node
= NULL
;
2029 img_iterator_node
*tmp
= NULL
;
2035 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2038 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2040 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2043 g_enumerate_time_checked
= 0;
2044 g_enumerate_start_time_ms
= grub_get_time_ms();
2046 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2047 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2049 g_filt_dot_underscore_file
= 1;
2052 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2053 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2055 g_sort_case_sensitive
= 1;
2058 device_name
= grub_file_get_device_name(args
[0]);
2064 g_enum_dev
= dev
= grub_device_open(device_name
);
2070 g_enum_fs
= fs
= grub_fs_probe(dev
);
2076 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2078 debug("unsupported fs:<%s>\n", fs
->name
);
2079 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2083 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2085 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2086 if (strdata
&& strdata
[0] == '1')
2088 g_default_menu_mode
= 1;
2091 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2093 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2095 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2096 if (strdata
&& strdata
[0] == '/')
2098 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2099 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2101 g_img_iterator_head
.dir
[len
++] = '/';
2103 g_img_iterator_head
.dirlen
= len
;
2107 g_img_iterator_head
.dirlen
= 1;
2108 grub_strcpy(g_img_iterator_head
.dir
, "/");
2111 g_img_iterator_head
.tail
= &tail
;
2113 if (g_img_max_search_level
< 0)
2115 g_img_max_search_level
= GRUB_INT_MAX
;
2116 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2117 if (strdata
&& ventoy_is_decimal(strdata
))
2119 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2123 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2124 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2125 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2126 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2127 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2128 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2130 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2132 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2135 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2136 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2138 g_tree_view_menu_style
= 1;
2141 ventoy_set_default_menu();
2143 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2145 ventoy_dynamic_tree_menu(node
);
2149 node
= g_img_iterator_head
.next
;
2157 /* sort image list by image name */
2158 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2160 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2162 if (ventoy_cmp_img(cur
, tail
) > 0)
2164 ventoy_swap_img(cur
, tail
);
2169 if (g_default_menu_mode
== 1)
2171 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2172 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2173 " echo 'return ...' \n"
2177 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2179 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2180 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2183 cur
->unsupport
? "[***********] " : "",
2184 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2186 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2189 g_tree_script_buf
[g_tree_script_pos
] = 0;
2190 g_list_script_buf
[g_list_script_pos
] = 0;
2192 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2193 grub_env_set(args
[1], buf
);
2197 check_free(device_name
, grub_free
);
2198 check_free(dev
, grub_device_close
);
2200 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2204 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2206 img_info
*next
= NULL
;
2207 img_info
*cur
= g_ventoy_img_list
;
2220 g_ventoy_img_list
= NULL
;
2221 g_ventoy_img_count
= 0;
2223 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2226 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2229 img_info
*cur
= g_ventoy_img_list
;
2233 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2235 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2238 img_id
= grub_strtol(args
[0], NULL
, 10);
2239 if (img_id
>= g_ventoy_img_count
)
2241 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2244 debug("Find image %ld name \n", img_id
);
2246 while (cur
&& img_id
> 0)
2254 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2257 debug("image name is %s\n", cur
->name
);
2259 grub_env_set(args
[1], cur
->name
);
2261 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2264 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2268 img_info
*cur
= g_ventoy_img_list
;
2274 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2277 len
= (int)grub_strlen(args
[0]);
2281 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2290 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2293 grub_snprintf(id
, sizeof(id
), "VID_%d", cur
->id
);
2294 grub_env_set("chosen", id
);
2295 grub_env_export("chosen");
2297 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2300 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2305 const char *id
= NULL
;
2306 img_info
*cur
= g_ventoy_img_list
;
2310 if (argc
< 1 || argc
> 2)
2312 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2315 id
= grub_env_get("chosen");
2317 pos
= grub_strstr(id
, "VID_");
2320 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2324 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2329 if (img_id
== cur
->id
)
2338 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2341 grub_env_set(args
[0], cur
->path
);
2345 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2346 grub_env_set(args
[1], value
);
2349 g_svd_replace_offset
= 0;
2351 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2354 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2361 device_name
= grub_file_get_device_name(filename
);
2373 pos2
= grub_strstr(pos
, ",");
2376 pos2
= grub_strstr(pos
, ")");
2384 disk
= grub_disk_open(pos
);
2387 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2388 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2389 grub_disk_close(disk
);
2396 grub_free(device_name
);
2400 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2402 eltorito_descriptor desc
;
2404 grub_memset(&desc
, 0, sizeof(desc
));
2405 grub_file_seek(file
, 17 * 2048);
2406 grub_file_read(file
, &desc
, sizeof(desc
));
2408 if (desc
.type
!= 0 || desc
.version
!= 1)
2413 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2414 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2422 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2426 grub_uint8_t buf
[512];
2427 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2429 grub_file_seek(file
, sector
* 2048);
2430 grub_file_read(file
, buf
, sizeof(buf
));
2432 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2434 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2438 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2443 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2445 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2447 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2451 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2453 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2458 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2460 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2462 if (buf
[36] == parttype
[i
])
2464 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2470 debug("%s does not contain efi eltorito\n", file
->name
);
2474 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2477 const char *fs
= NULL
;
2478 const char *cdprompt
= NULL
;
2480 grub_uint8_t chksum
= 0;
2483 disk
= file
->device
->disk
;
2484 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2486 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2487 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2488 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2490 pos
= grub_strstr(file
->name
, "/");
2496 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2498 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2500 param
->vtoy_img_size
= file
->size
;
2502 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2503 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2505 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2507 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2508 param
->vtoy_reserved
[4] = 0;
2509 if (g_ventoy_chain_type
== 1) /* Windows */
2511 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2512 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2514 param
->vtoy_reserved
[4] = 1;
2518 fs
= ventoy_get_env("ventoy_fs_probe");
2519 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2521 param
->vtoy_reserved
[3] = 1;
2524 /* calculate checksum */
2525 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2527 chksum
+= *((grub_uint8_t
*)param
+ i
);
2529 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2534 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2536 grub_uint32_t i
= 0;
2537 grub_uint64_t total
= 0;
2538 grub_uint64_t fileblk
= 0;
2539 ventoy_img_chunk
*chunk
= NULL
;
2541 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2543 chunk
= chunklist
->chunk
+ i
;
2545 if (chunk
->disk_start_sector
<= start
)
2547 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2551 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2554 fileblk
= (file
->size
+ 511) / 512;
2556 if (total
!= fileblk
)
2558 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2559 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2561 debug("maybe img file to be processed.\n");
2571 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2575 grub_uint32_t i
= 0;
2576 grub_uint32_t sector
= 0;
2577 grub_uint32_t count
= 0;
2578 grub_off_t size
= 0;
2579 grub_off_t read
= 0;
2581 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2582 if (fs_type
== ventoy_fs_exfat
)
2584 grub_fat_get_file_chunk(start
, file
, chunklist
);
2586 else if (fs_type
== ventoy_fs_ext
)
2588 grub_ext_get_file_chunk(start
, file
, chunklist
);
2592 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2593 file
->read_hook_data
= chunklist
;
2595 for (size
= file
->size
; size
> 0; size
-= read
)
2597 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2598 grub_file_read(file
, NULL
, read
);
2601 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2603 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2604 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2607 if (ventoy_fs_udf
== fs_type
)
2609 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2611 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2612 chunklist
->chunk
[i
].img_start_sector
= sector
;
2613 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2619 len
= (int)grub_strlen(file
->name
);
2620 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2621 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2622 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2623 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2625 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2627 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2637 chunklist
->chunk
[i
].img_start_sector
= sector
;
2638 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2646 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2650 grub_disk_addr_t start
;
2655 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2658 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2661 g_conf_replace_node
= NULL
;
2662 g_conf_replace_offset
= 0;
2664 if (g_img_chunk_list
.chunk
)
2666 grub_free(g_img_chunk_list
.chunk
);
2669 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2671 grub_file_close(file
);
2672 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2675 /* get image chunk data */
2676 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2677 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2678 if (NULL
== g_img_chunk_list
.chunk
)
2680 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2683 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2684 g_img_chunk_list
.cur_chunk
= 0;
2686 start
= file
->device
->disk
->partition
->start
;
2688 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2690 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2691 grub_file_close(file
);
2695 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2698 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2699 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2702 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2704 grub_uint64_t offset
= 0;
2705 grub_uint32_t align
= 0;
2706 grub_file_t file
= NULL
;
2707 conf_replace
*node
= NULL
;
2713 debug("select conf replace argc:%d\n", argc
);
2720 node
= ventoy_plugin_find_conf_replace(args
[1]);
2723 debug("Conf replace not found for %s\n", args
[1]);
2727 debug("Find conf replace for %s\n", args
[1]);
2729 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2732 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2736 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2737 grub_file_close(file
);
2739 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2742 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2746 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2748 if (align
> vtoy_max_replace_file_size
)
2750 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2754 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2755 g_conf_replace_new_len
= (int)file
->size
;
2756 g_conf_replace_new_len_align
= align
;
2758 g_conf_replace_node
= node
;
2759 g_conf_replace_offset
= offset
+ 2;
2761 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2766 grub_file_close(file
);
2768 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2771 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2776 char configfile
[128];
2777 install_template
*node
= NULL
;
2783 debug("select auto installation argc:%d\n", argc
);
2790 node
= ventoy_plugin_find_install_template(args
[0]);
2793 debug("Auto install template not found for %s\n", args
[0]);
2797 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2799 node
->cursel
= node
->autosel
- 1;
2800 debug("Auto install template auto select %d\n", node
->autosel
);
2804 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2810 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2811 " echo %s\n}\n", "123");
2813 for (i
= 0; i
< node
->templatenum
; i
++)
2815 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2817 node
->templatepath
[i
].path
);
2820 g_ventoy_menu_esc
= 1;
2821 g_ventoy_suppress_esc
= 1;
2823 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2824 grub_script_execute_sourcecode(configfile
);
2826 g_ventoy_menu_esc
= 0;
2827 g_ventoy_suppress_esc
= 0;
2831 node
->cursel
= g_ventoy_last_entry
- 1;
2833 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2836 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2841 char configfile
[128];
2842 persistence_config
*node
;
2848 debug("select persistence argc:%d\n", argc
);
2855 node
= ventoy_plugin_find_persistent(args
[0]);
2858 debug("Persistence image not found for %s\n", args
[0]);
2862 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2864 node
->cursel
= node
->autosel
- 1;
2865 debug("Persistence image auto select %d\n", node
->autosel
);
2869 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2875 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2876 " echo %s\n}\n", "123");
2878 for (i
= 0; i
< node
->backendnum
; i
++)
2880 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2882 node
->backendpath
[i
].path
);
2886 g_ventoy_menu_esc
= 1;
2887 g_ventoy_suppress_esc
= 1;
2889 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2890 grub_script_execute_sourcecode(configfile
);
2892 g_ventoy_menu_esc
= 0;
2893 g_ventoy_suppress_esc
= 0;
2897 node
->cursel
= g_ventoy_last_entry
- 1;
2899 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2902 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2905 ventoy_img_chunk
*cur
;
2911 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2913 cur
= g_img_chunk_list
.chunk
+ i
;
2914 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2915 cur
->img_start_sector
, cur
->img_end_sector
,
2916 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2920 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2923 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2927 ventoy_img_chunk_list chunklist
;
2932 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2935 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2938 /* get image chunk data */
2939 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2940 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2941 if (NULL
== chunklist
.chunk
)
2943 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2946 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2947 chunklist
.cur_chunk
= 0;
2949 ventoy_get_block_list(file
, &chunklist
, 0);
2951 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2953 grub_printf("########## UNSUPPORTED ###############\n");
2956 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2958 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2960 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2961 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2964 grub_printf("\n==================================\n");
2966 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2968 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2969 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2970 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2971 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2972 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2976 grub_free(chunklist
.chunk
);
2977 grub_file_close(file
);
2979 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2982 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2985 ventoy_grub_param_file_replace
*replace
= NULL
;
2993 replace
= &(g_grub_param
->file_replace
);
2994 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2996 replace
->old_name_cnt
= 0;
2997 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2999 replace
->old_name_cnt
++;
3000 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3003 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3006 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3009 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3017 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3018 grub_printf("%s", g_list_script_buf
);
3022 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3023 grub_printf("%s", g_tree_script_buf
);
3029 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3031 img_info
*cur
= g_ventoy_img_list
;
3039 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3040 grub_printf("name:<%s>\n\n", cur
->name
);
3047 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3053 ventoy_plugin_dump_injection();
3058 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3064 ventoy_plugin_dump_auto_install();
3069 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3075 ventoy_plugin_dump_persistence();
3080 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3091 if (args
[0][0] == '0')
3093 return g_ventoy_memdisk_mode
? 0 : 1;
3095 else if (args
[0][0] == '1')
3097 return g_ventoy_iso_raw
? 0 : 1;
3099 else if (args
[0][0] == '2')
3101 return g_ventoy_iso_uefi_drv
? 0 : 1;
3103 else if (args
[0][0] == '3')
3105 return g_ventoy_grub2_mode
? 0 : 1;
3111 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3113 static int configfile_mode
= 0;
3114 char memfile
[128] = {0};
3121 * args[0]: 0:normal 1:configfile
3122 * args[1]: 0:list_buf 1:tree_buf
3127 debug("Invalid argc %d\n", argc
);
3131 if (args
[0][0] == '0')
3133 if (args
[1][0] == '0')
3135 grub_script_execute_sourcecode(g_list_script_buf
);
3139 grub_script_execute_sourcecode(g_tree_script_buf
);
3144 if (configfile_mode
)
3146 debug("Now already in F3 mode %d\n", configfile_mode
);
3150 if (args
[1][0] == '0')
3152 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3153 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3157 g_ventoy_last_entry
= -1;
3158 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3159 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3162 configfile_mode
= 1;
3163 grub_script_execute_sourcecode(memfile
);
3164 configfile_mode
= 0;
3170 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3181 g_ventoy_case_insensitive
= 1;
3182 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3183 g_ventoy_case_insensitive
= 0;
3189 grub_file_close(file
);
3195 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3200 const char *isopath
= NULL
;
3202 ventoy_mbr_head mbr
;
3209 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3212 isopath
= grub_env_get("vtoy_iso_part");
3215 debug("isopath is null %p\n", isopath
);
3219 debug("isopath is %s\n", isopath
);
3221 for (id
= 0; id
< 30 && (find
== 0); id
++)
3223 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3224 if (grub_strstr(isopath
, hdname
))
3226 debug("skip %s ...\n", hdname
);
3230 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3232 disk
= grub_disk_open(hdname
);
3235 debug("%s not exist\n", hdname
);
3239 grub_memset(&mbr
, 0, sizeof(mbr
));
3240 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3242 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3244 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3245 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3248 grub_env_set(args
[0], hdname
);
3252 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3256 debug("read %s failed\n", hdname
);
3259 grub_disk_close(disk
);
3265 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3276 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3279 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3282 debug("failed to open file %s\n", args
[0]);
3286 buf
= grub_malloc(len
);
3293 grub_file_read(file
, buf
, len
- 1);
3295 ventoy_get_line(buf
);
3296 ventoy_set_env(args
[1], buf
);
3300 grub_check_free(buf
);
3301 grub_file_close(file
);
3306 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3311 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3312 "0 %llu linear /dev/ventoy %llu\n",
3313 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3318 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3320 char *device_name
= NULL
;
3321 grub_device_t dev
= NULL
;
3326 g_part_list_pos
= 0;
3327 grub_env_unset("vtoy_img_part_file");
3334 device_name
= grub_file_get_device_name(args
[0]);
3337 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3341 dev
= grub_device_open(device_name
);
3344 debug("grub_device_open failed, %s\n", device_name
);
3348 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3350 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3351 grub_env_set("vtoy_img_part_file", buf
);
3355 check_free(device_name
, grub_free
);
3356 check_free(dev
, grub_device_close
);
3362 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3373 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3376 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3379 debug("failed to open file %s\n", args
[0]);
3383 buf
= grub_malloc(file
->size
+ 1);
3389 buf
[file
->size
] = 0;
3390 grub_file_read(file
, buf
, file
->size
);
3392 if (grub_strstr(buf
, args
[1]))
3399 grub_check_free(buf
);
3400 grub_file_close(file
);
3405 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3411 ventoy_iso9660_vd pvd
;
3418 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3421 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3424 debug("failed to open file %s\n", args
[0]);
3428 grub_file_seek(file
, 16 * 2048);
3429 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3430 if (len
!= sizeof(pvd
))
3432 debug("failed to read pvd %d\n", len
);
3436 grub_memset(buf
, 0, sizeof(buf
));
3437 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3438 ventoy_set_env(args
[1], buf
);
3440 grub_memset(buf
, 0, sizeof(buf
));
3441 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3442 ventoy_set_env(args
[2], buf
);
3446 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3447 ventoy_set_env(args
[3], buf
);
3450 grub_file_close(file
);
3455 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3466 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3469 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3472 debug("failed to open file %s\n", args
[0]);
3476 grub_memset(buf
, 0, sizeof(buf
));
3477 grub_file_seek(file
, 16 * 2048 + 813);
3478 len
= (int)grub_file_read(file
, buf
, 17);
3481 debug("failed to read create date %d\n", len
);
3485 ventoy_set_env(args
[1], buf
);
3488 grub_file_close(file
);
3493 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3499 ventoy_env_hook_root(1);
3504 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3510 ventoy_env_hook_root(0);
3515 #ifdef GRUB_MACHINE_EFI
3516 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3521 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3527 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3528 if (var
&& *var
== 1)
3536 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3545 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3550 grub_uint64_t FileSectors
= 0;
3551 ventoy_gpt_info
*gpt
= NULL
;
3552 ventoy_part_table
*pt
= NULL
;
3553 grub_uint8_t zeroguid
[16] = {0};
3558 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3561 debug("failed to open file %s\n", args
[0]);
3565 if (file
->size
% 512)
3567 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3571 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3577 FileSectors
= file
->size
/ 512;
3579 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3580 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3582 debug("This is EFI partition table\n");
3584 for (i
= 0; i
< 128; i
++)
3586 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3588 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3590 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3591 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3599 debug("This is MBR partition table\n");
3601 for (i
= 0; i
< 4; i
++)
3603 pt
= gpt
->MBR
.PartTbl
+ i
;
3604 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3606 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3607 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3608 (ulonglong
)FileSectors
);
3617 grub_file_close(file
);
3618 grub_check_free(gpt
);
3619 grub_errno
= GRUB_ERR_NONE
;
3623 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3632 for (i
= 0; i
< 500; i
++)
3634 ret
= grub_getkey_noblock();
3635 if (ret
== GRUB_TERM_NO_KEY
)
3644 grub_printf("\n\n Still have key input after clear.\n");
3652 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3659 int image_sector_size
;
3661 ventoy_chain_head
*chain
;
3662 ventoy_img_chunk
*chunk
;
3663 ventoy_os_param
*osparam
;
3664 ventoy_image_location
*location
;
3665 ventoy_image_disk_region
*region
;
3666 struct grub_acpi_table_header
*acpi
;
3675 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3677 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3683 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3685 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3687 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3691 img_chunk_num
= chain
->img_chunk_num
;
3693 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3694 datalen
= sizeof(ventoy_os_param
) + loclen
;
3696 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3697 acpi
= grub_zalloc(buflen
);
3703 /* Step1: Fill acpi table header */
3704 grub_memcpy(acpi
->signature
, "VTOY", 4);
3705 acpi
->length
= buflen
;
3707 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3708 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3710 acpi
->creator_id
[0] = 1;
3711 acpi
->creator_rev
= 1;
3713 /* Step2: Fill data */
3714 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3715 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3716 osparam
->vtoy_img_location_addr
= 0;
3717 osparam
->vtoy_img_location_len
= loclen
;
3718 osparam
->chksum
= 0;
3719 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3721 location
= (ventoy_image_location
*)(osparam
+ 1);
3722 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3723 location
->image_sector_size
= image_sector_size
;
3724 location
->disk_sector_size
= chain
->disk_sector_size
;
3725 location
->region_count
= img_chunk_num
;
3727 region
= location
->regions
;
3728 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3729 if (512 == image_sector_size
)
3731 for (i
= 0; i
< img_chunk_num
; i
++)
3733 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3734 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3735 region
->disk_start_sector
= chunk
->disk_start_sector
;
3742 for (i
= 0; i
< img_chunk_num
; i
++)
3744 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3745 region
->image_start_sector
= chunk
->img_start_sector
;
3746 region
->disk_start_sector
= chunk
->disk_start_sector
;
3752 /* Step3: Fill acpi checksum */
3754 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3756 /* load acpi table */
3757 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3758 grub_script_execute_sourcecode(cmd
);
3762 VENTOY_CMD_RETURN(0);
3765 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3771 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3772 g_ventoy_last_entry
= -1;
3777 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3783 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3788 grub_uint64_t
ventoy_get_part1_size(ventoy_gpt_info
*gpt
)
3790 grub_uint64_t sectors
;
3792 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3794 sectors
= gpt
->PartTbl
[0].LastLBA
+ 1 - gpt
->PartTbl
[0].StartLBA
;
3798 sectors
= gpt
->MBR
.PartTbl
[0].SectorCount
;
3801 return sectors
* 512;
3804 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3806 const char *pos
= filename
+ 1;
3814 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3816 grub_strncpy((char *)data
, filename
, 128);
3827 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3830 char *device_name
= NULL
;
3831 grub_device_t dev
= NULL
;
3832 grub_fs_t fs
= NULL
;
3833 char buf
[128] = {0};
3839 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3843 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3845 device_name
= grub_file_get_device_name(args
[0]);
3848 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3852 dev
= grub_device_open(device_name
);
3855 debug("grub_device_open failed, %s\n", device_name
);
3859 fs
= grub_fs_probe(dev
);
3862 debug("grub_fs_probe failed, %s\n", device_name
);
3866 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3870 ventoy_set_env(args
[2], buf
);
3877 check_free(device_name
, grub_free
);
3878 check_free(dev
, grub_device_close
);
3883 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3893 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3894 if (!g_ventoy_part_info
)
3899 disk
= grub_disk_open(args
[0]);
3902 debug("Failed to open disk %s\n", args
[0]);
3906 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
3908 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3909 grub_disk_close(disk
);
3911 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3912 dev
= grub_device_open(name
);
3915 /* make sure that we are running in a correct Ventoy device */
3916 ret
= ventoy_check_device(dev
);
3917 grub_device_close(dev
);
3928 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3931 const char *vcfg
= NULL
;
3936 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
3939 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
3940 grub_env_set(args
[1], vcfg
);
3945 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
3953 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3956 grub_uint8_t zeroguid
[16] = {0};
3961 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3964 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3966 if (id
>= 1 && id
<= 128)
3968 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3976 if (id
>= 1 && id
<= 4)
3978 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3988 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3991 char *device_name
= NULL
;
3992 grub_device_t dev
= NULL
;
3993 grub_fs_t fs
= NULL
;
3998 debug("get fs label for %s\n", args
[0]);
4002 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4006 device_name
= grub_file_get_device_name(args
[0]);
4009 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4013 dev
= grub_device_open(device_name
);
4016 debug("grub_device_open failed, %s\n", device_name
);
4020 fs
= grub_fs_probe(dev
);
4021 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4023 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4027 fs
->fs_label(dev
, &label
);
4030 debug("label=<%s>\n", label
);
4031 ventoy_set_env(args
[1], label
);
4039 check_free(device_name
, grub_free
);
4040 check_free(dev
, grub_device_close
);
4045 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4049 grub_snprintf((char *)data
, 256, "%s", filename
);
4057 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4060 char *device_name
= NULL
;
4061 grub_device_t dev
= NULL
;
4062 grub_fs_t fs
= NULL
;
4063 char name
[256] ={0};
4069 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
4073 device_name
= grub_file_get_device_name(args
[0]);
4076 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4080 dev
= grub_device_open(device_name
);
4083 debug("grub_device_open failed, %s\n", device_name
);
4087 fs
= grub_fs_probe(dev
);
4090 debug("grub_fs_probe failed, %s\n", device_name
);
4094 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
4097 ventoy_set_env(args
[2], name
);
4104 check_free(device_name
, grub_free
);
4105 check_free(dev
, grub_device_close
);
4110 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4120 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4124 for (pos
= args
[0]; *pos
; pos
++)
4138 grub_env_set(args
[1], args
[0]);
4148 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4158 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4163 len
= (int)grub_strlen(buf
);
4164 for (i
= len
; i
> 0; i
--)
4166 if (buf
[i
- 1] == '/')
4168 grub_env_set(args
[1], buf
+ i
);
4173 grub_env_set(args
[1], buf
);
4178 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4180 struct grub_video_mode_info info
;
4187 if (!g_video_mode_list
)
4189 ventoy_enum_video_mode();
4192 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4194 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4198 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4201 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4203 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4204 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4206 VENTOY_CMD_RETURN(0);
4209 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4211 struct grub_video_mode_info info
;
4218 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4220 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4224 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4227 grub_env_set(args
[0], buf
);
4229 VENTOY_CMD_RETURN(0);
4232 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4240 if (!g_video_mode_list
)
4245 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4246 if (id
< g_video_mode_num
)
4248 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4249 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4252 grub_env_set(args
[1], buf
);
4254 VENTOY_CMD_RETURN(0);
4257 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
4259 grub_uint64_t size
= 0;
4262 char fullpath
[256] = {0};
4265 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4268 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
4271 debug("grub_file_open failed <%s>\n", fullpath
);
4277 grub_file_close(file
);
4281 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
4285 char fullpath
[256] = {0};
4288 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4291 file
= grub_file_open(fullpath
, type
);
4294 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
4301 int ventoy_is_file_exist(const char *fmt
, ...)
4306 char buf
[256] = {0};
4308 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
4312 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4315 grub_strncpy(pos
+ len
, "\" ]", 3);
4317 debug("script exec %s\n", buf
);
4319 if (0 == grub_script_execute_sourcecode(buf
))
4327 int ventoy_is_dir_exist(const char *fmt
, ...)
4332 char buf
[256] = {0};
4334 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
4338 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4341 grub_strncpy(pos
+ len
, "\" ]", 3);
4343 debug("script exec %s\n", buf
);
4345 if (0 == grub_script_execute_sourcecode(buf
))
4353 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
4356 grub_uint8_t
*outbuf
;
4357 grub_uint8_t gzHdr
[10] =
4359 0x1F, 0x8B, /* magic */
4362 0,0,0,0, /* mtime */
4367 grub_memset(&s
, 0, sizeof(mz_stream
));
4369 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
4371 outbuf
= (grub_uint8_t
*)mem_out
;
4373 mem_out_len
-= sizeof(gzHdr
) + 8;
4374 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
4375 outbuf
+= sizeof(gzHdr
);
4377 s
.avail_in
= mem_in_len
;
4380 s
.avail_out
= mem_out_len
;
4381 s
.next_out
= outbuf
;
4383 mz_deflate(&s
, MZ_FINISH
);
4387 outbuf
+= s
.total_out
;
4388 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
4389 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
4391 return s
.total_out
+ sizeof(gzHdr
) + 8;
4394 static int ventoy_env_init(void)
4398 grub_env_set("vtdebug_flag", "");
4400 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4401 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4402 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4403 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4405 ventoy_filt_register(0, ventoy_wrapper_open
);
4407 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4410 g_grub_param
->grub_env_get
= grub_env_get
;
4411 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4412 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4413 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4414 grub_env_set("env_param", buf
);
4415 grub_env_set("ventoy_env_param", buf
);
4417 grub_env_export("env_param");
4418 grub_env_export("ventoy_env_param");
4424 static cmd_para ventoy_cmds
[] =
4426 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4427 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4428 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4429 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4430 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4431 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4432 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4433 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4434 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4435 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4436 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4437 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4438 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4439 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4440 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4441 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4442 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4443 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4444 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4445 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4446 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4447 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4448 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4449 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4451 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4452 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4453 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4454 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4455 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4456 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4457 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4459 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4460 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4461 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4462 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4463 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4464 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4465 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4466 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4467 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4470 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4471 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4472 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4473 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4474 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4475 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4476 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4477 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4478 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4479 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4480 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4482 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4483 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4484 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4485 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4486 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4487 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4489 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4490 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4491 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4492 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4493 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4494 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4495 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4496 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4497 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4498 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4500 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4501 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4502 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4503 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4504 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4505 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4506 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4507 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4509 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4510 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4511 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4514 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4515 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4516 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4518 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4519 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4520 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4523 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4524 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4525 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4526 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4527 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
4528 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4529 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4530 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4531 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4532 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4533 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4535 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4536 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4537 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4538 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4539 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
4540 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
4546 GRUB_MOD_INIT(ventoy
)
4549 cmd_para
*cur
= NULL
;
4553 ventoy_arch_mode_init();
4555 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4557 cur
= ventoy_cmds
+ i
;
4558 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4559 cur
->summary
, cur
->description
, cur
->parser
);
4563 GRUB_MOD_FINI(ventoy
)
4567 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4569 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);