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");
1432 g_ventoy_plat_data
= VTOY_PLAT_X86_64_UEFI
;
1433 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "uefi");
1436 g_ventoy_plat_data
= VTOY_PLAT_X86_LEGACY
;
1437 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "legacy");
1443 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1445 int len
= GRUB_UINT_MAX
;
1446 const char *value
= NULL
;
1447 char name
[32] = {0};
1448 char plat
[32] = {0};
1449 char guidstr
[32] = {0};
1450 ventoy_guid guid
= VENTOY_GUID
;
1451 const char *fmt1
= NULL
;
1452 const char *fmt2
= NULL
;
1453 const char *fmt3
= NULL
;
1454 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1455 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1456 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1457 const char fmtcode
[]={
1458 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1459 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1460 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1461 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1462 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1463 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1466 grub_memset(name
, 0, sizeof(name
));
1467 puint
[0] = grub_swap_bytes32(0x56454e54);
1468 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1469 puint
[2] = grub_swap_bytes32(0x45525349);
1470 puint
[1] = grub_swap_bytes32(0x4f595f56);
1471 value
= ventoy_get_env(name
);
1473 grub_memset(name
, 0, sizeof(name
));
1474 puint
[1] = grub_swap_bytes32(0x5f544f50);
1475 puint
[0] = grub_swap_bytes32(0x56544c45);
1476 fmt1
= ventoy_get_env(name
);
1482 grub_memset(name
, 0, sizeof(name
));
1483 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1484 puint
[0] = grub_swap_bytes32(0x56544c45);
1485 fmt2
= ventoy_get_env(name
);
1487 grub_memset(name
, 0, sizeof(name
));
1488 puint
[1] = grub_swap_bytes32(0x5f434c52);
1489 puint
[0] = grub_swap_bytes32(0x56544c45);
1490 fmt3
= ventoy_get_env(name
);
1492 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1494 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1496 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1497 #pragma GCC diagnostic push
1498 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1499 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1500 fmt1
? fmt1
: fmtdata
,
1501 fmt2
? fmt2
: fmtdata
+ 4,
1502 value
? value
: "", plat
, guidstr
,
1503 fmt3
? fmt3
: fmtdata
+ 6);
1504 #pragma GCC diagnostic pop
1506 grub_memset(name
, 0, sizeof(name
));
1507 puint
[0] = grub_swap_bytes32(0x76746f79);
1508 puint
[2] = grub_swap_bytes32(0x656e7365);
1509 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1510 ventoy_set_env(name
, guidstr
);
1515 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1519 grub_uint8_t md5
[16];
1523 grub_memset(input
, 0, sizeof(input
));
1525 grub_printf("Enter password: ");
1528 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1530 grub_password_get(input
, 128);
1531 if (grub_strcmp(pwd
->text
, input
) == 0)
1536 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1538 grub_password_get(input
, 128);
1539 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1540 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1545 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1547 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1548 grub_password_get(input
+ offset
, 128);
1550 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1551 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1557 grub_printf("Invalid password!\n\n");
1564 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1566 img_info
*minimg
= NULL
;
1567 img_info
*img
= (img_info
*)(node
->firstiso
);
1569 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1571 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1586 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1588 img_iterator_node
*Minchild
= NULL
;
1589 img_iterator_node
*child
= node
->firstchild
;
1591 while (child
&& child
->parent
== node
)
1593 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1597 child
= child
->next
;
1602 Minchild
->select
= 1;
1608 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1611 img_info
*img
= NULL
;
1612 const char *dir_class
= NULL
;
1613 const char *dir_alias
= NULL
;
1614 img_iterator_node
*child
= NULL
;
1616 if (node
->isocnt
== 0 || node
->done
== 1)
1621 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1623 offset
= node
->parent
->dirlen
;
1626 if (node
== &g_img_iterator_head
)
1628 if (g_default_menu_mode
== 0)
1630 if (g_tree_view_menu_style
== 0)
1632 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1633 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1634 " echo 'return ...' \n"
1639 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1640 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1648 node
->dir
[node
->dirlen
- 1] = 0;
1649 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1652 dir_class
= "vtoydir";
1655 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1658 if (g_tree_view_menu_style
== 0)
1660 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1661 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1662 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1666 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1667 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1668 dir_alias
, dir_class
, node
->dir
+ offset
);
1673 dir_alias
= node
->dir
+ offset
;
1675 if (g_tree_view_menu_style
== 0)
1677 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1678 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1679 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1683 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1684 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1685 dir_alias
, dir_class
, node
->dir
+ offset
);
1689 if (g_tree_view_menu_style
== 0)
1691 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1692 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1693 " echo 'return ...' \n"
1698 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1699 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1705 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1707 ventoy_dynamic_tree_menu(child
);
1710 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1712 if (g_tree_view_menu_style
== 0)
1714 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1715 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1718 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1719 img
->unsupport
? "[***********] " : "",
1720 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1722 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1726 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1727 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1730 img
->unsupport
? "[***********] " : "",
1731 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1733 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1737 if (node
!= &g_img_iterator_head
)
1739 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1746 int ventoy_check_device_result(int ret
)
1750 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1751 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1752 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1756 grub_printf(VTOY_WARNING
"\n");
1757 grub_printf(VTOY_WARNING
"\n");
1758 grub_printf(VTOY_WARNING
"\n\n\n");
1760 grub_printf("This is NOT a standard Ventoy device and is NOT supported.\n\n");
1761 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1763 grub_printf("\n\nWill exit after 10 seconds ...... ");
1771 int ventoy_check_device(grub_device_t dev
)
1775 grub_uint64_t offset
;
1780 struct grub_partition
*partition
;
1782 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1784 return ventoy_check_device_result(1 | 0x1000);
1787 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1788 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1789 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1791 #ifndef GRUB_MACHINE_EFI
1792 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1793 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
1794 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1796 return ventoy_check_device_result(2 | 0x1000);
1805 /* We must have partition 2 */
1808 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
1812 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1816 return ventoy_check_device_result(3 | 0x1000);
1819 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1821 grub_file_close(file
);
1822 return ventoy_check_device_result(4 | 0x1000);
1825 partition
= dev
->disk
->partition
;
1826 if (partition
->number
!= 0 || partition
->start
!= 2048)
1828 return ventoy_check_device_result(5);
1833 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
1835 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
1836 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
1837 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
1839 grub_file_close(file
);
1840 return ventoy_check_device_result(6);
1845 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
1846 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
1847 PartTbl
[1].SectorCount
!= 65536)
1849 grub_file_close(file
);
1850 return ventoy_check_device_result(6);
1856 offset
= partition
->start
+ partition
->len
;
1857 partition
= file
->device
->disk
->partition
;
1858 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1860 grub_file_close(file
);
1861 return ventoy_check_device_result(7);
1865 grub_file_close(file
);
1867 if (workaround
== 0)
1869 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1870 dev2
= grub_device_open(devname
);
1873 return ventoy_check_device_result(8);
1876 fs
= grub_fs_probe(dev2
);
1879 grub_device_close(dev2
);
1880 return ventoy_check_device_result(9);
1883 fs
->fs_label(dev2
, &label
);
1884 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1886 grub_device_close(dev2
);
1887 return ventoy_check_device_result(10);
1890 grub_device_close(dev2
);
1893 return ventoy_check_device_result(0);
1896 static int ventoy_set_default_menu(void)
1902 const char *strdata
= NULL
;
1903 img_info
*cur
= NULL
;
1904 img_info
*default_node
= NULL
;
1905 const char *default_image
= NULL
;
1907 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1908 if (default_image
&& default_image
[0] == '/')
1910 img_len
= grub_strlen(default_image
);
1912 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1914 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1926 if (0 == g_default_menu_mode
)
1928 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1932 def
= grub_strdup(default_image
);
1938 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1940 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1941 if (strdata
&& strdata
[0] == '/')
1943 pos
= def
+ grub_strlen(strdata
);
1954 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1957 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1961 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1969 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1973 grub_device_t dev
= NULL
;
1974 img_info
*cur
= NULL
;
1975 img_info
*tail
= NULL
;
1976 const char *strdata
= NULL
;
1977 char *device_name
= NULL
;
1979 img_iterator_node
*node
= NULL
;
1980 img_iterator_node
*tmp
= NULL
;
1986 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1989 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1991 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1994 g_enumerate_time_checked
= 0;
1995 g_enumerate_start_time_ms
= grub_get_time_ms();
1997 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1998 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2000 g_filt_dot_underscore_file
= 1;
2003 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2004 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2006 g_sort_case_sensitive
= 1;
2009 device_name
= grub_file_get_device_name(args
[0]);
2015 g_enum_dev
= dev
= grub_device_open(device_name
);
2021 g_enum_fs
= fs
= grub_fs_probe(dev
);
2027 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2029 debug("unsupported fs:<%s>\n", fs
->name
);
2030 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2034 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2036 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2037 if (strdata
&& strdata
[0] == '1')
2039 g_default_menu_mode
= 1;
2042 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2044 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2046 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2047 if (strdata
&& strdata
[0] == '/')
2049 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2050 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2052 g_img_iterator_head
.dir
[len
++] = '/';
2054 g_img_iterator_head
.dirlen
= len
;
2058 g_img_iterator_head
.dirlen
= 1;
2059 grub_strcpy(g_img_iterator_head
.dir
, "/");
2062 g_img_iterator_head
.tail
= &tail
;
2064 if (g_img_max_search_level
< 0)
2066 g_img_max_search_level
= GRUB_INT_MAX
;
2067 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2068 if (strdata
&& ventoy_is_decimal(strdata
))
2070 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2074 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2076 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2079 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2080 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2082 g_tree_view_menu_style
= 1;
2085 ventoy_set_default_menu();
2087 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2089 ventoy_dynamic_tree_menu(node
);
2093 node
= g_img_iterator_head
.next
;
2101 /* sort image list by image name */
2102 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2104 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2106 if (ventoy_cmp_img(cur
, tail
) > 0)
2108 ventoy_swap_img(cur
, tail
);
2113 if (g_default_menu_mode
== 1)
2115 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2116 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2117 " echo 'return ...' \n"
2121 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2123 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2124 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2127 cur
->unsupport
? "[***********] " : "",
2128 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2130 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2133 g_tree_script_buf
[g_tree_script_pos
] = 0;
2134 g_list_script_buf
[g_list_script_pos
] = 0;
2136 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2137 grub_env_set(args
[1], buf
);
2141 check_free(device_name
, grub_free
);
2142 check_free(dev
, grub_device_close
);
2144 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2148 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2150 img_info
*next
= NULL
;
2151 img_info
*cur
= g_ventoy_img_list
;
2164 g_ventoy_img_list
= NULL
;
2165 g_ventoy_img_count
= 0;
2167 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2170 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2173 img_info
*cur
= g_ventoy_img_list
;
2177 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2179 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2182 img_id
= grub_strtol(args
[0], NULL
, 10);
2183 if (img_id
>= g_ventoy_img_count
)
2185 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2188 debug("Find image %ld name \n", img_id
);
2190 while (cur
&& img_id
> 0)
2198 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2201 debug("image name is %s\n", cur
->name
);
2203 grub_env_set(args
[1], cur
->name
);
2205 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2208 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2213 const char *id
= NULL
;
2214 img_info
*cur
= g_ventoy_img_list
;
2218 if (argc
< 1 || argc
> 2)
2220 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2223 id
= grub_env_get("chosen");
2225 pos
= grub_strstr(id
, "VID_");
2228 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2232 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2237 if (img_id
== cur
->id
)
2246 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2249 grub_env_set(args
[0], cur
->path
);
2253 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2254 grub_env_set(args
[1], value
);
2257 g_svd_replace_offset
= 0;
2259 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2262 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2269 device_name
= grub_file_get_device_name(filename
);
2281 pos2
= grub_strstr(pos
, ",");
2284 pos2
= grub_strstr(pos
, ")");
2292 disk
= grub_disk_open(pos
);
2295 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2296 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2297 grub_disk_close(disk
);
2304 grub_free(device_name
);
2308 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2310 eltorito_descriptor desc
;
2312 grub_memset(&desc
, 0, sizeof(desc
));
2313 grub_file_seek(file
, 17 * 2048);
2314 grub_file_read(file
, &desc
, sizeof(desc
));
2316 if (desc
.type
!= 0 || desc
.version
!= 1)
2321 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2322 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2330 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2334 grub_uint8_t buf
[512];
2335 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2337 grub_file_seek(file
, sector
* 2048);
2338 grub_file_read(file
, buf
, sizeof(buf
));
2340 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2342 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2346 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2351 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2353 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2355 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2359 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2361 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2366 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2368 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2370 if (buf
[36] == parttype
[i
])
2372 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2378 debug("%s does not contain efi eltorito\n", file
->name
);
2382 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2385 const char *fs
= NULL
;
2386 const char *cdprompt
= NULL
;
2388 grub_uint8_t chksum
= 0;
2391 disk
= file
->device
->disk
;
2392 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2394 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2395 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2396 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2398 pos
= grub_strstr(file
->name
, "/");
2404 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2406 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2408 param
->vtoy_img_size
= file
->size
;
2410 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2411 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2413 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2415 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2416 param
->vtoy_reserved
[4] = 0;
2417 if (g_ventoy_chain_type
== 1) /* Windows */
2419 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2420 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2422 param
->vtoy_reserved
[4] = 1;
2426 fs
= ventoy_get_env("ventoy_fs_probe");
2427 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2429 param
->vtoy_reserved
[3] = 1;
2432 /* calculate checksum */
2433 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2435 chksum
+= *((grub_uint8_t
*)param
+ i
);
2437 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2442 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2444 grub_uint32_t i
= 0;
2445 grub_uint64_t total
= 0;
2446 ventoy_img_chunk
*chunk
= NULL
;
2448 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2450 chunk
= chunklist
->chunk
+ i
;
2452 if (chunk
->disk_start_sector
<= start
)
2454 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2458 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2461 if (total
!= ((file
->size
+ 511) / 512))
2463 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2470 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2474 grub_uint32_t i
= 0;
2475 grub_uint32_t sector
= 0;
2476 grub_uint32_t count
= 0;
2477 grub_off_t size
= 0;
2478 grub_off_t read
= 0;
2480 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2481 if (fs_type
== ventoy_fs_exfat
)
2483 grub_fat_get_file_chunk(start
, file
, chunklist
);
2485 else if (fs_type
== ventoy_fs_ext
)
2487 grub_ext_get_file_chunk(start
, file
, chunklist
);
2491 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2492 file
->read_hook_data
= chunklist
;
2494 for (size
= file
->size
; size
> 0; size
-= read
)
2496 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2497 grub_file_read(file
, NULL
, read
);
2500 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2502 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2503 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2506 if (ventoy_fs_udf
== fs_type
)
2508 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2510 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2511 chunklist
->chunk
[i
].img_start_sector
= sector
;
2512 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2518 len
= (int)grub_strlen(file
->name
);
2519 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2520 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2521 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2522 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2524 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2526 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2536 chunklist
->chunk
[i
].img_start_sector
= sector
;
2537 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2545 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2549 grub_disk_addr_t start
;
2554 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2557 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2560 g_conf_replace_node
= NULL
;
2561 g_conf_replace_offset
= 0;
2563 if (g_img_chunk_list
.chunk
)
2565 grub_free(g_img_chunk_list
.chunk
);
2568 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2570 grub_file_close(file
);
2571 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2574 /* get image chunk data */
2575 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2576 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2577 if (NULL
== g_img_chunk_list
.chunk
)
2579 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2582 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2583 g_img_chunk_list
.cur_chunk
= 0;
2585 start
= file
->device
->disk
->partition
->start
;
2587 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2589 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2590 grub_file_close(file
);
2594 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2597 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2598 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2601 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2603 grub_uint64_t offset
= 0;
2604 grub_uint32_t align
= 0;
2605 grub_file_t file
= NULL
;
2606 conf_replace
*node
= NULL
;
2612 debug("select conf replace argc:%d\n", argc
);
2619 node
= ventoy_plugin_find_conf_replace(args
[1]);
2622 debug("Conf replace not found for %s\n", args
[1]);
2626 debug("Find conf replace for %s\n", args
[1]);
2628 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2631 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2635 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2636 grub_file_close(file
);
2638 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2641 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2645 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2647 if (align
> vtoy_max_replace_file_size
)
2649 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2653 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2654 g_conf_replace_new_len
= (int)file
->size
;
2655 g_conf_replace_new_len_align
= align
;
2657 g_conf_replace_node
= node
;
2658 g_conf_replace_offset
= offset
+ 2;
2660 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2665 grub_file_close(file
);
2667 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2670 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2675 char configfile
[128];
2676 install_template
*node
= NULL
;
2682 debug("select auto installation argc:%d\n", argc
);
2689 node
= ventoy_plugin_find_install_template(args
[0]);
2692 debug("Auto install template not found for %s\n", args
[0]);
2696 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2698 node
->cursel
= node
->autosel
- 1;
2699 debug("Auto install template auto select %d\n", node
->autosel
);
2703 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2709 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2710 " echo %s\n}\n", "123");
2712 for (i
= 0; i
< node
->templatenum
; i
++)
2714 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2716 node
->templatepath
[i
].path
);
2719 g_ventoy_menu_esc
= 1;
2720 g_ventoy_suppress_esc
= 1;
2722 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2723 grub_script_execute_sourcecode(configfile
);
2725 g_ventoy_menu_esc
= 0;
2726 g_ventoy_suppress_esc
= 0;
2730 node
->cursel
= g_ventoy_last_entry
- 1;
2732 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2735 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2740 char configfile
[128];
2741 persistence_config
*node
;
2747 debug("select persistence argc:%d\n", argc
);
2754 node
= ventoy_plugin_find_persistent(args
[0]);
2757 debug("Persistence image not found for %s\n", args
[0]);
2761 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2763 node
->cursel
= node
->autosel
- 1;
2764 debug("Persistence image auto select %d\n", node
->autosel
);
2768 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2774 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2775 " echo %s\n}\n", "123");
2777 for (i
= 0; i
< node
->backendnum
; i
++)
2779 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2781 node
->backendpath
[i
].path
);
2785 g_ventoy_menu_esc
= 1;
2786 g_ventoy_suppress_esc
= 1;
2788 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2789 grub_script_execute_sourcecode(configfile
);
2791 g_ventoy_menu_esc
= 0;
2792 g_ventoy_suppress_esc
= 0;
2796 node
->cursel
= g_ventoy_last_entry
- 1;
2798 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2801 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2804 ventoy_img_chunk
*cur
;
2810 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2812 cur
= g_img_chunk_list
.chunk
+ i
;
2813 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2814 cur
->img_start_sector
, cur
->img_end_sector
,
2815 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2819 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2822 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2826 ventoy_img_chunk_list chunklist
;
2831 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2834 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2837 /* get image chunk data */
2838 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2839 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2840 if (NULL
== chunklist
.chunk
)
2842 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2845 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2846 chunklist
.cur_chunk
= 0;
2848 ventoy_get_block_list(file
, &chunklist
, 0);
2850 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2852 grub_printf("########## UNSUPPORTED ###############\n");
2855 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2857 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2859 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2860 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2863 grub_printf("\n==================================\n");
2865 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2867 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2868 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2869 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2870 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2871 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2875 grub_free(chunklist
.chunk
);
2876 grub_file_close(file
);
2878 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2881 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2884 ventoy_grub_param_file_replace
*replace
= NULL
;
2892 replace
= &(g_grub_param
->file_replace
);
2893 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2895 replace
->old_name_cnt
= 0;
2896 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2898 replace
->old_name_cnt
++;
2899 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2902 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2905 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2908 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2916 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2917 grub_printf("%s", g_list_script_buf
);
2921 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2922 grub_printf("%s", g_tree_script_buf
);
2928 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2930 img_info
*cur
= g_ventoy_img_list
;
2938 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
2939 grub_printf("name:<%s>\n\n", cur
->name
);
2946 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2952 ventoy_plugin_dump_injection();
2957 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2963 ventoy_plugin_dump_auto_install();
2968 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2974 ventoy_plugin_dump_persistence();
2979 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2990 if (args
[0][0] == '0')
2992 return g_ventoy_memdisk_mode
? 0 : 1;
2994 else if (args
[0][0] == '1')
2996 return g_ventoy_iso_raw
? 0 : 1;
2998 else if (args
[0][0] == '2')
3000 return g_ventoy_iso_uefi_drv
? 0 : 1;
3006 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3008 static int configfile_mode
= 0;
3009 char memfile
[128] = {0};
3016 * args[0]: 0:normal 1:configfile
3017 * args[1]: 0:list_buf 1:tree_buf
3022 debug("Invalid argc %d\n", argc
);
3026 if (args
[0][0] == '0')
3028 if (args
[1][0] == '0')
3030 grub_script_execute_sourcecode(g_list_script_buf
);
3034 grub_script_execute_sourcecode(g_tree_script_buf
);
3039 if (configfile_mode
)
3041 debug("Now already in F3 mode %d\n", configfile_mode
);
3045 if (args
[1][0] == '0')
3047 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3048 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3052 g_ventoy_last_entry
= -1;
3053 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3054 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3057 configfile_mode
= 1;
3058 grub_script_execute_sourcecode(memfile
);
3059 configfile_mode
= 0;
3065 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3076 g_ventoy_case_insensitive
= 1;
3077 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3078 g_ventoy_case_insensitive
= 0;
3084 grub_file_close(file
);
3090 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3095 const char *isopath
= NULL
;
3097 ventoy_mbr_head mbr
;
3104 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3107 isopath
= grub_env_get("vtoy_iso_part");
3110 debug("isopath is null %p\n", isopath
);
3114 debug("isopath is %s\n", isopath
);
3116 for (id
= 0; id
< 30 && (find
== 0); id
++)
3118 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3119 if (grub_strstr(isopath
, hdname
))
3121 debug("skip %s ...\n", hdname
);
3125 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3127 disk
= grub_disk_open(hdname
);
3130 debug("%s not exist\n", hdname
);
3134 grub_memset(&mbr
, 0, sizeof(mbr
));
3135 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3137 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3139 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3140 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3143 grub_env_set(args
[0], hdname
);
3147 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3151 debug("read %s failed\n", hdname
);
3154 grub_disk_close(disk
);
3160 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3171 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3174 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3177 debug("failed to open file %s\n", args
[0]);
3181 buf
= grub_malloc(len
);
3188 grub_file_read(file
, buf
, len
- 1);
3190 ventoy_get_line(buf
);
3191 ventoy_set_env(args
[1], buf
);
3195 grub_check_free(buf
);
3196 grub_file_close(file
);
3201 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3206 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3207 "0 %llu linear /dev/ventoy %llu\n",
3208 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3213 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3215 char *device_name
= NULL
;
3216 grub_device_t dev
= NULL
;
3221 g_part_list_pos
= 0;
3222 grub_env_unset("vtoy_img_part_file");
3229 device_name
= grub_file_get_device_name(args
[0]);
3232 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3236 dev
= grub_device_open(device_name
);
3239 debug("grub_device_open failed, %s\n", device_name
);
3243 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3245 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3246 grub_env_set("vtoy_img_part_file", buf
);
3250 check_free(device_name
, grub_free
);
3251 check_free(dev
, grub_device_close
);
3257 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3268 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3271 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3274 debug("failed to open file %s\n", args
[0]);
3278 buf
= grub_malloc(file
->size
+ 1);
3284 buf
[file
->size
] = 0;
3285 grub_file_read(file
, buf
, file
->size
);
3287 if (grub_strstr(buf
, args
[1]))
3294 grub_check_free(buf
);
3295 grub_file_close(file
);
3300 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3306 ventoy_iso9660_vd pvd
;
3313 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3316 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3319 debug("failed to open file %s\n", args
[0]);
3323 grub_file_seek(file
, 16 * 2048);
3324 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3325 if (len
!= sizeof(pvd
))
3327 debug("failed to read pvd %d\n", len
);
3331 grub_memset(buf
, 0, sizeof(buf
));
3332 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3333 ventoy_set_env(args
[1], buf
);
3335 grub_memset(buf
, 0, sizeof(buf
));
3336 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3337 ventoy_set_env(args
[2], buf
);
3341 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3342 ventoy_set_env(args
[3], buf
);
3345 grub_file_close(file
);
3350 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3361 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3364 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3367 debug("failed to open file %s\n", args
[0]);
3371 grub_memset(buf
, 0, sizeof(buf
));
3372 grub_file_seek(file
, 16 * 2048 + 813);
3373 len
= (int)grub_file_read(file
, buf
, 17);
3376 debug("failed to read create date %d\n", len
);
3380 ventoy_set_env(args
[1], buf
);
3383 grub_file_close(file
);
3388 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3394 ventoy_env_hook_root(1);
3399 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3405 ventoy_env_hook_root(0);
3410 #ifdef GRUB_MACHINE_EFI
3411 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3416 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3422 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3423 if (var
&& *var
== 1)
3431 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3440 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3447 int image_sector_size
;
3449 ventoy_chain_head
*chain
;
3450 ventoy_img_chunk
*chunk
;
3451 ventoy_os_param
*osparam
;
3452 ventoy_image_location
*location
;
3453 ventoy_image_disk_region
*region
;
3454 struct grub_acpi_table_header
*acpi
;
3463 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3465 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3471 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3473 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3475 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3479 img_chunk_num
= chain
->img_chunk_num
;
3481 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3482 datalen
= sizeof(ventoy_os_param
) + loclen
;
3484 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3485 acpi
= grub_zalloc(buflen
);
3491 /* Step1: Fill acpi table header */
3492 grub_memcpy(acpi
->signature
, "VTOY", 4);
3493 acpi
->length
= buflen
;
3495 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3496 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3498 acpi
->creator_id
[0] = 1;
3499 acpi
->creator_rev
= 1;
3501 /* Step2: Fill data */
3502 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3503 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3504 osparam
->vtoy_img_location_addr
= 0;
3505 osparam
->vtoy_img_location_len
= loclen
;
3506 osparam
->chksum
= 0;
3507 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3509 location
= (ventoy_image_location
*)(osparam
+ 1);
3510 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3511 location
->image_sector_size
= image_sector_size
;
3512 location
->disk_sector_size
= chain
->disk_sector_size
;
3513 location
->region_count
= img_chunk_num
;
3515 region
= location
->regions
;
3516 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3517 if (512 == image_sector_size
)
3519 for (i
= 0; i
< img_chunk_num
; i
++)
3521 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3522 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3523 region
->disk_start_sector
= chunk
->disk_start_sector
;
3530 for (i
= 0; i
< img_chunk_num
; i
++)
3532 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3533 region
->image_start_sector
= chunk
->img_start_sector
;
3534 region
->disk_start_sector
= chunk
->disk_start_sector
;
3540 /* Step3: Fill acpi checksum */
3542 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3544 /* load acpi table */
3545 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3546 grub_script_execute_sourcecode(cmd
);
3550 VENTOY_CMD_RETURN(0);
3553 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3559 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3560 g_ventoy_last_entry
= -1;
3565 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3571 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3576 grub_uint64_t
ventoy_get_part1_size(ventoy_gpt_info
*gpt
)
3578 grub_uint64_t sectors
;
3580 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3582 sectors
= gpt
->PartTbl
[0].LastLBA
+ 1 - gpt
->PartTbl
[0].StartLBA
;
3586 sectors
= gpt
->MBR
.PartTbl
[0].SectorCount
;
3589 return sectors
* 512;
3592 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3594 const char *pos
= filename
+ 1;
3602 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3604 grub_strncpy((char *)data
, filename
, 128);
3615 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3618 char *device_name
= NULL
;
3619 grub_device_t dev
= NULL
;
3620 grub_fs_t fs
= NULL
;
3621 char buf
[128] = {0};
3627 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3631 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3633 device_name
= grub_file_get_device_name(args
[0]);
3636 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3640 dev
= grub_device_open(device_name
);
3643 debug("grub_device_open failed, %s\n", device_name
);
3647 fs
= grub_fs_probe(dev
);
3650 debug("grub_fs_probe failed, %s\n", device_name
);
3654 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3658 ventoy_set_env(args
[2], buf
);
3665 check_free(device_name
, grub_free
);
3666 check_free(dev
, grub_device_close
);
3671 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3681 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3682 if (!g_ventoy_part_info
)
3687 disk
= grub_disk_open(args
[0]);
3690 debug("Failed to open disk %s\n", args
[0]);
3694 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
3696 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3697 grub_disk_close(disk
);
3699 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3700 dev
= grub_device_open(name
);
3703 /* make sure that we are running in a correct Ventoy device */
3704 ret
= ventoy_check_device(dev
);
3705 grub_device_close(dev
);
3716 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3719 const char *vcfg
= NULL
;
3724 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
3727 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
3728 grub_env_set(args
[1], vcfg
);
3733 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
3741 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3744 grub_uint8_t zeroguid
[16] = {0};
3749 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3752 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3754 if (id
>= 1 && id
<= 128)
3756 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3764 if (id
>= 1 && id
<= 4)
3766 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3776 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3779 char *device_name
= NULL
;
3780 grub_device_t dev
= NULL
;
3781 grub_fs_t fs
= NULL
;
3788 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3792 device_name
= grub_file_get_device_name(args
[0]);
3795 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3799 dev
= grub_device_open(device_name
);
3802 debug("grub_device_open failed, %s\n", device_name
);
3806 fs
= grub_fs_probe(dev
);
3809 debug("grub_fs_probe failed, %s\n", device_name
);
3813 fs
->fs_label(dev
, &label
);
3816 ventoy_set_env(args
[1], label
);
3824 check_free(device_name
, grub_free
);
3825 check_free(dev
, grub_device_close
);
3830 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3834 grub_snprintf((char *)data
, 256, "%s", filename
);
3842 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3845 char *device_name
= NULL
;
3846 grub_device_t dev
= NULL
;
3847 grub_fs_t fs
= NULL
;
3848 char name
[256] ={0};
3854 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3858 device_name
= grub_file_get_device_name(args
[0]);
3861 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3865 dev
= grub_device_open(device_name
);
3868 debug("grub_device_open failed, %s\n", device_name
);
3872 fs
= grub_fs_probe(dev
);
3875 debug("grub_fs_probe failed, %s\n", device_name
);
3879 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3882 ventoy_set_env(args
[2], name
);
3889 check_free(device_name
, grub_free
);
3890 check_free(dev
, grub_device_close
);
3895 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3905 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3909 for (pos
= args
[0]; *pos
; pos
++)
3923 grub_env_set(args
[1], args
[0]);
3933 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3943 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
3948 len
= (int)grub_strlen(buf
);
3949 for (i
= len
; i
> 0; i
--)
3951 if (buf
[i
- 1] == '/')
3953 grub_env_set(args
[1], buf
+ i
);
3958 grub_env_set(args
[1], buf
);
3963 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3965 struct grub_video_mode_info info
;
3972 if (!g_video_mode_list
)
3974 ventoy_enum_video_mode();
3977 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3979 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3983 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3986 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3988 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3989 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3991 VENTOY_CMD_RETURN(0);
3994 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3996 struct grub_video_mode_info info
;
4003 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4005 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4009 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4012 grub_env_set(args
[0], buf
);
4014 VENTOY_CMD_RETURN(0);
4017 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4025 if (!g_video_mode_list
)
4030 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4031 if (id
< g_video_mode_num
)
4033 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4034 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4037 grub_env_set(args
[1], buf
);
4039 VENTOY_CMD_RETURN(0);
4042 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
4044 grub_uint64_t size
= 0;
4047 char fullpath
[256] = {0};
4050 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4053 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
4056 debug("grub_file_open failed <%s>\n", fullpath
);
4062 grub_file_close(file
);
4066 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
4070 char fullpath
[256] = {0};
4073 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4076 file
= grub_file_open(fullpath
, type
);
4079 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
4086 int ventoy_is_file_exist(const char *fmt
, ...)
4091 char buf
[256] = {0};
4093 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
4097 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4100 grub_strncpy(pos
+ len
, "\" ]", 3);
4102 debug("script exec %s\n", buf
);
4104 if (0 == grub_script_execute_sourcecode(buf
))
4112 int ventoy_is_dir_exist(const char *fmt
, ...)
4117 char buf
[256] = {0};
4119 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
4123 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4126 grub_strncpy(pos
+ len
, "\" ]", 3);
4128 debug("script exec %s\n", buf
);
4130 if (0 == grub_script_execute_sourcecode(buf
))
4138 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
4141 grub_uint8_t
*outbuf
;
4142 grub_uint8_t gzHdr
[10] =
4144 0x1F, 0x8B, /* magic */
4147 0,0,0,0, /* mtime */
4152 grub_memset(&s
, 0, sizeof(mz_stream
));
4154 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
4156 outbuf
= (grub_uint8_t
*)mem_out
;
4158 mem_out_len
-= sizeof(gzHdr
) + 8;
4159 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
4160 outbuf
+= sizeof(gzHdr
);
4162 s
.avail_in
= mem_in_len
;
4165 s
.avail_out
= mem_out_len
;
4166 s
.next_out
= outbuf
;
4168 mz_deflate(&s
, MZ_FINISH
);
4172 outbuf
+= s
.total_out
;
4173 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
4174 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
4176 return s
.total_out
+ sizeof(gzHdr
) + 8;
4179 static int ventoy_env_init(void)
4183 grub_env_set("vtdebug_flag", "");
4185 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4186 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4187 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4188 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4190 ventoy_filt_register(0, ventoy_wrapper_open
);
4192 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4195 g_grub_param
->grub_env_get
= grub_env_get
;
4196 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4197 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4198 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4199 grub_env_set("env_param", buf
);
4200 grub_env_set("ventoy_env_param", buf
);
4201 grub_env_export("ventoy_env_param");
4207 static cmd_para ventoy_cmds
[] =
4209 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4210 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4211 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4212 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4213 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4214 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4215 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4216 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4217 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4218 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4219 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4220 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4221 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4222 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4223 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4224 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4225 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4226 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4227 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4228 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4229 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4230 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4231 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4233 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4234 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4235 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4236 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4237 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4238 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4239 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4241 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4242 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4243 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4244 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4245 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4246 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4247 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4248 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4249 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4252 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4253 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4254 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4255 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4256 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4257 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4258 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4259 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4260 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4261 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4262 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4264 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4265 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4266 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4267 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4268 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4269 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4271 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4272 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4273 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4274 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4275 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4276 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4277 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4278 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4279 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4280 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4282 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4283 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4284 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4285 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4286 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4287 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4288 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4289 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4291 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4292 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4293 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4296 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4297 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4298 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4300 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4301 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4302 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4305 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4306 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4307 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4308 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4309 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4310 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4311 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4312 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4313 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4314 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4316 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4317 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4318 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4319 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4325 GRUB_MOD_INIT(ventoy
)
4328 cmd_para
*cur
= NULL
;
4332 ventoy_arch_mode_init();
4334 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4336 cur
= ventoy_cmds
+ i
;
4337 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4338 cur
->summary
, cur
->description
, cur
->parser
);
4342 GRUB_MOD_FINI(ventoy
)
4346 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4348 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);