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
);
1789 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1792 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1796 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1804 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1808 grub_device_t dev
= NULL
;
1809 img_info
*cur
= NULL
;
1810 img_info
*tail
= NULL
;
1811 const char *strdata
= NULL
;
1812 char *device_name
= NULL
;
1814 img_iterator_node
*node
= NULL
;
1815 img_iterator_node
*tmp
= NULL
;
1821 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1824 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1826 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1829 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1830 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1832 g_filt_dot_underscore_file
= 1;
1835 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
1836 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1838 g_sort_case_sensitive
= 1;
1841 device_name
= grub_file_get_device_name(args
[0]);
1847 g_enum_dev
= dev
= grub_device_open(device_name
);
1853 g_enum_fs
= fs
= grub_fs_probe(dev
);
1859 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1861 debug("unsupported fs:<%s>\n", fs
->name
);
1862 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1866 ventoy_set_env("vtoy_iso_fs", fs
->name
);
1868 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1869 if (strdata
&& strdata
[0] == '1')
1871 g_default_menu_mode
= 1;
1874 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1876 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1878 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1879 if (strdata
&& strdata
[0] == '/')
1881 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1882 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1884 g_img_iterator_head
.dir
[len
++] = '/';
1886 g_img_iterator_head
.dirlen
= len
;
1890 g_img_iterator_head
.dirlen
= 1;
1891 grub_strcpy(g_img_iterator_head
.dir
, "/");
1894 g_img_iterator_head
.tail
= &tail
;
1896 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1898 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1901 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
1902 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1904 g_tree_view_menu_style
= 1;
1907 ventoy_set_default_menu();
1909 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1911 ventoy_dynamic_tree_menu(node
);
1915 node
= g_img_iterator_head
.next
;
1923 /* sort image list by image name */
1924 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1926 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1928 if (ventoy_cmp_img(cur
, tail
) > 0)
1930 ventoy_swap_img(cur
, tail
);
1935 if (g_default_menu_mode
== 1)
1937 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1938 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1939 " echo 'return ...' \n"
1943 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1945 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1946 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1949 cur
->unsupport
? "[***********] " : "",
1950 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1952 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1955 g_tree_script_buf
[g_tree_script_pos
] = 0;
1956 g_list_script_buf
[g_list_script_pos
] = 0;
1958 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1959 grub_env_set(args
[1], buf
);
1963 check_free(device_name
, grub_free
);
1964 check_free(dev
, grub_device_close
);
1966 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1970 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1972 img_info
*next
= NULL
;
1973 img_info
*cur
= g_ventoy_img_list
;
1986 g_ventoy_img_list
= NULL
;
1987 g_ventoy_img_count
= 0;
1989 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1992 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1995 img_info
*cur
= g_ventoy_img_list
;
1999 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2001 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2004 img_id
= grub_strtol(args
[0], NULL
, 10);
2005 if (img_id
>= g_ventoy_img_count
)
2007 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2010 debug("Find image %ld name \n", img_id
);
2012 while (cur
&& img_id
> 0)
2020 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2023 debug("image name is %s\n", cur
->name
);
2025 grub_env_set(args
[1], cur
->name
);
2027 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2030 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2035 const char *id
= NULL
;
2036 img_info
*cur
= g_ventoy_img_list
;
2040 if (argc
< 1 || argc
> 2)
2042 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2045 id
= grub_env_get("chosen");
2047 pos
= grub_strstr(id
, "VID_");
2050 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2054 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2059 if (img_id
== cur
->id
)
2068 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2071 grub_env_set(args
[0], cur
->path
);
2075 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2076 grub_env_set(args
[1], value
);
2079 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2082 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2089 device_name
= grub_file_get_device_name(filename
);
2101 pos2
= grub_strstr(pos
, ",");
2104 pos2
= grub_strstr(pos
, ")");
2112 disk
= grub_disk_open(pos
);
2115 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2116 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2117 grub_disk_close(disk
);
2124 grub_free(device_name
);
2128 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2130 eltorito_descriptor desc
;
2132 grub_memset(&desc
, 0, sizeof(desc
));
2133 grub_file_seek(file
, 17 * 2048);
2134 grub_file_read(file
, &desc
, sizeof(desc
));
2136 if (desc
.type
!= 0 || desc
.version
!= 1)
2141 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2142 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2150 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2154 grub_uint8_t buf
[512];
2156 grub_file_seek(file
, sector
* 2048);
2157 grub_file_read(file
, buf
, sizeof(buf
));
2159 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2161 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2165 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2170 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2172 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2174 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2178 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2180 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2185 debug("%s does not contain efi eltorito\n", file
->name
);
2189 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2192 const char *fs
= NULL
;
2193 const char *cdprompt
= NULL
;
2195 grub_uint8_t chksum
= 0;
2198 disk
= file
->device
->disk
;
2199 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2201 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2202 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2203 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2205 pos
= grub_strstr(file
->name
, "/");
2211 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2213 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2215 param
->vtoy_img_size
= file
->size
;
2217 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2218 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2220 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2222 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2223 param
->vtoy_reserved
[4] = 0;
2224 if (g_ventoy_chain_type
== 1) /* Windows */
2226 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2227 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2229 param
->vtoy_reserved
[4] = 1;
2233 fs
= ventoy_get_env("ventoy_fs_probe");
2234 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2236 param
->vtoy_reserved
[3] = 1;
2239 /* calculate checksum */
2240 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2242 chksum
+= *((grub_uint8_t
*)param
+ i
);
2244 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2249 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2251 grub_uint32_t i
= 0;
2252 grub_uint64_t total
= 0;
2253 ventoy_img_chunk
*chunk
= NULL
;
2255 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2257 chunk
= chunklist
->chunk
+ i
;
2259 if (chunk
->disk_start_sector
<= start
)
2261 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2265 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2268 if (total
!= ((file
->size
+ 511) / 512))
2270 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2277 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2281 grub_uint32_t i
= 0;
2282 grub_uint32_t sector
= 0;
2283 grub_uint32_t count
= 0;
2284 grub_off_t size
= 0;
2285 grub_off_t read
= 0;
2287 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2288 if (fs_type
== ventoy_fs_exfat
)
2290 grub_fat_get_file_chunk(start
, file
, chunklist
);
2292 else if (fs_type
== ventoy_fs_ext
)
2294 grub_ext_get_file_chunk(start
, file
, chunklist
);
2298 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2299 file
->read_hook_data
= chunklist
;
2301 for (size
= file
->size
; size
> 0; size
-= read
)
2303 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2304 grub_file_read(file
, NULL
, read
);
2307 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2309 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2310 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2313 if (ventoy_fs_udf
== fs_type
)
2315 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2317 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2318 chunklist
->chunk
[i
].img_start_sector
= sector
;
2319 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2325 len
= (int)grub_strlen(file
->name
);
2326 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2327 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2328 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2329 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2331 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2333 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2343 chunklist
->chunk
[i
].img_start_sector
= sector
;
2344 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2352 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2356 grub_disk_addr_t start
;
2361 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2364 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2367 if (g_img_chunk_list
.chunk
)
2369 grub_free(g_img_chunk_list
.chunk
);
2372 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2374 grub_file_close(file
);
2375 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2378 /* get image chunk data */
2379 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2380 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2381 if (NULL
== g_img_chunk_list
.chunk
)
2383 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2386 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2387 g_img_chunk_list
.cur_chunk
= 0;
2389 start
= file
->device
->disk
->partition
->start
;
2391 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2393 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2394 grub_file_close(file
);
2398 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2401 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2402 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2405 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2410 char configfile
[128];
2411 install_template
*node
= NULL
;
2417 debug("select auto installation argc:%d\n", argc
);
2424 node
= ventoy_plugin_find_install_template(args
[0]);
2427 debug("Auto install template not found for %s\n", args
[0]);
2431 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2433 node
->cursel
= node
->autosel
- 1;
2434 debug("Auto install template auto select %d\n", node
->autosel
);
2438 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2444 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2445 " echo %s\n}\n", "123");
2447 for (i
= 0; i
< node
->templatenum
; i
++)
2449 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2451 node
->templatepath
[i
].path
);
2454 g_ventoy_menu_esc
= 1;
2455 g_ventoy_suppress_esc
= 1;
2457 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2458 grub_script_execute_sourcecode(configfile
);
2460 g_ventoy_menu_esc
= 0;
2461 g_ventoy_suppress_esc
= 0;
2465 node
->cursel
= g_ventoy_last_entry
- 1;
2467 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2470 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2475 char configfile
[128];
2476 persistence_config
*node
;
2482 debug("select persistence argc:%d\n", argc
);
2489 node
= ventoy_plugin_find_persistent(args
[0]);
2492 debug("Persistence image not found for %s\n", args
[0]);
2496 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2498 node
->cursel
= node
->autosel
- 1;
2499 debug("Persistence image auto select %d\n", node
->autosel
);
2503 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2509 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2510 " echo %s\n}\n", "123");
2512 for (i
= 0; i
< node
->backendnum
; i
++)
2514 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2516 node
->backendpath
[i
].path
);
2520 g_ventoy_menu_esc
= 1;
2521 g_ventoy_suppress_esc
= 1;
2523 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2524 grub_script_execute_sourcecode(configfile
);
2526 g_ventoy_menu_esc
= 0;
2527 g_ventoy_suppress_esc
= 0;
2531 node
->cursel
= g_ventoy_last_entry
- 1;
2533 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2536 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2539 ventoy_img_chunk
*cur
;
2545 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2547 cur
= g_img_chunk_list
.chunk
+ i
;
2548 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2549 cur
->img_start_sector
, cur
->img_end_sector
,
2550 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2554 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2557 #ifdef GRUB_MACHINE_EFI
2558 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2566 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2569 ulong chain_len
= 0;
2570 char *chain_data
= NULL
;
2571 char *relocator_addr
= NULL
;
2572 grub_relocator_chunk_t ch
;
2573 struct grub_relocator
*relocator
= NULL
;
2574 char envbuf
[64] = { 0 };
2585 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2586 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2588 relocator
= grub_relocator_new ();
2591 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2595 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2596 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2600 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2601 grub_relocator_unload (relocator
);
2605 relocator_addr
= get_virtual_current_address(ch
);
2607 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2609 grub_relocator_unload (relocator
);
2611 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2612 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2614 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2618 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2622 ventoy_img_chunk_list chunklist
;
2627 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2630 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2633 /* get image chunk data */
2634 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2635 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2636 if (NULL
== chunklist
.chunk
)
2638 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2641 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2642 chunklist
.cur_chunk
= 0;
2644 ventoy_get_block_list(file
, &chunklist
, 0);
2646 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2648 grub_printf("########## UNSUPPORTED ###############\n");
2651 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2653 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2655 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2656 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2659 grub_printf("\n==================================\n");
2661 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2663 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2664 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2665 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2666 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2667 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2671 grub_free(chunklist
.chunk
);
2672 grub_file_close(file
);
2674 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2677 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2680 ventoy_grub_param_file_replace
*replace
= NULL
;
2688 replace
= &(g_grub_param
->file_replace
);
2689 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2691 replace
->old_name_cnt
= 0;
2692 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2694 replace
->old_name_cnt
++;
2695 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2698 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2701 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2704 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2712 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2713 grub_printf("%s", g_list_script_buf
);
2717 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2718 grub_printf("%s", g_tree_script_buf
);
2724 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2726 img_info
*cur
= g_ventoy_img_list
;
2734 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
2735 grub_printf("name:<%s>\n\n", cur
->name
);
2742 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2748 ventoy_plugin_dump_injection();
2753 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2759 ventoy_plugin_dump_auto_install();
2764 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2770 ventoy_plugin_dump_persistence();
2775 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2786 if (args
[0][0] == '0')
2788 return g_ventoy_memdisk_mode
? 0 : 1;
2790 else if (args
[0][0] == '1')
2792 return g_ventoy_iso_raw
? 0 : 1;
2794 else if (args
[0][0] == '2')
2796 return g_ventoy_iso_uefi_drv
? 0 : 1;
2802 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2804 static int configfile_mode
= 0;
2805 char memfile
[128] = {0};
2812 * args[0]: 0:normal 1:configfile
2813 * args[1]: 0:list_buf 1:tree_buf
2818 debug("Invalid argc %d\n", argc
);
2822 if (args
[0][0] == '0')
2824 if (args
[1][0] == '0')
2826 grub_script_execute_sourcecode(g_list_script_buf
);
2830 grub_script_execute_sourcecode(g_tree_script_buf
);
2835 if (configfile_mode
)
2837 debug("Now already in F3 mode %d\n", configfile_mode
);
2841 if (args
[1][0] == '0')
2843 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2844 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2848 g_ventoy_last_entry
= -1;
2849 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2850 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2853 configfile_mode
= 1;
2854 grub_script_execute_sourcecode(memfile
);
2855 configfile_mode
= 0;
2861 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2872 g_ventoy_case_insensitive
= 1;
2873 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2874 g_ventoy_case_insensitive
= 0;
2880 grub_file_close(file
);
2886 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2891 const char *isopath
= NULL
;
2893 ventoy_mbr_head mbr
;
2900 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2903 isopath
= grub_env_get("vtoy_iso_part");
2906 debug("isopath is null %p\n", isopath
);
2910 debug("isopath is %s\n", isopath
);
2912 for (id
= 0; id
< 30 && (find
== 0); id
++)
2914 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2915 if (grub_strstr(isopath
, hdname
))
2917 debug("skip %s ...\n", hdname
);
2921 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2923 disk
= grub_disk_open(hdname
);
2926 debug("%s not exist\n", hdname
);
2930 grub_memset(&mbr
, 0, sizeof(mbr
));
2931 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2933 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2935 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2936 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2939 grub_env_set(args
[0], hdname
);
2943 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2947 debug("read %s failed\n", hdname
);
2950 grub_disk_close(disk
);
2956 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2967 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2970 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2973 debug("failed to open file %s\n", args
[0]);
2977 buf
= grub_malloc(len
);
2984 grub_file_read(file
, buf
, len
- 1);
2986 ventoy_get_line(buf
);
2987 ventoy_set_env(args
[1], buf
);
2991 grub_check_free(buf
);
2992 grub_file_close(file
);
2997 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3002 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3003 "0 %llu linear /dev/ventoy %llu\n",
3004 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3009 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3011 char *device_name
= NULL
;
3012 grub_device_t dev
= NULL
;
3017 g_part_list_pos
= 0;
3018 grub_env_unset("vtoy_img_part_file");
3025 device_name
= grub_file_get_device_name(args
[0]);
3028 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3032 dev
= grub_device_open(device_name
);
3035 debug("grub_device_open failed, %s\n", device_name
);
3039 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3041 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3042 grub_env_set("vtoy_img_part_file", buf
);
3046 check_free(device_name
, grub_free
);
3047 check_free(dev
, grub_device_close
);
3053 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3064 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3067 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3070 debug("failed to open file %s\n", args
[0]);
3074 buf
= grub_malloc(file
->size
+ 1);
3080 buf
[file
->size
] = 0;
3081 grub_file_read(file
, buf
, file
->size
);
3083 if (grub_strstr(buf
, args
[1]))
3090 grub_check_free(buf
);
3091 grub_file_close(file
);
3096 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3101 ventoy_iso9660_vd pvd
;
3108 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
3111 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3114 debug("failed to open file %s\n", args
[0]);
3118 grub_file_seek(file
, 16 * 2048);
3119 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3120 if (len
!= sizeof(pvd
))
3122 debug("failed to read pvd %d\n", len
);
3126 grub_memset(buf
, 0, sizeof(buf
));
3127 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3128 ventoy_set_env(args
[1], buf
);
3130 grub_memset(buf
, 0, sizeof(buf
));
3131 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3132 ventoy_set_env(args
[2], buf
);
3135 grub_file_close(file
);
3140 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3151 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3154 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3157 debug("failed to open file %s\n", args
[0]);
3161 grub_memset(buf
, 0, sizeof(buf
));
3162 grub_file_seek(file
, 16 * 2048 + 813);
3163 len
= (int)grub_file_read(file
, buf
, 17);
3166 debug("failed to read create date %d\n", len
);
3170 ventoy_set_env(args
[1], buf
);
3173 grub_file_close(file
);
3178 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3184 ventoy_env_hook_root(1);
3189 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3195 ventoy_env_hook_root(0);
3200 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3207 int image_sector_size
;
3209 ventoy_chain_head
*chain
;
3210 ventoy_img_chunk
*chunk
;
3211 ventoy_os_param
*osparam
;
3212 ventoy_image_location
*location
;
3213 ventoy_image_disk_region
*region
;
3214 struct grub_acpi_table_header
*acpi
;
3223 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3225 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3231 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3233 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3235 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3239 img_chunk_num
= chain
->img_chunk_num
;
3241 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3242 datalen
= sizeof(ventoy_os_param
) + loclen
;
3244 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3245 acpi
= grub_zalloc(buflen
);
3251 /* Step1: Fill acpi table header */
3252 grub_memcpy(acpi
->signature
, "VTOY", 4);
3253 acpi
->length
= buflen
;
3255 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3256 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3258 acpi
->creator_id
[0] = 1;
3259 acpi
->creator_rev
= 1;
3261 /* Step2: Fill data */
3262 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3263 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3264 osparam
->vtoy_img_location_addr
= 0;
3265 osparam
->vtoy_img_location_len
= loclen
;
3266 osparam
->chksum
= 0;
3267 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3269 location
= (ventoy_image_location
*)(osparam
+ 1);
3270 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3271 location
->image_sector_size
= image_sector_size
;
3272 location
->disk_sector_size
= chain
->disk_sector_size
;
3273 location
->region_count
= img_chunk_num
;
3275 region
= location
->regions
;
3276 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3277 if (512 == image_sector_size
)
3279 for (i
= 0; i
< img_chunk_num
; i
++)
3281 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3282 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3283 region
->disk_start_sector
= chunk
->disk_start_sector
;
3290 for (i
= 0; i
< img_chunk_num
; i
++)
3292 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3293 region
->image_start_sector
= chunk
->img_start_sector
;
3294 region
->disk_start_sector
= chunk
->disk_start_sector
;
3300 /* Step3: Fill acpi checksum */
3302 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3304 /* load acpi table */
3305 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3306 grub_script_execute_sourcecode(cmd
);
3310 VENTOY_CMD_RETURN(0);
3313 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3319 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3320 g_ventoy_last_entry
= -1;
3325 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3331 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3336 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3338 const char *pos
= filename
+ 1;
3346 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3348 grub_strncpy((char *)data
, filename
, 128);
3359 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3362 char *device_name
= NULL
;
3363 grub_device_t dev
= NULL
;
3364 grub_fs_t fs
= NULL
;
3365 char buf
[128] = {0};
3371 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3375 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3377 device_name
= grub_file_get_device_name(args
[0]);
3380 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3384 dev
= grub_device_open(device_name
);
3387 debug("grub_device_open failed, %s\n", device_name
);
3391 fs
= grub_fs_probe(dev
);
3394 debug("grub_fs_probe failed, %s\n", device_name
);
3398 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3402 ventoy_set_env(args
[2], buf
);
3409 check_free(device_name
, grub_free
);
3410 check_free(dev
, grub_device_close
);
3415 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3425 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3426 if (!g_ventoy_part_info
)
3431 disk
= grub_disk_open(args
[0]);
3434 debug("Failed to open disk %s\n", args
[0]);
3438 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3439 grub_disk_close(disk
);
3441 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3442 dev
= grub_device_open(name
);
3445 /* make sure that we are running in a correct Ventoy device */
3446 ret
= ventoy_check_device(dev
);
3447 grub_device_close(dev
);
3458 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3461 grub_uint8_t zeroguid
[16] = {0};
3466 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3469 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3471 if (id
>= 1 && id
<= 128)
3473 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3481 if (id
>= 1 && id
<= 4)
3483 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3493 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3496 char *device_name
= NULL
;
3497 grub_device_t dev
= NULL
;
3498 grub_fs_t fs
= NULL
;
3505 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3509 device_name
= grub_file_get_device_name(args
[0]);
3512 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3516 dev
= grub_device_open(device_name
);
3519 debug("grub_device_open failed, %s\n", device_name
);
3523 fs
= grub_fs_probe(dev
);
3526 debug("grub_fs_probe failed, %s\n", device_name
);
3530 fs
->fs_label(dev
, &label
);
3533 ventoy_set_env(args
[1], label
);
3541 check_free(device_name
, grub_free
);
3542 check_free(dev
, grub_device_close
);
3547 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3551 grub_snprintf((char *)data
, 256, "%s", filename
);
3559 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3562 char *device_name
= NULL
;
3563 grub_device_t dev
= NULL
;
3564 grub_fs_t fs
= NULL
;
3565 char name
[256] ={0};
3571 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3575 device_name
= grub_file_get_device_name(args
[0]);
3578 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3582 dev
= grub_device_open(device_name
);
3585 debug("grub_device_open failed, %s\n", device_name
);
3589 fs
= grub_fs_probe(dev
);
3592 debug("grub_fs_probe failed, %s\n", device_name
);
3596 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3599 ventoy_set_env(args
[2], name
);
3606 check_free(device_name
, grub_free
);
3607 check_free(dev
, grub_device_close
);
3612 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3622 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3626 for (pos
= args
[0]; *pos
; pos
++)
3640 grub_env_set(args
[1], args
[0]);
3650 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3652 struct grub_video_mode_info info
;
3659 if (!g_video_mode_list
)
3661 ventoy_enum_video_mode();
3664 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3666 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3670 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3673 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3675 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3676 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3678 VENTOY_CMD_RETURN(0);
3681 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3683 struct grub_video_mode_info info
;
3690 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3692 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3696 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3699 grub_env_set(args
[0], buf
);
3701 VENTOY_CMD_RETURN(0);
3704 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3712 if (!g_video_mode_list
)
3717 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3718 if (id
< g_video_mode_num
)
3720 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
3721 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
3724 grub_env_set(args
[1], buf
);
3726 VENTOY_CMD_RETURN(0);
3729 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
3731 grub_uint64_t size
= 0;
3734 char fullpath
[256] = {0};
3737 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3740 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
3743 debug("grub_file_open failed <%s>\n", fullpath
);
3749 grub_file_close(file
);
3753 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
3757 char fullpath
[256] = {0};
3760 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3763 file
= grub_file_open(fullpath
, type
);
3766 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
3773 int ventoy_is_file_exist(const char *fmt
, ...)
3778 char buf
[256] = {0};
3780 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
3784 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3787 grub_strncpy(pos
+ len
, " ]", 2);
3789 debug("script exec %s\n", buf
);
3791 if (0 == grub_script_execute_sourcecode(buf
))
3799 int ventoy_is_dir_exist(const char *fmt
, ...)
3804 char buf
[256] = {0};
3806 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
3810 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3813 grub_strncpy(pos
+ len
, " ]", 2);
3815 debug("script exec %s\n", buf
);
3817 if (0 == grub_script_execute_sourcecode(buf
))
3825 static int ventoy_env_init(void)
3829 grub_env_set("vtdebug_flag", "");
3831 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
3832 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3833 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3835 ventoy_filt_register(0, ventoy_wrapper_open
);
3837 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
3840 g_grub_param
->grub_env_get
= grub_env_get
;
3841 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
3842 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
3843 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
3844 grub_env_set("env_param", buf
);
3845 grub_env_set("ventoy_env_param", buf
);
3846 grub_env_export("ventoy_env_param");
3852 static cmd_para ventoy_cmds
[] =
3854 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
3855 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
3856 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
3857 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3858 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3859 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
3860 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
3861 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
3862 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
3863 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
3864 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
3865 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
3866 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
3867 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
3868 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
3869 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
3870 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
3871 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
3872 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
3873 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
3875 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
3876 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
3877 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
3878 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
3879 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
3880 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
3882 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
3883 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
3884 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
3885 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
3886 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
3887 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
3888 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
3889 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
3892 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
3893 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
3894 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
3895 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
3896 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
3897 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
3898 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
3899 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
3900 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
3901 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
3903 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
3904 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
3905 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
3906 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
3907 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
3908 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
3910 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3911 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3912 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
3913 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
3914 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
3915 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
3916 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
3917 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
3918 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
3919 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
3921 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
3922 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
3923 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
3924 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
3925 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
3926 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
3927 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
3929 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
3930 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
3931 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
3932 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
3935 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
3936 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
3938 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
3939 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
3940 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
3943 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
3944 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
3945 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
3946 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
3947 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
3948 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
3949 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
3950 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
3952 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
3953 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
3954 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
3960 GRUB_MOD_INIT(ventoy
)
3963 cmd_para
*cur
= NULL
;
3967 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3969 cur
= ventoy_cmds
+ i
;
3970 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
3971 cur
->summary
, cur
->description
, cur
->parser
);
3975 GRUB_MOD_FINI(ventoy
)
3979 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3981 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);