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/acpi.h>
44 #include <grub/relocator.h>
45 #include <grub/charset.h>
46 #include <grub/ventoy.h>
47 #include "ventoy_def.h"
49 GRUB_MOD_LICENSE ("GPLv3+");
51 int g_ventoy_debug
= 0;
52 static int g_efi_os
= 0xFF;
53 initrd_info
*g_initrd_img_list
= NULL
;
54 initrd_info
*g_initrd_img_tail
= NULL
;
55 int g_initrd_img_count
= 0;
56 int g_valid_initrd_count
= 0;
57 int g_default_menu_mode
= 0;
58 int g_filt_dot_underscore_file
= 0;
59 int g_sort_case_sensitive
= 0;
60 static grub_file_t g_old_file
;
61 static int g_ventoy_last_entry_back
;
64 char g_img_swap_tmp_buf
[1024];
65 img_info g_img_swap_tmp
;
66 img_info
*g_ventoy_img_list
= NULL
;
68 int g_ventoy_img_count
= 0;
70 grub_device_t g_enum_dev
= NULL
;
71 grub_fs_t g_enum_fs
= NULL
;
72 img_iterator_node g_img_iterator_head
;
73 img_iterator_node
*g_img_iterator_tail
= NULL
;
75 grub_uint8_t g_ventoy_break_level
= 0;
76 grub_uint8_t g_ventoy_debug_level
= 0;
77 grub_uint8_t g_ventoy_chain_type
= 0;
79 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
80 grub_uint32_t g_ventoy_cpio_size
= 0;
81 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
82 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
84 ventoy_grub_param
*g_grub_param
= NULL
;
86 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
88 ventoy_img_chunk_list g_img_chunk_list
;
90 int g_wimboot_enable
= 0;
91 ventoy_img_chunk_list g_wimiso_chunk_list
;
92 char *g_wimiso_path
= NULL
;
94 int g_vhdboot_enable
= 0;
96 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
98 static char *g_tree_script_buf
= NULL
;
99 static int g_tree_script_pos
= 0;
101 static char *g_list_script_buf
= NULL
;
102 static int g_list_script_pos
= 0;
104 static char *g_part_list_buf
= NULL
;
105 static int g_part_list_pos
= 0;
107 static int g_video_mode_max
= 0;
108 static int g_video_mode_num
= 0;
109 static ventoy_video_mode
*g_video_mode_list
= NULL
;
111 static const char *g_menu_class
[] =
113 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
116 static const char *g_menu_prefix
[] =
118 "iso", "wim", "efi", "img", "vhd", "vtoy"
121 void ventoy_debug(const char *fmt
, ...)
125 va_start (args
, fmt
);
126 grub_vprintf (fmt
, args
);
130 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
140 for (i
= 0; i
< 16; i
++)
142 grub_printf("%02x ", guid
[i
]);
147 int ventoy_is_efi_os(void)
151 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
157 static int ventoy_get_fs_type(const char *fs
)
161 return ventoy_fs_max
;
163 else if (grub_strncmp(fs
, "exfat", 5) == 0)
165 return ventoy_fs_exfat
;
167 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
169 return ventoy_fs_ntfs
;
171 else if (grub_strncmp(fs
, "ext", 3) == 0)
173 return ventoy_fs_ext
;
175 else if (grub_strncmp(fs
, "xfs", 3) == 0)
177 return ventoy_fs_xfs
;
179 else if (grub_strncmp(fs
, "udf", 3) == 0)
181 return ventoy_fs_udf
;
183 else if (grub_strncmp(fs
, "fat", 3) == 0)
185 return ventoy_fs_fat
;
188 return ventoy_fs_max
;
191 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
210 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
212 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
216 static grub_err_t
ventoy_fs_close(grub_file_t file
)
218 grub_file_close(g_old_file
);
219 grub_free(file
->data
);
227 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
233 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
238 for (i
= 0; i
< g_video_mode_num
; i
++)
240 if (g_video_mode_list
[i
].width
== info
->width
&&
241 g_video_mode_list
[i
].height
== info
->height
&&
242 g_video_mode_list
[i
].bpp
== info
->bpp
)
248 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
249 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
250 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
253 if (g_video_mode_num
== g_video_mode_max
)
255 g_video_mode_max
*= 2;
256 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
262 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
264 if (v1
->bpp
== v2
->bpp
)
266 if (v1
->width
== v2
->width
)
268 if (v1
->height
== v2
->height
)
274 return (v1
->height
< v2
->height
) ? -1 : 1;
279 return (v1
->width
< v2
->width
) ? -1 : 1;
284 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
288 static int ventoy_enum_video_mode(void)
291 grub_video_adapter_t adapter
;
292 grub_video_driver_id_t id
;
293 ventoy_video_mode mode
;
295 g_video_mode_num
= 0;
296 g_video_mode_max
= 1024;
297 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
298 if (!g_video_mode_list
)
303 #ifdef GRUB_MACHINE_PCBIOS
304 grub_dl_load ("vbe");
307 id
= grub_video_get_driver_id ();
309 FOR_VIDEO_ADAPTERS (adapter
)
311 if (!adapter
->iterate
||
312 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
313 adapter
->init() != GRUB_ERR_NONE
)))
318 adapter
->iterate(ventoy_video_hook
, NULL
);
320 if (adapter
->id
!= id
)
326 /* sort video mode */
327 for (i
= 0; i
< g_video_mode_num
; i
++)
328 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
330 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
332 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
333 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
334 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
338 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
341 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
345 static struct grub_fs vtoy_fs
=
350 .fs_read
= ventoy_fs_read
,
351 .fs_close
= ventoy_fs_close
,
361 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
367 file
->data
= grub_malloc(rawFile
->size
+ 4096);
373 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
374 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
376 g_old_file
= rawFile
;
378 file
->size
= rawFile
->size
+ len
;
379 file
->device
= rawFile
->device
;
381 file
->not_easily_seekable
= 1;
386 static int ventoy_check_decimal_var(const char *name
, long *value
)
388 const char *value_str
= NULL
;
390 value_str
= grub_env_get(name
);
391 if (NULL
== value_str
)
393 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
396 if (!ventoy_is_decimal(value_str
))
398 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
401 *value
= grub_strtol(value_str
, NULL
, 10);
403 return GRUB_ERR_NONE
;
406 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
410 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
413 if (0 == grub_strcmp(args
[0], "on"))
416 grub_env_set("vtdebug_flag", "debug");
421 grub_env_set("vtdebug_flag", "");
424 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
427 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
431 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
433 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
434 grub_printf(" level:\r\n");
435 grub_printf(" 01/11: busybox / (+cat log)\r\n");
436 grub_printf(" 02/12: initrd / (+cat log)\r\n");
437 grub_printf(" 03/13: hook / (+cat log)\r\n");
439 grub_printf(" debug:\r\n");
440 grub_printf(" 0: debug is on\r\n");
441 grub_printf(" 1: debug is off\r\n");
443 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
446 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
448 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
450 g_ventoy_debug_level
= 1;
453 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
456 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
465 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
468 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
500 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
505 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
507 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
510 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
515 value_long
+= grub_strtol(args
[1], NULL
, 10);
517 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
518 grub_env_set(args
[0], buf
);
520 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
523 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
538 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
541 debug("failed to open file <%s> for udf check\n", args
[0]);
545 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
547 grub_env_set(args
[1], buf
);
549 grub_file_close(file
);
555 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
563 g_wimboot_enable
= 0;
564 grub_check_free(g_wimiso_path
);
565 grub_check_free(g_wimiso_chunk_list
.chunk
);
567 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
573 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
574 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
575 if (NULL
== g_wimiso_chunk_list
.chunk
)
577 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
580 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
581 g_wimiso_chunk_list
.cur_chunk
= 0;
583 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
585 g_wimboot_enable
= 1;
586 g_wimiso_path
= grub_strdup(args
[0]);
588 grub_file_close(file
);
593 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
599 grub_uint32_t offset
;
601 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
604 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
608 len
= (int)file
->size
;
610 data
= (char *)grub_malloc(file
->size
);
616 grub_file_read(file
, data
, file
->size
);
617 grub_file_close(file
);
619 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
620 grub_script_execute_sourcecode(exec
);
622 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
623 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
624 grub_file_close(file
);
626 grub_script_execute_sourcecode("loopback -d efiboot");
630 *direntoff
= offset
+ 2;
635 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
645 ventoy_iso9660_override
*dirent
;
654 totlen
= sizeof(ventoy_chain_head
);
656 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
658 debug("failed to load efiboot template %d\n", len
);
664 debug("efiboot template len:%d offset:%d\n", len
, offset
);
666 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
669 debug("failed to open file <%s>\n", args
[0]);
673 totlen
+= ventoy_align_2k(file
->size
);
675 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
676 dirent
->first_sector
= len
/ 2048;
677 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
678 dirent
->size
= (grub_uint32_t
)file
->size
;
679 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
681 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
683 #ifdef GRUB_MACHINE_EFI
684 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
686 data
= (char *)grub_malloc(totlen
);
689 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
691 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
692 grub_check_free(buf
);
694 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
695 grub_file_close(file
);
697 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
698 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
699 grub_env_set(name
, value
);
701 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
702 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
703 grub_env_set(name
, value
);
708 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
725 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
728 debug("failed to open file <%s>\n", args
[0]);
732 #ifdef GRUB_MACHINE_EFI
733 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
735 buf
= (char *)grub_malloc(file
->size
);
738 grub_file_read(file
, buf
, file
->size
);
740 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
741 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
742 grub_env_set(name
, value
);
744 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
745 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
746 grub_env_set(name
, value
);
748 grub_file_close(file
);
754 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
772 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
775 debug("failed to open file <%s> for udf check\n", args
[0]);
779 headlen
= sizeof(ventoy_chain_head
);
781 #ifdef GRUB_MACHINE_EFI
782 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
784 buf
= (char *)grub_malloc(headlen
+ file
->size
);
787 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
789 grub_file_read(file
, buf
+ headlen
, file
->size
);
791 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
792 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
793 grub_env_set(name
, value
);
795 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
796 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
797 grub_env_set(name
, value
);
799 grub_file_close(file
);
805 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
814 if (args
[0][0] == '1')
816 grub_iso9660_set_nojoliet(1);
820 grub_iso9660_set_nojoliet(0);
826 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
831 grub_uint8_t buf
[32];
842 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
845 debug("failed to open file <%s> for udf check\n", args
[0]);
849 for (i
= 16; i
< 32; i
++)
851 grub_file_seek(file
, i
* 2048);
852 grub_file_read(file
, buf
, sizeof(buf
));
860 grub_file_seek(file
, i
* 2048);
861 grub_file_read(file
, buf
, sizeof(buf
));
863 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
866 grub_file_seek(file
, i
* 2048);
867 grub_file_read(file
, buf
, sizeof(buf
));
869 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
870 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
876 grub_file_close(file
);
878 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
883 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
885 long value_long1
= 0;
886 long value_long2
= 0;
888 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
890 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
893 value_long1
= grub_strtol(args
[0], NULL
, 10);
894 value_long2
= grub_strtol(args
[2], NULL
, 10);
896 if (0 == grub_strcmp(args
[1], "eq"))
898 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
900 else if (0 == grub_strcmp(args
[1], "ne"))
902 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
904 else if (0 == grub_strcmp(args
[1], "gt"))
906 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
908 else if (0 == grub_strcmp(args
[1], "lt"))
910 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
912 else if (0 == grub_strcmp(args
[1], "ge"))
914 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
916 else if (0 == grub_strcmp(args
[1], "le"))
918 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
922 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
928 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
935 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
938 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
939 pos
= grub_strstr(buf
, ",");
945 grub_env_set(args
[1], buf
);
947 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
950 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
956 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
962 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
965 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
967 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
968 if (0 == grub_script_execute_sourcecode(buf
))
970 debug("file %s exist, ventoy_compatible YES\n", buf
);
971 grub_env_set("ventoy_compatible", "YES");
972 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
976 debug("file %s NOT exist\n", buf
);
980 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
981 pos
= grub_strstr(buf
, ")");
987 disk
= grub_disk_open(buf
);
990 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
991 grub_disk_close(disk
);
993 g_img_swap_tmp_buf
[703] = 0;
994 for (i
= 319; i
< 703; i
++)
996 if (g_img_swap_tmp_buf
[i
] == 'V' &&
997 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
999 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1000 grub_env_set("ventoy_compatible", "YES");
1001 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1007 debug("failed to open disk <%s>\n", buf
);
1010 grub_env_set("ventoy_compatible", "NO");
1011 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1014 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1020 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1025 if (0 == g_sort_case_sensitive
)
1027 if (grub_islower(c1
))
1029 c1
= c1
- 'a' + 'A';
1032 if (grub_islower(c2
))
1034 c2
= c2
- 'a' + 'A';
1047 static int ventoy_cmp_subdir(char *name1
, char *name2
)
1053 for (s1
= name1
, s2
= name2
; *s1
&& *s2
; s1
++, s2
++)
1058 if (0 == g_sort_case_sensitive
)
1060 if (grub_islower(c1
))
1062 c1
= c1
- 'a' + 'A';
1065 if (grub_islower(c2
))
1067 c2
= c2
- 'a' + 'A';
1080 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1082 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1084 grub_memcpy(img1
, img2
, sizeof(img_info
));
1085 img1
->next
= g_img_swap_tmp
.next
;
1086 img1
->prev
= g_img_swap_tmp
.prev
;
1088 g_img_swap_tmp
.next
= img2
->next
;
1089 g_img_swap_tmp
.prev
= img2
->prev
;
1090 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1093 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1097 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1102 for (i
= 0; i
< namelen
; i
++)
1104 if (filename
[i
] == ' ' || filename
[i
] == '\t')
1109 if ((grub_uint8_t
)(filename
[i
]) >= 127)
1118 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1122 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1132 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1140 img_iterator_node
*tmp
;
1141 img_iterator_node
*new_node
;
1142 img_iterator_node
*node
= (img_iterator_node
*)data
;
1144 len
= grub_strlen(filename
);
1148 if ((len
== 1 && filename
[0] == '.') ||
1149 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1154 if (!ventoy_img_name_valid(filename
, len
))
1159 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1164 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1167 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1169 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1172 debug("Directory %s ignored...\n", new_node
->dir
);
1173 grub_free(new_node
);
1177 new_node
->tail
= node
->tail
;
1179 new_node
->parent
= node
;
1180 if (!node
->firstchild
)
1182 node
->firstchild
= new_node
;
1185 if (g_img_iterator_tail
)
1187 g_img_iterator_tail
->next
= new_node
;
1188 g_img_iterator_tail
= new_node
;
1192 g_img_iterator_head
.next
= new_node
;
1193 g_img_iterator_tail
= new_node
;
1199 debug("Find a file %s\n", filename
);
1205 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1207 type
= img_type_iso
;
1209 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1211 type
= img_type_wim
;
1213 else if (g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1214 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1216 type
= img_type_vhd
;
1218 #ifdef GRUB_MACHINE_EFI
1219 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1221 type
= img_type_efi
;
1224 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1226 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1228 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1229 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1234 type
= img_type_img
;
1236 else if (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1238 type
= img_type_vtoy
;
1245 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1250 img
= grub_zalloc(sizeof(img_info
));
1254 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1256 for (i
= 0; i
< (int)len
; i
++)
1258 if (filename
[i
] == ' ' || filename
[i
] == '\t' || (0 == grub_isprint(filename
[i
])))
1265 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1267 img
->size
= info
->size
;
1270 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1273 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1275 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1280 if (g_ventoy_img_list
)
1282 tail
= *(node
->tail
);
1288 g_ventoy_img_list
= img
;
1291 img
->id
= g_ventoy_img_count
;
1293 if (node
&& NULL
== node
->firstiso
)
1295 node
->firstiso
= img
;
1306 *((img_info
**)(node
->tail
)) = img
;
1307 g_ventoy_img_count
++;
1309 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1310 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1313 img
->class = g_menu_class
[type
];
1315 img
->menu_prefix
= g_menu_prefix
[type
];
1317 if (img_type_iso
== type
)
1319 if (ventoy_plugin_check_memdisk(img
->path
))
1321 img
->menu_prefix
= "miso";
1325 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1332 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1334 int len
= GRUB_UINT_MAX
;
1335 const char *value
= NULL
;
1336 char name
[32] = {0};
1337 char plat
[32] = {0};
1338 char guidstr
[32] = {0};
1339 ventoy_guid guid
= VENTOY_GUID
;
1340 const char *fmt1
= NULL
;
1341 const char *fmt2
= NULL
;
1342 const char *fmt3
= NULL
;
1343 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1344 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1345 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1346 const char fmtcode
[]={
1347 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1348 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1349 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1350 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1351 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1352 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1355 grub_memset(name
, 0, sizeof(name
));
1356 puint
[0] = grub_swap_bytes32(0x56454e54);
1357 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1358 puint
[2] = grub_swap_bytes32(0x45525349);
1359 puint
[1] = grub_swap_bytes32(0x4f595f56);
1360 value
= ventoy_get_env(name
);
1362 grub_memset(name
, 0, sizeof(name
));
1363 puint
[1] = grub_swap_bytes32(0x5f544f50);
1364 puint
[0] = grub_swap_bytes32(0x56544c45);
1365 fmt1
= ventoy_get_env(name
);
1371 grub_memset(name
, 0, sizeof(name
));
1372 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1373 puint
[0] = grub_swap_bytes32(0x56544c45);
1374 fmt2
= ventoy_get_env(name
);
1376 grub_memset(name
, 0, sizeof(name
));
1377 puint
[1] = grub_swap_bytes32(0x5f434c52);
1378 puint
[0] = grub_swap_bytes32(0x56544c45);
1379 fmt3
= ventoy_get_env(name
);
1381 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1383 #if defined (GRUB_MACHINE_EFI)
1384 puint2
[0] = grub_swap_bytes32(0x55454649);
1386 puint2
[0] = grub_swap_bytes32(0x42494f53);
1389 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1390 #pragma GCC diagnostic push
1391 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1392 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1393 fmt1
? fmt1
: fmtdata
,
1394 fmt2
? fmt2
: fmtdata
+ 4,
1395 value
? value
: "", plat
, guidstr
,
1396 fmt3
? fmt3
: fmtdata
+ 6);
1397 #pragma GCC diagnostic pop
1399 grub_memset(name
, 0, sizeof(name
));
1400 puint
[0] = grub_swap_bytes32(0x76746f79);
1401 puint
[2] = grub_swap_bytes32(0x656e7365);
1402 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1403 ventoy_set_env(name
, guidstr
);
1408 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1410 img_info
*minimg
= NULL
;
1411 img_info
*img
= (img_info
*)(node
->firstiso
);
1413 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1415 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1430 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1432 img_iterator_node
*Minchild
= NULL
;
1433 img_iterator_node
*child
= node
->firstchild
;
1435 while (child
&& child
->parent
== node
)
1437 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
->dir
, Minchild
->dir
) < 0))
1441 child
= child
->next
;
1446 Minchild
->select
= 1;
1452 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1455 img_info
*img
= NULL
;
1456 const char *dir_class
= NULL
;
1457 const char *dir_alias
= NULL
;
1458 img_iterator_node
*child
= NULL
;
1460 if (node
->isocnt
== 0 || node
->done
== 1)
1465 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1467 offset
= node
->parent
->dirlen
;
1470 if (node
== &g_img_iterator_head
)
1472 if (g_default_menu_mode
== 0)
1474 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1475 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1476 " echo 'return ...' \n"
1482 node
->dir
[node
->dirlen
- 1] = 0;
1483 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1486 dir_class
= "vtoydir";
1489 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1492 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1493 "submenu \"%-10s %s\" --class=\"%s\" {\n",
1494 "DIR", dir_alias
, dir_class
);
1498 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1499 "submenu \"%-10s [%s]\" --class=\"%s\" {\n",
1500 "DIR", node
->dir
+ offset
, dir_class
);
1503 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1504 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1505 " echo 'return ...' \n"
1509 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1511 ventoy_dynamic_tree_menu(child
);
1514 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1516 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1517 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1520 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1521 img
->unsupport
? "[***********] " : "",
1522 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1524 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1527 if (node
!= &g_img_iterator_head
)
1529 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1536 int ventoy_check_device_result(int ret
)
1540 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1541 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1542 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1546 grub_printf(VTOY_WARNING
"\n");
1547 grub_printf(VTOY_WARNING
"\n");
1548 grub_printf(VTOY_WARNING
"\n\n\n");
1550 grub_printf("Unsatisfied conditions detected for Ventoy.\n\n");
1551 grub_printf("This is NOT a standard Ventoy device and is NOT officially supported.\n\n");
1552 grub_printf("Recommend to follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1554 grub_printf("\n\nWill exit after 10 seconds ...... ");
1562 int ventoy_check_device(grub_device_t dev
)
1565 grub_uint64_t offset
;
1570 struct grub_partition
*partition
;
1572 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1574 return ventoy_check_device_result(1 | 0x1000);
1577 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1578 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1579 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_64", dev
->disk
->name
))
1581 return ventoy_check_device_result(2 | 0x1000);
1584 /* We must have partition 2 */
1585 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1588 return ventoy_check_device_result(3 | 0x1000);
1591 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1593 grub_file_close(file
);
1594 return ventoy_check_device_result(4 | 0x1000);
1597 partition
= dev
->disk
->partition
;
1598 if (partition
->number
!= 0 || partition
->start
!= 2048)
1600 return ventoy_check_device_result(5);
1603 offset
= partition
->start
+ partition
->len
;
1604 partition
= file
->device
->disk
->partition
;
1605 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1607 grub_file_close(file
);
1608 return ventoy_check_device_result(6);
1610 grub_file_close(file
);
1612 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1613 dev2
= grub_device_open(devname
);
1616 return ventoy_check_device_result(7);
1619 fs
= grub_fs_probe(dev2
);
1622 grub_device_close(dev2
);
1623 return ventoy_check_device_result(8);
1626 fs
->fs_label(dev2
, &label
);
1627 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1629 grub_device_close(dev2
);
1630 return ventoy_check_device_result(9);
1633 grub_device_close(dev2
);
1634 return ventoy_check_device_result(0);
1637 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1641 grub_device_t dev
= NULL
;
1642 img_info
*cur
= NULL
;
1643 img_info
*tail
= NULL
;
1644 img_info
*default_node
= NULL
;
1645 const char *strdata
= NULL
;
1646 char *device_name
= NULL
;
1647 const char *default_image
= NULL
;
1650 img_iterator_node
*node
= NULL
;
1651 img_iterator_node
*tmp
= NULL
;
1657 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1660 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1662 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1665 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1666 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1668 g_filt_dot_underscore_file
= 1;
1671 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
1672 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1674 g_sort_case_sensitive
= 1;
1677 device_name
= grub_file_get_device_name(args
[0]);
1683 g_enum_dev
= dev
= grub_device_open(device_name
);
1689 g_enum_fs
= fs
= grub_fs_probe(dev
);
1695 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1697 debug("unsupported fs:<%s>\n", fs
->name
);
1698 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1702 ventoy_set_env("vtoy_iso_fs", fs
->name
);
1704 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1705 if (strdata
&& strdata
[0] == '1')
1707 g_default_menu_mode
= 1;
1710 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1712 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1714 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1715 if (strdata
&& strdata
[0] == '/')
1717 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1718 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1720 g_img_iterator_head
.dir
[len
++] = '/';
1722 g_img_iterator_head
.dirlen
= len
;
1726 g_img_iterator_head
.dirlen
= 1;
1727 grub_strcpy(g_img_iterator_head
.dir
, "/");
1730 g_img_iterator_head
.tail
= &tail
;
1732 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1734 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1737 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1739 ventoy_dynamic_tree_menu(node
);
1743 node
= g_img_iterator_head
.next
;
1751 /* sort image list by image name */
1752 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1754 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1756 if (ventoy_cmp_img(cur
, tail
) > 0)
1758 ventoy_swap_img(cur
, tail
);
1763 if (g_default_menu_mode
== 1)
1765 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1766 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1767 " echo 'return ...' \n"
1771 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1772 if (g_default_menu_mode
== 0)
1776 img_len
= grub_strlen(default_image
);
1780 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1782 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1783 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1786 cur
->unsupport
? "[***********] " : "",
1787 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1789 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1791 if (g_default_menu_mode
== 0 && default_image
&& default_node
== NULL
)
1793 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1802 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1805 g_list_script_buf
[g_list_script_pos
] = 0;
1807 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1808 grub_env_set(args
[1], buf
);
1812 check_free(device_name
, grub_free
);
1813 check_free(dev
, grub_device_close
);
1815 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1819 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1821 img_info
*next
= NULL
;
1822 img_info
*cur
= g_ventoy_img_list
;
1835 g_ventoy_img_list
= NULL
;
1836 g_ventoy_img_count
= 0;
1838 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1841 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1844 img_info
*cur
= g_ventoy_img_list
;
1848 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1850 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1853 img_id
= grub_strtol(args
[0], NULL
, 10);
1854 if (img_id
>= g_ventoy_img_count
)
1856 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
1859 debug("Find image %ld name \n", img_id
);
1861 while (cur
&& img_id
> 0)
1869 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
1872 debug("image name is %s\n", cur
->name
);
1874 grub_env_set(args
[1], cur
->name
);
1876 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1879 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1884 const char *id
= NULL
;
1885 img_info
*cur
= g_ventoy_img_list
;
1889 if (argc
< 1 || argc
> 2)
1891 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
1894 id
= grub_env_get("chosen");
1896 pos
= grub_strstr(id
, "VID_");
1899 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
1903 img_id
= (int)grub_strtoul(id
, NULL
, 10);
1908 if (img_id
== cur
->id
)
1917 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
1920 grub_env_set(args
[0], cur
->path
);
1924 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
1925 grub_env_set(args
[1], value
);
1928 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1931 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
1938 device_name
= grub_file_get_device_name(filename
);
1950 pos2
= grub_strstr(pos
, ",");
1953 pos2
= grub_strstr(pos
, ")");
1961 disk
= grub_disk_open(pos
);
1964 grub_disk_read(disk
, 0, 0x180, 16, guid
);
1965 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
1966 grub_disk_close(disk
);
1973 grub_free(device_name
);
1977 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
1979 eltorito_descriptor desc
;
1981 grub_memset(&desc
, 0, sizeof(desc
));
1982 grub_file_seek(file
, 17 * 2048);
1983 grub_file_read(file
, &desc
, sizeof(desc
));
1985 if (desc
.type
!= 0 || desc
.version
!= 1)
1990 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
1991 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
1999 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2003 grub_uint8_t buf
[512];
2005 grub_file_seek(file
, sector
* 2048);
2006 grub_file_read(file
, buf
, sizeof(buf
));
2008 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2010 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2014 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2019 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2021 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2023 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2027 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2029 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2034 debug("%s does not contain efi eltorito\n", file
->name
);
2038 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2041 const char *fs
= NULL
;
2042 const char *cdprompt
= NULL
;
2044 grub_uint8_t chksum
= 0;
2047 disk
= file
->device
->disk
;
2048 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2050 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2051 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2052 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2054 pos
= grub_strstr(file
->name
, "/");
2060 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2062 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2064 param
->vtoy_img_size
= file
->size
;
2066 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2067 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2069 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2071 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2072 param
->vtoy_reserved
[4] = 0;
2073 if (g_ventoy_chain_type
== 1) /* Windows */
2075 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2076 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2078 param
->vtoy_reserved
[4] = 1;
2082 fs
= ventoy_get_env("ventoy_fs_probe");
2083 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2085 param
->vtoy_reserved
[3] = 1;
2088 /* calculate checksum */
2089 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2091 chksum
+= *((grub_uint8_t
*)param
+ i
);
2093 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2098 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2100 grub_uint32_t i
= 0;
2101 grub_uint64_t total
= 0;
2102 ventoy_img_chunk
*chunk
= NULL
;
2104 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2106 chunk
= chunklist
->chunk
+ i
;
2108 if (chunk
->disk_start_sector
<= start
)
2110 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2114 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2117 if (total
!= ((file
->size
+ 511) / 512))
2119 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2126 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2130 grub_uint32_t i
= 0;
2131 grub_uint32_t sector
= 0;
2132 grub_uint32_t count
= 0;
2133 grub_off_t size
= 0;
2134 grub_off_t read
= 0;
2136 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2137 if (fs_type
== ventoy_fs_exfat
)
2139 grub_fat_get_file_chunk(start
, file
, chunklist
);
2141 else if (fs_type
== ventoy_fs_ext
)
2143 grub_ext_get_file_chunk(start
, file
, chunklist
);
2147 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2148 file
->read_hook_data
= chunklist
;
2150 for (size
= file
->size
; size
> 0; size
-= read
)
2152 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2153 grub_file_read(file
, NULL
, read
);
2156 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2158 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2159 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2162 if (ventoy_fs_udf
== fs_type
)
2164 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2166 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2167 chunklist
->chunk
[i
].img_start_sector
= sector
;
2168 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2174 len
= (int)grub_strlen(file
->name
);
2175 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2176 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2177 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2178 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2180 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2182 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2192 chunklist
->chunk
[i
].img_start_sector
= sector
;
2193 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2201 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2205 grub_disk_addr_t start
;
2210 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2213 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2216 if (g_img_chunk_list
.chunk
)
2218 grub_free(g_img_chunk_list
.chunk
);
2221 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2223 grub_file_close(file
);
2224 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2227 /* get image chunk data */
2228 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2229 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2230 if (NULL
== g_img_chunk_list
.chunk
)
2232 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2235 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2236 g_img_chunk_list
.cur_chunk
= 0;
2238 start
= file
->device
->disk
->partition
->start
;
2240 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2242 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2243 grub_file_close(file
);
2247 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2250 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2251 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2254 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2259 char configfile
[128];
2260 install_template
*node
= NULL
;
2266 debug("select auto installation argc:%d\n", argc
);
2273 node
= ventoy_plugin_find_install_template(args
[0]);
2276 debug("Auto install template not found for %s\n", args
[0]);
2280 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2282 node
->cursel
= node
->autosel
- 1;
2283 debug("Auto install template auto select %d\n", node
->autosel
);
2287 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2293 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2294 " echo %s\n}\n", "123");
2296 for (i
= 0; i
< node
->templatenum
; i
++)
2298 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2300 node
->templatepath
[i
].path
);
2303 g_ventoy_menu_esc
= 1;
2304 g_ventoy_suppress_esc
= 1;
2306 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2307 grub_script_execute_sourcecode(configfile
);
2309 g_ventoy_menu_esc
= 0;
2310 g_ventoy_suppress_esc
= 0;
2314 node
->cursel
= g_ventoy_last_entry
- 1;
2316 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2319 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2324 char configfile
[128];
2325 persistence_config
*node
;
2331 debug("select persistence argc:%d\n", argc
);
2338 node
= ventoy_plugin_find_persistent(args
[0]);
2341 debug("Persistence image not found for %s\n", args
[0]);
2345 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2347 node
->cursel
= node
->autosel
- 1;
2348 debug("Persistence image auto select %d\n", node
->autosel
);
2352 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2358 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2359 " echo %s\n}\n", "123");
2361 for (i
= 0; i
< node
->backendnum
; i
++)
2363 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2365 node
->backendpath
[i
].path
);
2369 g_ventoy_menu_esc
= 1;
2370 g_ventoy_suppress_esc
= 1;
2372 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2373 grub_script_execute_sourcecode(configfile
);
2375 g_ventoy_menu_esc
= 0;
2376 g_ventoy_suppress_esc
= 0;
2380 node
->cursel
= g_ventoy_last_entry
- 1;
2382 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2385 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2388 ventoy_img_chunk
*cur
;
2394 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2396 cur
= g_img_chunk_list
.chunk
+ i
;
2397 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2398 cur
->img_start_sector
, cur
->img_end_sector
,
2399 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2403 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2406 #ifdef GRUB_MACHINE_EFI
2407 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2415 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2418 ulong chain_len
= 0;
2419 char *chain_data
= NULL
;
2420 char *relocator_addr
= NULL
;
2421 grub_relocator_chunk_t ch
;
2422 struct grub_relocator
*relocator
= NULL
;
2423 char envbuf
[64] = { 0 };
2434 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2435 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2437 relocator
= grub_relocator_new ();
2440 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2444 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2445 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2449 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2450 grub_relocator_unload (relocator
);
2454 relocator_addr
= get_virtual_current_address(ch
);
2456 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2458 grub_relocator_unload (relocator
);
2460 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2461 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2463 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2467 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2471 ventoy_img_chunk_list chunklist
;
2476 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2479 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2482 /* get image chunk data */
2483 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2484 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2485 if (NULL
== chunklist
.chunk
)
2487 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2490 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2491 chunklist
.cur_chunk
= 0;
2493 ventoy_get_block_list(file
, &chunklist
, 0);
2495 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2497 grub_printf("########## UNSUPPORTED ###############\n");
2500 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2502 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2504 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2505 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2508 grub_printf("\n==================================\n");
2510 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2512 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2513 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2514 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2515 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2516 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2520 grub_free(chunklist
.chunk
);
2521 grub_file_close(file
);
2523 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2526 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2529 ventoy_grub_param_file_replace
*replace
= NULL
;
2537 replace
= &(g_grub_param
->file_replace
);
2538 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2540 replace
->old_name_cnt
= 0;
2541 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2543 replace
->old_name_cnt
++;
2544 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2547 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2550 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2553 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2561 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2562 grub_printf("%s", g_list_script_buf
);
2566 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2567 grub_printf("%s", g_tree_script_buf
);
2573 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2575 img_info
*cur
= g_ventoy_img_list
;
2583 grub_printf("path:<%s> id=%d\n", cur
->path
, cur
->id
);
2584 grub_printf("name:<%s>\n\n", cur
->name
);
2591 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2597 ventoy_plugin_dump_injection();
2602 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2608 ventoy_plugin_dump_auto_install();
2613 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2619 ventoy_plugin_dump_persistence();
2624 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2635 if (args
[0][0] == '0')
2637 return g_ventoy_memdisk_mode
? 0 : 1;
2639 else if (args
[0][0] == '1')
2641 return g_ventoy_iso_raw
? 0 : 1;
2643 else if (args
[0][0] == '2')
2645 return g_ventoy_iso_uefi_drv
? 0 : 1;
2651 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2653 static int configfile_mode
= 0;
2654 char memfile
[128] = {0};
2661 * args[0]: 0:normal 1:configfile
2662 * args[1]: 0:list_buf 1:tree_buf
2667 debug("Invalid argc %d\n", argc
);
2671 if (args
[0][0] == '0')
2673 if (args
[1][0] == '0')
2675 grub_script_execute_sourcecode(g_list_script_buf
);
2679 grub_script_execute_sourcecode(g_tree_script_buf
);
2684 if (configfile_mode
)
2686 debug("Now already in F3 mode %d\n", configfile_mode
);
2690 if (args
[1][0] == '0')
2692 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2693 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2697 g_ventoy_last_entry
= -1;
2698 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2699 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2702 configfile_mode
= 1;
2703 grub_script_execute_sourcecode(memfile
);
2704 configfile_mode
= 0;
2710 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2721 g_ventoy_case_insensitive
= 1;
2722 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2723 g_ventoy_case_insensitive
= 0;
2729 grub_file_close(file
);
2735 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2740 const char *isopath
= NULL
;
2742 ventoy_mbr_head mbr
;
2749 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2752 isopath
= grub_env_get("vtoy_iso_part");
2755 debug("isopath is null %p\n", isopath
);
2759 debug("isopath is %s\n", isopath
);
2761 for (id
= 0; id
< 30 && (find
== 0); id
++)
2763 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2764 if (grub_strstr(isopath
, hdname
))
2766 debug("skip %s ...\n", hdname
);
2770 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2772 disk
= grub_disk_open(hdname
);
2775 debug("%s not exist\n", hdname
);
2779 grub_memset(&mbr
, 0, sizeof(mbr
));
2780 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2782 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2784 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2785 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2788 grub_env_set(args
[0], hdname
);
2792 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2796 debug("read %s failed\n", hdname
);
2799 grub_disk_close(disk
);
2805 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2816 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2819 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2822 debug("failed to open file %s\n", args
[0]);
2826 buf
= grub_malloc(len
);
2833 grub_file_read(file
, buf
, len
- 1);
2835 ventoy_get_line(buf
);
2836 ventoy_set_env(args
[1], buf
);
2840 grub_check_free(buf
);
2841 grub_file_close(file
);
2846 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
2851 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
2852 "0 %llu linear /dev/ventoy %llu\n",
2853 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
2858 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2860 char *device_name
= NULL
;
2861 grub_device_t dev
= NULL
;
2866 g_part_list_pos
= 0;
2867 grub_env_unset("vtoy_img_part_file");
2874 device_name
= grub_file_get_device_name(args
[0]);
2877 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
2881 dev
= grub_device_open(device_name
);
2884 debug("grub_device_open failed, %s\n", device_name
);
2888 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
2890 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
2891 grub_env_set("vtoy_img_part_file", buf
);
2895 check_free(device_name
, grub_free
);
2896 check_free(dev
, grub_device_close
);
2902 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2913 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
2916 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2919 debug("failed to open file %s\n", args
[0]);
2923 buf
= grub_malloc(file
->size
+ 1);
2929 buf
[file
->size
] = 0;
2930 grub_file_read(file
, buf
, file
->size
);
2932 if (grub_strstr(buf
, args
[1]))
2939 grub_check_free(buf
);
2940 grub_file_close(file
);
2945 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2950 ventoy_iso9660_vd pvd
;
2957 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
2960 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2963 debug("failed to open file %s\n", args
[0]);
2967 grub_file_seek(file
, 16 * 2048);
2968 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
2969 if (len
!= sizeof(pvd
))
2971 debug("failed to read pvd %d\n", len
);
2975 grub_memset(buf
, 0, sizeof(buf
));
2976 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
2977 ventoy_set_env(args
[1], buf
);
2979 grub_memset(buf
, 0, sizeof(buf
));
2980 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
2981 ventoy_set_env(args
[2], buf
);
2984 grub_file_close(file
);
2989 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3000 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3003 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3006 debug("failed to open file %s\n", args
[0]);
3010 grub_memset(buf
, 0, sizeof(buf
));
3011 grub_file_seek(file
, 16 * 2048 + 813);
3012 len
= (int)grub_file_read(file
, buf
, 17);
3015 debug("failed to read create date %d\n", len
);
3019 ventoy_set_env(args
[1], buf
);
3022 grub_file_close(file
);
3027 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3033 ventoy_env_hook_root(1);
3038 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3044 ventoy_env_hook_root(0);
3049 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3056 int image_sector_size
;
3058 ventoy_chain_head
*chain
;
3059 ventoy_img_chunk
*chunk
;
3060 ventoy_os_param
*osparam
;
3061 ventoy_image_location
*location
;
3062 ventoy_image_disk_region
*region
;
3063 struct grub_acpi_table_header
*acpi
;
3072 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3074 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3080 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3082 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3084 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3088 img_chunk_num
= chain
->img_chunk_num
;
3090 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3091 datalen
= sizeof(ventoy_os_param
) + loclen
;
3093 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3094 acpi
= grub_zalloc(buflen
);
3100 /* Step1: Fill acpi table header */
3101 grub_memcpy(acpi
->signature
, "VTOY", 4);
3102 acpi
->length
= buflen
;
3104 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3105 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3107 acpi
->creator_id
[0] = 1;
3108 acpi
->creator_rev
= 1;
3110 /* Step2: Fill data */
3111 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3112 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3113 osparam
->vtoy_img_location_addr
= 0;
3114 osparam
->vtoy_img_location_len
= loclen
;
3115 osparam
->chksum
= 0;
3116 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3118 location
= (ventoy_image_location
*)(osparam
+ 1);
3119 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3120 location
->image_sector_size
= image_sector_size
;
3121 location
->disk_sector_size
= chain
->disk_sector_size
;
3122 location
->region_count
= img_chunk_num
;
3124 region
= location
->regions
;
3125 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3126 if (512 == image_sector_size
)
3128 for (i
= 0; i
< img_chunk_num
; i
++)
3130 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3131 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3132 region
->disk_start_sector
= chunk
->disk_start_sector
;
3139 for (i
= 0; i
< img_chunk_num
; i
++)
3141 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3142 region
->image_start_sector
= chunk
->img_start_sector
;
3143 region
->disk_start_sector
= chunk
->disk_start_sector
;
3149 /* Step3: Fill acpi checksum */
3151 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3153 /* load acpi table */
3154 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3155 grub_script_execute_sourcecode(cmd
);
3159 VENTOY_CMD_RETURN(0);
3162 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3168 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3169 g_ventoy_last_entry
= -1;
3174 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3180 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3185 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3187 const char *pos
= filename
+ 1;
3195 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3197 grub_strncpy((char *)data
, filename
, 128);
3208 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3211 char *device_name
= NULL
;
3212 grub_device_t dev
= NULL
;
3213 grub_fs_t fs
= NULL
;
3214 char buf
[128] = {0};
3220 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3224 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3226 device_name
= grub_file_get_device_name(args
[0]);
3229 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3233 dev
= grub_device_open(device_name
);
3236 debug("grub_device_open failed, %s\n", device_name
);
3240 fs
= grub_fs_probe(dev
);
3243 debug("grub_fs_probe failed, %s\n", device_name
);
3247 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3251 ventoy_set_env(args
[2], buf
);
3258 check_free(device_name
, grub_free
);
3259 check_free(dev
, grub_device_close
);
3264 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3274 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3275 if (!g_ventoy_part_info
)
3280 disk
= grub_disk_open(args
[0]);
3283 debug("Failed to open disk %s\n", args
[0]);
3287 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3288 grub_disk_close(disk
);
3290 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3291 dev
= grub_device_open(name
);
3294 /* make sure that we are running in a correct Ventoy device */
3295 ret
= ventoy_check_device(dev
);
3296 grub_device_close(dev
);
3307 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3310 grub_uint8_t zeroguid
[16] = {0};
3315 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3318 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3320 if (id
>= 1 && id
<= 128)
3322 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3330 if (id
>= 1 && id
<= 4)
3332 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3342 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3345 char *device_name
= NULL
;
3346 grub_device_t dev
= NULL
;
3347 grub_fs_t fs
= NULL
;
3354 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3358 device_name
= grub_file_get_device_name(args
[0]);
3361 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3365 dev
= grub_device_open(device_name
);
3368 debug("grub_device_open failed, %s\n", device_name
);
3372 fs
= grub_fs_probe(dev
);
3375 debug("grub_fs_probe failed, %s\n", device_name
);
3379 fs
->fs_label(dev
, &label
);
3382 ventoy_set_env(args
[1], label
);
3390 check_free(device_name
, grub_free
);
3391 check_free(dev
, grub_device_close
);
3396 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3400 grub_snprintf((char *)data
, 256, "%s", filename
);
3408 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3411 char *device_name
= NULL
;
3412 grub_device_t dev
= NULL
;
3413 grub_fs_t fs
= NULL
;
3414 char name
[256] ={0};
3420 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3424 device_name
= grub_file_get_device_name(args
[0]);
3427 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3431 dev
= grub_device_open(device_name
);
3434 debug("grub_device_open failed, %s\n", device_name
);
3438 fs
= grub_fs_probe(dev
);
3441 debug("grub_fs_probe failed, %s\n", device_name
);
3445 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3448 ventoy_set_env(args
[2], name
);
3455 check_free(device_name
, grub_free
);
3456 check_free(dev
, grub_device_close
);
3461 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3471 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3475 for (pos
= args
[0]; *pos
; pos
++)
3489 grub_env_set(args
[1], args
[0]);
3499 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3501 struct grub_video_mode_info info
;
3508 if (!g_video_mode_list
)
3510 ventoy_enum_video_mode();
3513 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3515 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3519 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3522 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3524 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3525 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3527 VENTOY_CMD_RETURN(0);
3530 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3532 struct grub_video_mode_info info
;
3539 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3541 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3545 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3548 grub_env_set(args
[0], buf
);
3550 VENTOY_CMD_RETURN(0);
3553 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3561 if (!g_video_mode_list
)
3566 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3567 if (id
< g_video_mode_num
)
3569 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
3570 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
3573 grub_env_set(args
[1], buf
);
3575 VENTOY_CMD_RETURN(0);
3578 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
3580 grub_uint64_t size
= 0;
3583 char fullpath
[256] = {0};
3586 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3589 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
3592 debug("grub_file_open failed <%s>\n", fullpath
);
3598 grub_file_close(file
);
3602 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
3606 char fullpath
[256] = {0};
3609 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3612 file
= grub_file_open(fullpath
, type
);
3615 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
3622 int ventoy_is_file_exist(const char *fmt
, ...)
3627 char buf
[256] = {0};
3629 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
3633 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3636 grub_strncpy(pos
+ len
, " ]", 2);
3638 debug("script exec %s\n", buf
);
3640 if (0 == grub_script_execute_sourcecode(buf
))
3648 int ventoy_is_dir_exist(const char *fmt
, ...)
3653 char buf
[256] = {0};
3655 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
3659 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3662 grub_strncpy(pos
+ len
, " ]", 2);
3664 debug("script exec %s\n", buf
);
3666 if (0 == grub_script_execute_sourcecode(buf
))
3674 static int ventoy_env_init(void)
3678 grub_env_set("vtdebug_flag", "");
3680 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
3681 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3682 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3684 ventoy_filt_register(0, ventoy_wrapper_open
);
3686 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
3689 g_grub_param
->grub_env_get
= grub_env_get
;
3690 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
3691 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
3692 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
3693 grub_env_set("env_param", buf
);
3694 grub_env_set("ventoy_env_param", buf
);
3695 grub_env_export("ventoy_env_param");
3701 static cmd_para ventoy_cmds
[] =
3703 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
3704 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
3705 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
3706 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3707 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3708 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
3709 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
3710 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
3711 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
3712 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
3713 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
3714 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
3715 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
3716 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
3717 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
3718 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
3719 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
3720 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
3721 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
3722 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
3724 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
3725 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
3726 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
3727 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
3728 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
3729 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
3731 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
3732 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
3733 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
3734 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
3735 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
3736 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
3737 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
3738 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
3741 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
3742 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
3743 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
3744 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
3745 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
3746 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
3747 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
3748 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
3749 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
3750 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
3752 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
3753 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
3754 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
3755 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
3756 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
3757 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
3759 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3760 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3761 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
3762 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
3763 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
3764 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
3765 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
3766 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
3767 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
3768 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
3770 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
3771 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
3772 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
3773 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
3774 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
3775 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
3776 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
3778 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
3779 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
3780 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
3781 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
3784 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
3785 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
3787 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
3788 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
3789 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
3792 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
3793 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
3794 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
3795 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
3796 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
3797 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
3798 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
3799 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
3801 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
3802 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
3803 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
3809 GRUB_MOD_INIT(ventoy
)
3812 cmd_para
*cur
= NULL
;
3816 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3818 cur
= ventoy_cmds
+ i
;
3819 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
3820 cur
->summary
, cur
->description
, cur
->parser
);
3824 GRUB_MOD_FINI(ventoy
)
3828 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3830 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);