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 img_info
*cur
= NULL
;
1740 img_info
*default_node
= NULL
;
1741 const char *default_image
= NULL
;
1743 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1744 if (default_image
&& default_image
[0] == '/')
1746 img_len
= grub_strlen(default_image
);
1748 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1750 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1762 if (0 == g_default_menu_mode
)
1764 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1768 def
= grub_strdup(default_image
);
1774 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1777 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1780 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1784 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1792 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1796 grub_device_t dev
= NULL
;
1797 img_info
*cur
= NULL
;
1798 img_info
*tail
= NULL
;
1799 const char *strdata
= NULL
;
1800 char *device_name
= NULL
;
1802 img_iterator_node
*node
= NULL
;
1803 img_iterator_node
*tmp
= NULL
;
1809 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1812 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1814 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1817 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1818 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1820 g_filt_dot_underscore_file
= 1;
1823 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
1824 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1826 g_sort_case_sensitive
= 1;
1829 device_name
= grub_file_get_device_name(args
[0]);
1835 g_enum_dev
= dev
= grub_device_open(device_name
);
1841 g_enum_fs
= fs
= grub_fs_probe(dev
);
1847 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1849 debug("unsupported fs:<%s>\n", fs
->name
);
1850 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1854 ventoy_set_env("vtoy_iso_fs", fs
->name
);
1856 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1857 if (strdata
&& strdata
[0] == '1')
1859 g_default_menu_mode
= 1;
1862 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1864 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1866 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1867 if (0 == g_plugin_image_list
&& strdata
&& strdata
[0] == '/')
1869 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1870 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1872 g_img_iterator_head
.dir
[len
++] = '/';
1874 g_img_iterator_head
.dirlen
= len
;
1878 g_img_iterator_head
.dirlen
= 1;
1879 grub_strcpy(g_img_iterator_head
.dir
, "/");
1882 g_img_iterator_head
.tail
= &tail
;
1884 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1886 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1889 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
1890 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1892 g_tree_view_menu_style
= 1;
1895 ventoy_set_default_menu();
1897 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1899 ventoy_dynamic_tree_menu(node
);
1903 node
= g_img_iterator_head
.next
;
1911 /* sort image list by image name if image_list is not set in ventoy.json */
1912 if (0 == g_plugin_image_list
)
1914 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1916 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1918 if (ventoy_cmp_img(cur
, tail
) > 0)
1920 ventoy_swap_img(cur
, tail
);
1926 if (g_default_menu_mode
== 1)
1928 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1929 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1930 " echo 'return ...' \n"
1934 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1936 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1937 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1940 cur
->unsupport
? "[***********] " : "",
1941 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1943 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1946 g_tree_script_buf
[g_tree_script_pos
] = 0;
1947 g_list_script_buf
[g_list_script_pos
] = 0;
1949 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1950 grub_env_set(args
[1], buf
);
1954 check_free(device_name
, grub_free
);
1955 check_free(dev
, grub_device_close
);
1957 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1961 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1963 img_info
*next
= NULL
;
1964 img_info
*cur
= g_ventoy_img_list
;
1977 g_ventoy_img_list
= NULL
;
1978 g_ventoy_img_count
= 0;
1980 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1983 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1986 img_info
*cur
= g_ventoy_img_list
;
1990 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1992 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1995 img_id
= grub_strtol(args
[0], NULL
, 10);
1996 if (img_id
>= g_ventoy_img_count
)
1998 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2001 debug("Find image %ld name \n", img_id
);
2003 while (cur
&& img_id
> 0)
2011 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2014 debug("image name is %s\n", cur
->name
);
2016 grub_env_set(args
[1], cur
->name
);
2018 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2021 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2026 const char *id
= NULL
;
2027 img_info
*cur
= g_ventoy_img_list
;
2031 if (argc
< 1 || argc
> 2)
2033 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2036 id
= grub_env_get("chosen");
2038 pos
= grub_strstr(id
, "VID_");
2041 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2045 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2050 if (img_id
== cur
->id
)
2059 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2062 grub_env_set(args
[0], cur
->path
);
2066 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2067 grub_env_set(args
[1], value
);
2070 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2073 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2080 device_name
= grub_file_get_device_name(filename
);
2092 pos2
= grub_strstr(pos
, ",");
2095 pos2
= grub_strstr(pos
, ")");
2103 disk
= grub_disk_open(pos
);
2106 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2107 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2108 grub_disk_close(disk
);
2115 grub_free(device_name
);
2119 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2121 eltorito_descriptor desc
;
2123 grub_memset(&desc
, 0, sizeof(desc
));
2124 grub_file_seek(file
, 17 * 2048);
2125 grub_file_read(file
, &desc
, sizeof(desc
));
2127 if (desc
.type
!= 0 || desc
.version
!= 1)
2132 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2133 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2141 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2145 grub_uint8_t buf
[512];
2147 grub_file_seek(file
, sector
* 2048);
2148 grub_file_read(file
, buf
, sizeof(buf
));
2150 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2152 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2156 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2161 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2163 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2165 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2169 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2171 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2176 debug("%s does not contain efi eltorito\n", file
->name
);
2180 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2183 const char *fs
= NULL
;
2184 const char *cdprompt
= NULL
;
2186 grub_uint8_t chksum
= 0;
2189 disk
= file
->device
->disk
;
2190 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2192 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2193 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2194 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2196 pos
= grub_strstr(file
->name
, "/");
2202 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2204 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2206 param
->vtoy_img_size
= file
->size
;
2208 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2209 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2211 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2213 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2214 param
->vtoy_reserved
[4] = 0;
2215 if (g_ventoy_chain_type
== 1) /* Windows */
2217 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2218 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2220 param
->vtoy_reserved
[4] = 1;
2224 fs
= ventoy_get_env("ventoy_fs_probe");
2225 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2227 param
->vtoy_reserved
[3] = 1;
2230 /* calculate checksum */
2231 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2233 chksum
+= *((grub_uint8_t
*)param
+ i
);
2235 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2240 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2242 grub_uint32_t i
= 0;
2243 grub_uint64_t total
= 0;
2244 ventoy_img_chunk
*chunk
= NULL
;
2246 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2248 chunk
= chunklist
->chunk
+ i
;
2250 if (chunk
->disk_start_sector
<= start
)
2252 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2256 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2259 if (total
!= ((file
->size
+ 511) / 512))
2261 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2268 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2272 grub_uint32_t i
= 0;
2273 grub_uint32_t sector
= 0;
2274 grub_uint32_t count
= 0;
2275 grub_off_t size
= 0;
2276 grub_off_t read
= 0;
2278 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2279 if (fs_type
== ventoy_fs_exfat
)
2281 grub_fat_get_file_chunk(start
, file
, chunklist
);
2283 else if (fs_type
== ventoy_fs_ext
)
2285 grub_ext_get_file_chunk(start
, file
, chunklist
);
2289 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2290 file
->read_hook_data
= chunklist
;
2292 for (size
= file
->size
; size
> 0; size
-= read
)
2294 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2295 grub_file_read(file
, NULL
, read
);
2298 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2300 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2301 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2304 if (ventoy_fs_udf
== fs_type
)
2306 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2308 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2309 chunklist
->chunk
[i
].img_start_sector
= sector
;
2310 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2316 len
= (int)grub_strlen(file
->name
);
2317 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2318 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2319 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2320 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2322 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2324 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2334 chunklist
->chunk
[i
].img_start_sector
= sector
;
2335 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2343 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2347 grub_disk_addr_t start
;
2352 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2355 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2358 if (g_img_chunk_list
.chunk
)
2360 grub_free(g_img_chunk_list
.chunk
);
2363 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2365 grub_file_close(file
);
2366 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2369 /* get image chunk data */
2370 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2371 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2372 if (NULL
== g_img_chunk_list
.chunk
)
2374 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2377 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2378 g_img_chunk_list
.cur_chunk
= 0;
2380 start
= file
->device
->disk
->partition
->start
;
2382 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2384 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2385 grub_file_close(file
);
2389 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2392 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2393 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2396 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2401 char configfile
[128];
2402 install_template
*node
= NULL
;
2408 debug("select auto installation argc:%d\n", argc
);
2415 node
= ventoy_plugin_find_install_template(args
[0]);
2418 debug("Auto install template not found for %s\n", args
[0]);
2422 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2424 node
->cursel
= node
->autosel
- 1;
2425 debug("Auto install template auto select %d\n", node
->autosel
);
2429 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2435 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2436 " echo %s\n}\n", "123");
2438 for (i
= 0; i
< node
->templatenum
; i
++)
2440 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2442 node
->templatepath
[i
].path
);
2445 g_ventoy_menu_esc
= 1;
2446 g_ventoy_suppress_esc
= 1;
2448 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2449 grub_script_execute_sourcecode(configfile
);
2451 g_ventoy_menu_esc
= 0;
2452 g_ventoy_suppress_esc
= 0;
2456 node
->cursel
= g_ventoy_last_entry
- 1;
2458 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2461 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2466 char configfile
[128];
2467 persistence_config
*node
;
2473 debug("select persistence argc:%d\n", argc
);
2480 node
= ventoy_plugin_find_persistent(args
[0]);
2483 debug("Persistence image not found for %s\n", args
[0]);
2487 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2489 node
->cursel
= node
->autosel
- 1;
2490 debug("Persistence image auto select %d\n", node
->autosel
);
2494 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2500 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2501 " echo %s\n}\n", "123");
2503 for (i
= 0; i
< node
->backendnum
; i
++)
2505 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2507 node
->backendpath
[i
].path
);
2511 g_ventoy_menu_esc
= 1;
2512 g_ventoy_suppress_esc
= 1;
2514 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2515 grub_script_execute_sourcecode(configfile
);
2517 g_ventoy_menu_esc
= 0;
2518 g_ventoy_suppress_esc
= 0;
2522 node
->cursel
= g_ventoy_last_entry
- 1;
2524 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2527 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2530 ventoy_img_chunk
*cur
;
2536 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2538 cur
= g_img_chunk_list
.chunk
+ i
;
2539 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2540 cur
->img_start_sector
, cur
->img_end_sector
,
2541 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2545 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2548 #ifdef GRUB_MACHINE_EFI
2549 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2557 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2560 ulong chain_len
= 0;
2561 char *chain_data
= NULL
;
2562 char *relocator_addr
= NULL
;
2563 grub_relocator_chunk_t ch
;
2564 struct grub_relocator
*relocator
= NULL
;
2565 char envbuf
[64] = { 0 };
2576 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2577 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2579 relocator
= grub_relocator_new ();
2582 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2586 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2587 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2591 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2592 grub_relocator_unload (relocator
);
2596 relocator_addr
= get_virtual_current_address(ch
);
2598 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2600 grub_relocator_unload (relocator
);
2602 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2603 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2605 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2609 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2613 ventoy_img_chunk_list chunklist
;
2618 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2621 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2624 /* get image chunk data */
2625 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2626 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2627 if (NULL
== chunklist
.chunk
)
2629 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2632 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2633 chunklist
.cur_chunk
= 0;
2635 ventoy_get_block_list(file
, &chunklist
, 0);
2637 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2639 grub_printf("########## UNSUPPORTED ###############\n");
2642 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2644 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2646 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2647 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2650 grub_printf("\n==================================\n");
2652 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2654 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2655 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2656 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2657 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2658 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2662 grub_free(chunklist
.chunk
);
2663 grub_file_close(file
);
2665 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2668 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2671 ventoy_grub_param_file_replace
*replace
= NULL
;
2679 replace
= &(g_grub_param
->file_replace
);
2680 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2682 replace
->old_name_cnt
= 0;
2683 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2685 replace
->old_name_cnt
++;
2686 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2689 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2692 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2695 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2703 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2704 grub_printf("%s", g_list_script_buf
);
2708 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2709 grub_printf("%s", g_tree_script_buf
);
2715 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2717 img_info
*cur
= g_ventoy_img_list
;
2725 grub_printf("path:<%s> id=%d\n", cur
->path
, cur
->id
);
2726 grub_printf("name:<%s>\n\n", cur
->name
);
2733 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2739 ventoy_plugin_dump_injection();
2744 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2750 ventoy_plugin_dump_auto_install();
2755 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2761 ventoy_plugin_dump_persistence();
2766 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2777 if (args
[0][0] == '0')
2779 return g_ventoy_memdisk_mode
? 0 : 1;
2781 else if (args
[0][0] == '1')
2783 return g_ventoy_iso_raw
? 0 : 1;
2785 else if (args
[0][0] == '2')
2787 return g_ventoy_iso_uefi_drv
? 0 : 1;
2793 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2795 static int configfile_mode
= 0;
2796 char memfile
[128] = {0};
2803 * args[0]: 0:normal 1:configfile
2804 * args[1]: 0:list_buf 1:tree_buf
2809 debug("Invalid argc %d\n", argc
);
2813 if (args
[0][0] == '0')
2815 if (args
[1][0] == '0')
2817 grub_script_execute_sourcecode(g_list_script_buf
);
2821 grub_script_execute_sourcecode(g_tree_script_buf
);
2826 if (configfile_mode
)
2828 debug("Now already in F3 mode %d\n", configfile_mode
);
2832 if (args
[1][0] == '0')
2834 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2835 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2839 g_ventoy_last_entry
= -1;
2840 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2841 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2844 configfile_mode
= 1;
2845 grub_script_execute_sourcecode(memfile
);
2846 configfile_mode
= 0;
2852 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2863 g_ventoy_case_insensitive
= 1;
2864 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2865 g_ventoy_case_insensitive
= 0;
2871 grub_file_close(file
);
2877 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2882 const char *isopath
= NULL
;
2884 ventoy_mbr_head mbr
;
2891 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2894 isopath
= grub_env_get("vtoy_iso_part");
2897 debug("isopath is null %p\n", isopath
);
2901 debug("isopath is %s\n", isopath
);
2903 for (id
= 0; id
< 30 && (find
== 0); id
++)
2905 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2906 if (grub_strstr(isopath
, hdname
))
2908 debug("skip %s ...\n", hdname
);
2912 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2914 disk
= grub_disk_open(hdname
);
2917 debug("%s not exist\n", hdname
);
2921 grub_memset(&mbr
, 0, sizeof(mbr
));
2922 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2924 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2926 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2927 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2930 grub_env_set(args
[0], hdname
);
2934 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2938 debug("read %s failed\n", hdname
);
2941 grub_disk_close(disk
);
2947 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2958 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2961 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2964 debug("failed to open file %s\n", args
[0]);
2968 buf
= grub_malloc(len
);
2975 grub_file_read(file
, buf
, len
- 1);
2977 ventoy_get_line(buf
);
2978 ventoy_set_env(args
[1], buf
);
2982 grub_check_free(buf
);
2983 grub_file_close(file
);
2988 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
2993 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
2994 "0 %llu linear /dev/ventoy %llu\n",
2995 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3000 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3002 char *device_name
= NULL
;
3003 grub_device_t dev
= NULL
;
3008 g_part_list_pos
= 0;
3009 grub_env_unset("vtoy_img_part_file");
3016 device_name
= grub_file_get_device_name(args
[0]);
3019 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3023 dev
= grub_device_open(device_name
);
3026 debug("grub_device_open failed, %s\n", device_name
);
3030 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3032 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3033 grub_env_set("vtoy_img_part_file", buf
);
3037 check_free(device_name
, grub_free
);
3038 check_free(dev
, grub_device_close
);
3044 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3055 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3058 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3061 debug("failed to open file %s\n", args
[0]);
3065 buf
= grub_malloc(file
->size
+ 1);
3071 buf
[file
->size
] = 0;
3072 grub_file_read(file
, buf
, file
->size
);
3074 if (grub_strstr(buf
, args
[1]))
3081 grub_check_free(buf
);
3082 grub_file_close(file
);
3087 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3092 ventoy_iso9660_vd pvd
;
3099 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
3102 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3105 debug("failed to open file %s\n", args
[0]);
3109 grub_file_seek(file
, 16 * 2048);
3110 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3111 if (len
!= sizeof(pvd
))
3113 debug("failed to read pvd %d\n", len
);
3117 grub_memset(buf
, 0, sizeof(buf
));
3118 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3119 ventoy_set_env(args
[1], buf
);
3121 grub_memset(buf
, 0, sizeof(buf
));
3122 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3123 ventoy_set_env(args
[2], buf
);
3126 grub_file_close(file
);
3131 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3142 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3145 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3148 debug("failed to open file %s\n", args
[0]);
3152 grub_memset(buf
, 0, sizeof(buf
));
3153 grub_file_seek(file
, 16 * 2048 + 813);
3154 len
= (int)grub_file_read(file
, buf
, 17);
3157 debug("failed to read create date %d\n", len
);
3161 ventoy_set_env(args
[1], buf
);
3164 grub_file_close(file
);
3169 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3175 ventoy_env_hook_root(1);
3180 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3186 ventoy_env_hook_root(0);
3191 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3198 int image_sector_size
;
3200 ventoy_chain_head
*chain
;
3201 ventoy_img_chunk
*chunk
;
3202 ventoy_os_param
*osparam
;
3203 ventoy_image_location
*location
;
3204 ventoy_image_disk_region
*region
;
3205 struct grub_acpi_table_header
*acpi
;
3214 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3216 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3222 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3224 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3226 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3230 img_chunk_num
= chain
->img_chunk_num
;
3232 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3233 datalen
= sizeof(ventoy_os_param
) + loclen
;
3235 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3236 acpi
= grub_zalloc(buflen
);
3242 /* Step1: Fill acpi table header */
3243 grub_memcpy(acpi
->signature
, "VTOY", 4);
3244 acpi
->length
= buflen
;
3246 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3247 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3249 acpi
->creator_id
[0] = 1;
3250 acpi
->creator_rev
= 1;
3252 /* Step2: Fill data */
3253 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3254 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3255 osparam
->vtoy_img_location_addr
= 0;
3256 osparam
->vtoy_img_location_len
= loclen
;
3257 osparam
->chksum
= 0;
3258 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3260 location
= (ventoy_image_location
*)(osparam
+ 1);
3261 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3262 location
->image_sector_size
= image_sector_size
;
3263 location
->disk_sector_size
= chain
->disk_sector_size
;
3264 location
->region_count
= img_chunk_num
;
3266 region
= location
->regions
;
3267 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3268 if (512 == image_sector_size
)
3270 for (i
= 0; i
< img_chunk_num
; i
++)
3272 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3273 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3274 region
->disk_start_sector
= chunk
->disk_start_sector
;
3281 for (i
= 0; i
< img_chunk_num
; i
++)
3283 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3284 region
->image_start_sector
= chunk
->img_start_sector
;
3285 region
->disk_start_sector
= chunk
->disk_start_sector
;
3291 /* Step3: Fill acpi checksum */
3293 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3295 /* load acpi table */
3296 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3297 grub_script_execute_sourcecode(cmd
);
3301 VENTOY_CMD_RETURN(0);
3304 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3310 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3311 g_ventoy_last_entry
= -1;
3316 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3322 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3327 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3329 const char *pos
= filename
+ 1;
3337 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3339 grub_strncpy((char *)data
, filename
, 128);
3350 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3353 char *device_name
= NULL
;
3354 grub_device_t dev
= NULL
;
3355 grub_fs_t fs
= NULL
;
3356 char buf
[128] = {0};
3362 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3366 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3368 device_name
= grub_file_get_device_name(args
[0]);
3371 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3375 dev
= grub_device_open(device_name
);
3378 debug("grub_device_open failed, %s\n", device_name
);
3382 fs
= grub_fs_probe(dev
);
3385 debug("grub_fs_probe failed, %s\n", device_name
);
3389 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3393 ventoy_set_env(args
[2], buf
);
3400 check_free(device_name
, grub_free
);
3401 check_free(dev
, grub_device_close
);
3406 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3416 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3417 if (!g_ventoy_part_info
)
3422 disk
= grub_disk_open(args
[0]);
3425 debug("Failed to open disk %s\n", args
[0]);
3429 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3430 grub_disk_close(disk
);
3432 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3433 dev
= grub_device_open(name
);
3436 /* make sure that we are running in a correct Ventoy device */
3437 ret
= ventoy_check_device(dev
);
3438 grub_device_close(dev
);
3449 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3452 grub_uint8_t zeroguid
[16] = {0};
3457 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3460 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3462 if (id
>= 1 && id
<= 128)
3464 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3472 if (id
>= 1 && id
<= 4)
3474 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3484 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3487 char *device_name
= NULL
;
3488 grub_device_t dev
= NULL
;
3489 grub_fs_t fs
= NULL
;
3496 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3500 device_name
= grub_file_get_device_name(args
[0]);
3503 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3507 dev
= grub_device_open(device_name
);
3510 debug("grub_device_open failed, %s\n", device_name
);
3514 fs
= grub_fs_probe(dev
);
3517 debug("grub_fs_probe failed, %s\n", device_name
);
3521 fs
->fs_label(dev
, &label
);
3524 ventoy_set_env(args
[1], label
);
3532 check_free(device_name
, grub_free
);
3533 check_free(dev
, grub_device_close
);
3538 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3542 grub_snprintf((char *)data
, 256, "%s", filename
);
3550 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3553 char *device_name
= NULL
;
3554 grub_device_t dev
= NULL
;
3555 grub_fs_t fs
= NULL
;
3556 char name
[256] ={0};
3562 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3566 device_name
= grub_file_get_device_name(args
[0]);
3569 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3573 dev
= grub_device_open(device_name
);
3576 debug("grub_device_open failed, %s\n", device_name
);
3580 fs
= grub_fs_probe(dev
);
3583 debug("grub_fs_probe failed, %s\n", device_name
);
3587 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3590 ventoy_set_env(args
[2], name
);
3597 check_free(device_name
, grub_free
);
3598 check_free(dev
, grub_device_close
);
3603 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3613 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3617 for (pos
= args
[0]; *pos
; pos
++)
3631 grub_env_set(args
[1], args
[0]);
3641 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3643 struct grub_video_mode_info info
;
3650 if (!g_video_mode_list
)
3652 ventoy_enum_video_mode();
3655 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3657 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3661 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3664 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3666 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3667 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3669 VENTOY_CMD_RETURN(0);
3672 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3674 struct grub_video_mode_info info
;
3681 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3683 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3687 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3690 grub_env_set(args
[0], buf
);
3692 VENTOY_CMD_RETURN(0);
3695 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3703 if (!g_video_mode_list
)
3708 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3709 if (id
< g_video_mode_num
)
3711 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
3712 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
3715 grub_env_set(args
[1], buf
);
3717 VENTOY_CMD_RETURN(0);
3720 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
3722 grub_uint64_t size
= 0;
3725 char fullpath
[256] = {0};
3728 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3731 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
3734 debug("grub_file_open failed <%s>\n", fullpath
);
3740 grub_file_close(file
);
3744 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
3748 char fullpath
[256] = {0};
3751 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3754 file
= grub_file_open(fullpath
, type
);
3757 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
3764 int ventoy_is_file_exist(const char *fmt
, ...)
3769 char buf
[256] = {0};
3771 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
3775 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3778 grub_strncpy(pos
+ len
, " ]", 2);
3780 debug("script exec %s\n", buf
);
3782 if (0 == grub_script_execute_sourcecode(buf
))
3790 int ventoy_is_dir_exist(const char *fmt
, ...)
3795 char buf
[256] = {0};
3797 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
3801 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3804 grub_strncpy(pos
+ len
, " ]", 2);
3806 debug("script exec %s\n", buf
);
3808 if (0 == grub_script_execute_sourcecode(buf
))
3816 static int ventoy_env_init(void)
3820 grub_env_set("vtdebug_flag", "");
3822 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
3823 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3824 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3826 ventoy_filt_register(0, ventoy_wrapper_open
);
3828 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
3831 g_grub_param
->grub_env_get
= grub_env_get
;
3832 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
3833 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
3834 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
3835 grub_env_set("env_param", buf
);
3836 grub_env_set("ventoy_env_param", buf
);
3837 grub_env_export("ventoy_env_param");
3843 static cmd_para ventoy_cmds
[] =
3845 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
3846 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
3847 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
3848 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3849 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3850 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
3851 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
3852 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
3853 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
3854 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
3855 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
3856 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
3857 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
3858 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
3859 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
3860 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
3861 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
3862 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
3863 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
3864 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
3866 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
3867 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
3868 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
3869 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
3870 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
3871 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
3873 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
3874 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
3875 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
3876 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
3877 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
3878 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
3879 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
3880 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
3883 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
3884 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
3885 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
3886 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
3887 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
3888 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
3889 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
3890 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
3891 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
3892 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
3894 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
3895 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
3896 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
3897 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
3898 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
3899 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
3901 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3902 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3903 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
3904 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
3905 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
3906 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
3907 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
3908 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
3909 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
3910 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
3912 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
3913 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
3914 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
3915 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
3916 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
3917 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
3918 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
3920 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
3921 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
3922 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
3923 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
3926 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
3927 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
3929 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
3930 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
3931 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
3934 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
3935 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
3936 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
3937 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
3938 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
3939 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
3940 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
3941 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
3943 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
3944 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
3945 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
3951 GRUB_MOD_INIT(ventoy
)
3954 cmd_para
*cur
= NULL
;
3958 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3960 cur
= ventoy_cmds
+ i
;
3961 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
3962 cur
->summary
, cur
->description
, cur
->parser
);
3966 GRUB_MOD_FINI(ventoy
)
3970 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3972 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);