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 int g_tree_view_menu_style
= 0;
61 static grub_file_t g_old_file
;
62 static int g_ventoy_last_entry_back
;
65 char g_img_swap_tmp_buf
[1024];
66 img_info g_img_swap_tmp
;
67 img_info
*g_ventoy_img_list
= NULL
;
69 int g_ventoy_img_count
= 0;
71 grub_device_t g_enum_dev
= NULL
;
72 grub_fs_t g_enum_fs
= NULL
;
73 img_iterator_node g_img_iterator_head
;
74 img_iterator_node
*g_img_iterator_tail
= NULL
;
76 grub_uint8_t g_ventoy_break_level
= 0;
77 grub_uint8_t g_ventoy_debug_level
= 0;
78 grub_uint8_t g_ventoy_chain_type
= 0;
80 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
81 grub_uint32_t g_ventoy_cpio_size
= 0;
82 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
83 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
85 ventoy_grub_param
*g_grub_param
= NULL
;
87 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
89 ventoy_img_chunk_list g_img_chunk_list
;
91 int g_wimboot_enable
= 0;
92 ventoy_img_chunk_list g_wimiso_chunk_list
;
93 char *g_wimiso_path
= NULL
;
95 int g_vhdboot_enable
= 0;
97 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
99 static char *g_tree_script_buf
= NULL
;
100 static int g_tree_script_pos
= 0;
102 static char *g_list_script_buf
= NULL
;
103 static int g_list_script_pos
= 0;
105 static char *g_part_list_buf
= NULL
;
106 static int g_part_list_pos
= 0;
108 static int g_video_mode_max
= 0;
109 static int g_video_mode_num
= 0;
110 static ventoy_video_mode
*g_video_mode_list
= NULL
;
112 static const char *g_menu_class
[] =
114 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
117 static const char *g_menu_prefix
[] =
119 "iso", "wim", "efi", "img", "vhd", "vtoy"
122 void ventoy_debug(const char *fmt
, ...)
126 va_start (args
, fmt
);
127 grub_vprintf (fmt
, args
);
131 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
141 for (i
= 0; i
< 16; i
++)
143 grub_printf("%02x ", guid
[i
]);
148 int ventoy_is_efi_os(void)
152 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
158 static int ventoy_get_fs_type(const char *fs
)
162 return ventoy_fs_max
;
164 else if (grub_strncmp(fs
, "exfat", 5) == 0)
166 return ventoy_fs_exfat
;
168 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
170 return ventoy_fs_ntfs
;
172 else if (grub_strncmp(fs
, "ext", 3) == 0)
174 return ventoy_fs_ext
;
176 else if (grub_strncmp(fs
, "xfs", 3) == 0)
178 return ventoy_fs_xfs
;
180 else if (grub_strncmp(fs
, "udf", 3) == 0)
182 return ventoy_fs_udf
;
184 else if (grub_strncmp(fs
, "fat", 3) == 0)
186 return ventoy_fs_fat
;
189 return ventoy_fs_max
;
192 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
211 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
213 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
217 static grub_err_t
ventoy_fs_close(grub_file_t file
)
219 grub_file_close(g_old_file
);
220 grub_free(file
->data
);
228 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
234 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
239 for (i
= 0; i
< g_video_mode_num
; i
++)
241 if (g_video_mode_list
[i
].width
== info
->width
&&
242 g_video_mode_list
[i
].height
== info
->height
&&
243 g_video_mode_list
[i
].bpp
== info
->bpp
)
249 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
250 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
251 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
254 if (g_video_mode_num
== g_video_mode_max
)
256 g_video_mode_max
*= 2;
257 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
263 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
265 if (v1
->bpp
== v2
->bpp
)
267 if (v1
->width
== v2
->width
)
269 if (v1
->height
== v2
->height
)
275 return (v1
->height
< v2
->height
) ? -1 : 1;
280 return (v1
->width
< v2
->width
) ? -1 : 1;
285 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
289 static int ventoy_enum_video_mode(void)
292 grub_video_adapter_t adapter
;
293 grub_video_driver_id_t id
;
294 ventoy_video_mode mode
;
296 g_video_mode_num
= 0;
297 g_video_mode_max
= 1024;
298 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
299 if (!g_video_mode_list
)
304 #ifdef GRUB_MACHINE_PCBIOS
305 grub_dl_load ("vbe");
308 id
= grub_video_get_driver_id ();
310 FOR_VIDEO_ADAPTERS (adapter
)
312 if (!adapter
->iterate
||
313 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
314 adapter
->init() != GRUB_ERR_NONE
)))
319 adapter
->iterate(ventoy_video_hook
, NULL
);
321 if (adapter
->id
!= id
)
327 /* sort video mode */
328 for (i
= 0; i
< g_video_mode_num
; i
++)
329 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
331 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
333 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
334 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
335 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
339 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
342 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
346 static struct grub_fs vtoy_fs
=
351 .fs_read
= ventoy_fs_read
,
352 .fs_close
= ventoy_fs_close
,
362 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
368 file
->data
= grub_malloc(rawFile
->size
+ 4096);
374 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
375 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
377 g_old_file
= rawFile
;
379 file
->size
= rawFile
->size
+ len
;
380 file
->device
= rawFile
->device
;
382 file
->not_easily_seekable
= 1;
387 static int ventoy_check_decimal_var(const char *name
, long *value
)
389 const char *value_str
= NULL
;
391 value_str
= grub_env_get(name
);
392 if (NULL
== value_str
)
394 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
397 if (!ventoy_is_decimal(value_str
))
399 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
402 *value
= grub_strtol(value_str
, NULL
, 10);
404 return GRUB_ERR_NONE
;
407 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
411 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
414 if (0 == grub_strcmp(args
[0], "on"))
417 grub_env_set("vtdebug_flag", "debug");
422 grub_env_set("vtdebug_flag", "");
425 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
428 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
432 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
434 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
435 grub_printf(" level:\r\n");
436 grub_printf(" 01/11: busybox / (+cat log)\r\n");
437 grub_printf(" 02/12: initrd / (+cat log)\r\n");
438 grub_printf(" 03/13: hook / (+cat log)\r\n");
440 grub_printf(" debug:\r\n");
441 grub_printf(" 0: debug is on\r\n");
442 grub_printf(" 1: debug is off\r\n");
444 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
447 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
449 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
451 g_ventoy_debug_level
= 1;
454 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
457 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
466 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
469 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
501 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
506 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
508 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
511 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
516 value_long
+= grub_strtol(args
[1], NULL
, 10);
518 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
519 grub_env_set(args
[0], buf
);
521 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
524 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
539 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
542 debug("failed to open file <%s> for udf check\n", args
[0]);
546 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
548 grub_env_set(args
[1], buf
);
550 grub_file_close(file
);
556 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
564 g_wimboot_enable
= 0;
565 grub_check_free(g_wimiso_path
);
566 grub_check_free(g_wimiso_chunk_list
.chunk
);
568 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
574 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
575 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
576 if (NULL
== g_wimiso_chunk_list
.chunk
)
578 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
581 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
582 g_wimiso_chunk_list
.cur_chunk
= 0;
584 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
586 g_wimboot_enable
= 1;
587 g_wimiso_path
= grub_strdup(args
[0]);
589 grub_file_close(file
);
594 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
600 grub_uint32_t offset
;
602 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
605 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
609 len
= (int)file
->size
;
611 data
= (char *)grub_malloc(file
->size
);
617 grub_file_read(file
, data
, file
->size
);
618 grub_file_close(file
);
620 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
621 grub_script_execute_sourcecode(exec
);
623 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
624 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
625 grub_file_close(file
);
627 grub_script_execute_sourcecode("loopback -d efiboot");
631 *direntoff
= offset
+ 2;
636 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
646 ventoy_iso9660_override
*dirent
;
655 totlen
= sizeof(ventoy_chain_head
);
657 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
659 debug("failed to load efiboot template %d\n", len
);
665 debug("efiboot template len:%d offset:%d\n", len
, offset
);
667 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
670 debug("failed to open file <%s>\n", args
[0]);
674 totlen
+= ventoy_align_2k(file
->size
);
676 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
677 dirent
->first_sector
= len
/ 2048;
678 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
679 dirent
->size
= (grub_uint32_t
)file
->size
;
680 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
682 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
684 #ifdef GRUB_MACHINE_EFI
685 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
687 data
= (char *)grub_malloc(totlen
);
690 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
692 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
693 grub_check_free(buf
);
695 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
696 grub_file_close(file
);
698 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
699 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
700 grub_env_set(name
, value
);
702 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
703 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
704 grub_env_set(name
, value
);
709 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
726 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
729 debug("failed to open file <%s>\n", args
[0]);
733 #ifdef GRUB_MACHINE_EFI
734 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
736 buf
= (char *)grub_malloc(file
->size
);
739 grub_file_read(file
, buf
, file
->size
);
741 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
742 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
743 grub_env_set(name
, value
);
745 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
746 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
747 grub_env_set(name
, value
);
749 grub_file_close(file
);
755 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
773 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
776 debug("failed to open file <%s> for udf check\n", args
[0]);
780 headlen
= sizeof(ventoy_chain_head
);
782 #ifdef GRUB_MACHINE_EFI
783 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
785 buf
= (char *)grub_malloc(headlen
+ file
->size
);
788 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
790 grub_file_read(file
, buf
+ headlen
, file
->size
);
792 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
793 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
794 grub_env_set(name
, value
);
796 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
797 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
798 grub_env_set(name
, value
);
800 grub_file_close(file
);
806 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
815 if (args
[0][0] == '1')
817 grub_iso9660_set_nojoliet(1);
821 grub_iso9660_set_nojoliet(0);
827 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
832 grub_uint8_t buf
[32];
843 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
846 debug("failed to open file <%s> for udf check\n", args
[0]);
850 for (i
= 16; i
< 32; i
++)
852 grub_file_seek(file
, i
* 2048);
853 grub_file_read(file
, buf
, sizeof(buf
));
861 grub_file_seek(file
, i
* 2048);
862 grub_file_read(file
, buf
, sizeof(buf
));
864 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
867 grub_file_seek(file
, i
* 2048);
868 grub_file_read(file
, buf
, sizeof(buf
));
870 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
871 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
877 grub_file_close(file
);
879 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
884 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
886 long value_long1
= 0;
887 long value_long2
= 0;
889 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
891 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
894 value_long1
= grub_strtol(args
[0], NULL
, 10);
895 value_long2
= grub_strtol(args
[2], NULL
, 10);
897 if (0 == grub_strcmp(args
[1], "eq"))
899 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
901 else if (0 == grub_strcmp(args
[1], "ne"))
903 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
905 else if (0 == grub_strcmp(args
[1], "gt"))
907 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
909 else if (0 == grub_strcmp(args
[1], "lt"))
911 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
913 else if (0 == grub_strcmp(args
[1], "ge"))
915 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
917 else if (0 == grub_strcmp(args
[1], "le"))
919 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
923 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
929 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
936 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
939 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
940 pos
= grub_strstr(buf
, ",");
946 grub_env_set(args
[1], buf
);
948 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
951 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
957 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
963 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
966 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
968 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
969 if (0 == grub_script_execute_sourcecode(buf
))
971 debug("file %s exist, ventoy_compatible YES\n", buf
);
972 grub_env_set("ventoy_compatible", "YES");
973 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
977 debug("file %s NOT exist\n", buf
);
981 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
982 pos
= grub_strstr(buf
, ")");
988 disk
= grub_disk_open(buf
);
991 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
992 grub_disk_close(disk
);
994 g_img_swap_tmp_buf
[703] = 0;
995 for (i
= 318; i
< 703; i
++)
997 if (g_img_swap_tmp_buf
[i
] == 'V' &&
998 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1000 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1001 grub_env_set("ventoy_compatible", "YES");
1002 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1008 debug("failed to open disk <%s>\n", buf
);
1011 grub_env_set("ventoy_compatible", "NO");
1012 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1015 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1021 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1026 if (0 == g_sort_case_sensitive
)
1028 if (grub_islower(c1
))
1030 c1
= c1
- 'a' + 'A';
1033 if (grub_islower(c2
))
1035 c2
= c2
- 'a' + 'A';
1048 static int ventoy_cmp_subdir(char *name1
, char *name2
)
1054 for (s1
= name1
, s2
= name2
; *s1
&& *s2
; s1
++, s2
++)
1059 if (0 == g_sort_case_sensitive
)
1061 if (grub_islower(c1
))
1063 c1
= c1
- 'a' + 'A';
1066 if (grub_islower(c2
))
1068 c2
= c2
- 'a' + 'A';
1081 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1083 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1085 grub_memcpy(img1
, img2
, sizeof(img_info
));
1086 img1
->next
= g_img_swap_tmp
.next
;
1087 img1
->prev
= g_img_swap_tmp
.prev
;
1089 g_img_swap_tmp
.next
= img2
->next
;
1090 g_img_swap_tmp
.prev
= img2
->prev
;
1091 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1094 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1098 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1103 for (i
= 0; i
< namelen
; i
++)
1105 if (filename
[i
] == ' ' || filename
[i
] == '\t')
1110 if ((grub_uint8_t
)(filename
[i
]) >= 127)
1119 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1123 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1133 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1141 img_iterator_node
*tmp
;
1142 img_iterator_node
*new_node
;
1143 img_iterator_node
*node
= (img_iterator_node
*)data
;
1145 len
= grub_strlen(filename
);
1149 if ((len
== 1 && filename
[0] == '.') ||
1150 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1155 if (!ventoy_img_name_valid(filename
, len
))
1160 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1165 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1168 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1170 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1173 debug("Directory %s ignored...\n", new_node
->dir
);
1174 grub_free(new_node
);
1178 new_node
->tail
= node
->tail
;
1180 new_node
->parent
= node
;
1181 if (!node
->firstchild
)
1183 node
->firstchild
= new_node
;
1186 if (g_img_iterator_tail
)
1188 g_img_iterator_tail
->next
= new_node
;
1189 g_img_iterator_tail
= new_node
;
1193 g_img_iterator_head
.next
= new_node
;
1194 g_img_iterator_tail
= new_node
;
1200 debug("Find a file %s\n", filename
);
1206 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1208 type
= img_type_iso
;
1210 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1212 type
= img_type_wim
;
1214 else if (g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1215 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1217 type
= img_type_vhd
;
1219 #ifdef GRUB_MACHINE_EFI
1220 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1222 type
= img_type_efi
;
1225 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1227 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1229 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1230 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1235 type
= img_type_img
;
1237 else if (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1239 type
= img_type_vtoy
;
1246 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1251 img
= grub_zalloc(sizeof(img_info
));
1255 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1257 for (i
= 0; i
< (int)len
; i
++)
1259 if (filename
[i
] == ' ' || filename
[i
] == '\t' || (0 == grub_isprint(filename
[i
])))
1266 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1268 img
->size
= info
->size
;
1271 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1274 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1276 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1281 if (g_ventoy_img_list
)
1283 tail
= *(node
->tail
);
1289 g_ventoy_img_list
= img
;
1292 img
->id
= g_ventoy_img_count
;
1294 if (node
&& NULL
== node
->firstiso
)
1296 node
->firstiso
= img
;
1307 *((img_info
**)(node
->tail
)) = img
;
1308 g_ventoy_img_count
++;
1310 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1311 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1314 img
->class = g_menu_class
[type
];
1316 img
->menu_prefix
= g_menu_prefix
[type
];
1318 if (img_type_iso
== type
)
1320 if (ventoy_plugin_check_memdisk(img
->path
))
1322 img
->menu_prefix
= "miso";
1326 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1333 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1335 int len
= GRUB_UINT_MAX
;
1336 const char *value
= NULL
;
1337 char name
[32] = {0};
1338 char plat
[32] = {0};
1339 char guidstr
[32] = {0};
1340 ventoy_guid guid
= VENTOY_GUID
;
1341 const char *fmt1
= NULL
;
1342 const char *fmt2
= NULL
;
1343 const char *fmt3
= NULL
;
1344 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1345 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1346 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1347 const char fmtcode
[]={
1348 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1349 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1350 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1351 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1352 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1353 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1356 grub_memset(name
, 0, sizeof(name
));
1357 puint
[0] = grub_swap_bytes32(0x56454e54);
1358 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1359 puint
[2] = grub_swap_bytes32(0x45525349);
1360 puint
[1] = grub_swap_bytes32(0x4f595f56);
1361 value
= ventoy_get_env(name
);
1363 grub_memset(name
, 0, sizeof(name
));
1364 puint
[1] = grub_swap_bytes32(0x5f544f50);
1365 puint
[0] = grub_swap_bytes32(0x56544c45);
1366 fmt1
= ventoy_get_env(name
);
1372 grub_memset(name
, 0, sizeof(name
));
1373 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1374 puint
[0] = grub_swap_bytes32(0x56544c45);
1375 fmt2
= ventoy_get_env(name
);
1377 grub_memset(name
, 0, sizeof(name
));
1378 puint
[1] = grub_swap_bytes32(0x5f434c52);
1379 puint
[0] = grub_swap_bytes32(0x56544c45);
1380 fmt3
= ventoy_get_env(name
);
1382 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1384 #if defined (GRUB_MACHINE_EFI)
1385 puint2
[0] = grub_swap_bytes32(0x55454649);
1387 puint2
[0] = grub_swap_bytes32(0x42494f53);
1390 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1391 #pragma GCC diagnostic push
1392 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1393 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1394 fmt1
? fmt1
: fmtdata
,
1395 fmt2
? fmt2
: fmtdata
+ 4,
1396 value
? value
: "", plat
, guidstr
,
1397 fmt3
? fmt3
: fmtdata
+ 6);
1398 #pragma GCC diagnostic pop
1400 grub_memset(name
, 0, sizeof(name
));
1401 puint
[0] = grub_swap_bytes32(0x76746f79);
1402 puint
[2] = grub_swap_bytes32(0x656e7365);
1403 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1404 ventoy_set_env(name
, guidstr
);
1409 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1411 img_info
*minimg
= NULL
;
1412 img_info
*img
= (img_info
*)(node
->firstiso
);
1414 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1416 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1431 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1433 img_iterator_node
*Minchild
= NULL
;
1434 img_iterator_node
*child
= node
->firstchild
;
1436 while (child
&& child
->parent
== node
)
1438 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
->dir
, Minchild
->dir
) < 0))
1442 child
= child
->next
;
1447 Minchild
->select
= 1;
1453 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1456 img_info
*img
= NULL
;
1457 const char *dir_class
= NULL
;
1458 const char *dir_alias
= NULL
;
1459 img_iterator_node
*child
= NULL
;
1461 if (node
->isocnt
== 0 || node
->done
== 1)
1466 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1468 offset
= node
->parent
->dirlen
;
1471 if (node
== &g_img_iterator_head
)
1473 if (g_default_menu_mode
== 0)
1475 if (g_tree_view_menu_style
== 0)
1477 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1478 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1479 " echo 'return ...' \n"
1484 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1485 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1493 node
->dir
[node
->dirlen
- 1] = 0;
1494 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1497 dir_class
= "vtoydir";
1500 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1503 if (g_tree_view_menu_style
== 0)
1505 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1506 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1507 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1511 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1512 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1513 dir_alias
, dir_class
, node
->dir
+ offset
);
1518 dir_alias
= node
->dir
+ offset
;
1520 if (g_tree_view_menu_style
== 0)
1522 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1523 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1524 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1528 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1529 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1530 dir_alias
, dir_class
, node
->dir
+ offset
);
1534 if (g_tree_view_menu_style
== 0)
1536 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1537 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1538 " echo 'return ...' \n"
1543 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1544 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1550 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1552 ventoy_dynamic_tree_menu(child
);
1555 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1557 if (g_tree_view_menu_style
== 0)
1559 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1560 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1563 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1564 img
->unsupport
? "[***********] " : "",
1565 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1567 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1571 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1572 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1575 img
->unsupport
? "[***********] " : "",
1576 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1578 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1582 if (node
!= &g_img_iterator_head
)
1584 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1591 int ventoy_check_device_result(int ret
)
1595 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1596 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1597 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1601 grub_printf(VTOY_WARNING
"\n");
1602 grub_printf(VTOY_WARNING
"\n");
1603 grub_printf(VTOY_WARNING
"\n\n\n");
1605 grub_printf("Unsatisfied conditions detected for Ventoy.\n\n");
1606 grub_printf("This is NOT a standard Ventoy device and is NOT officially supported.\n\n");
1607 grub_printf("Recommend to follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1609 grub_printf("\n\nWill exit after 10 seconds ...... ");
1617 int ventoy_check_device(grub_device_t dev
)
1620 grub_uint64_t offset
;
1625 struct grub_partition
*partition
;
1627 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1629 return ventoy_check_device_result(1 | 0x1000);
1632 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1633 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1634 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_64", dev
->disk
->name
))
1636 return ventoy_check_device_result(2 | 0x1000);
1639 /* We must have partition 2 */
1640 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1643 return ventoy_check_device_result(3 | 0x1000);
1646 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1648 grub_file_close(file
);
1649 return ventoy_check_device_result(4 | 0x1000);
1652 partition
= dev
->disk
->partition
;
1653 if (partition
->number
!= 0 || partition
->start
!= 2048)
1655 return ventoy_check_device_result(5);
1658 offset
= partition
->start
+ partition
->len
;
1659 partition
= file
->device
->disk
->partition
;
1660 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1662 grub_file_close(file
);
1663 return ventoy_check_device_result(6);
1665 grub_file_close(file
);
1667 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1668 dev2
= grub_device_open(devname
);
1671 return ventoy_check_device_result(7);
1674 fs
= grub_fs_probe(dev2
);
1677 grub_device_close(dev2
);
1678 return ventoy_check_device_result(8);
1681 fs
->fs_label(dev2
, &label
);
1682 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1684 grub_device_close(dev2
);
1685 return ventoy_check_device_result(9);
1688 grub_device_close(dev2
);
1689 return ventoy_check_device_result(0);
1692 static int ventoy_set_default_menu(void)
1698 img_info
*cur
= NULL
;
1699 img_info
*default_node
= NULL
;
1700 const char *default_image
= NULL
;
1702 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1703 if (default_image
&& default_image
[0] == '/')
1705 img_len
= grub_strlen(default_image
);
1707 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1709 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1721 if (0 == g_default_menu_mode
)
1723 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1727 def
= grub_strdup(default_image
);
1733 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1736 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1739 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1743 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1751 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1755 grub_device_t dev
= NULL
;
1756 img_info
*cur
= NULL
;
1757 img_info
*tail
= NULL
;
1758 const char *strdata
= NULL
;
1759 char *device_name
= NULL
;
1761 img_iterator_node
*node
= NULL
;
1762 img_iterator_node
*tmp
= NULL
;
1768 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1771 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1773 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1776 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1777 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1779 g_filt_dot_underscore_file
= 1;
1782 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
1783 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1785 g_sort_case_sensitive
= 1;
1788 device_name
= grub_file_get_device_name(args
[0]);
1794 g_enum_dev
= dev
= grub_device_open(device_name
);
1800 g_enum_fs
= fs
= grub_fs_probe(dev
);
1806 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1808 debug("unsupported fs:<%s>\n", fs
->name
);
1809 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1813 ventoy_set_env("vtoy_iso_fs", fs
->name
);
1815 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1816 if (strdata
&& strdata
[0] == '1')
1818 g_default_menu_mode
= 1;
1821 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1823 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1825 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1826 if (strdata
&& strdata
[0] == '/')
1828 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1829 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1831 g_img_iterator_head
.dir
[len
++] = '/';
1833 g_img_iterator_head
.dirlen
= len
;
1837 g_img_iterator_head
.dirlen
= 1;
1838 grub_strcpy(g_img_iterator_head
.dir
, "/");
1841 g_img_iterator_head
.tail
= &tail
;
1843 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1845 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1848 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
1849 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1851 g_tree_view_menu_style
= 1;
1854 ventoy_set_default_menu();
1856 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1858 ventoy_dynamic_tree_menu(node
);
1862 node
= g_img_iterator_head
.next
;
1870 /* sort image list by image name */
1871 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1873 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1875 if (ventoy_cmp_img(cur
, tail
) > 0)
1877 ventoy_swap_img(cur
, tail
);
1882 if (g_default_menu_mode
== 1)
1884 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1885 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1886 " echo 'return ...' \n"
1890 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1892 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1893 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1896 cur
->unsupport
? "[***********] " : "",
1897 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1899 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1902 g_tree_script_buf
[g_tree_script_pos
] = 0;
1903 g_list_script_buf
[g_list_script_pos
] = 0;
1905 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1906 grub_env_set(args
[1], buf
);
1910 check_free(device_name
, grub_free
);
1911 check_free(dev
, grub_device_close
);
1913 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1917 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1919 img_info
*next
= NULL
;
1920 img_info
*cur
= g_ventoy_img_list
;
1933 g_ventoy_img_list
= NULL
;
1934 g_ventoy_img_count
= 0;
1936 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1939 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1942 img_info
*cur
= g_ventoy_img_list
;
1946 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1948 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1951 img_id
= grub_strtol(args
[0], NULL
, 10);
1952 if (img_id
>= g_ventoy_img_count
)
1954 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
1957 debug("Find image %ld name \n", img_id
);
1959 while (cur
&& img_id
> 0)
1967 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
1970 debug("image name is %s\n", cur
->name
);
1972 grub_env_set(args
[1], cur
->name
);
1974 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1977 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1982 const char *id
= NULL
;
1983 img_info
*cur
= g_ventoy_img_list
;
1987 if (argc
< 1 || argc
> 2)
1989 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
1992 id
= grub_env_get("chosen");
1994 pos
= grub_strstr(id
, "VID_");
1997 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2001 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2006 if (img_id
== cur
->id
)
2015 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2018 grub_env_set(args
[0], cur
->path
);
2022 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2023 grub_env_set(args
[1], value
);
2026 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2029 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2036 device_name
= grub_file_get_device_name(filename
);
2048 pos2
= grub_strstr(pos
, ",");
2051 pos2
= grub_strstr(pos
, ")");
2059 disk
= grub_disk_open(pos
);
2062 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2063 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2064 grub_disk_close(disk
);
2071 grub_free(device_name
);
2075 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2077 eltorito_descriptor desc
;
2079 grub_memset(&desc
, 0, sizeof(desc
));
2080 grub_file_seek(file
, 17 * 2048);
2081 grub_file_read(file
, &desc
, sizeof(desc
));
2083 if (desc
.type
!= 0 || desc
.version
!= 1)
2088 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2089 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2097 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2101 grub_uint8_t buf
[512];
2103 grub_file_seek(file
, sector
* 2048);
2104 grub_file_read(file
, buf
, sizeof(buf
));
2106 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2108 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2112 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2117 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2119 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2121 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2125 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2127 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2132 debug("%s does not contain efi eltorito\n", file
->name
);
2136 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2139 const char *fs
= NULL
;
2140 const char *cdprompt
= NULL
;
2142 grub_uint8_t chksum
= 0;
2145 disk
= file
->device
->disk
;
2146 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2148 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2149 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2150 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2152 pos
= grub_strstr(file
->name
, "/");
2158 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2160 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2162 param
->vtoy_img_size
= file
->size
;
2164 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2165 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2167 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2169 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2170 param
->vtoy_reserved
[4] = 0;
2171 if (g_ventoy_chain_type
== 1) /* Windows */
2173 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2174 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2176 param
->vtoy_reserved
[4] = 1;
2180 fs
= ventoy_get_env("ventoy_fs_probe");
2181 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2183 param
->vtoy_reserved
[3] = 1;
2186 /* calculate checksum */
2187 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2189 chksum
+= *((grub_uint8_t
*)param
+ i
);
2191 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2196 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2198 grub_uint32_t i
= 0;
2199 grub_uint64_t total
= 0;
2200 ventoy_img_chunk
*chunk
= NULL
;
2202 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2204 chunk
= chunklist
->chunk
+ i
;
2206 if (chunk
->disk_start_sector
<= start
)
2208 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2212 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2215 if (total
!= ((file
->size
+ 511) / 512))
2217 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2224 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2228 grub_uint32_t i
= 0;
2229 grub_uint32_t sector
= 0;
2230 grub_uint32_t count
= 0;
2231 grub_off_t size
= 0;
2232 grub_off_t read
= 0;
2234 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2235 if (fs_type
== ventoy_fs_exfat
)
2237 grub_fat_get_file_chunk(start
, file
, chunklist
);
2239 else if (fs_type
== ventoy_fs_ext
)
2241 grub_ext_get_file_chunk(start
, file
, chunklist
);
2245 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2246 file
->read_hook_data
= chunklist
;
2248 for (size
= file
->size
; size
> 0; size
-= read
)
2250 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2251 grub_file_read(file
, NULL
, read
);
2254 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2256 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2257 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2260 if (ventoy_fs_udf
== fs_type
)
2262 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2264 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2265 chunklist
->chunk
[i
].img_start_sector
= sector
;
2266 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2272 len
= (int)grub_strlen(file
->name
);
2273 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2274 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2275 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2276 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2278 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2280 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2290 chunklist
->chunk
[i
].img_start_sector
= sector
;
2291 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2299 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2303 grub_disk_addr_t start
;
2308 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2311 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2314 if (g_img_chunk_list
.chunk
)
2316 grub_free(g_img_chunk_list
.chunk
);
2319 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2321 grub_file_close(file
);
2322 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2325 /* get image chunk data */
2326 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2327 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2328 if (NULL
== g_img_chunk_list
.chunk
)
2330 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2333 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2334 g_img_chunk_list
.cur_chunk
= 0;
2336 start
= file
->device
->disk
->partition
->start
;
2338 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2340 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2341 grub_file_close(file
);
2345 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2348 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2349 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2352 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2357 char configfile
[128];
2358 install_template
*node
= NULL
;
2364 debug("select auto installation argc:%d\n", argc
);
2371 node
= ventoy_plugin_find_install_template(args
[0]);
2374 debug("Auto install template not found for %s\n", args
[0]);
2378 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2380 node
->cursel
= node
->autosel
- 1;
2381 debug("Auto install template auto select %d\n", node
->autosel
);
2385 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2391 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2392 " echo %s\n}\n", "123");
2394 for (i
= 0; i
< node
->templatenum
; i
++)
2396 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2398 node
->templatepath
[i
].path
);
2401 g_ventoy_menu_esc
= 1;
2402 g_ventoy_suppress_esc
= 1;
2404 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2405 grub_script_execute_sourcecode(configfile
);
2407 g_ventoy_menu_esc
= 0;
2408 g_ventoy_suppress_esc
= 0;
2412 node
->cursel
= g_ventoy_last_entry
- 1;
2414 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2417 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2422 char configfile
[128];
2423 persistence_config
*node
;
2429 debug("select persistence argc:%d\n", argc
);
2436 node
= ventoy_plugin_find_persistent(args
[0]);
2439 debug("Persistence image not found for %s\n", args
[0]);
2443 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2445 node
->cursel
= node
->autosel
- 1;
2446 debug("Persistence image auto select %d\n", node
->autosel
);
2450 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2456 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2457 " echo %s\n}\n", "123");
2459 for (i
= 0; i
< node
->backendnum
; i
++)
2461 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2463 node
->backendpath
[i
].path
);
2467 g_ventoy_menu_esc
= 1;
2468 g_ventoy_suppress_esc
= 1;
2470 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2471 grub_script_execute_sourcecode(configfile
);
2473 g_ventoy_menu_esc
= 0;
2474 g_ventoy_suppress_esc
= 0;
2478 node
->cursel
= g_ventoy_last_entry
- 1;
2480 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2483 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2486 ventoy_img_chunk
*cur
;
2492 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2494 cur
= g_img_chunk_list
.chunk
+ i
;
2495 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2496 cur
->img_start_sector
, cur
->img_end_sector
,
2497 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2501 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2504 #ifdef GRUB_MACHINE_EFI
2505 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2513 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2516 ulong chain_len
= 0;
2517 char *chain_data
= NULL
;
2518 char *relocator_addr
= NULL
;
2519 grub_relocator_chunk_t ch
;
2520 struct grub_relocator
*relocator
= NULL
;
2521 char envbuf
[64] = { 0 };
2532 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2533 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2535 relocator
= grub_relocator_new ();
2538 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2542 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2543 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2547 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2548 grub_relocator_unload (relocator
);
2552 relocator_addr
= get_virtual_current_address(ch
);
2554 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2556 grub_relocator_unload (relocator
);
2558 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2559 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2561 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2565 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2569 ventoy_img_chunk_list chunklist
;
2574 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2577 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2580 /* get image chunk data */
2581 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2582 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2583 if (NULL
== chunklist
.chunk
)
2585 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2588 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2589 chunklist
.cur_chunk
= 0;
2591 ventoy_get_block_list(file
, &chunklist
, 0);
2593 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2595 grub_printf("########## UNSUPPORTED ###############\n");
2598 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2600 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2602 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2603 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2606 grub_printf("\n==================================\n");
2608 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2610 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2611 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2612 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2613 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2614 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2618 grub_free(chunklist
.chunk
);
2619 grub_file_close(file
);
2621 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2624 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2627 ventoy_grub_param_file_replace
*replace
= NULL
;
2635 replace
= &(g_grub_param
->file_replace
);
2636 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2638 replace
->old_name_cnt
= 0;
2639 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2641 replace
->old_name_cnt
++;
2642 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2645 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2648 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2651 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2659 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2660 grub_printf("%s", g_list_script_buf
);
2664 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2665 grub_printf("%s", g_tree_script_buf
);
2671 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2673 img_info
*cur
= g_ventoy_img_list
;
2681 grub_printf("path:<%s> id=%d\n", cur
->path
, cur
->id
);
2682 grub_printf("name:<%s>\n\n", cur
->name
);
2689 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2695 ventoy_plugin_dump_injection();
2700 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2706 ventoy_plugin_dump_auto_install();
2711 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2717 ventoy_plugin_dump_persistence();
2722 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2733 if (args
[0][0] == '0')
2735 return g_ventoy_memdisk_mode
? 0 : 1;
2737 else if (args
[0][0] == '1')
2739 return g_ventoy_iso_raw
? 0 : 1;
2741 else if (args
[0][0] == '2')
2743 return g_ventoy_iso_uefi_drv
? 0 : 1;
2749 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2751 static int configfile_mode
= 0;
2752 char memfile
[128] = {0};
2759 * args[0]: 0:normal 1:configfile
2760 * args[1]: 0:list_buf 1:tree_buf
2765 debug("Invalid argc %d\n", argc
);
2769 if (args
[0][0] == '0')
2771 if (args
[1][0] == '0')
2773 grub_script_execute_sourcecode(g_list_script_buf
);
2777 grub_script_execute_sourcecode(g_tree_script_buf
);
2782 if (configfile_mode
)
2784 debug("Now already in F3 mode %d\n", configfile_mode
);
2788 if (args
[1][0] == '0')
2790 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2791 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2795 g_ventoy_last_entry
= -1;
2796 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2797 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2800 configfile_mode
= 1;
2801 grub_script_execute_sourcecode(memfile
);
2802 configfile_mode
= 0;
2808 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2819 g_ventoy_case_insensitive
= 1;
2820 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2821 g_ventoy_case_insensitive
= 0;
2827 grub_file_close(file
);
2833 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2838 const char *isopath
= NULL
;
2840 ventoy_mbr_head mbr
;
2847 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2850 isopath
= grub_env_get("vtoy_iso_part");
2853 debug("isopath is null %p\n", isopath
);
2857 debug("isopath is %s\n", isopath
);
2859 for (id
= 0; id
< 30 && (find
== 0); id
++)
2861 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2862 if (grub_strstr(isopath
, hdname
))
2864 debug("skip %s ...\n", hdname
);
2868 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2870 disk
= grub_disk_open(hdname
);
2873 debug("%s not exist\n", hdname
);
2877 grub_memset(&mbr
, 0, sizeof(mbr
));
2878 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2880 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2882 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2883 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2886 grub_env_set(args
[0], hdname
);
2890 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2894 debug("read %s failed\n", hdname
);
2897 grub_disk_close(disk
);
2903 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2914 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2917 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2920 debug("failed to open file %s\n", args
[0]);
2924 buf
= grub_malloc(len
);
2931 grub_file_read(file
, buf
, len
- 1);
2933 ventoy_get_line(buf
);
2934 ventoy_set_env(args
[1], buf
);
2938 grub_check_free(buf
);
2939 grub_file_close(file
);
2944 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
2949 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
2950 "0 %llu linear /dev/ventoy %llu\n",
2951 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
2956 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2958 char *device_name
= NULL
;
2959 grub_device_t dev
= NULL
;
2964 g_part_list_pos
= 0;
2965 grub_env_unset("vtoy_img_part_file");
2972 device_name
= grub_file_get_device_name(args
[0]);
2975 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
2979 dev
= grub_device_open(device_name
);
2982 debug("grub_device_open failed, %s\n", device_name
);
2986 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
2988 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
2989 grub_env_set("vtoy_img_part_file", buf
);
2993 check_free(device_name
, grub_free
);
2994 check_free(dev
, grub_device_close
);
3000 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3011 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3014 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3017 debug("failed to open file %s\n", args
[0]);
3021 buf
= grub_malloc(file
->size
+ 1);
3027 buf
[file
->size
] = 0;
3028 grub_file_read(file
, buf
, file
->size
);
3030 if (grub_strstr(buf
, args
[1]))
3037 grub_check_free(buf
);
3038 grub_file_close(file
);
3043 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3048 ventoy_iso9660_vd pvd
;
3055 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
3058 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3061 debug("failed to open file %s\n", args
[0]);
3065 grub_file_seek(file
, 16 * 2048);
3066 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3067 if (len
!= sizeof(pvd
))
3069 debug("failed to read pvd %d\n", len
);
3073 grub_memset(buf
, 0, sizeof(buf
));
3074 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3075 ventoy_set_env(args
[1], buf
);
3077 grub_memset(buf
, 0, sizeof(buf
));
3078 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3079 ventoy_set_env(args
[2], buf
);
3082 grub_file_close(file
);
3087 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3098 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3101 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3104 debug("failed to open file %s\n", args
[0]);
3108 grub_memset(buf
, 0, sizeof(buf
));
3109 grub_file_seek(file
, 16 * 2048 + 813);
3110 len
= (int)grub_file_read(file
, buf
, 17);
3113 debug("failed to read create date %d\n", len
);
3117 ventoy_set_env(args
[1], buf
);
3120 grub_file_close(file
);
3125 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3131 ventoy_env_hook_root(1);
3136 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3142 ventoy_env_hook_root(0);
3147 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3154 int image_sector_size
;
3156 ventoy_chain_head
*chain
;
3157 ventoy_img_chunk
*chunk
;
3158 ventoy_os_param
*osparam
;
3159 ventoy_image_location
*location
;
3160 ventoy_image_disk_region
*region
;
3161 struct grub_acpi_table_header
*acpi
;
3170 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3172 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3178 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3180 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3182 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3186 img_chunk_num
= chain
->img_chunk_num
;
3188 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3189 datalen
= sizeof(ventoy_os_param
) + loclen
;
3191 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3192 acpi
= grub_zalloc(buflen
);
3198 /* Step1: Fill acpi table header */
3199 grub_memcpy(acpi
->signature
, "VTOY", 4);
3200 acpi
->length
= buflen
;
3202 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3203 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3205 acpi
->creator_id
[0] = 1;
3206 acpi
->creator_rev
= 1;
3208 /* Step2: Fill data */
3209 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3210 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3211 osparam
->vtoy_img_location_addr
= 0;
3212 osparam
->vtoy_img_location_len
= loclen
;
3213 osparam
->chksum
= 0;
3214 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3216 location
= (ventoy_image_location
*)(osparam
+ 1);
3217 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3218 location
->image_sector_size
= image_sector_size
;
3219 location
->disk_sector_size
= chain
->disk_sector_size
;
3220 location
->region_count
= img_chunk_num
;
3222 region
= location
->regions
;
3223 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3224 if (512 == image_sector_size
)
3226 for (i
= 0; i
< img_chunk_num
; i
++)
3228 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3229 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3230 region
->disk_start_sector
= chunk
->disk_start_sector
;
3237 for (i
= 0; i
< img_chunk_num
; i
++)
3239 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3240 region
->image_start_sector
= chunk
->img_start_sector
;
3241 region
->disk_start_sector
= chunk
->disk_start_sector
;
3247 /* Step3: Fill acpi checksum */
3249 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3251 /* load acpi table */
3252 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3253 grub_script_execute_sourcecode(cmd
);
3257 VENTOY_CMD_RETURN(0);
3260 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3266 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3267 g_ventoy_last_entry
= -1;
3272 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3278 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3283 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3285 const char *pos
= filename
+ 1;
3293 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3295 grub_strncpy((char *)data
, filename
, 128);
3306 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3309 char *device_name
= NULL
;
3310 grub_device_t dev
= NULL
;
3311 grub_fs_t fs
= NULL
;
3312 char buf
[128] = {0};
3318 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3322 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3324 device_name
= grub_file_get_device_name(args
[0]);
3327 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3331 dev
= grub_device_open(device_name
);
3334 debug("grub_device_open failed, %s\n", device_name
);
3338 fs
= grub_fs_probe(dev
);
3341 debug("grub_fs_probe failed, %s\n", device_name
);
3345 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3349 ventoy_set_env(args
[2], buf
);
3356 check_free(device_name
, grub_free
);
3357 check_free(dev
, grub_device_close
);
3362 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3372 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3373 if (!g_ventoy_part_info
)
3378 disk
= grub_disk_open(args
[0]);
3381 debug("Failed to open disk %s\n", args
[0]);
3385 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3386 grub_disk_close(disk
);
3388 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3389 dev
= grub_device_open(name
);
3392 /* make sure that we are running in a correct Ventoy device */
3393 ret
= ventoy_check_device(dev
);
3394 grub_device_close(dev
);
3405 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3408 grub_uint8_t zeroguid
[16] = {0};
3413 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3416 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3418 if (id
>= 1 && id
<= 128)
3420 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3428 if (id
>= 1 && id
<= 4)
3430 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3440 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3443 char *device_name
= NULL
;
3444 grub_device_t dev
= NULL
;
3445 grub_fs_t fs
= NULL
;
3452 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3456 device_name
= grub_file_get_device_name(args
[0]);
3459 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3463 dev
= grub_device_open(device_name
);
3466 debug("grub_device_open failed, %s\n", device_name
);
3470 fs
= grub_fs_probe(dev
);
3473 debug("grub_fs_probe failed, %s\n", device_name
);
3477 fs
->fs_label(dev
, &label
);
3480 ventoy_set_env(args
[1], label
);
3488 check_free(device_name
, grub_free
);
3489 check_free(dev
, grub_device_close
);
3494 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3498 grub_snprintf((char *)data
, 256, "%s", filename
);
3506 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3509 char *device_name
= NULL
;
3510 grub_device_t dev
= NULL
;
3511 grub_fs_t fs
= NULL
;
3512 char name
[256] ={0};
3518 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3522 device_name
= grub_file_get_device_name(args
[0]);
3525 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3529 dev
= grub_device_open(device_name
);
3532 debug("grub_device_open failed, %s\n", device_name
);
3536 fs
= grub_fs_probe(dev
);
3539 debug("grub_fs_probe failed, %s\n", device_name
);
3543 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3546 ventoy_set_env(args
[2], name
);
3553 check_free(device_name
, grub_free
);
3554 check_free(dev
, grub_device_close
);
3559 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3569 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3573 for (pos
= args
[0]; *pos
; pos
++)
3587 grub_env_set(args
[1], args
[0]);
3597 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3599 struct grub_video_mode_info info
;
3606 if (!g_video_mode_list
)
3608 ventoy_enum_video_mode();
3611 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3613 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3617 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3620 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3622 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3623 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3625 VENTOY_CMD_RETURN(0);
3628 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3630 struct grub_video_mode_info info
;
3637 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3639 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3643 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3646 grub_env_set(args
[0], buf
);
3648 VENTOY_CMD_RETURN(0);
3651 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3659 if (!g_video_mode_list
)
3664 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3665 if (id
< g_video_mode_num
)
3667 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
3668 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
3671 grub_env_set(args
[1], buf
);
3673 VENTOY_CMD_RETURN(0);
3676 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
3678 grub_uint64_t size
= 0;
3681 char fullpath
[256] = {0};
3684 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3687 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
3690 debug("grub_file_open failed <%s>\n", fullpath
);
3696 grub_file_close(file
);
3700 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
3704 char fullpath
[256] = {0};
3707 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3710 file
= grub_file_open(fullpath
, type
);
3713 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
3720 int ventoy_is_file_exist(const char *fmt
, ...)
3725 char buf
[256] = {0};
3727 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
3731 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3734 grub_strncpy(pos
+ len
, " ]", 2);
3736 debug("script exec %s\n", buf
);
3738 if (0 == grub_script_execute_sourcecode(buf
))
3746 int ventoy_is_dir_exist(const char *fmt
, ...)
3751 char buf
[256] = {0};
3753 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
3757 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3760 grub_strncpy(pos
+ len
, " ]", 2);
3762 debug("script exec %s\n", buf
);
3764 if (0 == grub_script_execute_sourcecode(buf
))
3772 static int ventoy_env_init(void)
3776 grub_env_set("vtdebug_flag", "");
3778 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
3779 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3780 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3782 ventoy_filt_register(0, ventoy_wrapper_open
);
3784 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
3787 g_grub_param
->grub_env_get
= grub_env_get
;
3788 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
3789 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
3790 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
3791 grub_env_set("env_param", buf
);
3792 grub_env_set("ventoy_env_param", buf
);
3793 grub_env_export("ventoy_env_param");
3799 static cmd_para ventoy_cmds
[] =
3801 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
3802 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
3803 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
3804 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3805 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3806 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
3807 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
3808 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
3809 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
3810 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
3811 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
3812 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
3813 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
3814 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
3815 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
3816 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
3817 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
3818 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
3819 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
3820 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
3822 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
3823 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
3824 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
3825 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
3826 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
3827 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
3829 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
3830 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
3831 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
3832 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
3833 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
3834 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
3835 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
3836 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
3839 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
3840 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
3841 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
3842 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
3843 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
3844 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
3845 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
3846 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
3847 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
3848 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
3850 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
3851 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
3852 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
3853 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
3854 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
3855 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
3857 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3858 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3859 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
3860 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
3861 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
3862 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
3863 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
3864 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
3865 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
3866 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
3868 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
3869 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
3870 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
3871 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
3872 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
3873 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
3874 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
3876 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
3877 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
3878 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
3879 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
3882 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
3883 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
3885 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
3886 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
3887 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
3890 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
3891 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
3892 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
3893 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
3894 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
3895 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
3896 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
3897 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
3899 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
3900 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
3901 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
3907 GRUB_MOD_INIT(ventoy
)
3910 cmd_para
*cur
= NULL
;
3914 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3916 cur
= ventoy_cmds
+ i
;
3917 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
3918 cur
->summary
, cur
->description
, cur
->parser
);
3922 GRUB_MOD_FINI(ventoy
)
3926 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3928 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);