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 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1028 if (0 == g_sort_case_sensitive
)
1030 if (grub_islower(c1
))
1032 c1
= c1
- 'a' + 'A';
1035 if (grub_islower(c2
))
1037 c2
= c2
- 'a' + 'A';
1050 static int ventoy_cmp_subdir(char *name1
, char *name2
)
1056 for (s1
= name1
, s2
= name2
; *s1
&& *s2
; s1
++, s2
++)
1061 if (0 == g_sort_case_sensitive
)
1063 if (grub_islower(c1
))
1065 c1
= c1
- 'a' + 'A';
1068 if (grub_islower(c2
))
1070 c2
= c2
- 'a' + 'A';
1083 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1085 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1087 grub_memcpy(img1
, img2
, sizeof(img_info
));
1088 img1
->next
= g_img_swap_tmp
.next
;
1089 img1
->prev
= g_img_swap_tmp
.prev
;
1091 g_img_swap_tmp
.next
= img2
->next
;
1092 g_img_swap_tmp
.prev
= img2
->prev
;
1093 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1096 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1100 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1105 for (i
= 0; i
< namelen
; i
++)
1107 if (filename
[i
] == ' ' || filename
[i
] == '\t')
1112 if ((grub_uint8_t
)(filename
[i
]) >= 127)
1121 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1125 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1135 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1143 img_iterator_node
*tmp
;
1144 img_iterator_node
*new_node
;
1145 img_iterator_node
*node
= (img_iterator_node
*)data
;
1147 len
= grub_strlen(filename
);
1151 if ((len
== 1 && filename
[0] == '.') ||
1152 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1157 if (!ventoy_img_name_valid(filename
, len
))
1162 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1167 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1170 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1172 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1175 debug("Directory %s ignored...\n", new_node
->dir
);
1176 grub_free(new_node
);
1180 new_node
->tail
= node
->tail
;
1182 new_node
->parent
= node
;
1183 if (!node
->firstchild
)
1185 node
->firstchild
= new_node
;
1188 if (g_img_iterator_tail
)
1190 g_img_iterator_tail
->next
= new_node
;
1191 g_img_iterator_tail
= new_node
;
1195 g_img_iterator_head
.next
= new_node
;
1196 g_img_iterator_tail
= new_node
;
1202 debug("Find a file %s\n", filename
);
1208 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1210 type
= img_type_iso
;
1212 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1214 type
= img_type_wim
;
1216 else if (g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1217 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1219 type
= img_type_vhd
;
1221 #ifdef GRUB_MACHINE_EFI
1222 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1224 type
= img_type_efi
;
1227 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1229 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1231 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1232 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1237 type
= img_type_img
;
1239 else if (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1241 type
= img_type_vtoy
;
1248 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1253 if (g_plugin_image_list
)
1255 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1256 if (ventoy_plugin_check_image_list(g_img_swap_tmp_buf
) == 0)
1262 img
= grub_zalloc(sizeof(img_info
));
1266 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1268 for (i
= 0; i
< (int)len
; i
++)
1270 if (filename
[i
] == ' ' || filename
[i
] == '\t' || (0 == grub_isprint(filename
[i
])))
1277 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1279 img
->size
= info
->size
;
1282 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1285 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1287 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1292 if (g_ventoy_img_list
)
1294 tail
= *(node
->tail
);
1300 g_ventoy_img_list
= img
;
1303 img
->id
= g_ventoy_img_count
;
1305 if (node
&& NULL
== node
->firstiso
)
1307 node
->firstiso
= img
;
1318 *((img_info
**)(node
->tail
)) = img
;
1319 g_ventoy_img_count
++;
1321 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1322 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1325 img
->class = g_menu_class
[type
];
1327 img
->menu_prefix
= g_menu_prefix
[type
];
1329 if (img_type_iso
== type
)
1331 if (ventoy_plugin_check_memdisk(img
->path
))
1333 img
->menu_prefix
= "miso";
1337 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1344 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1346 int len
= GRUB_UINT_MAX
;
1347 const char *value
= NULL
;
1348 char name
[32] = {0};
1349 char plat
[32] = {0};
1350 char guidstr
[32] = {0};
1351 ventoy_guid guid
= VENTOY_GUID
;
1352 const char *fmt1
= NULL
;
1353 const char *fmt2
= NULL
;
1354 const char *fmt3
= NULL
;
1355 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1356 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1357 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1358 const char fmtcode
[]={
1359 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1360 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1361 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1362 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1363 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1364 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1367 grub_memset(name
, 0, sizeof(name
));
1368 puint
[0] = grub_swap_bytes32(0x56454e54);
1369 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1370 puint
[2] = grub_swap_bytes32(0x45525349);
1371 puint
[1] = grub_swap_bytes32(0x4f595f56);
1372 value
= ventoy_get_env(name
);
1374 grub_memset(name
, 0, sizeof(name
));
1375 puint
[1] = grub_swap_bytes32(0x5f544f50);
1376 puint
[0] = grub_swap_bytes32(0x56544c45);
1377 fmt1
= ventoy_get_env(name
);
1383 grub_memset(name
, 0, sizeof(name
));
1384 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1385 puint
[0] = grub_swap_bytes32(0x56544c45);
1386 fmt2
= ventoy_get_env(name
);
1388 grub_memset(name
, 0, sizeof(name
));
1389 puint
[1] = grub_swap_bytes32(0x5f434c52);
1390 puint
[0] = grub_swap_bytes32(0x56544c45);
1391 fmt3
= ventoy_get_env(name
);
1393 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1395 #if defined (GRUB_MACHINE_EFI)
1396 puint2
[0] = grub_swap_bytes32(0x55454649);
1398 puint2
[0] = grub_swap_bytes32(0x42494f53);
1401 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1402 #pragma GCC diagnostic push
1403 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1404 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1405 fmt1
? fmt1
: fmtdata
,
1406 fmt2
? fmt2
: fmtdata
+ 4,
1407 value
? value
: "", plat
, guidstr
,
1408 fmt3
? fmt3
: fmtdata
+ 6);
1409 #pragma GCC diagnostic pop
1411 grub_memset(name
, 0, sizeof(name
));
1412 puint
[0] = grub_swap_bytes32(0x76746f79);
1413 puint
[2] = grub_swap_bytes32(0x656e7365);
1414 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1415 ventoy_set_env(name
, guidstr
);
1420 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1422 img_info
*minimg
= NULL
;
1423 img_info
*img
= (img_info
*)(node
->firstiso
);
1425 if (g_plugin_image_list
)
1427 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1429 if (img
->select
== 0)
1439 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1441 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1457 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1459 img_iterator_node
*Minchild
= NULL
;
1460 img_iterator_node
*child
= node
->firstchild
;
1462 if (g_plugin_image_list
)
1464 while (child
&& child
->parent
== node
)
1466 if (child
->select
== 0)
1471 child
= child
->next
;
1476 while (child
&& child
->parent
== node
)
1478 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
->dir
, Minchild
->dir
) < 0))
1482 child
= child
->next
;
1488 Minchild
->select
= 1;
1494 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1497 img_info
*img
= NULL
;
1498 const char *dir_class
= NULL
;
1499 const char *dir_alias
= NULL
;
1500 img_iterator_node
*child
= NULL
;
1502 if (node
->isocnt
== 0 || node
->done
== 1)
1507 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1509 offset
= node
->parent
->dirlen
;
1512 if (node
== &g_img_iterator_head
)
1514 if (g_default_menu_mode
== 0)
1516 if (g_tree_view_menu_style
== 0)
1518 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1519 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1520 " echo 'return ...' \n"
1525 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1526 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1534 node
->dir
[node
->dirlen
- 1] = 0;
1535 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1538 dir_class
= "vtoydir";
1541 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1544 if (g_tree_view_menu_style
== 0)
1546 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1547 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1548 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1552 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1553 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1554 dir_alias
, dir_class
, node
->dir
+ offset
);
1559 dir_alias
= node
->dir
+ offset
;
1561 if (g_tree_view_menu_style
== 0)
1563 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1564 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1565 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1569 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1570 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1571 dir_alias
, dir_class
, node
->dir
+ offset
);
1575 if (g_tree_view_menu_style
== 0)
1577 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1578 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1579 " echo 'return ...' \n"
1584 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1585 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1591 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1593 ventoy_dynamic_tree_menu(child
);
1596 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1598 if (g_tree_view_menu_style
== 0)
1600 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1601 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1604 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1605 img
->unsupport
? "[***********] " : "",
1606 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1608 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1612 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1613 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1616 img
->unsupport
? "[***********] " : "",
1617 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1619 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1623 if (node
!= &g_img_iterator_head
)
1625 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1632 int ventoy_check_device_result(int ret
)
1636 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1637 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1638 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1642 grub_printf(VTOY_WARNING
"\n");
1643 grub_printf(VTOY_WARNING
"\n");
1644 grub_printf(VTOY_WARNING
"\n\n\n");
1646 grub_printf("Unsatisfied conditions detected for Ventoy.\n\n");
1647 grub_printf("This is NOT a standard Ventoy device and is NOT officially supported.\n\n");
1648 grub_printf("Recommend to follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1650 grub_printf("\n\nWill exit after 10 seconds ...... ");
1658 int ventoy_check_device(grub_device_t dev
)
1661 grub_uint64_t offset
;
1666 struct grub_partition
*partition
;
1668 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1670 return ventoy_check_device_result(1 | 0x1000);
1673 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1674 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1675 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_64", dev
->disk
->name
))
1677 return ventoy_check_device_result(2 | 0x1000);
1680 /* We must have partition 2 */
1681 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1684 return ventoy_check_device_result(3 | 0x1000);
1687 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1689 grub_file_close(file
);
1690 return ventoy_check_device_result(4 | 0x1000);
1693 partition
= dev
->disk
->partition
;
1694 if (partition
->number
!= 0 || partition
->start
!= 2048)
1696 return ventoy_check_device_result(5);
1699 offset
= partition
->start
+ partition
->len
;
1700 partition
= file
->device
->disk
->partition
;
1701 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1703 grub_file_close(file
);
1704 return ventoy_check_device_result(6);
1706 grub_file_close(file
);
1708 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1709 dev2
= grub_device_open(devname
);
1712 return ventoy_check_device_result(7);
1715 fs
= grub_fs_probe(dev2
);
1718 grub_device_close(dev2
);
1719 return ventoy_check_device_result(8);
1722 fs
->fs_label(dev2
, &label
);
1723 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1725 grub_device_close(dev2
);
1726 return ventoy_check_device_result(9);
1729 grub_device_close(dev2
);
1730 return ventoy_check_device_result(0);
1733 static int ventoy_set_default_menu(void)
1739 const char *strdata
= NULL
;
1740 img_info
*cur
= NULL
;
1741 img_info
*default_node
= NULL
;
1742 const char *default_image
= NULL
;
1744 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1745 if (default_image
&& default_image
[0] == '/')
1747 img_len
= grub_strlen(default_image
);
1749 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1751 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1763 if (0 == g_default_menu_mode
)
1765 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1769 def
= grub_strdup(default_image
);
1775 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1777 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1778 if (strdata
&& strdata
[0] == '/')
1780 pos
= def
+ grub_strlen(strdata
);
1793 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1796 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1800 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1808 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1812 grub_device_t dev
= NULL
;
1813 img_info
*cur
= NULL
;
1814 img_info
*tail
= NULL
;
1815 const char *strdata
= NULL
;
1816 char *device_name
= NULL
;
1818 img_iterator_node
*node
= NULL
;
1819 img_iterator_node
*tmp
= NULL
;
1825 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1828 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1830 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1833 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1834 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1836 g_filt_dot_underscore_file
= 1;
1839 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
1840 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1842 g_sort_case_sensitive
= 1;
1845 device_name
= grub_file_get_device_name(args
[0]);
1851 g_enum_dev
= dev
= grub_device_open(device_name
);
1857 g_enum_fs
= fs
= grub_fs_probe(dev
);
1863 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1865 debug("unsupported fs:<%s>\n", fs
->name
);
1866 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1870 ventoy_set_env("vtoy_iso_fs", fs
->name
);
1872 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1873 if (strdata
&& strdata
[0] == '1')
1875 g_default_menu_mode
= 1;
1878 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1880 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1882 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1883 if (0 == g_plugin_image_list
&& strdata
&& strdata
[0] == '/')
1885 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1886 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1888 g_img_iterator_head
.dir
[len
++] = '/';
1890 g_img_iterator_head
.dirlen
= len
;
1894 g_img_iterator_head
.dirlen
= 1;
1895 grub_strcpy(g_img_iterator_head
.dir
, "/");
1898 g_img_iterator_head
.tail
= &tail
;
1900 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1902 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1905 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
1906 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1908 g_tree_view_menu_style
= 1;
1911 ventoy_set_default_menu();
1913 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1915 ventoy_dynamic_tree_menu(node
);
1919 node
= g_img_iterator_head
.next
;
1927 /* sort image list by image name if image_list is not set in ventoy.json */
1928 if (0 == g_plugin_image_list
)
1930 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1932 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1934 if (ventoy_cmp_img(cur
, tail
) > 0)
1936 ventoy_swap_img(cur
, tail
);
1942 if (g_default_menu_mode
== 1)
1944 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1945 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1946 " echo 'return ...' \n"
1950 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1952 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1953 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1956 cur
->unsupport
? "[***********] " : "",
1957 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1959 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1962 g_tree_script_buf
[g_tree_script_pos
] = 0;
1963 g_list_script_buf
[g_list_script_pos
] = 0;
1965 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1966 grub_env_set(args
[1], buf
);
1970 check_free(device_name
, grub_free
);
1971 check_free(dev
, grub_device_close
);
1973 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1977 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1979 img_info
*next
= NULL
;
1980 img_info
*cur
= g_ventoy_img_list
;
1993 g_ventoy_img_list
= NULL
;
1994 g_ventoy_img_count
= 0;
1996 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1999 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2002 img_info
*cur
= g_ventoy_img_list
;
2006 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2008 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2011 img_id
= grub_strtol(args
[0], NULL
, 10);
2012 if (img_id
>= g_ventoy_img_count
)
2014 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2017 debug("Find image %ld name \n", img_id
);
2019 while (cur
&& img_id
> 0)
2027 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2030 debug("image name is %s\n", cur
->name
);
2032 grub_env_set(args
[1], cur
->name
);
2034 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2037 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2042 const char *id
= NULL
;
2043 img_info
*cur
= g_ventoy_img_list
;
2047 if (argc
< 1 || argc
> 2)
2049 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2052 id
= grub_env_get("chosen");
2054 pos
= grub_strstr(id
, "VID_");
2057 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2061 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2066 if (img_id
== cur
->id
)
2075 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2078 grub_env_set(args
[0], cur
->path
);
2082 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2083 grub_env_set(args
[1], value
);
2086 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2089 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2096 device_name
= grub_file_get_device_name(filename
);
2108 pos2
= grub_strstr(pos
, ",");
2111 pos2
= grub_strstr(pos
, ")");
2119 disk
= grub_disk_open(pos
);
2122 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2123 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2124 grub_disk_close(disk
);
2131 grub_free(device_name
);
2135 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2137 eltorito_descriptor desc
;
2139 grub_memset(&desc
, 0, sizeof(desc
));
2140 grub_file_seek(file
, 17 * 2048);
2141 grub_file_read(file
, &desc
, sizeof(desc
));
2143 if (desc
.type
!= 0 || desc
.version
!= 1)
2148 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2149 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2157 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2161 grub_uint8_t buf
[512];
2163 grub_file_seek(file
, sector
* 2048);
2164 grub_file_read(file
, buf
, sizeof(buf
));
2166 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2168 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2172 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2177 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2179 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2181 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2185 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2187 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2192 debug("%s does not contain efi eltorito\n", file
->name
);
2196 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2199 const char *fs
= NULL
;
2200 const char *cdprompt
= NULL
;
2202 grub_uint8_t chksum
= 0;
2205 disk
= file
->device
->disk
;
2206 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2208 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2209 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2210 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2212 pos
= grub_strstr(file
->name
, "/");
2218 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2220 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2222 param
->vtoy_img_size
= file
->size
;
2224 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2225 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2227 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2229 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2230 param
->vtoy_reserved
[4] = 0;
2231 if (g_ventoy_chain_type
== 1) /* Windows */
2233 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2234 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2236 param
->vtoy_reserved
[4] = 1;
2240 fs
= ventoy_get_env("ventoy_fs_probe");
2241 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2243 param
->vtoy_reserved
[3] = 1;
2246 /* calculate checksum */
2247 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2249 chksum
+= *((grub_uint8_t
*)param
+ i
);
2251 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2256 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2258 grub_uint32_t i
= 0;
2259 grub_uint64_t total
= 0;
2260 ventoy_img_chunk
*chunk
= NULL
;
2262 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2264 chunk
= chunklist
->chunk
+ i
;
2266 if (chunk
->disk_start_sector
<= start
)
2268 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2272 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2275 if (total
!= ((file
->size
+ 511) / 512))
2277 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2284 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2288 grub_uint32_t i
= 0;
2289 grub_uint32_t sector
= 0;
2290 grub_uint32_t count
= 0;
2291 grub_off_t size
= 0;
2292 grub_off_t read
= 0;
2294 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2295 if (fs_type
== ventoy_fs_exfat
)
2297 grub_fat_get_file_chunk(start
, file
, chunklist
);
2299 else if (fs_type
== ventoy_fs_ext
)
2301 grub_ext_get_file_chunk(start
, file
, chunklist
);
2305 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2306 file
->read_hook_data
= chunklist
;
2308 for (size
= file
->size
; size
> 0; size
-= read
)
2310 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2311 grub_file_read(file
, NULL
, read
);
2314 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2316 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2317 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2320 if (ventoy_fs_udf
== fs_type
)
2322 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2324 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2325 chunklist
->chunk
[i
].img_start_sector
= sector
;
2326 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2332 len
= (int)grub_strlen(file
->name
);
2333 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2334 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2335 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2336 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2338 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2340 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2350 chunklist
->chunk
[i
].img_start_sector
= sector
;
2351 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2359 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2363 grub_disk_addr_t start
;
2368 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2371 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2374 if (g_img_chunk_list
.chunk
)
2376 grub_free(g_img_chunk_list
.chunk
);
2379 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2381 grub_file_close(file
);
2382 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2385 /* get image chunk data */
2386 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2387 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2388 if (NULL
== g_img_chunk_list
.chunk
)
2390 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2393 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2394 g_img_chunk_list
.cur_chunk
= 0;
2396 start
= file
->device
->disk
->partition
->start
;
2398 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2400 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2401 grub_file_close(file
);
2405 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2408 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2409 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2412 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2417 char configfile
[128];
2418 install_template
*node
= NULL
;
2424 debug("select auto installation argc:%d\n", argc
);
2431 node
= ventoy_plugin_find_install_template(args
[0]);
2434 debug("Auto install template not found for %s\n", args
[0]);
2438 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2440 node
->cursel
= node
->autosel
- 1;
2441 debug("Auto install template auto select %d\n", node
->autosel
);
2445 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2451 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2452 " echo %s\n}\n", "123");
2454 for (i
= 0; i
< node
->templatenum
; i
++)
2456 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2458 node
->templatepath
[i
].path
);
2461 g_ventoy_menu_esc
= 1;
2462 g_ventoy_suppress_esc
= 1;
2464 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2465 grub_script_execute_sourcecode(configfile
);
2467 g_ventoy_menu_esc
= 0;
2468 g_ventoy_suppress_esc
= 0;
2472 node
->cursel
= g_ventoy_last_entry
- 1;
2474 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2477 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2482 char configfile
[128];
2483 persistence_config
*node
;
2489 debug("select persistence argc:%d\n", argc
);
2496 node
= ventoy_plugin_find_persistent(args
[0]);
2499 debug("Persistence image not found for %s\n", args
[0]);
2503 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2505 node
->cursel
= node
->autosel
- 1;
2506 debug("Persistence image auto select %d\n", node
->autosel
);
2510 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2516 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2517 " echo %s\n}\n", "123");
2519 for (i
= 0; i
< node
->backendnum
; i
++)
2521 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2523 node
->backendpath
[i
].path
);
2527 g_ventoy_menu_esc
= 1;
2528 g_ventoy_suppress_esc
= 1;
2530 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2531 grub_script_execute_sourcecode(configfile
);
2533 g_ventoy_menu_esc
= 0;
2534 g_ventoy_suppress_esc
= 0;
2538 node
->cursel
= g_ventoy_last_entry
- 1;
2540 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2543 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2546 ventoy_img_chunk
*cur
;
2552 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2554 cur
= g_img_chunk_list
.chunk
+ i
;
2555 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2556 cur
->img_start_sector
, cur
->img_end_sector
,
2557 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2561 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2564 #ifdef GRUB_MACHINE_EFI
2565 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2573 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2576 ulong chain_len
= 0;
2577 char *chain_data
= NULL
;
2578 char *relocator_addr
= NULL
;
2579 grub_relocator_chunk_t ch
;
2580 struct grub_relocator
*relocator
= NULL
;
2581 char envbuf
[64] = { 0 };
2592 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2593 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2595 relocator
= grub_relocator_new ();
2598 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2602 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2603 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2607 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2608 grub_relocator_unload (relocator
);
2612 relocator_addr
= get_virtual_current_address(ch
);
2614 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2616 grub_relocator_unload (relocator
);
2618 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2619 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2621 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2625 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2629 ventoy_img_chunk_list chunklist
;
2634 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2637 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2640 /* get image chunk data */
2641 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2642 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2643 if (NULL
== chunklist
.chunk
)
2645 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2648 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2649 chunklist
.cur_chunk
= 0;
2651 ventoy_get_block_list(file
, &chunklist
, 0);
2653 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2655 grub_printf("########## UNSUPPORTED ###############\n");
2658 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2660 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2662 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2663 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2666 grub_printf("\n==================================\n");
2668 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2670 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2671 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2672 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2673 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2674 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2678 grub_free(chunklist
.chunk
);
2679 grub_file_close(file
);
2681 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2684 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2687 ventoy_grub_param_file_replace
*replace
= NULL
;
2695 replace
= &(g_grub_param
->file_replace
);
2696 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2698 replace
->old_name_cnt
= 0;
2699 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2701 replace
->old_name_cnt
++;
2702 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2705 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2708 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2711 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2719 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2720 grub_printf("%s", g_list_script_buf
);
2724 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2725 grub_printf("%s", g_tree_script_buf
);
2731 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2733 img_info
*cur
= g_ventoy_img_list
;
2741 grub_printf("path:<%s> id=%d\n", cur
->path
, cur
->id
);
2742 grub_printf("name:<%s>\n\n", cur
->name
);
2749 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2755 ventoy_plugin_dump_injection();
2760 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2766 ventoy_plugin_dump_auto_install();
2771 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2777 ventoy_plugin_dump_persistence();
2782 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2793 if (args
[0][0] == '0')
2795 return g_ventoy_memdisk_mode
? 0 : 1;
2797 else if (args
[0][0] == '1')
2799 return g_ventoy_iso_raw
? 0 : 1;
2801 else if (args
[0][0] == '2')
2803 return g_ventoy_iso_uefi_drv
? 0 : 1;
2809 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2811 static int configfile_mode
= 0;
2812 char memfile
[128] = {0};
2819 * args[0]: 0:normal 1:configfile
2820 * args[1]: 0:list_buf 1:tree_buf
2825 debug("Invalid argc %d\n", argc
);
2829 if (args
[0][0] == '0')
2831 if (args
[1][0] == '0')
2833 grub_script_execute_sourcecode(g_list_script_buf
);
2837 grub_script_execute_sourcecode(g_tree_script_buf
);
2842 if (configfile_mode
)
2844 debug("Now already in F3 mode %d\n", configfile_mode
);
2848 if (args
[1][0] == '0')
2850 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2851 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2855 g_ventoy_last_entry
= -1;
2856 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2857 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2860 configfile_mode
= 1;
2861 grub_script_execute_sourcecode(memfile
);
2862 configfile_mode
= 0;
2868 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2879 g_ventoy_case_insensitive
= 1;
2880 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2881 g_ventoy_case_insensitive
= 0;
2887 grub_file_close(file
);
2893 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2898 const char *isopath
= NULL
;
2900 ventoy_mbr_head mbr
;
2907 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2910 isopath
= grub_env_get("vtoy_iso_part");
2913 debug("isopath is null %p\n", isopath
);
2917 debug("isopath is %s\n", isopath
);
2919 for (id
= 0; id
< 30 && (find
== 0); id
++)
2921 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2922 if (grub_strstr(isopath
, hdname
))
2924 debug("skip %s ...\n", hdname
);
2928 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2930 disk
= grub_disk_open(hdname
);
2933 debug("%s not exist\n", hdname
);
2937 grub_memset(&mbr
, 0, sizeof(mbr
));
2938 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2940 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2942 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2943 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2946 grub_env_set(args
[0], hdname
);
2950 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2954 debug("read %s failed\n", hdname
);
2957 grub_disk_close(disk
);
2963 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2974 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2977 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2980 debug("failed to open file %s\n", args
[0]);
2984 buf
= grub_malloc(len
);
2991 grub_file_read(file
, buf
, len
- 1);
2993 ventoy_get_line(buf
);
2994 ventoy_set_env(args
[1], buf
);
2998 grub_check_free(buf
);
2999 grub_file_close(file
);
3004 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3009 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3010 "0 %llu linear /dev/ventoy %llu\n",
3011 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3016 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3018 char *device_name
= NULL
;
3019 grub_device_t dev
= NULL
;
3024 g_part_list_pos
= 0;
3025 grub_env_unset("vtoy_img_part_file");
3032 device_name
= grub_file_get_device_name(args
[0]);
3035 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3039 dev
= grub_device_open(device_name
);
3042 debug("grub_device_open failed, %s\n", device_name
);
3046 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3048 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3049 grub_env_set("vtoy_img_part_file", buf
);
3053 check_free(device_name
, grub_free
);
3054 check_free(dev
, grub_device_close
);
3060 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3071 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3074 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3077 debug("failed to open file %s\n", args
[0]);
3081 buf
= grub_malloc(file
->size
+ 1);
3087 buf
[file
->size
] = 0;
3088 grub_file_read(file
, buf
, file
->size
);
3090 if (grub_strstr(buf
, args
[1]))
3097 grub_check_free(buf
);
3098 grub_file_close(file
);
3103 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3108 ventoy_iso9660_vd pvd
;
3115 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
3118 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3121 debug("failed to open file %s\n", args
[0]);
3125 grub_file_seek(file
, 16 * 2048);
3126 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3127 if (len
!= sizeof(pvd
))
3129 debug("failed to read pvd %d\n", len
);
3133 grub_memset(buf
, 0, sizeof(buf
));
3134 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3135 ventoy_set_env(args
[1], buf
);
3137 grub_memset(buf
, 0, sizeof(buf
));
3138 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3139 ventoy_set_env(args
[2], buf
);
3142 grub_file_close(file
);
3147 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3158 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3161 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3164 debug("failed to open file %s\n", args
[0]);
3168 grub_memset(buf
, 0, sizeof(buf
));
3169 grub_file_seek(file
, 16 * 2048 + 813);
3170 len
= (int)grub_file_read(file
, buf
, 17);
3173 debug("failed to read create date %d\n", len
);
3177 ventoy_set_env(args
[1], buf
);
3180 grub_file_close(file
);
3185 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3191 ventoy_env_hook_root(1);
3196 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3202 ventoy_env_hook_root(0);
3207 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3214 int image_sector_size
;
3216 ventoy_chain_head
*chain
;
3217 ventoy_img_chunk
*chunk
;
3218 ventoy_os_param
*osparam
;
3219 ventoy_image_location
*location
;
3220 ventoy_image_disk_region
*region
;
3221 struct grub_acpi_table_header
*acpi
;
3230 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3232 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3238 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3240 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3242 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3246 img_chunk_num
= chain
->img_chunk_num
;
3248 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3249 datalen
= sizeof(ventoy_os_param
) + loclen
;
3251 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3252 acpi
= grub_zalloc(buflen
);
3258 /* Step1: Fill acpi table header */
3259 grub_memcpy(acpi
->signature
, "VTOY", 4);
3260 acpi
->length
= buflen
;
3262 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3263 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3265 acpi
->creator_id
[0] = 1;
3266 acpi
->creator_rev
= 1;
3268 /* Step2: Fill data */
3269 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3270 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3271 osparam
->vtoy_img_location_addr
= 0;
3272 osparam
->vtoy_img_location_len
= loclen
;
3273 osparam
->chksum
= 0;
3274 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3276 location
= (ventoy_image_location
*)(osparam
+ 1);
3277 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3278 location
->image_sector_size
= image_sector_size
;
3279 location
->disk_sector_size
= chain
->disk_sector_size
;
3280 location
->region_count
= img_chunk_num
;
3282 region
= location
->regions
;
3283 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3284 if (512 == image_sector_size
)
3286 for (i
= 0; i
< img_chunk_num
; i
++)
3288 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3289 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3290 region
->disk_start_sector
= chunk
->disk_start_sector
;
3297 for (i
= 0; i
< img_chunk_num
; i
++)
3299 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3300 region
->image_start_sector
= chunk
->img_start_sector
;
3301 region
->disk_start_sector
= chunk
->disk_start_sector
;
3307 /* Step3: Fill acpi checksum */
3309 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3311 /* load acpi table */
3312 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3313 grub_script_execute_sourcecode(cmd
);
3317 VENTOY_CMD_RETURN(0);
3320 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3326 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3327 g_ventoy_last_entry
= -1;
3332 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3338 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3343 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3345 const char *pos
= filename
+ 1;
3353 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3355 grub_strncpy((char *)data
, filename
, 128);
3366 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3369 char *device_name
= NULL
;
3370 grub_device_t dev
= NULL
;
3371 grub_fs_t fs
= NULL
;
3372 char buf
[128] = {0};
3378 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3382 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3384 device_name
= grub_file_get_device_name(args
[0]);
3387 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3391 dev
= grub_device_open(device_name
);
3394 debug("grub_device_open failed, %s\n", device_name
);
3398 fs
= grub_fs_probe(dev
);
3401 debug("grub_fs_probe failed, %s\n", device_name
);
3405 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3409 ventoy_set_env(args
[2], buf
);
3416 check_free(device_name
, grub_free
);
3417 check_free(dev
, grub_device_close
);
3422 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3432 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3433 if (!g_ventoy_part_info
)
3438 disk
= grub_disk_open(args
[0]);
3441 debug("Failed to open disk %s\n", args
[0]);
3445 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3446 grub_disk_close(disk
);
3448 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3449 dev
= grub_device_open(name
);
3452 /* make sure that we are running in a correct Ventoy device */
3453 ret
= ventoy_check_device(dev
);
3454 grub_device_close(dev
);
3465 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3468 grub_uint8_t zeroguid
[16] = {0};
3473 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3476 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3478 if (id
>= 1 && id
<= 128)
3480 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3488 if (id
>= 1 && id
<= 4)
3490 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3500 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3503 char *device_name
= NULL
;
3504 grub_device_t dev
= NULL
;
3505 grub_fs_t fs
= NULL
;
3512 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3516 device_name
= grub_file_get_device_name(args
[0]);
3519 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3523 dev
= grub_device_open(device_name
);
3526 debug("grub_device_open failed, %s\n", device_name
);
3530 fs
= grub_fs_probe(dev
);
3533 debug("grub_fs_probe failed, %s\n", device_name
);
3537 fs
->fs_label(dev
, &label
);
3540 ventoy_set_env(args
[1], label
);
3548 check_free(device_name
, grub_free
);
3549 check_free(dev
, grub_device_close
);
3554 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3558 grub_snprintf((char *)data
, 256, "%s", filename
);
3566 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3569 char *device_name
= NULL
;
3570 grub_device_t dev
= NULL
;
3571 grub_fs_t fs
= NULL
;
3572 char name
[256] ={0};
3578 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3582 device_name
= grub_file_get_device_name(args
[0]);
3585 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3589 dev
= grub_device_open(device_name
);
3592 debug("grub_device_open failed, %s\n", device_name
);
3596 fs
= grub_fs_probe(dev
);
3599 debug("grub_fs_probe failed, %s\n", device_name
);
3603 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3606 ventoy_set_env(args
[2], name
);
3613 check_free(device_name
, grub_free
);
3614 check_free(dev
, grub_device_close
);
3619 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3629 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3633 for (pos
= args
[0]; *pos
; pos
++)
3647 grub_env_set(args
[1], args
[0]);
3657 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3659 struct grub_video_mode_info info
;
3666 if (!g_video_mode_list
)
3668 ventoy_enum_video_mode();
3671 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3673 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3677 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3680 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3682 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3683 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3685 VENTOY_CMD_RETURN(0);
3688 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3690 struct grub_video_mode_info info
;
3697 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3699 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3703 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3706 grub_env_set(args
[0], buf
);
3708 VENTOY_CMD_RETURN(0);
3711 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3719 if (!g_video_mode_list
)
3724 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3725 if (id
< g_video_mode_num
)
3727 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
3728 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
3731 grub_env_set(args
[1], buf
);
3733 VENTOY_CMD_RETURN(0);
3736 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
3738 grub_uint64_t size
= 0;
3741 char fullpath
[256] = {0};
3744 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3747 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
3750 debug("grub_file_open failed <%s>\n", fullpath
);
3756 grub_file_close(file
);
3760 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
3764 char fullpath
[256] = {0};
3767 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3770 file
= grub_file_open(fullpath
, type
);
3773 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
3780 int ventoy_is_file_exist(const char *fmt
, ...)
3785 char buf
[256] = {0};
3787 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
3791 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3794 grub_strncpy(pos
+ len
, " ]", 2);
3796 debug("script exec %s\n", buf
);
3798 if (0 == grub_script_execute_sourcecode(buf
))
3806 int ventoy_is_dir_exist(const char *fmt
, ...)
3811 char buf
[256] = {0};
3813 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
3817 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3820 grub_strncpy(pos
+ len
, " ]", 2);
3822 debug("script exec %s\n", buf
);
3824 if (0 == grub_script_execute_sourcecode(buf
))
3832 static int ventoy_env_init(void)
3836 grub_env_set("vtdebug_flag", "");
3838 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
3839 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3840 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3842 ventoy_filt_register(0, ventoy_wrapper_open
);
3844 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
3847 g_grub_param
->grub_env_get
= grub_env_get
;
3848 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
3849 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
3850 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
3851 grub_env_set("env_param", buf
);
3852 grub_env_set("ventoy_env_param", buf
);
3853 grub_env_export("ventoy_env_param");
3859 static cmd_para ventoy_cmds
[] =
3861 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
3862 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
3863 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
3864 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3865 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3866 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
3867 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
3868 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
3869 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
3870 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
3871 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
3872 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
3873 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
3874 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
3875 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
3876 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
3877 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
3878 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
3879 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
3880 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
3882 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
3883 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
3884 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
3885 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
3886 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
3887 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
3889 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
3890 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
3891 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
3892 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
3893 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
3894 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
3895 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
3896 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
3899 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
3900 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
3901 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
3902 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
3903 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
3904 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
3905 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
3906 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
3907 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
3908 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
3910 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
3911 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
3912 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
3913 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
3914 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
3915 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
3917 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3918 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3919 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
3920 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
3921 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
3922 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
3923 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
3924 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
3925 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
3926 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
3928 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
3929 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
3930 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
3931 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
3932 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
3933 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
3934 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
3936 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
3937 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
3938 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
3939 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
3942 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
3943 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
3945 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
3946 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
3947 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
3950 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
3951 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
3952 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
3953 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
3954 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
3955 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
3956 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
3957 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
3959 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
3960 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
3961 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
3967 GRUB_MOD_INIT(ventoy
)
3970 cmd_para
*cur
= NULL
;
3974 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3976 cur
= ventoy_cmds
+ i
;
3977 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
3978 cur
->summary
, cur
->description
, cur
->parser
);
3982 GRUB_MOD_FINI(ventoy
)
3986 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3988 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);