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
;
131 static const char *g_menu_class
[] =
133 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
136 static const char *g_menu_prefix
[] =
138 "iso", "wim", "efi", "img", "vhd", "vtoy"
141 void ventoy_debug(const char *fmt
, ...)
145 va_start (args
, fmt
);
146 grub_vprintf (fmt
, args
);
150 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
160 for (i
= 0; i
< 16; i
++)
162 grub_printf("%02x ", guid
[i
]);
167 int ventoy_is_efi_os(void)
171 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
177 static int ventoy_get_fs_type(const char *fs
)
181 return ventoy_fs_max
;
183 else if (grub_strncmp(fs
, "exfat", 5) == 0)
185 return ventoy_fs_exfat
;
187 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
189 return ventoy_fs_ntfs
;
191 else if (grub_strncmp(fs
, "ext", 3) == 0)
193 return ventoy_fs_ext
;
195 else if (grub_strncmp(fs
, "xfs", 3) == 0)
197 return ventoy_fs_xfs
;
199 else if (grub_strncmp(fs
, "udf", 3) == 0)
201 return ventoy_fs_udf
;
203 else if (grub_strncmp(fs
, "fat", 3) == 0)
205 return ventoy_fs_fat
;
208 return ventoy_fs_max
;
211 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
230 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
232 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
236 static grub_err_t
ventoy_fs_close(grub_file_t file
)
238 grub_file_close(g_old_file
);
239 grub_free(file
->data
);
247 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
253 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
258 for (i
= 0; i
< g_video_mode_num
; i
++)
260 if (g_video_mode_list
[i
].width
== info
->width
&&
261 g_video_mode_list
[i
].height
== info
->height
&&
262 g_video_mode_list
[i
].bpp
== info
->bpp
)
268 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
269 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
270 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
273 if (g_video_mode_num
== g_video_mode_max
)
275 g_video_mode_max
*= 2;
276 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
282 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
284 if (v1
->bpp
== v2
->bpp
)
286 if (v1
->width
== v2
->width
)
288 if (v1
->height
== v2
->height
)
294 return (v1
->height
< v2
->height
) ? -1 : 1;
299 return (v1
->width
< v2
->width
) ? -1 : 1;
304 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
308 static int ventoy_enum_video_mode(void)
311 grub_video_adapter_t adapter
;
312 grub_video_driver_id_t id
;
313 ventoy_video_mode mode
;
315 g_video_mode_num
= 0;
316 g_video_mode_max
= 1024;
317 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
318 if (!g_video_mode_list
)
323 #ifdef GRUB_MACHINE_PCBIOS
324 grub_dl_load ("vbe");
327 id
= grub_video_get_driver_id ();
329 FOR_VIDEO_ADAPTERS (adapter
)
331 if (!adapter
->iterate
||
332 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
333 adapter
->init() != GRUB_ERR_NONE
)))
338 adapter
->iterate(ventoy_video_hook
, NULL
);
340 if (adapter
->id
!= id
)
346 /* sort video mode */
347 for (i
= 0; i
< g_video_mode_num
; i
++)
348 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
350 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
352 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
353 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
354 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
358 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
361 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
365 static struct grub_fs vtoy_fs
=
370 .fs_read
= ventoy_fs_read
,
371 .fs_close
= ventoy_fs_close
,
381 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
387 file
->data
= grub_malloc(rawFile
->size
+ 4096);
393 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
394 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
396 g_old_file
= rawFile
;
398 file
->size
= rawFile
->size
+ len
;
399 file
->device
= rawFile
->device
;
401 file
->not_easily_seekable
= 1;
406 static int ventoy_check_decimal_var(const char *name
, long *value
)
408 const char *value_str
= NULL
;
410 value_str
= grub_env_get(name
);
411 if (NULL
== value_str
)
413 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
416 if (!ventoy_is_decimal(value_str
))
418 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
421 *value
= grub_strtol(value_str
, NULL
, 10);
423 return GRUB_ERR_NONE
;
426 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
430 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
433 if (0 == grub_strcmp(args
[0], "on"))
436 grub_env_set("vtdebug_flag", "debug");
441 grub_env_set("vtdebug_flag", "");
444 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
447 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
451 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
453 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
454 grub_printf(" level:\r\n");
455 grub_printf(" 01/11: busybox / (+cat log)\r\n");
456 grub_printf(" 02/12: initrd / (+cat log)\r\n");
457 grub_printf(" 03/13: hook / (+cat log)\r\n");
459 grub_printf(" debug:\r\n");
460 grub_printf(" 0: debug is off\r\n");
461 grub_printf(" 1: debug is on\r\n");
463 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
466 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
468 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
470 g_ventoy_debug_level
= 1;
473 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
476 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
485 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
488 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
520 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
525 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
527 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
530 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
535 value_long
+= grub_strtol(args
[1], NULL
, 10);
537 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
538 grub_env_set(args
[0], buf
);
540 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
543 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
545 ulonglong value1
= 0;
546 ulonglong value2
= 0;
551 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
554 value1
= grub_strtoull(args
[0], NULL
, 10);
555 value2
= grub_strtoull(args
[1], NULL
, 10);
557 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
558 grub_env_set(args
[2], buf
);
560 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
563 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
578 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
581 debug("failed to open file <%s> for udf check\n", args
[0]);
585 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
587 grub_env_set(args
[1], buf
);
589 grub_file_close(file
);
595 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
603 g_wimboot_enable
= 0;
604 grub_check_free(g_wimiso_path
);
605 grub_check_free(g_wimiso_chunk_list
.chunk
);
607 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
613 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
614 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
615 if (NULL
== g_wimiso_chunk_list
.chunk
)
617 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
620 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
621 g_wimiso_chunk_list
.cur_chunk
= 0;
623 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
625 g_wimboot_enable
= 1;
626 g_wimiso_path
= grub_strdup(args
[0]);
628 grub_file_close(file
);
633 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
639 grub_uint32_t offset
;
641 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
644 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
648 len
= (int)file
->size
;
650 data
= (char *)grub_malloc(file
->size
);
656 grub_file_read(file
, data
, file
->size
);
657 grub_file_close(file
);
659 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
660 grub_script_execute_sourcecode(exec
);
662 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
663 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
664 grub_file_close(file
);
666 grub_script_execute_sourcecode("loopback -d efiboot");
670 *direntoff
= offset
+ 2;
675 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
685 ventoy_iso9660_override
*dirent
;
694 totlen
= sizeof(ventoy_chain_head
);
696 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
698 debug("failed to load efiboot template %d\n", len
);
704 debug("efiboot template len:%d offset:%d\n", len
, offset
);
706 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
709 debug("failed to open file <%s>\n", args
[0]);
713 totlen
+= ventoy_align_2k(file
->size
);
715 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
716 dirent
->first_sector
= len
/ 2048;
717 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
718 dirent
->size
= (grub_uint32_t
)file
->size
;
719 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
721 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
723 #ifdef GRUB_MACHINE_EFI
724 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
726 data
= (char *)grub_malloc(totlen
);
729 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
731 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
732 grub_check_free(buf
);
734 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
735 grub_file_close(file
);
737 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
738 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
739 grub_env_set(name
, value
);
741 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
742 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
743 grub_env_set(name
, value
);
748 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
765 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
768 debug("failed to open file <%s>\n", args
[0]);
772 #ifdef GRUB_MACHINE_EFI
773 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
775 buf
= (char *)grub_malloc(file
->size
);
778 grub_file_read(file
, buf
, file
->size
);
780 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
781 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
782 grub_env_set(name
, value
);
784 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
785 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
786 grub_env_set(name
, value
);
788 grub_file_close(file
);
794 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
812 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
815 debug("failed to open file <%s> for udf check\n", args
[0]);
819 headlen
= sizeof(ventoy_chain_head
);
821 #ifdef GRUB_MACHINE_EFI
822 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
824 buf
= (char *)grub_malloc(headlen
+ file
->size
);
827 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
829 grub_file_read(file
, buf
+ headlen
, file
->size
);
831 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
832 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
833 grub_env_set(name
, value
);
835 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
836 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
837 grub_env_set(name
, value
);
839 grub_file_close(file
);
845 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
854 if (args
[0][0] == '1')
856 grub_iso9660_set_nojoliet(1);
860 grub_iso9660_set_nojoliet(0);
866 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
871 grub_uint8_t buf
[32];
882 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
885 debug("failed to open file <%s> for udf check\n", args
[0]);
889 for (i
= 16; i
< 32; i
++)
891 grub_file_seek(file
, i
* 2048);
892 grub_file_read(file
, buf
, sizeof(buf
));
900 grub_file_seek(file
, i
* 2048);
901 grub_file_read(file
, buf
, sizeof(buf
));
903 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
906 grub_file_seek(file
, i
* 2048);
907 grub_file_read(file
, buf
, sizeof(buf
));
909 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
910 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
916 grub_file_close(file
);
918 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
923 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
925 long value_long1
= 0;
926 long value_long2
= 0;
928 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
930 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
933 value_long1
= grub_strtol(args
[0], NULL
, 10);
934 value_long2
= grub_strtol(args
[2], NULL
, 10);
936 if (0 == grub_strcmp(args
[1], "eq"))
938 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
940 else if (0 == grub_strcmp(args
[1], "ne"))
942 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
944 else if (0 == grub_strcmp(args
[1], "gt"))
946 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
948 else if (0 == grub_strcmp(args
[1], "lt"))
950 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
952 else if (0 == grub_strcmp(args
[1], "ge"))
954 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
956 else if (0 == grub_strcmp(args
[1], "le"))
958 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
962 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
968 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
975 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
978 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
979 pos
= grub_strstr(buf
, ",");
985 grub_env_set(args
[1], buf
);
987 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
990 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
996 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1002 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1005 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1007 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1008 if (0 == grub_script_execute_sourcecode(buf
))
1010 debug("file %s exist, ventoy_compatible YES\n", buf
);
1011 grub_env_set("ventoy_compatible", "YES");
1012 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1016 debug("file %s NOT exist\n", buf
);
1020 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1021 pos
= grub_strstr(buf
, ")");
1027 disk
= grub_disk_open(buf
);
1030 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1031 grub_disk_close(disk
);
1033 g_img_swap_tmp_buf
[703] = 0;
1034 for (i
= 318; i
< 703; i
++)
1036 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1037 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1039 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1040 grub_env_set("ventoy_compatible", "YES");
1041 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1047 debug("failed to open disk <%s>\n", buf
);
1050 grub_env_set("ventoy_compatible", "NO");
1051 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1054 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1060 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1062 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1065 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1070 if (0 == g_sort_case_sensitive
)
1072 if (grub_islower(c1
))
1074 c1
= c1
- 'a' + 'A';
1077 if (grub_islower(c2
))
1079 c2
= c2
- 'a' + 'A';
1092 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1098 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1100 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1103 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1108 if (0 == g_sort_case_sensitive
)
1110 if (grub_islower(c1
))
1112 c1
= c1
- 'a' + 'A';
1115 if (grub_islower(c2
))
1117 c2
= c2
- 'a' + 'A';
1130 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1132 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1134 grub_memcpy(img1
, img2
, sizeof(img_info
));
1135 img1
->next
= g_img_swap_tmp
.next
;
1136 img1
->prev
= g_img_swap_tmp
.prev
;
1138 g_img_swap_tmp
.next
= img2
->next
;
1139 g_img_swap_tmp
.prev
= img2
->prev
;
1140 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1143 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1147 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1155 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1159 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1169 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1178 img_iterator_node
*tmp
;
1179 img_iterator_node
*new_node
;
1180 img_iterator_node
*node
= (img_iterator_node
*)data
;
1182 if (g_enumerate_time_checked
== 0)
1184 g_enumerate_finish_time_ms
= grub_get_time_ms();
1185 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1188 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1190 g_enumerate_time_checked
= 1;
1194 len
= grub_strlen(filename
);
1198 if (node
->level
+ 1 > g_img_max_search_level
)
1203 if ((len
== 1 && filename
[0] == '.') ||
1204 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1209 if (!ventoy_img_name_valid(filename
, len
))
1214 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1219 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1221 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1222 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1225 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1230 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1233 new_node
->level
= node
->level
+ 1;
1234 new_node
->plugin_list_index
= index
;
1235 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1237 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1240 debug("Directory %s ignored...\n", new_node
->dir
);
1241 grub_free(new_node
);
1245 new_node
->tail
= node
->tail
;
1247 new_node
->parent
= node
;
1248 if (!node
->firstchild
)
1250 node
->firstchild
= new_node
;
1253 if (g_img_iterator_tail
)
1255 g_img_iterator_tail
->next
= new_node
;
1256 g_img_iterator_tail
= new_node
;
1260 g_img_iterator_head
.next
= new_node
;
1261 g_img_iterator_tail
= new_node
;
1267 debug("Find a file %s\n", filename
);
1273 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1275 type
= img_type_iso
;
1277 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1279 type
= img_type_wim
;
1281 else if (g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1282 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1284 type
= img_type_vhd
;
1286 #ifdef GRUB_MACHINE_EFI
1287 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1289 type
= img_type_efi
;
1292 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1294 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1296 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1297 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1302 type
= img_type_img
;
1304 else if (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1306 type
= img_type_vtoy
;
1308 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1310 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1312 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1313 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1322 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1327 if (g_plugin_image_list
)
1329 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1330 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1331 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1333 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1336 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1338 debug("File %s found in image_blacklist plugin config...\n", g_img_swap_tmp_buf
);
1343 img
= grub_zalloc(sizeof(img_info
));
1347 img
->plugin_list_index
= index
;
1348 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1350 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1352 img
->size
= info
->size
;
1355 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1358 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1360 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1365 if (g_ventoy_img_list
)
1367 tail
= *(node
->tail
);
1373 g_ventoy_img_list
= img
;
1376 img
->id
= g_ventoy_img_count
;
1378 if (node
&& NULL
== node
->firstiso
)
1380 node
->firstiso
= img
;
1391 *((img_info
**)(node
->tail
)) = img
;
1392 g_ventoy_img_count
++;
1394 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1395 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1398 img
->class = g_menu_class
[type
];
1400 img
->menu_prefix
= g_menu_prefix
[type
];
1402 if (img_type_iso
== type
)
1404 if (ventoy_plugin_check_memdisk(img
->path
))
1406 img
->menu_prefix
= "miso";
1410 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1417 static int ventoy_arch_mode_init(void)
1419 #ifdef GRUB_MACHINE_EFI
1420 if (grub_strcmp(GRUB_TARGET_CPU
, "i386") == 0)
1422 g_ventoy_plat_data
= VTOY_PLAT_I386_UEFI
;
1423 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "ia32");
1425 else if (grub_strcmp(GRUB_TARGET_CPU
, "arm64") == 0)
1427 g_ventoy_plat_data
= VTOY_PLAT_ARM64_UEFI
;
1428 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "aa64");
1430 else if (grub_strcmp(GRUB_TARGET_CPU
, "mips64el") == 0)
1432 g_ventoy_plat_data
= VTOY_PLAT_MIPS_UEFI
;
1433 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "mips");
1437 g_ventoy_plat_data
= VTOY_PLAT_X86_64_UEFI
;
1438 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "uefi");
1441 g_ventoy_plat_data
= VTOY_PLAT_X86_LEGACY
;
1442 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "legacy");
1448 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1450 int len
= GRUB_UINT_MAX
;
1451 const char *value
= NULL
;
1452 char name
[32] = {0};
1453 char plat
[32] = {0};
1454 char guidstr
[32] = {0};
1455 ventoy_guid guid
= VENTOY_GUID
;
1456 const char *fmt1
= NULL
;
1457 const char *fmt2
= NULL
;
1458 const char *fmt3
= NULL
;
1459 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1460 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1461 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1462 const char fmtcode
[]={
1463 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1464 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1465 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1466 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1467 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1468 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1471 grub_memset(name
, 0, sizeof(name
));
1472 puint
[0] = grub_swap_bytes32(0x56454e54);
1473 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1474 puint
[2] = grub_swap_bytes32(0x45525349);
1475 puint
[1] = grub_swap_bytes32(0x4f595f56);
1476 value
= ventoy_get_env(name
);
1478 grub_memset(name
, 0, sizeof(name
));
1479 puint
[1] = grub_swap_bytes32(0x5f544f50);
1480 puint
[0] = grub_swap_bytes32(0x56544c45);
1481 fmt1
= ventoy_get_env(name
);
1487 grub_memset(name
, 0, sizeof(name
));
1488 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1489 puint
[0] = grub_swap_bytes32(0x56544c45);
1490 fmt2
= ventoy_get_env(name
);
1492 grub_memset(name
, 0, sizeof(name
));
1493 puint
[1] = grub_swap_bytes32(0x5f434c52);
1494 puint
[0] = grub_swap_bytes32(0x56544c45);
1495 fmt3
= ventoy_get_env(name
);
1497 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1499 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1501 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1502 #pragma GCC diagnostic push
1503 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1504 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1505 fmt1
? fmt1
: fmtdata
,
1506 fmt2
? fmt2
: fmtdata
+ 4,
1507 value
? value
: "", plat
, guidstr
,
1508 fmt3
? fmt3
: fmtdata
+ 6);
1509 #pragma GCC diagnostic pop
1511 grub_memset(name
, 0, sizeof(name
));
1512 puint
[0] = grub_swap_bytes32(0x76746f79);
1513 puint
[2] = grub_swap_bytes32(0x656e7365);
1514 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1515 ventoy_set_env(name
, guidstr
);
1520 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1524 grub_uint8_t md5
[16];
1528 grub_memset(input
, 0, sizeof(input
));
1530 grub_printf("Enter password: ");
1533 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1535 grub_password_get(input
, 128);
1536 if (grub_strcmp(pwd
->text
, input
) == 0)
1541 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1543 grub_password_get(input
, 128);
1544 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1545 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1550 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1552 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1553 grub_password_get(input
+ offset
, 128);
1555 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1556 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1562 grub_printf("Invalid password!\n\n");
1569 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1571 img_info
*minimg
= NULL
;
1572 img_info
*img
= (img_info
*)(node
->firstiso
);
1574 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1576 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1591 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1593 img_iterator_node
*Minchild
= NULL
;
1594 img_iterator_node
*child
= node
->firstchild
;
1596 while (child
&& child
->parent
== node
)
1598 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1602 child
= child
->next
;
1607 Minchild
->select
= 1;
1613 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1616 img_info
*img
= NULL
;
1617 const char *dir_class
= NULL
;
1618 const char *dir_alias
= NULL
;
1619 img_iterator_node
*child
= NULL
;
1621 if (node
->isocnt
== 0 || node
->done
== 1)
1626 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1628 offset
= node
->parent
->dirlen
;
1631 if (node
== &g_img_iterator_head
)
1633 if (g_default_menu_mode
== 0)
1635 if (g_tree_view_menu_style
== 0)
1637 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1638 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1639 " echo 'return ...' \n"
1644 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1645 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1653 node
->dir
[node
->dirlen
- 1] = 0;
1654 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1657 dir_class
= "vtoydir";
1660 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1663 if (g_tree_view_menu_style
== 0)
1665 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1666 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1667 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1671 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1672 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1673 dir_alias
, dir_class
, node
->dir
+ offset
);
1678 dir_alias
= node
->dir
+ offset
;
1680 if (g_tree_view_menu_style
== 0)
1682 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1683 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1684 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1688 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1689 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1690 dir_alias
, dir_class
, node
->dir
+ offset
);
1694 if (g_tree_view_menu_style
== 0)
1696 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1697 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1698 " echo 'return ...' \n"
1703 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1704 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1710 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1712 ventoy_dynamic_tree_menu(child
);
1715 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1717 if (g_tree_view_menu_style
== 0)
1719 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1720 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1723 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1724 img
->unsupport
? "[***********] " : "",
1725 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1727 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1731 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1732 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1735 img
->unsupport
? "[***********] " : "",
1736 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1738 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1742 if (node
!= &g_img_iterator_head
)
1744 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1751 int ventoy_check_device_result(int ret
)
1755 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1756 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1757 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1761 grub_printf(VTOY_WARNING
"\n");
1762 grub_printf(VTOY_WARNING
"\n");
1763 grub_printf(VTOY_WARNING
"\n\n\n");
1765 grub_printf("This is NOT a standard Ventoy device and is NOT supported.\n\n");
1766 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1768 grub_printf("\n\nWill exit after 10 seconds ...... ");
1776 int ventoy_check_device(grub_device_t dev
)
1780 grub_uint64_t offset
;
1785 struct grub_partition
*partition
;
1787 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1789 return ventoy_check_device_result(1 | 0x1000);
1792 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1793 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1794 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1796 #ifndef GRUB_MACHINE_EFI
1797 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1798 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
1799 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1801 return ventoy_check_device_result(2 | 0x1000);
1810 /* We must have partition 2 */
1813 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
1817 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1821 return ventoy_check_device_result(3 | 0x1000);
1824 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1826 grub_file_close(file
);
1827 return ventoy_check_device_result(4 | 0x1000);
1830 partition
= dev
->disk
->partition
;
1831 if (partition
->number
!= 0 || partition
->start
!= 2048)
1833 return ventoy_check_device_result(5);
1838 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
1840 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
1841 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
1842 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
1844 grub_file_close(file
);
1845 return ventoy_check_device_result(6);
1850 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
1851 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
1852 PartTbl
[1].SectorCount
!= 65536)
1854 grub_file_close(file
);
1855 return ventoy_check_device_result(6);
1861 offset
= partition
->start
+ partition
->len
;
1862 partition
= file
->device
->disk
->partition
;
1863 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1865 grub_file_close(file
);
1866 return ventoy_check_device_result(7);
1870 grub_file_close(file
);
1872 if (workaround
== 0)
1874 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1875 dev2
= grub_device_open(devname
);
1878 return ventoy_check_device_result(8);
1881 fs
= grub_fs_probe(dev2
);
1884 grub_device_close(dev2
);
1885 return ventoy_check_device_result(9);
1888 fs
->fs_label(dev2
, &label
);
1889 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1891 grub_device_close(dev2
);
1892 return ventoy_check_device_result(10);
1895 grub_device_close(dev2
);
1898 return ventoy_check_device_result(0);
1901 static int ventoy_set_default_menu(void)
1907 const char *strdata
= NULL
;
1908 img_info
*cur
= NULL
;
1909 img_info
*default_node
= NULL
;
1910 const char *default_image
= NULL
;
1912 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1913 if (default_image
&& default_image
[0] == '/')
1915 img_len
= grub_strlen(default_image
);
1917 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1919 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1931 if (0 == g_default_menu_mode
)
1933 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1937 def
= grub_strdup(default_image
);
1943 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1945 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1946 if (strdata
&& strdata
[0] == '/')
1948 pos
= def
+ grub_strlen(strdata
);
1959 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1962 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1966 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1974 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1978 grub_device_t dev
= NULL
;
1979 img_info
*cur
= NULL
;
1980 img_info
*tail
= NULL
;
1981 const char *strdata
= NULL
;
1982 char *device_name
= NULL
;
1984 img_iterator_node
*node
= NULL
;
1985 img_iterator_node
*tmp
= NULL
;
1991 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1994 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1996 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1999 g_enumerate_time_checked
= 0;
2000 g_enumerate_start_time_ms
= grub_get_time_ms();
2002 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2003 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2005 g_filt_dot_underscore_file
= 1;
2008 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2009 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2011 g_sort_case_sensitive
= 1;
2014 device_name
= grub_file_get_device_name(args
[0]);
2020 g_enum_dev
= dev
= grub_device_open(device_name
);
2026 g_enum_fs
= fs
= grub_fs_probe(dev
);
2032 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2034 debug("unsupported fs:<%s>\n", fs
->name
);
2035 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2039 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2041 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2042 if (strdata
&& strdata
[0] == '1')
2044 g_default_menu_mode
= 1;
2047 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2049 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2051 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2052 if (strdata
&& strdata
[0] == '/')
2054 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2055 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2057 g_img_iterator_head
.dir
[len
++] = '/';
2059 g_img_iterator_head
.dirlen
= len
;
2063 g_img_iterator_head
.dirlen
= 1;
2064 grub_strcpy(g_img_iterator_head
.dir
, "/");
2067 g_img_iterator_head
.tail
= &tail
;
2069 if (g_img_max_search_level
< 0)
2071 g_img_max_search_level
= GRUB_INT_MAX
;
2072 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2073 if (strdata
&& ventoy_is_decimal(strdata
))
2075 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2079 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2081 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2084 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2085 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2087 g_tree_view_menu_style
= 1;
2090 ventoy_set_default_menu();
2092 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2094 ventoy_dynamic_tree_menu(node
);
2098 node
= g_img_iterator_head
.next
;
2106 /* sort image list by image name */
2107 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2109 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2111 if (ventoy_cmp_img(cur
, tail
) > 0)
2113 ventoy_swap_img(cur
, tail
);
2118 if (g_default_menu_mode
== 1)
2120 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2121 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2122 " echo 'return ...' \n"
2126 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2128 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2129 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2132 cur
->unsupport
? "[***********] " : "",
2133 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2135 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2138 g_tree_script_buf
[g_tree_script_pos
] = 0;
2139 g_list_script_buf
[g_list_script_pos
] = 0;
2141 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2142 grub_env_set(args
[1], buf
);
2146 check_free(device_name
, grub_free
);
2147 check_free(dev
, grub_device_close
);
2149 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2153 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2155 img_info
*next
= NULL
;
2156 img_info
*cur
= g_ventoy_img_list
;
2169 g_ventoy_img_list
= NULL
;
2170 g_ventoy_img_count
= 0;
2172 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2175 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2178 img_info
*cur
= g_ventoy_img_list
;
2182 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2184 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2187 img_id
= grub_strtol(args
[0], NULL
, 10);
2188 if (img_id
>= g_ventoy_img_count
)
2190 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2193 debug("Find image %ld name \n", img_id
);
2195 while (cur
&& img_id
> 0)
2203 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2206 debug("image name is %s\n", cur
->name
);
2208 grub_env_set(args
[1], cur
->name
);
2210 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2213 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2218 const char *id
= NULL
;
2219 img_info
*cur
= g_ventoy_img_list
;
2223 if (argc
< 1 || argc
> 2)
2225 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2228 id
= grub_env_get("chosen");
2230 pos
= grub_strstr(id
, "VID_");
2233 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2237 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2242 if (img_id
== cur
->id
)
2251 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2254 grub_env_set(args
[0], cur
->path
);
2258 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2259 grub_env_set(args
[1], value
);
2262 g_svd_replace_offset
= 0;
2264 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2267 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2274 device_name
= grub_file_get_device_name(filename
);
2286 pos2
= grub_strstr(pos
, ",");
2289 pos2
= grub_strstr(pos
, ")");
2297 disk
= grub_disk_open(pos
);
2300 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2301 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2302 grub_disk_close(disk
);
2309 grub_free(device_name
);
2313 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2315 eltorito_descriptor desc
;
2317 grub_memset(&desc
, 0, sizeof(desc
));
2318 grub_file_seek(file
, 17 * 2048);
2319 grub_file_read(file
, &desc
, sizeof(desc
));
2321 if (desc
.type
!= 0 || desc
.version
!= 1)
2326 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2327 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2335 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2339 grub_uint8_t buf
[512];
2340 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2342 grub_file_seek(file
, sector
* 2048);
2343 grub_file_read(file
, buf
, sizeof(buf
));
2345 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2347 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2351 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2356 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2358 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2360 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2364 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2366 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2371 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2373 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2375 if (buf
[36] == parttype
[i
])
2377 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2383 debug("%s does not contain efi eltorito\n", file
->name
);
2387 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2390 const char *fs
= NULL
;
2391 const char *cdprompt
= NULL
;
2393 grub_uint8_t chksum
= 0;
2396 disk
= file
->device
->disk
;
2397 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2399 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2400 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2401 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2403 pos
= grub_strstr(file
->name
, "/");
2409 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2411 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2413 param
->vtoy_img_size
= file
->size
;
2415 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2416 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2418 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2420 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2421 param
->vtoy_reserved
[4] = 0;
2422 if (g_ventoy_chain_type
== 1) /* Windows */
2424 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2425 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2427 param
->vtoy_reserved
[4] = 1;
2431 fs
= ventoy_get_env("ventoy_fs_probe");
2432 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2434 param
->vtoy_reserved
[3] = 1;
2437 /* calculate checksum */
2438 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2440 chksum
+= *((grub_uint8_t
*)param
+ i
);
2442 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2447 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2449 grub_uint32_t i
= 0;
2450 grub_uint64_t total
= 0;
2451 ventoy_img_chunk
*chunk
= NULL
;
2453 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2455 chunk
= chunklist
->chunk
+ i
;
2457 if (chunk
->disk_start_sector
<= start
)
2459 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2463 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2466 if (total
!= ((file
->size
+ 511) / 512))
2468 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2475 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2479 grub_uint32_t i
= 0;
2480 grub_uint32_t sector
= 0;
2481 grub_uint32_t count
= 0;
2482 grub_off_t size
= 0;
2483 grub_off_t read
= 0;
2485 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2486 if (fs_type
== ventoy_fs_exfat
)
2488 grub_fat_get_file_chunk(start
, file
, chunklist
);
2490 else if (fs_type
== ventoy_fs_ext
)
2492 grub_ext_get_file_chunk(start
, file
, chunklist
);
2496 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2497 file
->read_hook_data
= chunklist
;
2499 for (size
= file
->size
; size
> 0; size
-= read
)
2501 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2502 grub_file_read(file
, NULL
, read
);
2505 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2507 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2508 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2511 if (ventoy_fs_udf
== fs_type
)
2513 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2515 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2516 chunklist
->chunk
[i
].img_start_sector
= sector
;
2517 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2523 len
= (int)grub_strlen(file
->name
);
2524 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2525 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2526 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2527 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2529 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2531 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2541 chunklist
->chunk
[i
].img_start_sector
= sector
;
2542 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2550 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2554 grub_disk_addr_t start
;
2559 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2562 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2565 g_conf_replace_node
= NULL
;
2566 g_conf_replace_offset
= 0;
2568 if (g_img_chunk_list
.chunk
)
2570 grub_free(g_img_chunk_list
.chunk
);
2573 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2575 grub_file_close(file
);
2576 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2579 /* get image chunk data */
2580 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2581 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2582 if (NULL
== g_img_chunk_list
.chunk
)
2584 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2587 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2588 g_img_chunk_list
.cur_chunk
= 0;
2590 start
= file
->device
->disk
->partition
->start
;
2592 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2594 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2595 grub_file_close(file
);
2599 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2602 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2603 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2606 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2608 grub_uint64_t offset
= 0;
2609 grub_uint32_t align
= 0;
2610 grub_file_t file
= NULL
;
2611 conf_replace
*node
= NULL
;
2617 debug("select conf replace argc:%d\n", argc
);
2624 node
= ventoy_plugin_find_conf_replace(args
[1]);
2627 debug("Conf replace not found for %s\n", args
[1]);
2631 debug("Find conf replace for %s\n", args
[1]);
2633 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2636 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2640 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2641 grub_file_close(file
);
2643 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2646 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2650 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2652 if (align
> vtoy_max_replace_file_size
)
2654 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2658 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2659 g_conf_replace_new_len
= (int)file
->size
;
2660 g_conf_replace_new_len_align
= align
;
2662 g_conf_replace_node
= node
;
2663 g_conf_replace_offset
= offset
+ 2;
2665 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2670 grub_file_close(file
);
2672 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2675 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2680 char configfile
[128];
2681 install_template
*node
= NULL
;
2687 debug("select auto installation argc:%d\n", argc
);
2694 node
= ventoy_plugin_find_install_template(args
[0]);
2697 debug("Auto install template not found for %s\n", args
[0]);
2701 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2703 node
->cursel
= node
->autosel
- 1;
2704 debug("Auto install template auto select %d\n", node
->autosel
);
2708 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2714 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2715 " echo %s\n}\n", "123");
2717 for (i
= 0; i
< node
->templatenum
; i
++)
2719 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2721 node
->templatepath
[i
].path
);
2724 g_ventoy_menu_esc
= 1;
2725 g_ventoy_suppress_esc
= 1;
2727 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2728 grub_script_execute_sourcecode(configfile
);
2730 g_ventoy_menu_esc
= 0;
2731 g_ventoy_suppress_esc
= 0;
2735 node
->cursel
= g_ventoy_last_entry
- 1;
2737 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2740 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2745 char configfile
[128];
2746 persistence_config
*node
;
2752 debug("select persistence argc:%d\n", argc
);
2759 node
= ventoy_plugin_find_persistent(args
[0]);
2762 debug("Persistence image not found for %s\n", args
[0]);
2766 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2768 node
->cursel
= node
->autosel
- 1;
2769 debug("Persistence image auto select %d\n", node
->autosel
);
2773 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2779 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2780 " echo %s\n}\n", "123");
2782 for (i
= 0; i
< node
->backendnum
; i
++)
2784 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2786 node
->backendpath
[i
].path
);
2790 g_ventoy_menu_esc
= 1;
2791 g_ventoy_suppress_esc
= 1;
2793 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2794 grub_script_execute_sourcecode(configfile
);
2796 g_ventoy_menu_esc
= 0;
2797 g_ventoy_suppress_esc
= 0;
2801 node
->cursel
= g_ventoy_last_entry
- 1;
2803 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2806 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2809 ventoy_img_chunk
*cur
;
2815 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2817 cur
= g_img_chunk_list
.chunk
+ i
;
2818 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2819 cur
->img_start_sector
, cur
->img_end_sector
,
2820 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2824 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2827 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2831 ventoy_img_chunk_list chunklist
;
2836 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2839 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2842 /* get image chunk data */
2843 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2844 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2845 if (NULL
== chunklist
.chunk
)
2847 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2850 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2851 chunklist
.cur_chunk
= 0;
2853 ventoy_get_block_list(file
, &chunklist
, 0);
2855 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2857 grub_printf("########## UNSUPPORTED ###############\n");
2860 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2862 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2864 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2865 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2868 grub_printf("\n==================================\n");
2870 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2872 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2873 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2874 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2875 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2876 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2880 grub_free(chunklist
.chunk
);
2881 grub_file_close(file
);
2883 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2886 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2889 ventoy_grub_param_file_replace
*replace
= NULL
;
2897 replace
= &(g_grub_param
->file_replace
);
2898 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2900 replace
->old_name_cnt
= 0;
2901 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2903 replace
->old_name_cnt
++;
2904 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2907 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2910 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2913 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2921 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2922 grub_printf("%s", g_list_script_buf
);
2926 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2927 grub_printf("%s", g_tree_script_buf
);
2933 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2935 img_info
*cur
= g_ventoy_img_list
;
2943 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
2944 grub_printf("name:<%s>\n\n", cur
->name
);
2951 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2957 ventoy_plugin_dump_injection();
2962 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2968 ventoy_plugin_dump_auto_install();
2973 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2979 ventoy_plugin_dump_persistence();
2984 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2995 if (args
[0][0] == '0')
2997 return g_ventoy_memdisk_mode
? 0 : 1;
2999 else if (args
[0][0] == '1')
3001 return g_ventoy_iso_raw
? 0 : 1;
3003 else if (args
[0][0] == '2')
3005 return g_ventoy_iso_uefi_drv
? 0 : 1;
3011 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3013 static int configfile_mode
= 0;
3014 char memfile
[128] = {0};
3021 * args[0]: 0:normal 1:configfile
3022 * args[1]: 0:list_buf 1:tree_buf
3027 debug("Invalid argc %d\n", argc
);
3031 if (args
[0][0] == '0')
3033 if (args
[1][0] == '0')
3035 grub_script_execute_sourcecode(g_list_script_buf
);
3039 grub_script_execute_sourcecode(g_tree_script_buf
);
3044 if (configfile_mode
)
3046 debug("Now already in F3 mode %d\n", configfile_mode
);
3050 if (args
[1][0] == '0')
3052 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3053 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3057 g_ventoy_last_entry
= -1;
3058 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3059 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3062 configfile_mode
= 1;
3063 grub_script_execute_sourcecode(memfile
);
3064 configfile_mode
= 0;
3070 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3081 g_ventoy_case_insensitive
= 1;
3082 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3083 g_ventoy_case_insensitive
= 0;
3089 grub_file_close(file
);
3095 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3100 const char *isopath
= NULL
;
3102 ventoy_mbr_head mbr
;
3109 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3112 isopath
= grub_env_get("vtoy_iso_part");
3115 debug("isopath is null %p\n", isopath
);
3119 debug("isopath is %s\n", isopath
);
3121 for (id
= 0; id
< 30 && (find
== 0); id
++)
3123 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3124 if (grub_strstr(isopath
, hdname
))
3126 debug("skip %s ...\n", hdname
);
3130 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3132 disk
= grub_disk_open(hdname
);
3135 debug("%s not exist\n", hdname
);
3139 grub_memset(&mbr
, 0, sizeof(mbr
));
3140 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3142 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3144 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3145 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3148 grub_env_set(args
[0], hdname
);
3152 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3156 debug("read %s failed\n", hdname
);
3159 grub_disk_close(disk
);
3165 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3176 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3179 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3182 debug("failed to open file %s\n", args
[0]);
3186 buf
= grub_malloc(len
);
3193 grub_file_read(file
, buf
, len
- 1);
3195 ventoy_get_line(buf
);
3196 ventoy_set_env(args
[1], buf
);
3200 grub_check_free(buf
);
3201 grub_file_close(file
);
3206 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3211 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3212 "0 %llu linear /dev/ventoy %llu\n",
3213 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3218 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3220 char *device_name
= NULL
;
3221 grub_device_t dev
= NULL
;
3226 g_part_list_pos
= 0;
3227 grub_env_unset("vtoy_img_part_file");
3234 device_name
= grub_file_get_device_name(args
[0]);
3237 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3241 dev
= grub_device_open(device_name
);
3244 debug("grub_device_open failed, %s\n", device_name
);
3248 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3250 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3251 grub_env_set("vtoy_img_part_file", buf
);
3255 check_free(device_name
, grub_free
);
3256 check_free(dev
, grub_device_close
);
3262 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3273 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3276 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3279 debug("failed to open file %s\n", args
[0]);
3283 buf
= grub_malloc(file
->size
+ 1);
3289 buf
[file
->size
] = 0;
3290 grub_file_read(file
, buf
, file
->size
);
3292 if (grub_strstr(buf
, args
[1]))
3299 grub_check_free(buf
);
3300 grub_file_close(file
);
3305 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3311 ventoy_iso9660_vd pvd
;
3318 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3321 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3324 debug("failed to open file %s\n", args
[0]);
3328 grub_file_seek(file
, 16 * 2048);
3329 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3330 if (len
!= sizeof(pvd
))
3332 debug("failed to read pvd %d\n", len
);
3336 grub_memset(buf
, 0, sizeof(buf
));
3337 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3338 ventoy_set_env(args
[1], buf
);
3340 grub_memset(buf
, 0, sizeof(buf
));
3341 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3342 ventoy_set_env(args
[2], buf
);
3346 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3347 ventoy_set_env(args
[3], buf
);
3350 grub_file_close(file
);
3355 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3366 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3369 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3372 debug("failed to open file %s\n", args
[0]);
3376 grub_memset(buf
, 0, sizeof(buf
));
3377 grub_file_seek(file
, 16 * 2048 + 813);
3378 len
= (int)grub_file_read(file
, buf
, 17);
3381 debug("failed to read create date %d\n", len
);
3385 ventoy_set_env(args
[1], buf
);
3388 grub_file_close(file
);
3393 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3399 ventoy_env_hook_root(1);
3404 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3410 ventoy_env_hook_root(0);
3415 #ifdef GRUB_MACHINE_EFI
3416 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3421 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3427 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3428 if (var
&& *var
== 1)
3436 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3445 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3452 int image_sector_size
;
3454 ventoy_chain_head
*chain
;
3455 ventoy_img_chunk
*chunk
;
3456 ventoy_os_param
*osparam
;
3457 ventoy_image_location
*location
;
3458 ventoy_image_disk_region
*region
;
3459 struct grub_acpi_table_header
*acpi
;
3468 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3470 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3476 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3478 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3480 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3484 img_chunk_num
= chain
->img_chunk_num
;
3486 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3487 datalen
= sizeof(ventoy_os_param
) + loclen
;
3489 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3490 acpi
= grub_zalloc(buflen
);
3496 /* Step1: Fill acpi table header */
3497 grub_memcpy(acpi
->signature
, "VTOY", 4);
3498 acpi
->length
= buflen
;
3500 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3501 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3503 acpi
->creator_id
[0] = 1;
3504 acpi
->creator_rev
= 1;
3506 /* Step2: Fill data */
3507 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3508 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3509 osparam
->vtoy_img_location_addr
= 0;
3510 osparam
->vtoy_img_location_len
= loclen
;
3511 osparam
->chksum
= 0;
3512 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3514 location
= (ventoy_image_location
*)(osparam
+ 1);
3515 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3516 location
->image_sector_size
= image_sector_size
;
3517 location
->disk_sector_size
= chain
->disk_sector_size
;
3518 location
->region_count
= img_chunk_num
;
3520 region
= location
->regions
;
3521 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3522 if (512 == image_sector_size
)
3524 for (i
= 0; i
< img_chunk_num
; i
++)
3526 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3527 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3528 region
->disk_start_sector
= chunk
->disk_start_sector
;
3535 for (i
= 0; i
< img_chunk_num
; i
++)
3537 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3538 region
->image_start_sector
= chunk
->img_start_sector
;
3539 region
->disk_start_sector
= chunk
->disk_start_sector
;
3545 /* Step3: Fill acpi checksum */
3547 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3549 /* load acpi table */
3550 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3551 grub_script_execute_sourcecode(cmd
);
3555 VENTOY_CMD_RETURN(0);
3558 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3564 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3565 g_ventoy_last_entry
= -1;
3570 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3576 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3581 grub_uint64_t
ventoy_get_part1_size(ventoy_gpt_info
*gpt
)
3583 grub_uint64_t sectors
;
3585 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3587 sectors
= gpt
->PartTbl
[0].LastLBA
+ 1 - gpt
->PartTbl
[0].StartLBA
;
3591 sectors
= gpt
->MBR
.PartTbl
[0].SectorCount
;
3594 return sectors
* 512;
3597 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3599 const char *pos
= filename
+ 1;
3607 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3609 grub_strncpy((char *)data
, filename
, 128);
3620 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3623 char *device_name
= NULL
;
3624 grub_device_t dev
= NULL
;
3625 grub_fs_t fs
= NULL
;
3626 char buf
[128] = {0};
3632 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3636 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3638 device_name
= grub_file_get_device_name(args
[0]);
3641 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3645 dev
= grub_device_open(device_name
);
3648 debug("grub_device_open failed, %s\n", device_name
);
3652 fs
= grub_fs_probe(dev
);
3655 debug("grub_fs_probe failed, %s\n", device_name
);
3659 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3663 ventoy_set_env(args
[2], buf
);
3670 check_free(device_name
, grub_free
);
3671 check_free(dev
, grub_device_close
);
3676 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3686 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3687 if (!g_ventoy_part_info
)
3692 disk
= grub_disk_open(args
[0]);
3695 debug("Failed to open disk %s\n", args
[0]);
3699 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
3701 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3702 grub_disk_close(disk
);
3704 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3705 dev
= grub_device_open(name
);
3708 /* make sure that we are running in a correct Ventoy device */
3709 ret
= ventoy_check_device(dev
);
3710 grub_device_close(dev
);
3721 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3724 const char *vcfg
= NULL
;
3729 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
3732 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
3733 grub_env_set(args
[1], vcfg
);
3738 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
3746 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3749 grub_uint8_t zeroguid
[16] = {0};
3754 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3757 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3759 if (id
>= 1 && id
<= 128)
3761 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3769 if (id
>= 1 && id
<= 4)
3771 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3781 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3784 char *device_name
= NULL
;
3785 grub_device_t dev
= NULL
;
3786 grub_fs_t fs
= NULL
;
3793 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3797 device_name
= grub_file_get_device_name(args
[0]);
3800 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3804 dev
= grub_device_open(device_name
);
3807 debug("grub_device_open failed, %s\n", device_name
);
3811 fs
= grub_fs_probe(dev
);
3814 debug("grub_fs_probe failed, %s\n", device_name
);
3818 fs
->fs_label(dev
, &label
);
3821 ventoy_set_env(args
[1], label
);
3829 check_free(device_name
, grub_free
);
3830 check_free(dev
, grub_device_close
);
3835 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3839 grub_snprintf((char *)data
, 256, "%s", filename
);
3847 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3850 char *device_name
= NULL
;
3851 grub_device_t dev
= NULL
;
3852 grub_fs_t fs
= NULL
;
3853 char name
[256] ={0};
3859 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3863 device_name
= grub_file_get_device_name(args
[0]);
3866 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3870 dev
= grub_device_open(device_name
);
3873 debug("grub_device_open failed, %s\n", device_name
);
3877 fs
= grub_fs_probe(dev
);
3880 debug("grub_fs_probe failed, %s\n", device_name
);
3884 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3887 ventoy_set_env(args
[2], name
);
3894 check_free(device_name
, grub_free
);
3895 check_free(dev
, grub_device_close
);
3900 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3910 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3914 for (pos
= args
[0]; *pos
; pos
++)
3928 grub_env_set(args
[1], args
[0]);
3938 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3948 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
3953 len
= (int)grub_strlen(buf
);
3954 for (i
= len
; i
> 0; i
--)
3956 if (buf
[i
- 1] == '/')
3958 grub_env_set(args
[1], buf
+ i
);
3963 grub_env_set(args
[1], buf
);
3968 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3970 struct grub_video_mode_info info
;
3977 if (!g_video_mode_list
)
3979 ventoy_enum_video_mode();
3982 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3984 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3988 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3991 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3993 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3994 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3996 VENTOY_CMD_RETURN(0);
3999 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4001 struct grub_video_mode_info info
;
4008 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4010 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4014 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4017 grub_env_set(args
[0], buf
);
4019 VENTOY_CMD_RETURN(0);
4022 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4030 if (!g_video_mode_list
)
4035 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4036 if (id
< g_video_mode_num
)
4038 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4039 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4042 grub_env_set(args
[1], buf
);
4044 VENTOY_CMD_RETURN(0);
4047 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
4049 grub_uint64_t size
= 0;
4052 char fullpath
[256] = {0};
4055 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4058 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
4061 debug("grub_file_open failed <%s>\n", fullpath
);
4067 grub_file_close(file
);
4071 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
4075 char fullpath
[256] = {0};
4078 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4081 file
= grub_file_open(fullpath
, type
);
4084 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
4091 int ventoy_is_file_exist(const char *fmt
, ...)
4096 char buf
[256] = {0};
4098 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
4102 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4105 grub_strncpy(pos
+ len
, "\" ]", 3);
4107 debug("script exec %s\n", buf
);
4109 if (0 == grub_script_execute_sourcecode(buf
))
4117 int ventoy_is_dir_exist(const char *fmt
, ...)
4122 char buf
[256] = {0};
4124 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
4128 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4131 grub_strncpy(pos
+ len
, "\" ]", 3);
4133 debug("script exec %s\n", buf
);
4135 if (0 == grub_script_execute_sourcecode(buf
))
4143 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
4146 grub_uint8_t
*outbuf
;
4147 grub_uint8_t gzHdr
[10] =
4149 0x1F, 0x8B, /* magic */
4152 0,0,0,0, /* mtime */
4157 grub_memset(&s
, 0, sizeof(mz_stream
));
4159 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
4161 outbuf
= (grub_uint8_t
*)mem_out
;
4163 mem_out_len
-= sizeof(gzHdr
) + 8;
4164 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
4165 outbuf
+= sizeof(gzHdr
);
4167 s
.avail_in
= mem_in_len
;
4170 s
.avail_out
= mem_out_len
;
4171 s
.next_out
= outbuf
;
4173 mz_deflate(&s
, MZ_FINISH
);
4177 outbuf
+= s
.total_out
;
4178 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
4179 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
4181 return s
.total_out
+ sizeof(gzHdr
) + 8;
4184 static int ventoy_env_init(void)
4188 grub_env_set("vtdebug_flag", "");
4190 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4191 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4192 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4193 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4195 ventoy_filt_register(0, ventoy_wrapper_open
);
4197 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4200 g_grub_param
->grub_env_get
= grub_env_get
;
4201 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4202 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4203 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4204 grub_env_set("env_param", buf
);
4205 grub_env_set("ventoy_env_param", buf
);
4206 grub_env_export("ventoy_env_param");
4212 static cmd_para ventoy_cmds
[] =
4214 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4215 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4216 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4217 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4218 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4219 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4220 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4221 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4222 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4223 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4224 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4225 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4226 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4227 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4228 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4229 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4230 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4231 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4232 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4233 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4234 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4235 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4236 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4238 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4239 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4240 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4241 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4242 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4243 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4244 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4246 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4247 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4248 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4249 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4250 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4251 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4252 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4253 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4254 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4257 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4258 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4259 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4260 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4261 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4262 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4263 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4264 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4265 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4266 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4267 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4269 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4270 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4271 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4272 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4273 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4274 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4276 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4277 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4278 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4279 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4280 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4281 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4282 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4283 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4284 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4285 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4287 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4288 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4289 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4290 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4291 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4292 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4293 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4294 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4296 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4297 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4298 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4301 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4302 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4303 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4305 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4306 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4307 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4310 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4311 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4312 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4313 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4314 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4315 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4316 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4317 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4318 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4319 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4321 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4322 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4323 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4324 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4330 GRUB_MOD_INIT(ventoy
)
4333 cmd_para
*cur
= NULL
;
4337 ventoy_arch_mode_init();
4339 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4341 cur
= ventoy_cmds
+ i
;
4342 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4343 cur
->summary
, cur
->description
, cur
->parser
);
4347 GRUB_MOD_FINI(ventoy
)
4351 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4353 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);