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/efi.h>
41 #include <grub/time.h>
42 #include <grub/video.h>
43 #include <grub/relocator.h>
44 #include <grub/charset.h>
45 #include <grub/ventoy.h>
46 #include "ventoy_def.h"
48 GRUB_MOD_LICENSE ("GPLv3+");
50 int g_ventoy_debug
= 0;
51 static int g_efi_os
= 0xFF;
52 initrd_info
*g_initrd_img_list
= NULL
;
53 initrd_info
*g_initrd_img_tail
= NULL
;
54 int g_initrd_img_count
= 0;
55 int g_valid_initrd_count
= 0;
56 int g_default_menu_mode
= 0;
57 int g_filt_dot_underscore_file
= 0;
58 static grub_file_t g_old_file
;
59 static int g_ventoy_last_entry_back
;
62 char g_img_swap_tmp_buf
[1024];
63 img_info g_img_swap_tmp
;
64 img_info
*g_ventoy_img_list
= NULL
;
66 int g_ventoy_img_count
= 0;
68 grub_device_t g_enum_dev
= NULL
;
69 grub_fs_t g_enum_fs
= NULL
;
70 img_iterator_node g_img_iterator_head
;
71 img_iterator_node
*g_img_iterator_tail
= NULL
;
73 grub_uint8_t g_ventoy_break_level
= 0;
74 grub_uint8_t g_ventoy_debug_level
= 0;
75 grub_uint8_t g_ventoy_chain_type
= 0;
77 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
78 grub_uint32_t g_ventoy_cpio_size
= 0;
79 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
80 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
82 ventoy_grub_param
*g_grub_param
= NULL
;
84 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
86 ventoy_img_chunk_list g_img_chunk_list
;
88 int g_wimboot_enable
= 0;
89 ventoy_img_chunk_list g_wimiso_chunk_list
;
90 char *g_wimiso_path
= NULL
;
92 int g_vhdboot_enable
= 0;
94 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
96 static char *g_tree_script_buf
= NULL
;
97 static int g_tree_script_pos
= 0;
99 static char *g_list_script_buf
= NULL
;
100 static int g_list_script_pos
= 0;
102 static char *g_part_list_buf
= NULL
;
103 static int g_part_list_pos
= 0;
105 static int g_video_mode_max
= 0;
106 static int g_video_mode_num
= 0;
107 static ventoy_video_mode
*g_video_mode_list
= NULL
;
109 static const char *g_menu_class
[] =
111 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd"
114 static const char *g_menu_prefix
[] =
116 "iso", "wim", "efi", "img", "vhd"
119 void ventoy_debug(const char *fmt
, ...)
123 va_start (args
, fmt
);
124 grub_vprintf (fmt
, args
);
128 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
138 for (i
= 0; i
< 16; i
++)
140 grub_printf("%02x ", guid
[i
]);
145 int ventoy_is_efi_os(void)
149 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
155 static int ventoy_get_fs_type(const char *fs
)
159 return ventoy_fs_max
;
161 else if (grub_strncmp(fs
, "exfat", 5) == 0)
163 return ventoy_fs_exfat
;
165 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
167 return ventoy_fs_ntfs
;
169 else if (grub_strncmp(fs
, "ext", 3) == 0)
171 return ventoy_fs_ext
;
173 else if (grub_strncmp(fs
, "xfs", 3) == 0)
175 return ventoy_fs_xfs
;
177 else if (grub_strncmp(fs
, "udf", 3) == 0)
179 return ventoy_fs_udf
;
181 else if (grub_strncmp(fs
, "fat", 3) == 0)
183 return ventoy_fs_fat
;
186 return ventoy_fs_max
;
189 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
208 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
210 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
214 static grub_err_t
ventoy_fs_close(grub_file_t file
)
216 grub_file_close(g_old_file
);
217 grub_free(file
->data
);
225 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
231 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
236 for (i
= 0; i
< g_video_mode_num
; i
++)
238 if (g_video_mode_list
[i
].width
== info
->width
&&
239 g_video_mode_list
[i
].height
== info
->height
&&
240 g_video_mode_list
[i
].bpp
== info
->bpp
)
246 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
247 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
248 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
251 if (g_video_mode_num
== g_video_mode_max
)
253 g_video_mode_max
*= 2;
254 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
260 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
262 if (v1
->bpp
== v2
->bpp
)
264 if (v1
->width
== v2
->width
)
266 if (v1
->height
== v2
->height
)
272 return (v1
->height
< v2
->height
) ? -1 : 1;
277 return (v1
->width
< v2
->width
) ? -1 : 1;
282 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
286 static int ventoy_enum_video_mode(void)
289 grub_video_adapter_t adapter
;
290 grub_video_driver_id_t id
;
291 ventoy_video_mode mode
;
293 g_video_mode_num
= 0;
294 g_video_mode_max
= 1024;
295 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
296 if (!g_video_mode_list
)
301 #ifdef GRUB_MACHINE_PCBIOS
302 grub_dl_load ("vbe");
305 id
= grub_video_get_driver_id ();
307 FOR_VIDEO_ADAPTERS (adapter
)
309 if (!adapter
->iterate
||
310 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
311 adapter
->init() != GRUB_ERR_NONE
)))
316 adapter
->iterate(ventoy_video_hook
, NULL
);
318 if (adapter
->id
!= id
)
324 /* sort video mode */
325 for (i
= 0; i
< g_video_mode_num
; i
++)
326 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
328 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
330 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
331 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
332 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
336 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
339 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
343 static struct grub_fs vtoy_fs
=
348 .fs_read
= ventoy_fs_read
,
349 .fs_close
= ventoy_fs_close
,
359 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
365 file
->data
= grub_malloc(rawFile
->size
+ 4096);
371 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
372 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
374 g_old_file
= rawFile
;
376 file
->size
= rawFile
->size
+ len
;
377 file
->device
= rawFile
->device
;
379 file
->not_easily_seekable
= 1;
384 static int ventoy_check_decimal_var(const char *name
, long *value
)
386 const char *value_str
= NULL
;
388 value_str
= grub_env_get(name
);
389 if (NULL
== value_str
)
391 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
394 if (!ventoy_is_decimal(value_str
))
396 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
399 *value
= grub_strtol(value_str
, NULL
, 10);
401 return GRUB_ERR_NONE
;
404 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
408 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
411 if (0 == grub_strcmp(args
[0], "on"))
414 grub_env_set("vtdebug_flag", "debug");
419 grub_env_set("vtdebug_flag", "");
422 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
425 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
429 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
431 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
432 grub_printf(" level:\r\n");
433 grub_printf(" 01/11: busybox / (+cat log)\r\n");
434 grub_printf(" 02/12: initrd / (+cat log)\r\n");
435 grub_printf(" 03/13: hook / (+cat log)\r\n");
437 grub_printf(" debug:\r\n");
438 grub_printf(" 0: debug is on\r\n");
439 grub_printf(" 1: debug is off\r\n");
441 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
444 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
446 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
448 g_ventoy_debug_level
= 1;
451 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
454 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
463 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
466 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
498 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
503 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
505 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
508 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
513 value_long
+= grub_strtol(args
[1], NULL
, 10);
515 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
516 grub_env_set(args
[0], buf
);
518 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
521 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
536 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
539 debug("failed to open file <%s> for udf check\n", args
[0]);
543 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
545 grub_env_set(args
[1], buf
);
547 grub_file_close(file
);
553 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
561 g_wimboot_enable
= 0;
562 grub_check_free(g_wimiso_path
);
563 grub_check_free(g_wimiso_chunk_list
.chunk
);
565 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
571 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
572 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
573 if (NULL
== g_wimiso_chunk_list
.chunk
)
575 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
578 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
579 g_wimiso_chunk_list
.cur_chunk
= 0;
581 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
583 g_wimboot_enable
= 1;
584 g_wimiso_path
= grub_strdup(args
[0]);
586 grub_file_close(file
);
591 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
597 grub_uint32_t offset
;
599 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
602 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
606 len
= (int)file
->size
;
608 data
= (char *)grub_malloc(file
->size
);
614 grub_file_read(file
, data
, file
->size
);
615 grub_file_close(file
);
617 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
618 grub_script_execute_sourcecode(exec
);
620 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
621 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
622 grub_file_close(file
);
624 grub_script_execute_sourcecode("loopback -d efiboot");
628 *direntoff
= offset
+ 2;
633 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
643 ventoy_iso9660_override
*dirent
;
652 totlen
= sizeof(ventoy_chain_head
);
654 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
656 debug("failed to load efiboot template %d\n", len
);
662 debug("efiboot template len:%d offset:%d\n", len
, offset
);
664 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
667 debug("failed to open file <%s>\n", args
[0]);
671 totlen
+= ventoy_align_2k(file
->size
);
673 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
674 dirent
->first_sector
= len
/ 2048;
675 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
676 dirent
->size
= (grub_uint32_t
)file
->size
;
677 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
679 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
681 #ifdef GRUB_MACHINE_EFI
682 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
684 data
= (char *)grub_malloc(totlen
);
687 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
689 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
690 grub_check_free(buf
);
692 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
693 grub_file_close(file
);
695 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
696 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
697 grub_env_set(name
, value
);
699 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
700 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
701 grub_env_set(name
, value
);
706 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
723 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
726 debug("failed to open file <%s>\n", args
[0]);
730 #ifdef GRUB_MACHINE_EFI
731 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
733 buf
= (char *)grub_malloc(file
->size
);
736 grub_file_read(file
, buf
, file
->size
);
738 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
739 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
740 grub_env_set(name
, value
);
742 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
743 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
744 grub_env_set(name
, value
);
746 grub_file_close(file
);
752 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
770 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
773 debug("failed to open file <%s> for udf check\n", args
[0]);
777 headlen
= sizeof(ventoy_chain_head
);
779 #ifdef GRUB_MACHINE_EFI
780 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
782 buf
= (char *)grub_malloc(headlen
+ file
->size
);
785 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
787 grub_file_read(file
, buf
+ headlen
, file
->size
);
789 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
790 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
791 grub_env_set(name
, value
);
793 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
794 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
795 grub_env_set(name
, value
);
797 grub_file_close(file
);
803 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
812 if (args
[0][0] == '1')
814 grub_iso9660_set_nojoliet(1);
818 grub_iso9660_set_nojoliet(0);
824 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
829 grub_uint8_t buf
[32];
840 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
843 debug("failed to open file <%s> for udf check\n", args
[0]);
847 for (i
= 16; i
< 32; i
++)
849 grub_file_seek(file
, i
* 2048);
850 grub_file_read(file
, buf
, sizeof(buf
));
858 grub_file_seek(file
, i
* 2048);
859 grub_file_read(file
, buf
, sizeof(buf
));
861 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
864 grub_file_seek(file
, i
* 2048);
865 grub_file_read(file
, buf
, sizeof(buf
));
867 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
868 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
874 grub_file_close(file
);
876 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
881 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
883 long value_long1
= 0;
884 long value_long2
= 0;
886 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
888 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
891 value_long1
= grub_strtol(args
[0], NULL
, 10);
892 value_long2
= grub_strtol(args
[2], NULL
, 10);
894 if (0 == grub_strcmp(args
[1], "eq"))
896 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
898 else if (0 == grub_strcmp(args
[1], "ne"))
900 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
902 else if (0 == grub_strcmp(args
[1], "gt"))
904 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
906 else if (0 == grub_strcmp(args
[1], "lt"))
908 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
910 else if (0 == grub_strcmp(args
[1], "ge"))
912 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
914 else if (0 == grub_strcmp(args
[1], "le"))
916 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
920 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
926 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
933 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
936 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
937 pos
= grub_strstr(buf
, ",");
943 grub_env_set(args
[1], buf
);
945 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
948 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
954 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
960 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
963 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
965 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
966 if (0 == grub_script_execute_sourcecode(buf
))
968 debug("file %s exist, ventoy_compatible YES\n", buf
);
969 grub_env_set("ventoy_compatible", "YES");
970 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
974 debug("file %s NOT exist\n", buf
);
978 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
979 pos
= grub_strstr(buf
, ")");
985 disk
= grub_disk_open(buf
);
988 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
989 grub_disk_close(disk
);
991 g_img_swap_tmp_buf
[703] = 0;
992 for (i
= 319; i
< 703; i
++)
994 if (g_img_swap_tmp_buf
[i
] == 'V' &&
995 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
997 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
998 grub_env_set("ventoy_compatible", "YES");
999 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1005 debug("failed to open disk <%s>\n", buf
);
1008 grub_env_set("ventoy_compatible", "NO");
1009 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1012 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1018 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1023 if (grub_islower(c1
))
1025 c1
= c1
- 'a' + 'A';
1028 if (grub_islower(c2
))
1030 c2
= c2
- 'a' + 'A';
1042 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1044 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1046 grub_memcpy(img1
, img2
, sizeof(img_info
));
1047 img1
->next
= g_img_swap_tmp
.next
;
1048 img1
->prev
= g_img_swap_tmp
.prev
;
1050 g_img_swap_tmp
.next
= img2
->next
;
1051 g_img_swap_tmp
.prev
= img2
->prev
;
1052 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1055 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1059 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1064 for (i
= 0; i
< namelen
; i
++)
1066 if (filename
[i
] == ' ' || filename
[i
] == '\t')
1071 if ((grub_uint8_t
)(filename
[i
]) >= 127)
1080 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1084 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1094 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1102 img_iterator_node
*tmp
;
1103 img_iterator_node
*new_node
;
1104 img_iterator_node
*node
= (img_iterator_node
*)data
;
1106 len
= grub_strlen(filename
);
1110 if ((len
== 1 && filename
[0] == '.') ||
1111 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1116 if (!ventoy_img_name_valid(filename
, len
))
1121 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1126 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1129 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1131 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1134 debug("Directory %s ignored...\n", new_node
->dir
);
1135 grub_free(new_node
);
1139 new_node
->tail
= node
->tail
;
1141 new_node
->parent
= node
;
1142 if (!node
->firstchild
)
1144 node
->firstchild
= new_node
;
1147 if (g_img_iterator_tail
)
1149 g_img_iterator_tail
->next
= new_node
;
1150 g_img_iterator_tail
= new_node
;
1154 g_img_iterator_head
.next
= new_node
;
1155 g_img_iterator_tail
= new_node
;
1161 debug("Find a file %s\n", filename
);
1167 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1169 type
= img_type_iso
;
1171 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1173 type
= img_type_wim
;
1175 else if (g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1176 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx")))
1178 type
= img_type_vhd
;
1180 #ifdef GRUB_MACHINE_EFI
1181 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1183 type
= img_type_efi
;
1186 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1188 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1190 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1191 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1196 type
= img_type_img
;
1203 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1208 img
= grub_zalloc(sizeof(img_info
));
1212 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1214 for (i
= 0; i
< (int)len
; i
++)
1216 if (filename
[i
] == ' ' || filename
[i
] == '\t' || (0 == grub_isprint(filename
[i
])))
1223 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1225 img
->size
= info
->size
;
1228 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1231 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1233 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1238 if (g_ventoy_img_list
)
1240 tail
= *(node
->tail
);
1246 g_ventoy_img_list
= img
;
1249 img
->id
= g_ventoy_img_count
;
1251 if (node
&& NULL
== node
->firstiso
)
1253 node
->firstiso
= img
;
1264 *((img_info
**)(node
->tail
)) = img
;
1265 g_ventoy_img_count
++;
1267 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1268 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1271 img
->class = g_menu_class
[type
];
1273 img
->menu_prefix
= g_menu_prefix
[type
];
1275 if (img_type_iso
== type
)
1277 if (ventoy_plugin_check_memdisk(img
->path
))
1279 img
->menu_prefix
= "miso";
1283 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1290 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1292 int len
= GRUB_UINT_MAX
;
1293 const char *value
= NULL
;
1294 char name
[32] = {0};
1295 char plat
[32] = {0};
1296 char guidstr
[32] = {0};
1297 ventoy_guid guid
= VENTOY_GUID
;
1298 const char *fmt1
= NULL
;
1299 const char *fmt2
= NULL
;
1300 const char *fmt3
= NULL
;
1301 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1302 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1303 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1304 const char fmtcode
[]={
1305 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1306 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1307 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1308 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1309 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1310 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1313 grub_memset(name
, 0, sizeof(name
));
1314 puint
[0] = grub_swap_bytes32(0x56454e54);
1315 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1316 puint
[2] = grub_swap_bytes32(0x45525349);
1317 puint
[1] = grub_swap_bytes32(0x4f595f56);
1318 value
= ventoy_get_env(name
);
1320 grub_memset(name
, 0, sizeof(name
));
1321 puint
[1] = grub_swap_bytes32(0x5f544f50);
1322 puint
[0] = grub_swap_bytes32(0x56544c45);
1323 fmt1
= ventoy_get_env(name
);
1329 grub_memset(name
, 0, sizeof(name
));
1330 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1331 puint
[0] = grub_swap_bytes32(0x56544c45);
1332 fmt2
= ventoy_get_env(name
);
1334 grub_memset(name
, 0, sizeof(name
));
1335 puint
[1] = grub_swap_bytes32(0x5f434c52);
1336 puint
[0] = grub_swap_bytes32(0x56544c45);
1337 fmt3
= ventoy_get_env(name
);
1339 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1341 #if defined (GRUB_MACHINE_EFI)
1342 puint2
[0] = grub_swap_bytes32(0x55454649);
1344 puint2
[0] = grub_swap_bytes32(0x42494f53);
1347 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1348 #pragma GCC diagnostic push
1349 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1350 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1351 fmt1
? fmt1
: fmtdata
,
1352 fmt2
? fmt2
: fmtdata
+ 4,
1353 value
? value
: "", plat
, guidstr
,
1354 fmt3
? fmt3
: fmtdata
+ 6);
1355 #pragma GCC diagnostic pop
1357 grub_memset(name
, 0, sizeof(name
));
1358 puint
[0] = grub_swap_bytes32(0x76746f79);
1359 puint
[2] = grub_swap_bytes32(0x656e7365);
1360 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1361 ventoy_set_env(name
, guidstr
);
1366 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1368 img_info
*minimg
= NULL
;
1369 img_info
*img
= (img_info
*)(node
->firstiso
);
1371 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1373 if (img
->select
== 0 && (NULL
== minimg
|| grub_strcmp(img
->name
, minimg
->name
) < 0))
1388 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1390 img_iterator_node
*Minchild
= NULL
;
1391 img_iterator_node
*child
= node
->firstchild
;
1393 while (child
&& child
->parent
== node
)
1395 if (child
->select
== 0 && (NULL
== Minchild
|| grub_strcmp(child
->dir
, Minchild
->dir
) < 0))
1399 child
= child
->next
;
1404 Minchild
->select
= 1;
1410 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1413 img_info
*img
= NULL
;
1414 const char *dir_class
= NULL
;
1415 const char *dir_alias
= NULL
;
1416 img_iterator_node
*child
= NULL
;
1418 if (node
->isocnt
== 0 || node
->done
== 1)
1423 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1425 offset
= node
->parent
->dirlen
;
1428 if (node
== &g_img_iterator_head
)
1430 if (g_default_menu_mode
== 0)
1432 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1433 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1434 " echo 'return ...' \n"
1440 node
->dir
[node
->dirlen
- 1] = 0;
1441 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1444 dir_class
= "vtoydir";
1447 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1450 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1451 "submenu \"%-10s %s\" --class=\"%s\" {\n",
1452 "DIR", dir_alias
, dir_class
);
1456 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1457 "submenu \"%-10s [%s]\" --class=\"%s\" {\n",
1458 "DIR", node
->dir
+ offset
, dir_class
);
1461 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1462 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1463 " echo 'return ...' \n"
1467 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1469 ventoy_dynamic_tree_menu(child
);
1472 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1474 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1475 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1478 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1479 img
->unsupport
? "[***********] " : "",
1480 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1482 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1485 if (node
!= &g_img_iterator_head
)
1487 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1494 int ventoy_check_device_result(int ret
)
1498 grub_snprintf(buf
, sizeof(buf
), "%d", ret
);
1499 ventoy_set_env("VTOY_CHKDEV_RESULT_STRING", buf
);
1503 grub_printf(VTOY_WARNING
"\n");
1504 grub_printf(VTOY_WARNING
"\n");
1505 grub_printf(VTOY_WARNING
"\n\n\n");
1507 grub_printf("This is NOT a standard Ventoy device and is NOT officially supported.\n\n");
1508 grub_printf("Recommend to follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1510 grub_printf("\n\nWill continue to boot after 10 seconds ...... ");
1518 int ventoy_check_device(grub_device_t dev
)
1521 grub_uint64_t offset
;
1526 struct grub_partition
*partition
;
1528 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1530 return ventoy_check_device_result(1);
1533 partition
= dev
->disk
->partition
;
1534 if (partition
->number
!= 0 || partition
->start
!= 2048)
1536 return ventoy_check_device_result(2);
1539 offset
= partition
->start
+ partition
->len
;
1541 /* We must have partition 2 */
1542 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1545 return ventoy_check_device_result(3);
1548 partition
= file
->device
->disk
->partition
;
1549 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1551 grub_file_close(file
);
1552 return ventoy_check_device_result(4);
1554 grub_file_close(file
);
1556 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1557 dev2
= grub_device_open(devname
);
1560 return ventoy_check_device_result(5);
1563 fs
= grub_fs_probe(dev2
);
1566 grub_device_close(dev2
);
1567 return ventoy_check_device_result(6);
1570 fs
->fs_label(dev2
, &label
);
1571 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1573 grub_device_close(dev2
);
1574 return ventoy_check_device_result(7);
1577 grub_device_close(dev2
);
1578 return ventoy_check_device_result(0);
1581 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1585 grub_device_t dev
= NULL
;
1586 img_info
*cur
= NULL
;
1587 img_info
*tail
= NULL
;
1588 img_info
*default_node
= NULL
;
1589 const char *strdata
= NULL
;
1590 char *device_name
= NULL
;
1591 const char *default_image
= NULL
;
1594 img_iterator_node
*node
= NULL
;
1595 img_iterator_node
*tmp
= NULL
;
1601 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1604 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1606 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1609 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1610 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1612 g_filt_dot_underscore_file
= 1;
1615 device_name
= grub_file_get_device_name(args
[0]);
1621 g_enum_dev
= dev
= grub_device_open(device_name
);
1627 /* make sure that we are running in a correct Ventoy device */
1628 ventoy_check_device(dev
);
1630 g_enum_fs
= fs
= grub_fs_probe(dev
);
1636 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1638 debug("unsupported fs:<%s>\n", fs
->name
);
1639 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1643 ventoy_set_env("vtoy_iso_fs", fs
->name
);
1645 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1646 if (strdata
&& strdata
[0] == '1')
1648 g_default_menu_mode
= 1;
1651 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1653 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1655 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1656 if (strdata
&& strdata
[0] == '/')
1658 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1659 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1661 g_img_iterator_head
.dir
[len
++] = '/';
1663 g_img_iterator_head
.dirlen
= len
;
1667 g_img_iterator_head
.dirlen
= 1;
1668 grub_strcpy(g_img_iterator_head
.dir
, "/");
1671 g_img_iterator_head
.tail
= &tail
;
1673 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1675 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1678 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1680 ventoy_dynamic_tree_menu(node
);
1684 node
= g_img_iterator_head
.next
;
1692 /* sort image list by image name */
1693 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1695 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1697 if (ventoy_cmp_img(cur
, tail
) > 0)
1699 ventoy_swap_img(cur
, tail
);
1704 if (g_default_menu_mode
== 1)
1706 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1707 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1708 " echo 'return ...' \n"
1712 if (g_default_menu_mode
== 0)
1714 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1717 img_len
= grub_strlen(default_image
);
1721 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1723 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1724 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1727 cur
->unsupport
? "[***********] " : "",
1728 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1730 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1732 if (g_default_menu_mode
== 0 && default_image
&& default_node
== NULL
)
1734 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1743 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1746 g_list_script_buf
[g_list_script_pos
] = 0;
1748 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1749 grub_env_set(args
[1], buf
);
1753 check_free(device_name
, grub_free
);
1754 check_free(dev
, grub_device_close
);
1756 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1760 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1762 img_info
*next
= NULL
;
1763 img_info
*cur
= g_ventoy_img_list
;
1776 g_ventoy_img_list
= NULL
;
1777 g_ventoy_img_count
= 0;
1779 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1782 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1785 img_info
*cur
= g_ventoy_img_list
;
1789 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1791 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1794 img_id
= grub_strtol(args
[0], NULL
, 10);
1795 if (img_id
>= g_ventoy_img_count
)
1797 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
1800 debug("Find image %ld name \n", img_id
);
1802 while (cur
&& img_id
> 0)
1810 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
1813 debug("image name is %s\n", cur
->name
);
1815 grub_env_set(args
[1], cur
->name
);
1817 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1820 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1825 const char *id
= NULL
;
1826 img_info
*cur
= g_ventoy_img_list
;
1830 if (argc
< 1 || argc
> 2)
1832 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
1835 id
= grub_env_get("chosen");
1837 pos
= grub_strstr(id
, "VID_");
1840 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
1844 img_id
= (int)grub_strtoul(id
, NULL
, 10);
1849 if (img_id
== cur
->id
)
1858 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
1861 grub_env_set(args
[0], cur
->path
);
1865 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
1866 grub_env_set(args
[1], value
);
1869 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1872 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
)
1879 device_name
= grub_file_get_device_name(filename
);
1891 pos2
= grub_strstr(pos
, ",");
1894 pos2
= grub_strstr(pos
, ")");
1902 disk
= grub_disk_open(pos
);
1905 grub_disk_read(disk
, 0, 0x180, 16, guid
);
1906 grub_disk_close(disk
);
1913 grub_free(device_name
);
1917 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
1919 eltorito_descriptor desc
;
1921 grub_memset(&desc
, 0, sizeof(desc
));
1922 grub_file_seek(file
, 17 * 2048);
1923 grub_file_read(file
, &desc
, sizeof(desc
));
1925 if (desc
.type
!= 0 || desc
.version
!= 1)
1930 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
1931 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
1939 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
1943 grub_uint8_t buf
[512];
1945 grub_file_seek(file
, sector
* 2048);
1946 grub_file_read(file
, buf
, sizeof(buf
));
1948 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
1950 debug("%s efi eltorito in Validation Entry\n", file
->name
);
1954 if (buf
[0] == 0x01 && buf
[1] == 0x00)
1959 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
1961 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
1963 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1967 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
1969 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1974 debug("%s does not contain efi eltorito\n", file
->name
);
1978 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
1981 const char *fs
= NULL
;
1982 const char *cdprompt
= NULL
;
1984 grub_uint8_t chksum
= 0;
1987 disk
= file
->device
->disk
;
1988 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
1990 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
1991 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
1992 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
1994 pos
= grub_strstr(file
->name
, "/");
2000 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2002 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
);
2004 param
->vtoy_img_size
= file
->size
;
2006 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2007 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2009 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2011 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2012 param
->vtoy_reserved
[4] = 0;
2013 if (g_ventoy_chain_type
== 1) /* Windows */
2015 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2016 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2018 param
->vtoy_reserved
[4] = 1;
2022 fs
= ventoy_get_env("ventoy_fs_probe");
2023 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2025 param
->vtoy_reserved
[3] = 1;
2028 /* calculate checksum */
2029 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2031 chksum
+= *((grub_uint8_t
*)param
+ i
);
2033 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2038 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2040 grub_uint32_t i
= 0;
2041 grub_uint64_t total
= 0;
2042 ventoy_img_chunk
*chunk
= NULL
;
2044 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2046 chunk
= chunklist
->chunk
+ i
;
2048 if (chunk
->disk_start_sector
<= start
)
2050 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2054 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2057 if (total
!= ((file
->size
+ 511) / 512))
2059 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2066 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2070 grub_uint32_t i
= 0;
2071 grub_uint32_t sector
= 0;
2072 grub_uint32_t count
= 0;
2073 grub_off_t size
= 0;
2074 grub_off_t read
= 0;
2076 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2077 if (fs_type
== ventoy_fs_exfat
)
2079 grub_fat_get_file_chunk(start
, file
, chunklist
);
2081 else if (fs_type
== ventoy_fs_ext
)
2083 grub_ext_get_file_chunk(start
, file
, chunklist
);
2087 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2088 file
->read_hook_data
= chunklist
;
2090 for (size
= file
->size
; size
> 0; size
-= read
)
2092 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2093 grub_file_read(file
, NULL
, read
);
2096 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2098 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2099 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2102 if (ventoy_fs_udf
== fs_type
)
2104 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2106 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2107 chunklist
->chunk
[i
].img_start_sector
= sector
;
2108 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2114 len
= (int)grub_strlen(file
->name
);
2115 if (grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0)
2117 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2119 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2129 chunklist
->chunk
[i
].img_start_sector
= sector
;
2130 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2138 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2142 grub_disk_addr_t start
;
2147 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2150 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2153 if (g_img_chunk_list
.chunk
)
2155 grub_free(g_img_chunk_list
.chunk
);
2158 /* get image chunk data */
2159 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2160 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2161 if (NULL
== g_img_chunk_list
.chunk
)
2163 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2166 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2167 g_img_chunk_list
.cur_chunk
= 0;
2169 start
= file
->device
->disk
->partition
->start
;
2171 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2173 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2174 grub_file_close(file
);
2178 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2181 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2182 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2185 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2190 char configfile
[128];
2191 install_template
*node
= NULL
;
2197 debug("select auto installation argc:%d\n", argc
);
2204 node
= ventoy_plugin_find_install_template(args
[0]);
2207 debug("Auto install template not found for %s\n", args
[0]);
2211 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2213 node
->cursel
= node
->autosel
- 1;
2214 debug("Auto install template auto select %d\n", node
->autosel
);
2218 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2224 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2225 " echo %s\n}\n", "123");
2227 for (i
= 0; i
< node
->templatenum
; i
++)
2229 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2231 node
->templatepath
[i
].path
);
2234 g_ventoy_menu_esc
= 1;
2235 g_ventoy_suppress_esc
= 1;
2237 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2238 grub_script_execute_sourcecode(configfile
);
2240 g_ventoy_menu_esc
= 0;
2241 g_ventoy_suppress_esc
= 0;
2245 node
->cursel
= g_ventoy_last_entry
- 1;
2247 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2250 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2255 char configfile
[128];
2256 persistence_config
*node
;
2262 debug("select persistence argc:%d\n", argc
);
2269 node
= ventoy_plugin_find_persistent(args
[0]);
2272 debug("Persistence image not found for %s\n", args
[0]);
2276 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2278 node
->cursel
= node
->autosel
- 1;
2279 debug("Persistence image auto select %d\n", node
->autosel
);
2283 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2289 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2290 " echo %s\n}\n", "123");
2292 for (i
= 0; i
< node
->backendnum
; i
++)
2294 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2296 node
->backendpath
[i
].path
);
2300 g_ventoy_menu_esc
= 1;
2301 g_ventoy_suppress_esc
= 1;
2303 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2304 grub_script_execute_sourcecode(configfile
);
2306 g_ventoy_menu_esc
= 0;
2307 g_ventoy_suppress_esc
= 0;
2311 node
->cursel
= g_ventoy_last_entry
- 1;
2313 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2316 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2319 ventoy_img_chunk
*cur
;
2325 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2327 cur
= g_img_chunk_list
.chunk
+ i
;
2328 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2329 cur
->img_start_sector
, cur
->img_end_sector
,
2330 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2334 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2337 #ifdef GRUB_MACHINE_EFI
2338 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2346 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2349 ulong chain_len
= 0;
2350 char *chain_data
= NULL
;
2351 char *relocator_addr
= NULL
;
2352 grub_relocator_chunk_t ch
;
2353 struct grub_relocator
*relocator
= NULL
;
2354 char envbuf
[64] = { 0 };
2365 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2366 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2368 relocator
= grub_relocator_new ();
2371 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2375 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2376 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2380 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2381 grub_relocator_unload (relocator
);
2385 relocator_addr
= get_virtual_current_address(ch
);
2387 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2389 grub_relocator_unload (relocator
);
2391 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2392 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2394 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2398 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2402 ventoy_img_chunk_list chunklist
;
2407 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2410 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2413 /* get image chunk data */
2414 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2415 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2416 if (NULL
== chunklist
.chunk
)
2418 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2421 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2422 chunklist
.cur_chunk
= 0;
2424 ventoy_get_block_list(file
, &chunklist
, 0);
2426 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2428 grub_printf("########## UNSUPPORTED ###############\n");
2431 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2433 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2435 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2436 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2439 grub_printf("\n==================================\n");
2441 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2443 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2444 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2445 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2446 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2447 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2451 grub_free(chunklist
.chunk
);
2452 grub_file_close(file
);
2454 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2457 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2460 ventoy_grub_param_file_replace
*replace
= NULL
;
2468 replace
= &(g_grub_param
->file_replace
);
2469 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2471 replace
->old_name_cnt
= 0;
2472 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2474 replace
->old_name_cnt
++;
2475 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2478 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2481 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2484 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2492 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2493 grub_printf("%s", g_list_script_buf
);
2497 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2498 grub_printf("%s", g_tree_script_buf
);
2504 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2506 img_info
*cur
= g_ventoy_img_list
;
2514 grub_printf("path:<%s> id=%d\n", cur
->path
, cur
->id
);
2515 grub_printf("name:<%s>\n\n", cur
->name
);
2522 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2528 ventoy_plugin_dump_injection();
2533 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2539 ventoy_plugin_dump_auto_install();
2544 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2550 ventoy_plugin_dump_persistence();
2555 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2566 if (args
[0][0] == '0')
2568 return g_ventoy_memdisk_mode
? 0 : 1;
2570 else if (args
[0][0] == '1')
2572 return g_ventoy_iso_raw
? 0 : 1;
2574 else if (args
[0][0] == '2')
2576 return g_ventoy_iso_uefi_drv
? 0 : 1;
2582 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2584 static int configfile_mode
= 0;
2585 char memfile
[128] = {0};
2592 * args[0]: 0:normal 1:configfile
2593 * args[1]: 0:list_buf 1:tree_buf
2598 debug("Invalid argc %d\n", argc
);
2602 if (args
[0][0] == '0')
2604 if (args
[1][0] == '0')
2606 grub_script_execute_sourcecode(g_list_script_buf
);
2610 grub_script_execute_sourcecode(g_tree_script_buf
);
2615 if (configfile_mode
)
2617 debug("Now already in F3 mode %d\n", configfile_mode
);
2621 if (args
[1][0] == '0')
2623 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2624 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2628 g_ventoy_last_entry
= -1;
2629 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2630 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2633 configfile_mode
= 1;
2634 grub_script_execute_sourcecode(memfile
);
2635 configfile_mode
= 0;
2641 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2652 g_ventoy_case_insensitive
= 1;
2653 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2654 g_ventoy_case_insensitive
= 0;
2660 grub_file_close(file
);
2666 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2671 const char *isopath
= NULL
;
2673 ventoy_mbr_head mbr
;
2680 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2683 isopath
= grub_env_get("vtoy_iso_part");
2686 debug("isopath is null %p\n", isopath
);
2690 debug("isopath is %s\n", isopath
);
2692 for (id
= 0; id
< 30 && (find
== 0); id
++)
2694 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2695 if (grub_strstr(isopath
, hdname
))
2697 debug("skip %s ...\n", hdname
);
2701 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2703 disk
= grub_disk_open(hdname
);
2706 debug("%s not exist\n", hdname
);
2710 grub_memset(&mbr
, 0, sizeof(mbr
));
2711 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2713 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2715 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2716 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2719 grub_env_set(args
[0], hdname
);
2723 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2727 debug("read %s failed\n", hdname
);
2730 grub_disk_close(disk
);
2736 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2747 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2750 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2753 debug("failed to open file %s\n", args
[0]);
2757 buf
= grub_malloc(len
);
2764 grub_file_read(file
, buf
, len
- 1);
2766 ventoy_get_line(buf
);
2767 ventoy_set_env(args
[1], buf
);
2771 grub_check_free(buf
);
2772 grub_file_close(file
);
2777 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
2782 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
2783 "0 %llu linear /dev/ventoy %llu\n",
2784 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
2789 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2791 char *device_name
= NULL
;
2792 grub_device_t dev
= NULL
;
2797 g_part_list_pos
= 0;
2798 grub_env_unset("vtoy_img_part_file");
2805 device_name
= grub_file_get_device_name(args
[0]);
2808 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
2812 dev
= grub_device_open(device_name
);
2815 debug("grub_device_open failed, %s\n", device_name
);
2819 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
2821 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
2822 grub_env_set("vtoy_img_part_file", buf
);
2826 check_free(device_name
, grub_free
);
2827 check_free(dev
, grub_device_close
);
2833 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2844 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
2847 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2850 debug("failed to open file %s\n", args
[0]);
2854 buf
= grub_malloc(file
->size
+ 1);
2860 buf
[file
->size
] = 0;
2861 grub_file_read(file
, buf
, file
->size
);
2863 if (grub_strstr(buf
, args
[1]))
2870 grub_check_free(buf
);
2871 grub_file_close(file
);
2876 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2881 ventoy_iso9660_vd pvd
;
2888 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
2891 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2894 debug("failed to open file %s\n", args
[0]);
2898 grub_file_seek(file
, 16 * 2048);
2899 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
2900 if (len
!= sizeof(pvd
))
2902 debug("failed to read pvd %d\n", len
);
2906 grub_memset(buf
, 0, sizeof(buf
));
2907 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
2908 ventoy_set_env(args
[1], buf
);
2910 grub_memset(buf
, 0, sizeof(buf
));
2911 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
2912 ventoy_set_env(args
[2], buf
);
2915 grub_file_close(file
);
2920 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2931 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
2934 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2937 debug("failed to open file %s\n", args
[0]);
2941 grub_memset(buf
, 0, sizeof(buf
));
2942 grub_file_seek(file
, 16 * 2048 + 813);
2943 len
= (int)grub_file_read(file
, buf
, 17);
2946 debug("failed to read create date %d\n", len
);
2950 ventoy_set_env(args
[1], buf
);
2953 grub_file_close(file
);
2958 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2964 ventoy_env_hook_root(1);
2969 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2975 ventoy_env_hook_root(0);
2980 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2986 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
2987 g_ventoy_last_entry
= -1;
2992 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2998 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3003 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3005 const char *pos
= filename
+ 1;
3013 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3015 grub_strncpy((char *)data
, filename
, 128);
3026 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3029 char *device_name
= NULL
;
3030 grub_device_t dev
= NULL
;
3031 grub_fs_t fs
= NULL
;
3032 char buf
[128] = {0};
3038 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3042 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3044 device_name
= grub_file_get_device_name(args
[0]);
3047 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3051 dev
= grub_device_open(device_name
);
3054 debug("grub_device_open failed, %s\n", device_name
);
3058 fs
= grub_fs_probe(dev
);
3061 debug("grub_fs_probe failed, %s\n", device_name
);
3065 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3069 ventoy_set_env(args
[2], buf
);
3076 check_free(device_name
, grub_free
);
3077 check_free(dev
, grub_device_close
);
3082 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3089 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3090 if (!g_ventoy_part_info
)
3095 disk
= grub_disk_open(args
[0]);
3098 debug("Failed to open disk %s\n", args
[0]);
3102 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3103 grub_disk_close(disk
);
3108 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3111 grub_uint8_t zeroguid
[16] = {0};
3116 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3119 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3121 if (id
>= 1 && id
<= 128)
3123 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3131 if (id
>= 1 && id
<= 4)
3133 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3143 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3146 char *device_name
= NULL
;
3147 grub_device_t dev
= NULL
;
3148 grub_fs_t fs
= NULL
;
3155 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3159 device_name
= grub_file_get_device_name(args
[0]);
3162 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3166 dev
= grub_device_open(device_name
);
3169 debug("grub_device_open failed, %s\n", device_name
);
3173 fs
= grub_fs_probe(dev
);
3176 debug("grub_fs_probe failed, %s\n", device_name
);
3180 fs
->fs_label(dev
, &label
);
3183 ventoy_set_env(args
[1], label
);
3191 check_free(device_name
, grub_free
);
3192 check_free(dev
, grub_device_close
);
3197 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3201 grub_snprintf((char *)data
, 256, "%s", filename
);
3209 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3212 char *device_name
= NULL
;
3213 grub_device_t dev
= NULL
;
3214 grub_fs_t fs
= NULL
;
3215 char name
[256] ={0};
3221 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3225 device_name
= grub_file_get_device_name(args
[0]);
3228 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3232 dev
= grub_device_open(device_name
);
3235 debug("grub_device_open failed, %s\n", device_name
);
3239 fs
= grub_fs_probe(dev
);
3242 debug("grub_fs_probe failed, %s\n", device_name
);
3246 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3249 ventoy_set_env(args
[2], name
);
3256 check_free(device_name
, grub_free
);
3257 check_free(dev
, grub_device_close
);
3262 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3272 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3276 for (pos
= args
[0]; *pos
; pos
++)
3290 grub_env_set(args
[1], args
[0]);
3300 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3302 struct grub_video_mode_info info
;
3309 if (!g_video_mode_list
)
3311 ventoy_enum_video_mode();
3314 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3316 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3320 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3323 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3325 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3326 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3328 VENTOY_CMD_RETURN(0);
3331 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3333 struct grub_video_mode_info info
;
3340 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3342 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3346 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3349 grub_env_set(args
[0], buf
);
3351 VENTOY_CMD_RETURN(0);
3354 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3362 if (!g_video_mode_list
)
3367 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3368 if (id
< g_video_mode_num
)
3370 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
3371 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
3374 grub_env_set(args
[1], buf
);
3376 VENTOY_CMD_RETURN(0);
3379 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
3381 grub_uint64_t size
= 0;
3384 char fullpath
[256] = {0};
3387 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3390 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
3393 debug("grub_file_open failed <%s>\n", fullpath
);
3399 grub_file_close(file
);
3403 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
3407 char fullpath
[256] = {0};
3410 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3413 file
= grub_file_open(fullpath
, type
);
3416 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
3423 int ventoy_is_file_exist(const char *fmt
, ...)
3428 char buf
[256] = {0};
3430 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
3434 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3437 grub_strncpy(pos
+ len
, " ]", 2);
3439 debug("script exec %s\n", buf
);
3441 if (0 == grub_script_execute_sourcecode(buf
))
3449 int ventoy_is_dir_exist(const char *fmt
, ...)
3454 char buf
[256] = {0};
3456 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
3460 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3463 grub_strncpy(pos
+ len
, " ]", 2);
3465 debug("script exec %s\n", buf
);
3467 if (0 == grub_script_execute_sourcecode(buf
))
3475 static int ventoy_env_init(void)
3479 grub_env_set("vtdebug_flag", "");
3481 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
3482 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3483 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3485 ventoy_filt_register(0, ventoy_wrapper_open
);
3487 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
3490 g_grub_param
->grub_env_get
= grub_env_get
;
3491 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
3492 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
3493 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
3494 grub_env_set("env_param", buf
);
3500 static cmd_para ventoy_cmds
[] =
3502 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
3503 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
3504 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
3505 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3506 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3507 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
3508 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
3509 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
3510 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
3511 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
3512 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
3513 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
3514 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
3515 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
3516 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
3517 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
3518 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
3519 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
3521 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
3522 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
3523 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
3524 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
3525 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
3526 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
3528 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
3529 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
3530 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
3531 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
3532 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
3533 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
3534 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
3535 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
3538 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
3539 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
3540 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
3541 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
3542 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
3543 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
3544 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
3545 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
3546 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
3547 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
3549 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
3550 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
3551 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
3552 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
3553 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
3554 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
3556 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3557 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3558 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
3559 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
3560 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
3561 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
3562 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
3563 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
3564 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
3565 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
3567 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
3568 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
3569 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
3570 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
3571 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
3572 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
3573 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
3575 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
3576 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
3577 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
3578 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
3581 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
3582 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
3584 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
3585 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
3586 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
3589 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
3590 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
3591 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
3592 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
3593 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
3594 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
3595 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
3596 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
3598 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
3599 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
3605 GRUB_MOD_INIT(ventoy
)
3608 cmd_para
*cur
= NULL
;
3612 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3614 cur
= ventoy_cmds
+ i
;
3615 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
3616 cur
->summary
, cur
->description
, cur
->parser
);
3620 GRUB_MOD_FINI(ventoy
)
3624 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3626 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);