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 int g_plugin_image_list
= 0;
87 ventoy_grub_param
*g_grub_param
= NULL
;
89 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
91 ventoy_img_chunk_list g_img_chunk_list
;
93 int g_wimboot_enable
= 0;
94 ventoy_img_chunk_list g_wimiso_chunk_list
;
95 char *g_wimiso_path
= NULL
;
97 int g_vhdboot_enable
= 0;
99 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
101 static char *g_tree_script_buf
= NULL
;
102 static int g_tree_script_pos
= 0;
104 static char *g_list_script_buf
= NULL
;
105 static int g_list_script_pos
= 0;
107 static char *g_part_list_buf
= NULL
;
108 static int g_part_list_pos
= 0;
110 static int g_video_mode_max
= 0;
111 static int g_video_mode_num
= 0;
112 static ventoy_video_mode
*g_video_mode_list
= NULL
;
114 static const char *g_menu_class
[] =
116 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
119 static const char *g_menu_prefix
[] =
121 "iso", "wim", "efi", "img", "vhd", "vtoy"
124 void ventoy_debug(const char *fmt
, ...)
128 va_start (args
, fmt
);
129 grub_vprintf (fmt
, args
);
133 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
143 for (i
= 0; i
< 16; i
++)
145 grub_printf("%02x ", guid
[i
]);
150 int ventoy_is_efi_os(void)
154 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
160 static int ventoy_get_fs_type(const char *fs
)
164 return ventoy_fs_max
;
166 else if (grub_strncmp(fs
, "exfat", 5) == 0)
168 return ventoy_fs_exfat
;
170 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
172 return ventoy_fs_ntfs
;
174 else if (grub_strncmp(fs
, "ext", 3) == 0)
176 return ventoy_fs_ext
;
178 else if (grub_strncmp(fs
, "xfs", 3) == 0)
180 return ventoy_fs_xfs
;
182 else if (grub_strncmp(fs
, "udf", 3) == 0)
184 return ventoy_fs_udf
;
186 else if (grub_strncmp(fs
, "fat", 3) == 0)
188 return ventoy_fs_fat
;
191 return ventoy_fs_max
;
194 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
213 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
215 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
219 static grub_err_t
ventoy_fs_close(grub_file_t file
)
221 grub_file_close(g_old_file
);
222 grub_free(file
->data
);
230 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
236 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
241 for (i
= 0; i
< g_video_mode_num
; i
++)
243 if (g_video_mode_list
[i
].width
== info
->width
&&
244 g_video_mode_list
[i
].height
== info
->height
&&
245 g_video_mode_list
[i
].bpp
== info
->bpp
)
251 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
252 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
253 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
256 if (g_video_mode_num
== g_video_mode_max
)
258 g_video_mode_max
*= 2;
259 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
265 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
267 if (v1
->bpp
== v2
->bpp
)
269 if (v1
->width
== v2
->width
)
271 if (v1
->height
== v2
->height
)
277 return (v1
->height
< v2
->height
) ? -1 : 1;
282 return (v1
->width
< v2
->width
) ? -1 : 1;
287 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
291 static int ventoy_enum_video_mode(void)
294 grub_video_adapter_t adapter
;
295 grub_video_driver_id_t id
;
296 ventoy_video_mode mode
;
298 g_video_mode_num
= 0;
299 g_video_mode_max
= 1024;
300 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
301 if (!g_video_mode_list
)
306 #ifdef GRUB_MACHINE_PCBIOS
307 grub_dl_load ("vbe");
310 id
= grub_video_get_driver_id ();
312 FOR_VIDEO_ADAPTERS (adapter
)
314 if (!adapter
->iterate
||
315 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
316 adapter
->init() != GRUB_ERR_NONE
)))
321 adapter
->iterate(ventoy_video_hook
, NULL
);
323 if (adapter
->id
!= id
)
329 /* sort video mode */
330 for (i
= 0; i
< g_video_mode_num
; i
++)
331 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
333 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
335 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
336 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
337 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
341 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
344 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
348 static struct grub_fs vtoy_fs
=
353 .fs_read
= ventoy_fs_read
,
354 .fs_close
= ventoy_fs_close
,
364 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
370 file
->data
= grub_malloc(rawFile
->size
+ 4096);
376 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
377 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
379 g_old_file
= rawFile
;
381 file
->size
= rawFile
->size
+ len
;
382 file
->device
= rawFile
->device
;
384 file
->not_easily_seekable
= 1;
389 static int ventoy_check_decimal_var(const char *name
, long *value
)
391 const char *value_str
= NULL
;
393 value_str
= grub_env_get(name
);
394 if (NULL
== value_str
)
396 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
399 if (!ventoy_is_decimal(value_str
))
401 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
404 *value
= grub_strtol(value_str
, NULL
, 10);
406 return GRUB_ERR_NONE
;
409 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
413 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
416 if (0 == grub_strcmp(args
[0], "on"))
419 grub_env_set("vtdebug_flag", "debug");
424 grub_env_set("vtdebug_flag", "");
427 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
430 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
434 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
436 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
437 grub_printf(" level:\r\n");
438 grub_printf(" 01/11: busybox / (+cat log)\r\n");
439 grub_printf(" 02/12: initrd / (+cat log)\r\n");
440 grub_printf(" 03/13: hook / (+cat log)\r\n");
442 grub_printf(" debug:\r\n");
443 grub_printf(" 0: debug is on\r\n");
444 grub_printf(" 1: debug is off\r\n");
446 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
449 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
451 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
453 g_ventoy_debug_level
= 1;
456 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
459 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
468 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
471 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
503 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
508 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
510 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
513 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
518 value_long
+= grub_strtol(args
[1], NULL
, 10);
520 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
521 grub_env_set(args
[0], buf
);
523 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
526 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
541 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
544 debug("failed to open file <%s> for udf check\n", args
[0]);
548 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
550 grub_env_set(args
[1], buf
);
552 grub_file_close(file
);
558 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
566 g_wimboot_enable
= 0;
567 grub_check_free(g_wimiso_path
);
568 grub_check_free(g_wimiso_chunk_list
.chunk
);
570 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
576 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
577 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
578 if (NULL
== g_wimiso_chunk_list
.chunk
)
580 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
583 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
584 g_wimiso_chunk_list
.cur_chunk
= 0;
586 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
588 g_wimboot_enable
= 1;
589 g_wimiso_path
= grub_strdup(args
[0]);
591 grub_file_close(file
);
596 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
602 grub_uint32_t offset
;
604 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
607 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
611 len
= (int)file
->size
;
613 data
= (char *)grub_malloc(file
->size
);
619 grub_file_read(file
, data
, file
->size
);
620 grub_file_close(file
);
622 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
623 grub_script_execute_sourcecode(exec
);
625 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
626 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
627 grub_file_close(file
);
629 grub_script_execute_sourcecode("loopback -d efiboot");
633 *direntoff
= offset
+ 2;
638 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
648 ventoy_iso9660_override
*dirent
;
657 totlen
= sizeof(ventoy_chain_head
);
659 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
661 debug("failed to load efiboot template %d\n", len
);
667 debug("efiboot template len:%d offset:%d\n", len
, offset
);
669 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
672 debug("failed to open file <%s>\n", args
[0]);
676 totlen
+= ventoy_align_2k(file
->size
);
678 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
679 dirent
->first_sector
= len
/ 2048;
680 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
681 dirent
->size
= (grub_uint32_t
)file
->size
;
682 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
684 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
686 #ifdef GRUB_MACHINE_EFI
687 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
689 data
= (char *)grub_malloc(totlen
);
692 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
694 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
695 grub_check_free(buf
);
697 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
698 grub_file_close(file
);
700 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
701 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
702 grub_env_set(name
, value
);
704 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
705 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
706 grub_env_set(name
, value
);
711 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
728 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
731 debug("failed to open file <%s>\n", args
[0]);
735 #ifdef GRUB_MACHINE_EFI
736 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
738 buf
= (char *)grub_malloc(file
->size
);
741 grub_file_read(file
, buf
, file
->size
);
743 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
744 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
745 grub_env_set(name
, value
);
747 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
748 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
749 grub_env_set(name
, value
);
751 grub_file_close(file
);
757 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
775 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
778 debug("failed to open file <%s> for udf check\n", args
[0]);
782 headlen
= sizeof(ventoy_chain_head
);
784 #ifdef GRUB_MACHINE_EFI
785 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
787 buf
= (char *)grub_malloc(headlen
+ file
->size
);
790 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
792 grub_file_read(file
, buf
+ headlen
, file
->size
);
794 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
795 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
796 grub_env_set(name
, value
);
798 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
799 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
800 grub_env_set(name
, value
);
802 grub_file_close(file
);
808 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
817 if (args
[0][0] == '1')
819 grub_iso9660_set_nojoliet(1);
823 grub_iso9660_set_nojoliet(0);
829 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
834 grub_uint8_t buf
[32];
845 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
848 debug("failed to open file <%s> for udf check\n", args
[0]);
852 for (i
= 16; i
< 32; i
++)
854 grub_file_seek(file
, i
* 2048);
855 grub_file_read(file
, buf
, sizeof(buf
));
863 grub_file_seek(file
, i
* 2048);
864 grub_file_read(file
, buf
, sizeof(buf
));
866 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
869 grub_file_seek(file
, i
* 2048);
870 grub_file_read(file
, buf
, sizeof(buf
));
872 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
873 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
879 grub_file_close(file
);
881 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
886 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
888 long value_long1
= 0;
889 long value_long2
= 0;
891 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
893 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
896 value_long1
= grub_strtol(args
[0], NULL
, 10);
897 value_long2
= grub_strtol(args
[2], NULL
, 10);
899 if (0 == grub_strcmp(args
[1], "eq"))
901 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
903 else if (0 == grub_strcmp(args
[1], "ne"))
905 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
907 else if (0 == grub_strcmp(args
[1], "gt"))
909 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
911 else if (0 == grub_strcmp(args
[1], "lt"))
913 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
915 else if (0 == grub_strcmp(args
[1], "ge"))
917 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
919 else if (0 == grub_strcmp(args
[1], "le"))
921 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
925 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
931 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
938 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
941 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
942 pos
= grub_strstr(buf
, ",");
948 grub_env_set(args
[1], buf
);
950 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
953 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
959 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
965 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
968 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
970 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
971 if (0 == grub_script_execute_sourcecode(buf
))
973 debug("file %s exist, ventoy_compatible YES\n", buf
);
974 grub_env_set("ventoy_compatible", "YES");
975 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
979 debug("file %s NOT exist\n", buf
);
983 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
984 pos
= grub_strstr(buf
, ")");
990 disk
= grub_disk_open(buf
);
993 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
994 grub_disk_close(disk
);
996 g_img_swap_tmp_buf
[703] = 0;
997 for (i
= 318; i
< 703; i
++)
999 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1000 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1002 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1003 grub_env_set("ventoy_compatible", "YES");
1004 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1010 debug("failed to open disk <%s>\n", buf
);
1013 grub_env_set("ventoy_compatible", "NO");
1014 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1017 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1023 if (g_plugin_image_list
)
1025 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1028 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1033 if (0 == g_sort_case_sensitive
)
1035 if (grub_islower(c1
))
1037 c1
= c1
- 'a' + 'A';
1040 if (grub_islower(c2
))
1042 c2
= c2
- 'a' + 'A';
1055 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1061 if (g_plugin_image_list
)
1063 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1066 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1071 if (0 == g_sort_case_sensitive
)
1073 if (grub_islower(c1
))
1075 c1
= c1
- 'a' + 'A';
1078 if (grub_islower(c2
))
1080 c2
= c2
- 'a' + 'A';
1093 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1095 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1097 grub_memcpy(img1
, img2
, sizeof(img_info
));
1098 img1
->next
= g_img_swap_tmp
.next
;
1099 img1
->prev
= g_img_swap_tmp
.prev
;
1101 g_img_swap_tmp
.next
= img2
->next
;
1102 g_img_swap_tmp
.prev
= img2
->prev
;
1103 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1106 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1110 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1115 for (i
= 0; i
< namelen
; i
++)
1117 if (filename
[i
] == ' ' || filename
[i
] == '\t')
1122 if ((grub_uint8_t
)(filename
[i
]) >= 127)
1131 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1135 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1145 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1154 img_iterator_node
*tmp
;
1155 img_iterator_node
*new_node
;
1156 img_iterator_node
*node
= (img_iterator_node
*)data
;
1158 len
= grub_strlen(filename
);
1162 if ((len
== 1 && filename
[0] == '.') ||
1163 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1168 if (!ventoy_img_name_valid(filename
, len
))
1173 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1178 if (g_plugin_image_list
)
1180 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1181 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1184 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1189 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1192 new_node
->plugin_list_index
= index
;
1193 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1195 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1198 debug("Directory %s ignored...\n", new_node
->dir
);
1199 grub_free(new_node
);
1203 new_node
->tail
= node
->tail
;
1205 new_node
->parent
= node
;
1206 if (!node
->firstchild
)
1208 node
->firstchild
= new_node
;
1211 if (g_img_iterator_tail
)
1213 g_img_iterator_tail
->next
= new_node
;
1214 g_img_iterator_tail
= new_node
;
1218 g_img_iterator_head
.next
= new_node
;
1219 g_img_iterator_tail
= new_node
;
1225 debug("Find a file %s\n", filename
);
1231 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1233 type
= img_type_iso
;
1235 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1237 type
= img_type_wim
;
1239 else if (g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1240 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1242 type
= img_type_vhd
;
1244 #ifdef GRUB_MACHINE_EFI
1245 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1247 type
= img_type_efi
;
1250 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1252 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1254 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1255 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1260 type
= img_type_img
;
1262 else if (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1264 type
= img_type_vtoy
;
1271 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1276 if (g_plugin_image_list
)
1278 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1279 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1282 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1287 img
= grub_zalloc(sizeof(img_info
));
1291 img
->plugin_list_index
= index
;
1292 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1294 for (i
= 0; i
< (int)len
; i
++)
1296 if (filename
[i
] == ' ' || filename
[i
] == '\t' || (0 == grub_isprint(filename
[i
])))
1303 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1305 img
->size
= info
->size
;
1308 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1311 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1313 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1318 if (g_ventoy_img_list
)
1320 tail
= *(node
->tail
);
1326 g_ventoy_img_list
= img
;
1329 img
->id
= g_ventoy_img_count
;
1331 if (node
&& NULL
== node
->firstiso
)
1333 node
->firstiso
= img
;
1344 *((img_info
**)(node
->tail
)) = img
;
1345 g_ventoy_img_count
++;
1347 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1348 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1351 img
->class = g_menu_class
[type
];
1353 img
->menu_prefix
= g_menu_prefix
[type
];
1355 if (img_type_iso
== type
)
1357 if (ventoy_plugin_check_memdisk(img
->path
))
1359 img
->menu_prefix
= "miso";
1363 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1370 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1372 int len
= GRUB_UINT_MAX
;
1373 const char *value
= NULL
;
1374 char name
[32] = {0};
1375 char plat
[32] = {0};
1376 char guidstr
[32] = {0};
1377 ventoy_guid guid
= VENTOY_GUID
;
1378 const char *fmt1
= NULL
;
1379 const char *fmt2
= NULL
;
1380 const char *fmt3
= NULL
;
1381 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1382 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1383 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1384 const char fmtcode
[]={
1385 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1386 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1387 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1388 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1389 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1390 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1393 grub_memset(name
, 0, sizeof(name
));
1394 puint
[0] = grub_swap_bytes32(0x56454e54);
1395 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1396 puint
[2] = grub_swap_bytes32(0x45525349);
1397 puint
[1] = grub_swap_bytes32(0x4f595f56);
1398 value
= ventoy_get_env(name
);
1400 grub_memset(name
, 0, sizeof(name
));
1401 puint
[1] = grub_swap_bytes32(0x5f544f50);
1402 puint
[0] = grub_swap_bytes32(0x56544c45);
1403 fmt1
= ventoy_get_env(name
);
1409 grub_memset(name
, 0, sizeof(name
));
1410 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1411 puint
[0] = grub_swap_bytes32(0x56544c45);
1412 fmt2
= ventoy_get_env(name
);
1414 grub_memset(name
, 0, sizeof(name
));
1415 puint
[1] = grub_swap_bytes32(0x5f434c52);
1416 puint
[0] = grub_swap_bytes32(0x56544c45);
1417 fmt3
= ventoy_get_env(name
);
1419 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1421 #if defined (GRUB_MACHINE_EFI)
1422 puint2
[0] = grub_swap_bytes32(0x55454649);
1424 puint2
[0] = grub_swap_bytes32(0x42494f53);
1427 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1428 #pragma GCC diagnostic push
1429 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1430 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1431 fmt1
? fmt1
: fmtdata
,
1432 fmt2
? fmt2
: fmtdata
+ 4,
1433 value
? value
: "", plat
, guidstr
,
1434 fmt3
? fmt3
: fmtdata
+ 6);
1435 #pragma GCC diagnostic pop
1437 grub_memset(name
, 0, sizeof(name
));
1438 puint
[0] = grub_swap_bytes32(0x76746f79);
1439 puint
[2] = grub_swap_bytes32(0x656e7365);
1440 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1441 ventoy_set_env(name
, guidstr
);
1446 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1448 img_info
*minimg
= NULL
;
1449 img_info
*img
= (img_info
*)(node
->firstiso
);
1451 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1453 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1468 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1470 img_iterator_node
*Minchild
= NULL
;
1471 img_iterator_node
*child
= node
->firstchild
;
1473 while (child
&& child
->parent
== node
)
1475 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1479 child
= child
->next
;
1484 Minchild
->select
= 1;
1490 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1493 img_info
*img
= NULL
;
1494 const char *dir_class
= NULL
;
1495 const char *dir_alias
= NULL
;
1496 img_iterator_node
*child
= NULL
;
1498 if (node
->isocnt
== 0 || node
->done
== 1)
1503 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1505 offset
= node
->parent
->dirlen
;
1508 if (node
== &g_img_iterator_head
)
1510 if (g_default_menu_mode
== 0)
1512 if (g_tree_view_menu_style
== 0)
1514 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1515 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1516 " echo 'return ...' \n"
1521 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1522 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1530 node
->dir
[node
->dirlen
- 1] = 0;
1531 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1534 dir_class
= "vtoydir";
1537 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1540 if (g_tree_view_menu_style
== 0)
1542 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1543 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1544 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1548 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1549 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1550 dir_alias
, dir_class
, node
->dir
+ offset
);
1555 dir_alias
= node
->dir
+ offset
;
1557 if (g_tree_view_menu_style
== 0)
1559 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1560 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1561 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1565 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1566 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1567 dir_alias
, dir_class
, node
->dir
+ offset
);
1571 if (g_tree_view_menu_style
== 0)
1573 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1574 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1575 " echo 'return ...' \n"
1580 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1581 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1587 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1589 ventoy_dynamic_tree_menu(child
);
1592 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1594 if (g_tree_view_menu_style
== 0)
1596 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1597 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1600 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1601 img
->unsupport
? "[***********] " : "",
1602 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1604 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1608 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1609 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1612 img
->unsupport
? "[***********] " : "",
1613 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1615 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1619 if (node
!= &g_img_iterator_head
)
1621 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1628 int ventoy_check_device_result(int ret
)
1632 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1633 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1634 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1638 grub_printf(VTOY_WARNING
"\n");
1639 grub_printf(VTOY_WARNING
"\n");
1640 grub_printf(VTOY_WARNING
"\n\n\n");
1642 grub_printf("Unsatisfied conditions detected for Ventoy.\n\n");
1643 grub_printf("This is NOT a standard Ventoy device and is NOT officially supported.\n\n");
1644 grub_printf("Recommend to follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1646 grub_printf("\n\nWill exit after 10 seconds ...... ");
1654 int ventoy_check_device(grub_device_t dev
)
1657 grub_uint64_t offset
;
1662 struct grub_partition
*partition
;
1664 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1666 return ventoy_check_device_result(1 | 0x1000);
1669 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1670 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1671 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_64", dev
->disk
->name
))
1673 return ventoy_check_device_result(2 | 0x1000);
1676 /* We must have partition 2 */
1677 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1680 return ventoy_check_device_result(3 | 0x1000);
1683 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1685 grub_file_close(file
);
1686 return ventoy_check_device_result(4 | 0x1000);
1689 partition
= dev
->disk
->partition
;
1690 if (partition
->number
!= 0 || partition
->start
!= 2048)
1692 return ventoy_check_device_result(5);
1695 offset
= partition
->start
+ partition
->len
;
1696 partition
= file
->device
->disk
->partition
;
1697 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1699 grub_file_close(file
);
1700 return ventoy_check_device_result(6);
1702 grub_file_close(file
);
1704 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1705 dev2
= grub_device_open(devname
);
1708 return ventoy_check_device_result(7);
1711 fs
= grub_fs_probe(dev2
);
1714 grub_device_close(dev2
);
1715 return ventoy_check_device_result(8);
1718 fs
->fs_label(dev2
, &label
);
1719 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1721 grub_device_close(dev2
);
1722 return ventoy_check_device_result(9);
1725 grub_device_close(dev2
);
1726 return ventoy_check_device_result(0);
1729 static int ventoy_set_default_menu(void)
1735 const char *strdata
= NULL
;
1736 img_info
*cur
= NULL
;
1737 img_info
*default_node
= NULL
;
1738 const char *default_image
= NULL
;
1740 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1741 if (default_image
&& default_image
[0] == '/')
1743 img_len
= grub_strlen(default_image
);
1745 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1747 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1759 if (0 == g_default_menu_mode
)
1761 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1765 def
= grub_strdup(default_image
);
1771 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1773 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1774 if (strdata
&& strdata
[0] == '/')
1776 pos
= def
+ grub_strlen(strdata
);
1787 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1790 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1794 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1802 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1806 grub_device_t dev
= NULL
;
1807 img_info
*cur
= NULL
;
1808 img_info
*tail
= NULL
;
1809 const char *strdata
= NULL
;
1810 char *device_name
= NULL
;
1812 img_iterator_node
*node
= NULL
;
1813 img_iterator_node
*tmp
= NULL
;
1819 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1822 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1824 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1827 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1828 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1830 g_filt_dot_underscore_file
= 1;
1833 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
1834 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1836 g_sort_case_sensitive
= 1;
1839 device_name
= grub_file_get_device_name(args
[0]);
1845 g_enum_dev
= dev
= grub_device_open(device_name
);
1851 g_enum_fs
= fs
= grub_fs_probe(dev
);
1857 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1859 debug("unsupported fs:<%s>\n", fs
->name
);
1860 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1864 ventoy_set_env("vtoy_iso_fs", fs
->name
);
1866 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1867 if (strdata
&& strdata
[0] == '1')
1869 g_default_menu_mode
= 1;
1872 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1874 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1876 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1877 if (strdata
&& strdata
[0] == '/')
1879 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1880 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1882 g_img_iterator_head
.dir
[len
++] = '/';
1884 g_img_iterator_head
.dirlen
= len
;
1888 g_img_iterator_head
.dirlen
= 1;
1889 grub_strcpy(g_img_iterator_head
.dir
, "/");
1892 g_img_iterator_head
.tail
= &tail
;
1894 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1896 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1899 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
1900 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1902 g_tree_view_menu_style
= 1;
1905 ventoy_set_default_menu();
1907 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1909 ventoy_dynamic_tree_menu(node
);
1913 node
= g_img_iterator_head
.next
;
1921 /* sort image list by image name */
1922 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1924 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1926 if (ventoy_cmp_img(cur
, tail
) > 0)
1928 ventoy_swap_img(cur
, tail
);
1933 if (g_default_menu_mode
== 1)
1935 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1936 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1937 " echo 'return ...' \n"
1941 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1943 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1944 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1947 cur
->unsupport
? "[***********] " : "",
1948 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1950 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1953 g_tree_script_buf
[g_tree_script_pos
] = 0;
1954 g_list_script_buf
[g_list_script_pos
] = 0;
1956 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1957 grub_env_set(args
[1], buf
);
1961 check_free(device_name
, grub_free
);
1962 check_free(dev
, grub_device_close
);
1964 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1968 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1970 img_info
*next
= NULL
;
1971 img_info
*cur
= g_ventoy_img_list
;
1984 g_ventoy_img_list
= NULL
;
1985 g_ventoy_img_count
= 0;
1987 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1990 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1993 img_info
*cur
= g_ventoy_img_list
;
1997 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1999 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2002 img_id
= grub_strtol(args
[0], NULL
, 10);
2003 if (img_id
>= g_ventoy_img_count
)
2005 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2008 debug("Find image %ld name \n", img_id
);
2010 while (cur
&& img_id
> 0)
2018 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2021 debug("image name is %s\n", cur
->name
);
2023 grub_env_set(args
[1], cur
->name
);
2025 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2028 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2033 const char *id
= NULL
;
2034 img_info
*cur
= g_ventoy_img_list
;
2038 if (argc
< 1 || argc
> 2)
2040 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2043 id
= grub_env_get("chosen");
2045 pos
= grub_strstr(id
, "VID_");
2048 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2052 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2057 if (img_id
== cur
->id
)
2066 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2069 grub_env_set(args
[0], cur
->path
);
2073 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2074 grub_env_set(args
[1], value
);
2077 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2080 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2087 device_name
= grub_file_get_device_name(filename
);
2099 pos2
= grub_strstr(pos
, ",");
2102 pos2
= grub_strstr(pos
, ")");
2110 disk
= grub_disk_open(pos
);
2113 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2114 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2115 grub_disk_close(disk
);
2122 grub_free(device_name
);
2126 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2128 eltorito_descriptor desc
;
2130 grub_memset(&desc
, 0, sizeof(desc
));
2131 grub_file_seek(file
, 17 * 2048);
2132 grub_file_read(file
, &desc
, sizeof(desc
));
2134 if (desc
.type
!= 0 || desc
.version
!= 1)
2139 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2140 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2148 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2152 grub_uint8_t buf
[512];
2154 grub_file_seek(file
, sector
* 2048);
2155 grub_file_read(file
, buf
, sizeof(buf
));
2157 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2159 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2163 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2168 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2170 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2172 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2176 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2178 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2183 debug("%s does not contain efi eltorito\n", file
->name
);
2187 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2190 const char *fs
= NULL
;
2191 const char *cdprompt
= NULL
;
2193 grub_uint8_t chksum
= 0;
2196 disk
= file
->device
->disk
;
2197 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2199 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2200 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2201 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2203 pos
= grub_strstr(file
->name
, "/");
2209 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2211 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2213 param
->vtoy_img_size
= file
->size
;
2215 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2216 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2218 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2220 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2221 param
->vtoy_reserved
[4] = 0;
2222 if (g_ventoy_chain_type
== 1) /* Windows */
2224 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2225 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2227 param
->vtoy_reserved
[4] = 1;
2231 fs
= ventoy_get_env("ventoy_fs_probe");
2232 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2234 param
->vtoy_reserved
[3] = 1;
2237 /* calculate checksum */
2238 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2240 chksum
+= *((grub_uint8_t
*)param
+ i
);
2242 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2247 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2249 grub_uint32_t i
= 0;
2250 grub_uint64_t total
= 0;
2251 ventoy_img_chunk
*chunk
= NULL
;
2253 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2255 chunk
= chunklist
->chunk
+ i
;
2257 if (chunk
->disk_start_sector
<= start
)
2259 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2263 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2266 if (total
!= ((file
->size
+ 511) / 512))
2268 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2275 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2279 grub_uint32_t i
= 0;
2280 grub_uint32_t sector
= 0;
2281 grub_uint32_t count
= 0;
2282 grub_off_t size
= 0;
2283 grub_off_t read
= 0;
2285 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2286 if (fs_type
== ventoy_fs_exfat
)
2288 grub_fat_get_file_chunk(start
, file
, chunklist
);
2290 else if (fs_type
== ventoy_fs_ext
)
2292 grub_ext_get_file_chunk(start
, file
, chunklist
);
2296 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2297 file
->read_hook_data
= chunklist
;
2299 for (size
= file
->size
; size
> 0; size
-= read
)
2301 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2302 grub_file_read(file
, NULL
, read
);
2305 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2307 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2308 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2311 if (ventoy_fs_udf
== fs_type
)
2313 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2315 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2316 chunklist
->chunk
[i
].img_start_sector
= sector
;
2317 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2323 len
= (int)grub_strlen(file
->name
);
2324 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2325 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2326 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2327 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2329 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2331 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2341 chunklist
->chunk
[i
].img_start_sector
= sector
;
2342 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2350 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2354 grub_disk_addr_t start
;
2359 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2362 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2365 if (g_img_chunk_list
.chunk
)
2367 grub_free(g_img_chunk_list
.chunk
);
2370 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2372 grub_file_close(file
);
2373 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2376 /* get image chunk data */
2377 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2378 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2379 if (NULL
== g_img_chunk_list
.chunk
)
2381 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2384 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2385 g_img_chunk_list
.cur_chunk
= 0;
2387 start
= file
->device
->disk
->partition
->start
;
2389 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2391 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2392 grub_file_close(file
);
2396 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2399 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2400 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2403 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2408 char configfile
[128];
2409 install_template
*node
= NULL
;
2415 debug("select auto installation argc:%d\n", argc
);
2422 node
= ventoy_plugin_find_install_template(args
[0]);
2425 debug("Auto install template not found for %s\n", args
[0]);
2429 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2431 node
->cursel
= node
->autosel
- 1;
2432 debug("Auto install template auto select %d\n", node
->autosel
);
2436 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2442 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2443 " echo %s\n}\n", "123");
2445 for (i
= 0; i
< node
->templatenum
; i
++)
2447 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2449 node
->templatepath
[i
].path
);
2452 g_ventoy_menu_esc
= 1;
2453 g_ventoy_suppress_esc
= 1;
2455 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2456 grub_script_execute_sourcecode(configfile
);
2458 g_ventoy_menu_esc
= 0;
2459 g_ventoy_suppress_esc
= 0;
2463 node
->cursel
= g_ventoy_last_entry
- 1;
2465 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2468 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2473 char configfile
[128];
2474 persistence_config
*node
;
2480 debug("select persistence argc:%d\n", argc
);
2487 node
= ventoy_plugin_find_persistent(args
[0]);
2490 debug("Persistence image not found for %s\n", args
[0]);
2494 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2496 node
->cursel
= node
->autosel
- 1;
2497 debug("Persistence image auto select %d\n", node
->autosel
);
2501 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2507 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2508 " echo %s\n}\n", "123");
2510 for (i
= 0; i
< node
->backendnum
; i
++)
2512 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2514 node
->backendpath
[i
].path
);
2518 g_ventoy_menu_esc
= 1;
2519 g_ventoy_suppress_esc
= 1;
2521 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2522 grub_script_execute_sourcecode(configfile
);
2524 g_ventoy_menu_esc
= 0;
2525 g_ventoy_suppress_esc
= 0;
2529 node
->cursel
= g_ventoy_last_entry
- 1;
2531 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2534 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2537 ventoy_img_chunk
*cur
;
2543 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2545 cur
= g_img_chunk_list
.chunk
+ i
;
2546 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2547 cur
->img_start_sector
, cur
->img_end_sector
,
2548 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2552 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2555 #ifdef GRUB_MACHINE_EFI
2556 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2564 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2567 ulong chain_len
= 0;
2568 char *chain_data
= NULL
;
2569 char *relocator_addr
= NULL
;
2570 grub_relocator_chunk_t ch
;
2571 struct grub_relocator
*relocator
= NULL
;
2572 char envbuf
[64] = { 0 };
2583 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2584 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2586 relocator
= grub_relocator_new ();
2589 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2593 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2594 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2598 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2599 grub_relocator_unload (relocator
);
2603 relocator_addr
= get_virtual_current_address(ch
);
2605 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2607 grub_relocator_unload (relocator
);
2609 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2610 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2612 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2616 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2620 ventoy_img_chunk_list chunklist
;
2625 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2628 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2631 /* get image chunk data */
2632 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2633 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2634 if (NULL
== chunklist
.chunk
)
2636 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2639 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2640 chunklist
.cur_chunk
= 0;
2642 ventoy_get_block_list(file
, &chunklist
, 0);
2644 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2646 grub_printf("########## UNSUPPORTED ###############\n");
2649 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2651 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2653 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2654 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2657 grub_printf("\n==================================\n");
2659 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2661 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2662 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2663 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2664 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2665 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2669 grub_free(chunklist
.chunk
);
2670 grub_file_close(file
);
2672 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2675 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2678 ventoy_grub_param_file_replace
*replace
= NULL
;
2686 replace
= &(g_grub_param
->file_replace
);
2687 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2689 replace
->old_name_cnt
= 0;
2690 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2692 replace
->old_name_cnt
++;
2693 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2696 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2699 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2702 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2710 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2711 grub_printf("%s", g_list_script_buf
);
2715 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2716 grub_printf("%s", g_tree_script_buf
);
2722 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2724 img_info
*cur
= g_ventoy_img_list
;
2732 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
2733 grub_printf("name:<%s>\n\n", cur
->name
);
2740 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2746 ventoy_plugin_dump_injection();
2751 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2757 ventoy_plugin_dump_auto_install();
2762 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2768 ventoy_plugin_dump_persistence();
2773 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2784 if (args
[0][0] == '0')
2786 return g_ventoy_memdisk_mode
? 0 : 1;
2788 else if (args
[0][0] == '1')
2790 return g_ventoy_iso_raw
? 0 : 1;
2792 else if (args
[0][0] == '2')
2794 return g_ventoy_iso_uefi_drv
? 0 : 1;
2800 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2802 static int configfile_mode
= 0;
2803 char memfile
[128] = {0};
2810 * args[0]: 0:normal 1:configfile
2811 * args[1]: 0:list_buf 1:tree_buf
2816 debug("Invalid argc %d\n", argc
);
2820 if (args
[0][0] == '0')
2822 if (args
[1][0] == '0')
2824 grub_script_execute_sourcecode(g_list_script_buf
);
2828 grub_script_execute_sourcecode(g_tree_script_buf
);
2833 if (configfile_mode
)
2835 debug("Now already in F3 mode %d\n", configfile_mode
);
2839 if (args
[1][0] == '0')
2841 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2842 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2846 g_ventoy_last_entry
= -1;
2847 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2848 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2851 configfile_mode
= 1;
2852 grub_script_execute_sourcecode(memfile
);
2853 configfile_mode
= 0;
2859 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2870 g_ventoy_case_insensitive
= 1;
2871 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2872 g_ventoy_case_insensitive
= 0;
2878 grub_file_close(file
);
2884 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2889 const char *isopath
= NULL
;
2891 ventoy_mbr_head mbr
;
2898 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2901 isopath
= grub_env_get("vtoy_iso_part");
2904 debug("isopath is null %p\n", isopath
);
2908 debug("isopath is %s\n", isopath
);
2910 for (id
= 0; id
< 30 && (find
== 0); id
++)
2912 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2913 if (grub_strstr(isopath
, hdname
))
2915 debug("skip %s ...\n", hdname
);
2919 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2921 disk
= grub_disk_open(hdname
);
2924 debug("%s not exist\n", hdname
);
2928 grub_memset(&mbr
, 0, sizeof(mbr
));
2929 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2931 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2933 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2934 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2937 grub_env_set(args
[0], hdname
);
2941 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2945 debug("read %s failed\n", hdname
);
2948 grub_disk_close(disk
);
2954 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2965 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2968 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2971 debug("failed to open file %s\n", args
[0]);
2975 buf
= grub_malloc(len
);
2982 grub_file_read(file
, buf
, len
- 1);
2984 ventoy_get_line(buf
);
2985 ventoy_set_env(args
[1], buf
);
2989 grub_check_free(buf
);
2990 grub_file_close(file
);
2995 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3000 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3001 "0 %llu linear /dev/ventoy %llu\n",
3002 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3007 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3009 char *device_name
= NULL
;
3010 grub_device_t dev
= NULL
;
3015 g_part_list_pos
= 0;
3016 grub_env_unset("vtoy_img_part_file");
3023 device_name
= grub_file_get_device_name(args
[0]);
3026 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3030 dev
= grub_device_open(device_name
);
3033 debug("grub_device_open failed, %s\n", device_name
);
3037 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3039 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3040 grub_env_set("vtoy_img_part_file", buf
);
3044 check_free(device_name
, grub_free
);
3045 check_free(dev
, grub_device_close
);
3051 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3062 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3065 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3068 debug("failed to open file %s\n", args
[0]);
3072 buf
= grub_malloc(file
->size
+ 1);
3078 buf
[file
->size
] = 0;
3079 grub_file_read(file
, buf
, file
->size
);
3081 if (grub_strstr(buf
, args
[1]))
3088 grub_check_free(buf
);
3089 grub_file_close(file
);
3094 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3099 ventoy_iso9660_vd pvd
;
3106 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
3109 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3112 debug("failed to open file %s\n", args
[0]);
3116 grub_file_seek(file
, 16 * 2048);
3117 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3118 if (len
!= sizeof(pvd
))
3120 debug("failed to read pvd %d\n", len
);
3124 grub_memset(buf
, 0, sizeof(buf
));
3125 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3126 ventoy_set_env(args
[1], buf
);
3128 grub_memset(buf
, 0, sizeof(buf
));
3129 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3130 ventoy_set_env(args
[2], buf
);
3133 grub_file_close(file
);
3138 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3149 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3152 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3155 debug("failed to open file %s\n", args
[0]);
3159 grub_memset(buf
, 0, sizeof(buf
));
3160 grub_file_seek(file
, 16 * 2048 + 813);
3161 len
= (int)grub_file_read(file
, buf
, 17);
3164 debug("failed to read create date %d\n", len
);
3168 ventoy_set_env(args
[1], buf
);
3171 grub_file_close(file
);
3176 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3182 ventoy_env_hook_root(1);
3187 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3193 ventoy_env_hook_root(0);
3198 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3205 int image_sector_size
;
3207 ventoy_chain_head
*chain
;
3208 ventoy_img_chunk
*chunk
;
3209 ventoy_os_param
*osparam
;
3210 ventoy_image_location
*location
;
3211 ventoy_image_disk_region
*region
;
3212 struct grub_acpi_table_header
*acpi
;
3221 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3223 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3229 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3231 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3233 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3237 img_chunk_num
= chain
->img_chunk_num
;
3239 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3240 datalen
= sizeof(ventoy_os_param
) + loclen
;
3242 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3243 acpi
= grub_zalloc(buflen
);
3249 /* Step1: Fill acpi table header */
3250 grub_memcpy(acpi
->signature
, "VTOY", 4);
3251 acpi
->length
= buflen
;
3253 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3254 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3256 acpi
->creator_id
[0] = 1;
3257 acpi
->creator_rev
= 1;
3259 /* Step2: Fill data */
3260 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3261 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3262 osparam
->vtoy_img_location_addr
= 0;
3263 osparam
->vtoy_img_location_len
= loclen
;
3264 osparam
->chksum
= 0;
3265 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3267 location
= (ventoy_image_location
*)(osparam
+ 1);
3268 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3269 location
->image_sector_size
= image_sector_size
;
3270 location
->disk_sector_size
= chain
->disk_sector_size
;
3271 location
->region_count
= img_chunk_num
;
3273 region
= location
->regions
;
3274 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3275 if (512 == image_sector_size
)
3277 for (i
= 0; i
< img_chunk_num
; i
++)
3279 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3280 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3281 region
->disk_start_sector
= chunk
->disk_start_sector
;
3288 for (i
= 0; i
< img_chunk_num
; i
++)
3290 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3291 region
->image_start_sector
= chunk
->img_start_sector
;
3292 region
->disk_start_sector
= chunk
->disk_start_sector
;
3298 /* Step3: Fill acpi checksum */
3300 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3302 /* load acpi table */
3303 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3304 grub_script_execute_sourcecode(cmd
);
3308 VENTOY_CMD_RETURN(0);
3311 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3317 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3318 g_ventoy_last_entry
= -1;
3323 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3329 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3334 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3336 const char *pos
= filename
+ 1;
3344 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3346 grub_strncpy((char *)data
, filename
, 128);
3357 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3360 char *device_name
= NULL
;
3361 grub_device_t dev
= NULL
;
3362 grub_fs_t fs
= NULL
;
3363 char buf
[128] = {0};
3369 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3373 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3375 device_name
= grub_file_get_device_name(args
[0]);
3378 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3382 dev
= grub_device_open(device_name
);
3385 debug("grub_device_open failed, %s\n", device_name
);
3389 fs
= grub_fs_probe(dev
);
3392 debug("grub_fs_probe failed, %s\n", device_name
);
3396 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3400 ventoy_set_env(args
[2], buf
);
3407 check_free(device_name
, grub_free
);
3408 check_free(dev
, grub_device_close
);
3413 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3423 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3424 if (!g_ventoy_part_info
)
3429 disk
= grub_disk_open(args
[0]);
3432 debug("Failed to open disk %s\n", args
[0]);
3436 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3437 grub_disk_close(disk
);
3439 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3440 dev
= grub_device_open(name
);
3443 /* make sure that we are running in a correct Ventoy device */
3444 ret
= ventoy_check_device(dev
);
3445 grub_device_close(dev
);
3456 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3459 grub_uint8_t zeroguid
[16] = {0};
3464 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3467 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3469 if (id
>= 1 && id
<= 128)
3471 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3479 if (id
>= 1 && id
<= 4)
3481 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3491 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3494 char *device_name
= NULL
;
3495 grub_device_t dev
= NULL
;
3496 grub_fs_t fs
= NULL
;
3503 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3507 device_name
= grub_file_get_device_name(args
[0]);
3510 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3514 dev
= grub_device_open(device_name
);
3517 debug("grub_device_open failed, %s\n", device_name
);
3521 fs
= grub_fs_probe(dev
);
3524 debug("grub_fs_probe failed, %s\n", device_name
);
3528 fs
->fs_label(dev
, &label
);
3531 ventoy_set_env(args
[1], label
);
3539 check_free(device_name
, grub_free
);
3540 check_free(dev
, grub_device_close
);
3545 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3549 grub_snprintf((char *)data
, 256, "%s", filename
);
3557 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3560 char *device_name
= NULL
;
3561 grub_device_t dev
= NULL
;
3562 grub_fs_t fs
= NULL
;
3563 char name
[256] ={0};
3569 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3573 device_name
= grub_file_get_device_name(args
[0]);
3576 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3580 dev
= grub_device_open(device_name
);
3583 debug("grub_device_open failed, %s\n", device_name
);
3587 fs
= grub_fs_probe(dev
);
3590 debug("grub_fs_probe failed, %s\n", device_name
);
3594 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3597 ventoy_set_env(args
[2], name
);
3604 check_free(device_name
, grub_free
);
3605 check_free(dev
, grub_device_close
);
3610 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3620 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3624 for (pos
= args
[0]; *pos
; pos
++)
3638 grub_env_set(args
[1], args
[0]);
3648 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3650 struct grub_video_mode_info info
;
3657 if (!g_video_mode_list
)
3659 ventoy_enum_video_mode();
3662 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3664 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3668 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3671 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3673 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3674 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3676 VENTOY_CMD_RETURN(0);
3679 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3681 struct grub_video_mode_info info
;
3688 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3690 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3694 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3697 grub_env_set(args
[0], buf
);
3699 VENTOY_CMD_RETURN(0);
3702 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3710 if (!g_video_mode_list
)
3715 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3716 if (id
< g_video_mode_num
)
3718 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
3719 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
3722 grub_env_set(args
[1], buf
);
3724 VENTOY_CMD_RETURN(0);
3727 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
3729 grub_uint64_t size
= 0;
3732 char fullpath
[256] = {0};
3735 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3738 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
3741 debug("grub_file_open failed <%s>\n", fullpath
);
3747 grub_file_close(file
);
3751 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
3755 char fullpath
[256] = {0};
3758 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3761 file
= grub_file_open(fullpath
, type
);
3764 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
3771 int ventoy_is_file_exist(const char *fmt
, ...)
3776 char buf
[256] = {0};
3778 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
3782 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3785 grub_strncpy(pos
+ len
, " ]", 2);
3787 debug("script exec %s\n", buf
);
3789 if (0 == grub_script_execute_sourcecode(buf
))
3797 int ventoy_is_dir_exist(const char *fmt
, ...)
3802 char buf
[256] = {0};
3804 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
3808 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3811 grub_strncpy(pos
+ len
, " ]", 2);
3813 debug("script exec %s\n", buf
);
3815 if (0 == grub_script_execute_sourcecode(buf
))
3823 static int ventoy_env_init(void)
3827 grub_env_set("vtdebug_flag", "");
3829 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
3830 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3831 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3833 ventoy_filt_register(0, ventoy_wrapper_open
);
3835 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
3838 g_grub_param
->grub_env_get
= grub_env_get
;
3839 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
3840 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
3841 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
3842 grub_env_set("env_param", buf
);
3843 grub_env_set("ventoy_env_param", buf
);
3844 grub_env_export("ventoy_env_param");
3850 static cmd_para ventoy_cmds
[] =
3852 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
3853 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
3854 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
3855 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3856 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3857 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
3858 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
3859 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
3860 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
3861 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
3862 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
3863 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
3864 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
3865 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
3866 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
3867 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
3868 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
3869 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
3870 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
3871 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
3873 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
3874 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
3875 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
3876 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
3877 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
3878 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
3880 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
3881 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
3882 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
3883 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
3884 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
3885 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
3886 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
3887 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
3890 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
3891 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
3892 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
3893 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
3894 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
3895 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
3896 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
3897 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
3898 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
3899 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
3901 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
3902 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
3903 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
3904 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
3905 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
3906 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
3908 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3909 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3910 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
3911 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
3912 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
3913 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
3914 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
3915 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
3916 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
3917 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
3919 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
3920 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
3921 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
3922 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
3923 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
3924 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
3925 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
3927 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
3928 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
3929 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
3930 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
3933 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
3934 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
3936 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
3937 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
3938 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
3941 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
3942 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
3943 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
3944 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
3945 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
3946 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
3947 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
3948 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
3950 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
3951 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
3952 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
3958 GRUB_MOD_INIT(ventoy
)
3961 cmd_para
*cur
= NULL
;
3965 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3967 cur
= ventoy_cmds
+ i
;
3968 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
3969 cur
->summary
, cur
->description
, cur
->parser
);
3973 GRUB_MOD_FINI(ventoy
)
3977 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3979 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);