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/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 int g_ventoy_debug
= 0;
55 static int g_efi_os
= 0xFF;
56 initrd_info
*g_initrd_img_list
= NULL
;
57 initrd_info
*g_initrd_img_tail
= NULL
;
58 int g_initrd_img_count
= 0;
59 int g_valid_initrd_count
= 0;
60 int g_default_menu_mode
= 0;
61 int g_filt_dot_underscore_file
= 0;
62 int g_sort_case_sensitive
= 0;
63 int g_tree_view_menu_style
= 0;
64 static grub_file_t g_old_file
;
65 static int g_ventoy_last_entry_back
;
66 static grub_uint32_t g_ventoy_plat_data
;
69 char g_img_swap_tmp_buf
[1024];
70 img_info g_img_swap_tmp
;
71 img_info
*g_ventoy_img_list
= NULL
;
73 int g_ventoy_img_count
= 0;
75 grub_device_t g_enum_dev
= NULL
;
76 grub_fs_t g_enum_fs
= NULL
;
77 img_iterator_node g_img_iterator_head
;
78 img_iterator_node
*g_img_iterator_tail
= NULL
;
80 grub_uint8_t g_ventoy_break_level
= 0;
81 grub_uint8_t g_ventoy_debug_level
= 0;
82 grub_uint8_t g_ventoy_chain_type
= 0;
84 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
85 grub_uint32_t g_ventoy_cpio_size
= 0;
86 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
87 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
89 int g_plugin_image_list
= 0;
91 ventoy_grub_param
*g_grub_param
= NULL
;
93 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
95 ventoy_img_chunk_list g_img_chunk_list
;
97 int g_wimboot_enable
= 0;
98 ventoy_img_chunk_list g_wimiso_chunk_list
;
99 char *g_wimiso_path
= NULL
;
101 int g_vhdboot_enable
= 0;
103 grub_uint64_t g_conf_replace_offset
= 0;
104 grub_uint64_t g_svd_replace_offset
= 0;
105 conf_replace
*g_conf_replace_node
= NULL
;
106 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
107 int g_conf_replace_new_len
= 0;
108 int g_conf_replace_new_len_align
= 0;
110 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
111 grub_uint64_t g_ventoy_disk_size
= 0;
113 static char *g_tree_script_buf
= NULL
;
114 static int g_tree_script_pos
= 0;
116 static char *g_list_script_buf
= NULL
;
117 static int g_list_script_pos
= 0;
119 static char *g_part_list_buf
= NULL
;
120 static int g_part_list_pos
= 0;
122 static int g_video_mode_max
= 0;
123 static int g_video_mode_num
= 0;
124 static ventoy_video_mode
*g_video_mode_list
= NULL
;
126 static int g_enumerate_time_checked
= 0;
127 static grub_uint64_t g_enumerate_start_time_ms
;
128 static grub_uint64_t g_enumerate_finish_time_ms
;
130 static const char *g_menu_class
[] =
132 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
135 static const char *g_menu_prefix
[] =
137 "iso", "wim", "efi", "img", "vhd", "vtoy"
140 void ventoy_debug(const char *fmt
, ...)
144 va_start (args
, fmt
);
145 grub_vprintf (fmt
, args
);
149 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
159 for (i
= 0; i
< 16; i
++)
161 grub_printf("%02x ", guid
[i
]);
166 int ventoy_is_efi_os(void)
170 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
176 static int ventoy_get_fs_type(const char *fs
)
180 return ventoy_fs_max
;
182 else if (grub_strncmp(fs
, "exfat", 5) == 0)
184 return ventoy_fs_exfat
;
186 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
188 return ventoy_fs_ntfs
;
190 else if (grub_strncmp(fs
, "ext", 3) == 0)
192 return ventoy_fs_ext
;
194 else if (grub_strncmp(fs
, "xfs", 3) == 0)
196 return ventoy_fs_xfs
;
198 else if (grub_strncmp(fs
, "udf", 3) == 0)
200 return ventoy_fs_udf
;
202 else if (grub_strncmp(fs
, "fat", 3) == 0)
204 return ventoy_fs_fat
;
207 return ventoy_fs_max
;
210 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
229 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
231 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
235 static grub_err_t
ventoy_fs_close(grub_file_t file
)
237 grub_file_close(g_old_file
);
238 grub_free(file
->data
);
246 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
252 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
257 for (i
= 0; i
< g_video_mode_num
; i
++)
259 if (g_video_mode_list
[i
].width
== info
->width
&&
260 g_video_mode_list
[i
].height
== info
->height
&&
261 g_video_mode_list
[i
].bpp
== info
->bpp
)
267 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
268 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
269 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
272 if (g_video_mode_num
== g_video_mode_max
)
274 g_video_mode_max
*= 2;
275 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
281 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
283 if (v1
->bpp
== v2
->bpp
)
285 if (v1
->width
== v2
->width
)
287 if (v1
->height
== v2
->height
)
293 return (v1
->height
< v2
->height
) ? -1 : 1;
298 return (v1
->width
< v2
->width
) ? -1 : 1;
303 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
307 static int ventoy_enum_video_mode(void)
310 grub_video_adapter_t adapter
;
311 grub_video_driver_id_t id
;
312 ventoy_video_mode mode
;
314 g_video_mode_num
= 0;
315 g_video_mode_max
= 1024;
316 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
317 if (!g_video_mode_list
)
322 #ifdef GRUB_MACHINE_PCBIOS
323 grub_dl_load ("vbe");
326 id
= grub_video_get_driver_id ();
328 FOR_VIDEO_ADAPTERS (adapter
)
330 if (!adapter
->iterate
||
331 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
332 adapter
->init() != GRUB_ERR_NONE
)))
337 adapter
->iterate(ventoy_video_hook
, NULL
);
339 if (adapter
->id
!= id
)
345 /* sort video mode */
346 for (i
= 0; i
< g_video_mode_num
; i
++)
347 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
349 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
351 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
352 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
353 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
357 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
360 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
364 static struct grub_fs vtoy_fs
=
369 .fs_read
= ventoy_fs_read
,
370 .fs_close
= ventoy_fs_close
,
380 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
386 file
->data
= grub_malloc(rawFile
->size
+ 4096);
392 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
393 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
395 g_old_file
= rawFile
;
397 file
->size
= rawFile
->size
+ len
;
398 file
->device
= rawFile
->device
;
400 file
->not_easily_seekable
= 1;
405 static int ventoy_check_decimal_var(const char *name
, long *value
)
407 const char *value_str
= NULL
;
409 value_str
= grub_env_get(name
);
410 if (NULL
== value_str
)
412 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
415 if (!ventoy_is_decimal(value_str
))
417 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
420 *value
= grub_strtol(value_str
, NULL
, 10);
422 return GRUB_ERR_NONE
;
425 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
429 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
432 if (0 == grub_strcmp(args
[0], "on"))
435 grub_env_set("vtdebug_flag", "debug");
440 grub_env_set("vtdebug_flag", "");
443 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
446 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
450 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
452 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
453 grub_printf(" level:\r\n");
454 grub_printf(" 01/11: busybox / (+cat log)\r\n");
455 grub_printf(" 02/12: initrd / (+cat log)\r\n");
456 grub_printf(" 03/13: hook / (+cat log)\r\n");
458 grub_printf(" debug:\r\n");
459 grub_printf(" 0: debug is off\r\n");
460 grub_printf(" 1: debug is on\r\n");
462 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
465 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
467 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
469 g_ventoy_debug_level
= 1;
472 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
475 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
484 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
487 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
519 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
524 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
526 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
529 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
534 value_long
+= grub_strtol(args
[1], NULL
, 10);
536 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
537 grub_env_set(args
[0], buf
);
539 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
542 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
544 ulonglong value1
= 0;
545 ulonglong value2
= 0;
550 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
553 value1
= grub_strtoull(args
[0], NULL
, 10);
554 value2
= grub_strtoull(args
[1], NULL
, 10);
556 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
557 grub_env_set(args
[2], buf
);
559 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
562 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
577 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
580 debug("failed to open file <%s> for udf check\n", args
[0]);
584 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
586 grub_env_set(args
[1], buf
);
588 grub_file_close(file
);
594 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
602 g_wimboot_enable
= 0;
603 grub_check_free(g_wimiso_path
);
604 grub_check_free(g_wimiso_chunk_list
.chunk
);
606 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
612 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
613 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
614 if (NULL
== g_wimiso_chunk_list
.chunk
)
616 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
619 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
620 g_wimiso_chunk_list
.cur_chunk
= 0;
622 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
624 g_wimboot_enable
= 1;
625 g_wimiso_path
= grub_strdup(args
[0]);
627 grub_file_close(file
);
632 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
638 grub_uint32_t offset
;
640 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
643 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
647 len
= (int)file
->size
;
649 data
= (char *)grub_malloc(file
->size
);
655 grub_file_read(file
, data
, file
->size
);
656 grub_file_close(file
);
658 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
659 grub_script_execute_sourcecode(exec
);
661 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
662 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
663 grub_file_close(file
);
665 grub_script_execute_sourcecode("loopback -d efiboot");
669 *direntoff
= offset
+ 2;
674 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
684 ventoy_iso9660_override
*dirent
;
693 totlen
= sizeof(ventoy_chain_head
);
695 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
697 debug("failed to load efiboot template %d\n", len
);
703 debug("efiboot template len:%d offset:%d\n", len
, offset
);
705 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
708 debug("failed to open file <%s>\n", args
[0]);
712 totlen
+= ventoy_align_2k(file
->size
);
714 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
715 dirent
->first_sector
= len
/ 2048;
716 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
717 dirent
->size
= (grub_uint32_t
)file
->size
;
718 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
720 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
722 #ifdef GRUB_MACHINE_EFI
723 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
725 data
= (char *)grub_malloc(totlen
);
728 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
730 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
731 grub_check_free(buf
);
733 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
734 grub_file_close(file
);
736 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
737 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
738 grub_env_set(name
, value
);
740 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
741 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
742 grub_env_set(name
, value
);
747 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
764 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
767 debug("failed to open file <%s>\n", args
[0]);
771 #ifdef GRUB_MACHINE_EFI
772 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
774 buf
= (char *)grub_malloc(file
->size
);
777 grub_file_read(file
, buf
, file
->size
);
779 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
780 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
781 grub_env_set(name
, value
);
783 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
784 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
785 grub_env_set(name
, value
);
787 grub_file_close(file
);
793 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
811 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
814 debug("failed to open file <%s> for udf check\n", args
[0]);
818 headlen
= sizeof(ventoy_chain_head
);
820 #ifdef GRUB_MACHINE_EFI
821 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
823 buf
= (char *)grub_malloc(headlen
+ file
->size
);
826 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
828 grub_file_read(file
, buf
+ headlen
, file
->size
);
830 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
831 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
832 grub_env_set(name
, value
);
834 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
835 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
836 grub_env_set(name
, value
);
838 grub_file_close(file
);
844 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
853 if (args
[0][0] == '1')
855 grub_iso9660_set_nojoliet(1);
859 grub_iso9660_set_nojoliet(0);
865 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
870 grub_uint8_t buf
[32];
881 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
884 debug("failed to open file <%s> for udf check\n", args
[0]);
888 for (i
= 16; i
< 32; i
++)
890 grub_file_seek(file
, i
* 2048);
891 grub_file_read(file
, buf
, sizeof(buf
));
899 grub_file_seek(file
, i
* 2048);
900 grub_file_read(file
, buf
, sizeof(buf
));
902 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
905 grub_file_seek(file
, i
* 2048);
906 grub_file_read(file
, buf
, sizeof(buf
));
908 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
909 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
915 grub_file_close(file
);
917 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
922 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
924 long value_long1
= 0;
925 long value_long2
= 0;
927 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
929 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
932 value_long1
= grub_strtol(args
[0], NULL
, 10);
933 value_long2
= grub_strtol(args
[2], NULL
, 10);
935 if (0 == grub_strcmp(args
[1], "eq"))
937 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
939 else if (0 == grub_strcmp(args
[1], "ne"))
941 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
943 else if (0 == grub_strcmp(args
[1], "gt"))
945 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
947 else if (0 == grub_strcmp(args
[1], "lt"))
949 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
951 else if (0 == grub_strcmp(args
[1], "ge"))
953 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
955 else if (0 == grub_strcmp(args
[1], "le"))
957 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
961 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
967 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
974 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
977 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
978 pos
= grub_strstr(buf
, ",");
984 grub_env_set(args
[1], buf
);
986 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
989 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
995 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1001 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1004 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1006 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1007 if (0 == grub_script_execute_sourcecode(buf
))
1009 debug("file %s exist, ventoy_compatible YES\n", buf
);
1010 grub_env_set("ventoy_compatible", "YES");
1011 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1015 debug("file %s NOT exist\n", buf
);
1019 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1020 pos
= grub_strstr(buf
, ")");
1026 disk
= grub_disk_open(buf
);
1029 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1030 grub_disk_close(disk
);
1032 g_img_swap_tmp_buf
[703] = 0;
1033 for (i
= 318; i
< 703; i
++)
1035 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1036 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1038 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1039 grub_env_set("ventoy_compatible", "YES");
1040 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1046 debug("failed to open disk <%s>\n", buf
);
1049 grub_env_set("ventoy_compatible", "NO");
1050 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1053 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1059 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1061 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1064 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1069 if (0 == g_sort_case_sensitive
)
1071 if (grub_islower(c1
))
1073 c1
= c1
- 'a' + 'A';
1076 if (grub_islower(c2
))
1078 c2
= c2
- 'a' + 'A';
1091 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1097 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1099 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1102 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1107 if (0 == g_sort_case_sensitive
)
1109 if (grub_islower(c1
))
1111 c1
= c1
- 'a' + 'A';
1114 if (grub_islower(c2
))
1116 c2
= c2
- 'a' + 'A';
1129 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1131 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1133 grub_memcpy(img1
, img2
, sizeof(img_info
));
1134 img1
->next
= g_img_swap_tmp
.next
;
1135 img1
->prev
= g_img_swap_tmp
.prev
;
1137 g_img_swap_tmp
.next
= img2
->next
;
1138 g_img_swap_tmp
.prev
= img2
->prev
;
1139 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1142 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1146 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1154 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1158 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1168 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1177 img_iterator_node
*tmp
;
1178 img_iterator_node
*new_node
;
1179 img_iterator_node
*node
= (img_iterator_node
*)data
;
1181 if (g_enumerate_time_checked
== 0)
1183 g_enumerate_finish_time_ms
= grub_get_time_ms();
1184 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1187 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1189 g_enumerate_time_checked
= 1;
1193 len
= grub_strlen(filename
);
1197 if ((len
== 1 && filename
[0] == '.') ||
1198 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1203 if (!ventoy_img_name_valid(filename
, len
))
1208 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1213 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1215 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1216 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1219 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1224 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1227 new_node
->plugin_list_index
= index
;
1228 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1230 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1233 debug("Directory %s ignored...\n", new_node
->dir
);
1234 grub_free(new_node
);
1238 new_node
->tail
= node
->tail
;
1240 new_node
->parent
= node
;
1241 if (!node
->firstchild
)
1243 node
->firstchild
= new_node
;
1246 if (g_img_iterator_tail
)
1248 g_img_iterator_tail
->next
= new_node
;
1249 g_img_iterator_tail
= new_node
;
1253 g_img_iterator_head
.next
= new_node
;
1254 g_img_iterator_tail
= new_node
;
1260 debug("Find a file %s\n", filename
);
1266 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1268 type
= img_type_iso
;
1270 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1272 type
= img_type_wim
;
1274 else if (g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1275 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1277 type
= img_type_vhd
;
1279 #ifdef GRUB_MACHINE_EFI
1280 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1282 type
= img_type_efi
;
1285 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1287 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1289 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1290 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1295 type
= img_type_img
;
1297 else if (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1299 type
= img_type_vtoy
;
1301 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1303 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1305 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1306 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1315 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1320 if (g_plugin_image_list
)
1322 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1323 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1324 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1326 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1329 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1331 debug("File %s found in image_blacklist plugin config...\n", g_img_swap_tmp_buf
);
1336 img
= grub_zalloc(sizeof(img_info
));
1340 img
->plugin_list_index
= index
;
1341 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1343 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1345 img
->size
= info
->size
;
1348 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1351 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1353 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1358 if (g_ventoy_img_list
)
1360 tail
= *(node
->tail
);
1366 g_ventoy_img_list
= img
;
1369 img
->id
= g_ventoy_img_count
;
1371 if (node
&& NULL
== node
->firstiso
)
1373 node
->firstiso
= img
;
1384 *((img_info
**)(node
->tail
)) = img
;
1385 g_ventoy_img_count
++;
1387 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1388 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1391 img
->class = g_menu_class
[type
];
1393 img
->menu_prefix
= g_menu_prefix
[type
];
1395 if (img_type_iso
== type
)
1397 if (ventoy_plugin_check_memdisk(img
->path
))
1399 img
->menu_prefix
= "miso";
1403 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1410 static int ventoy_arch_mode_init(void)
1412 #ifdef GRUB_MACHINE_EFI
1413 if (grub_strcmp(GRUB_TARGET_CPU
, "i386") == 0)
1415 g_ventoy_plat_data
= VTOY_PLAT_I386_UEFI
;
1416 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "ia32");
1418 else if (grub_strcmp(GRUB_TARGET_CPU
, "arm64") == 0)
1420 g_ventoy_plat_data
= VTOY_PLAT_ARM64_UEFI
;
1421 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "aa64");
1425 g_ventoy_plat_data
= VTOY_PLAT_X86_64_UEFI
;
1426 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "uefi");
1429 g_ventoy_plat_data
= VTOY_PLAT_X86_LEGACY
;
1430 grub_snprintf(g_arch_mode_suffix
, sizeof(g_arch_mode_suffix
), "%s", "legacy");
1436 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1438 int len
= GRUB_UINT_MAX
;
1439 const char *value
= NULL
;
1440 char name
[32] = {0};
1441 char plat
[32] = {0};
1442 char guidstr
[32] = {0};
1443 ventoy_guid guid
= VENTOY_GUID
;
1444 const char *fmt1
= NULL
;
1445 const char *fmt2
= NULL
;
1446 const char *fmt3
= NULL
;
1447 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1448 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1449 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1450 const char fmtcode
[]={
1451 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1452 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1453 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1454 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1455 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1456 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1459 grub_memset(name
, 0, sizeof(name
));
1460 puint
[0] = grub_swap_bytes32(0x56454e54);
1461 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1462 puint
[2] = grub_swap_bytes32(0x45525349);
1463 puint
[1] = grub_swap_bytes32(0x4f595f56);
1464 value
= ventoy_get_env(name
);
1466 grub_memset(name
, 0, sizeof(name
));
1467 puint
[1] = grub_swap_bytes32(0x5f544f50);
1468 puint
[0] = grub_swap_bytes32(0x56544c45);
1469 fmt1
= ventoy_get_env(name
);
1475 grub_memset(name
, 0, sizeof(name
));
1476 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1477 puint
[0] = grub_swap_bytes32(0x56544c45);
1478 fmt2
= ventoy_get_env(name
);
1480 grub_memset(name
, 0, sizeof(name
));
1481 puint
[1] = grub_swap_bytes32(0x5f434c52);
1482 puint
[0] = grub_swap_bytes32(0x56544c45);
1483 fmt3
= ventoy_get_env(name
);
1485 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1487 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1489 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1490 #pragma GCC diagnostic push
1491 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1492 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1493 fmt1
? fmt1
: fmtdata
,
1494 fmt2
? fmt2
: fmtdata
+ 4,
1495 value
? value
: "", plat
, guidstr
,
1496 fmt3
? fmt3
: fmtdata
+ 6);
1497 #pragma GCC diagnostic pop
1499 grub_memset(name
, 0, sizeof(name
));
1500 puint
[0] = grub_swap_bytes32(0x76746f79);
1501 puint
[2] = grub_swap_bytes32(0x656e7365);
1502 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1503 ventoy_set_env(name
, guidstr
);
1508 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1512 grub_uint8_t md5
[16];
1516 grub_memset(input
, 0, sizeof(input
));
1518 grub_printf("Enter password: ");
1521 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1523 grub_password_get(input
, 128);
1524 if (grub_strcmp(pwd
->text
, input
) == 0)
1529 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1531 grub_password_get(input
, 128);
1532 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1533 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1538 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1540 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1541 grub_password_get(input
+ offset
, 128);
1543 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1544 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1550 grub_printf("Invalid password!\n\n");
1557 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1559 img_info
*minimg
= NULL
;
1560 img_info
*img
= (img_info
*)(node
->firstiso
);
1562 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1564 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1579 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1581 img_iterator_node
*Minchild
= NULL
;
1582 img_iterator_node
*child
= node
->firstchild
;
1584 while (child
&& child
->parent
== node
)
1586 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1590 child
= child
->next
;
1595 Minchild
->select
= 1;
1601 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1604 img_info
*img
= NULL
;
1605 const char *dir_class
= NULL
;
1606 const char *dir_alias
= NULL
;
1607 img_iterator_node
*child
= NULL
;
1609 if (node
->isocnt
== 0 || node
->done
== 1)
1614 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1616 offset
= node
->parent
->dirlen
;
1619 if (node
== &g_img_iterator_head
)
1621 if (g_default_menu_mode
== 0)
1623 if (g_tree_view_menu_style
== 0)
1625 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1626 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1627 " echo 'return ...' \n"
1632 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1633 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1641 node
->dir
[node
->dirlen
- 1] = 0;
1642 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1645 dir_class
= "vtoydir";
1648 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1651 if (g_tree_view_menu_style
== 0)
1653 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1654 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1655 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1659 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1660 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1661 dir_alias
, dir_class
, node
->dir
+ offset
);
1666 dir_alias
= node
->dir
+ offset
;
1668 if (g_tree_view_menu_style
== 0)
1670 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1671 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1672 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1676 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1677 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1678 dir_alias
, dir_class
, node
->dir
+ offset
);
1682 if (g_tree_view_menu_style
== 0)
1684 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1685 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1686 " echo 'return ...' \n"
1691 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1692 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1698 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1700 ventoy_dynamic_tree_menu(child
);
1703 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1705 if (g_tree_view_menu_style
== 0)
1707 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1708 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1711 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1712 img
->unsupport
? "[***********] " : "",
1713 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1715 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1719 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1720 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1723 img
->unsupport
? "[***********] " : "",
1724 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1726 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1730 if (node
!= &g_img_iterator_head
)
1732 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1739 int ventoy_check_device_result(int ret
)
1743 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1744 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1745 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1749 grub_printf(VTOY_WARNING
"\n");
1750 grub_printf(VTOY_WARNING
"\n");
1751 grub_printf(VTOY_WARNING
"\n\n\n");
1753 grub_printf("This is NOT a standard Ventoy device and is NOT supported.\n\n");
1754 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1756 grub_printf("\n\nWill exit after 10 seconds ...... ");
1764 int ventoy_check_device(grub_device_t dev
)
1768 grub_uint64_t offset
;
1773 struct grub_partition
*partition
;
1775 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1777 return ventoy_check_device_result(1 | 0x1000);
1780 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1781 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1782 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1784 #ifndef GRUB_MACHINE_EFI
1785 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1786 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
1787 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
1789 return ventoy_check_device_result(2 | 0x1000);
1798 /* We must have partition 2 */
1801 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
1805 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1809 return ventoy_check_device_result(3 | 0x1000);
1812 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1814 grub_file_close(file
);
1815 return ventoy_check_device_result(4 | 0x1000);
1818 partition
= dev
->disk
->partition
;
1819 if (partition
->number
!= 0 || partition
->start
!= 2048)
1821 return ventoy_check_device_result(5);
1826 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
1828 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
1829 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
1830 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
1832 grub_file_close(file
);
1833 return ventoy_check_device_result(6);
1838 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
1839 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
1840 PartTbl
[1].SectorCount
!= 65536)
1842 grub_file_close(file
);
1843 return ventoy_check_device_result(6);
1849 offset
= partition
->start
+ partition
->len
;
1850 partition
= file
->device
->disk
->partition
;
1851 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1853 grub_file_close(file
);
1854 return ventoy_check_device_result(7);
1858 grub_file_close(file
);
1860 if (workaround
== 0)
1862 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1863 dev2
= grub_device_open(devname
);
1866 return ventoy_check_device_result(8);
1869 fs
= grub_fs_probe(dev2
);
1872 grub_device_close(dev2
);
1873 return ventoy_check_device_result(9);
1876 fs
->fs_label(dev2
, &label
);
1877 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1879 grub_device_close(dev2
);
1880 return ventoy_check_device_result(10);
1883 grub_device_close(dev2
);
1886 return ventoy_check_device_result(0);
1889 static int ventoy_set_default_menu(void)
1895 const char *strdata
= NULL
;
1896 img_info
*cur
= NULL
;
1897 img_info
*default_node
= NULL
;
1898 const char *default_image
= NULL
;
1900 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1901 if (default_image
&& default_image
[0] == '/')
1903 img_len
= grub_strlen(default_image
);
1905 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1907 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1919 if (0 == g_default_menu_mode
)
1921 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1925 def
= grub_strdup(default_image
);
1931 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
1933 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1934 if (strdata
&& strdata
[0] == '/')
1936 pos
= def
+ grub_strlen(strdata
);
1947 while ((end
= grub_strchr(pos
, '/')) != NULL
)
1950 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
1954 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
1962 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1966 grub_device_t dev
= NULL
;
1967 img_info
*cur
= NULL
;
1968 img_info
*tail
= NULL
;
1969 const char *strdata
= NULL
;
1970 char *device_name
= NULL
;
1972 img_iterator_node
*node
= NULL
;
1973 img_iterator_node
*tmp
= NULL
;
1979 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1982 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1984 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1987 g_enumerate_time_checked
= 0;
1988 g_enumerate_start_time_ms
= grub_get_time_ms();
1990 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1991 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1993 g_filt_dot_underscore_file
= 1;
1996 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
1997 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1999 g_sort_case_sensitive
= 1;
2002 device_name
= grub_file_get_device_name(args
[0]);
2008 g_enum_dev
= dev
= grub_device_open(device_name
);
2014 g_enum_fs
= fs
= grub_fs_probe(dev
);
2020 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2022 debug("unsupported fs:<%s>\n", fs
->name
);
2023 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2027 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2029 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2030 if (strdata
&& strdata
[0] == '1')
2032 g_default_menu_mode
= 1;
2035 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2037 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2039 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2040 if (strdata
&& strdata
[0] == '/')
2042 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2043 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2045 g_img_iterator_head
.dir
[len
++] = '/';
2047 g_img_iterator_head
.dirlen
= len
;
2051 g_img_iterator_head
.dirlen
= 1;
2052 grub_strcpy(g_img_iterator_head
.dir
, "/");
2055 g_img_iterator_head
.tail
= &tail
;
2057 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2059 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2062 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2063 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2065 g_tree_view_menu_style
= 1;
2068 ventoy_set_default_menu();
2070 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2072 ventoy_dynamic_tree_menu(node
);
2076 node
= g_img_iterator_head
.next
;
2084 /* sort image list by image name */
2085 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2087 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2089 if (ventoy_cmp_img(cur
, tail
) > 0)
2091 ventoy_swap_img(cur
, tail
);
2096 if (g_default_menu_mode
== 1)
2098 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2099 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2100 " echo 'return ...' \n"
2104 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2106 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2107 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2110 cur
->unsupport
? "[***********] " : "",
2111 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2113 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2116 g_tree_script_buf
[g_tree_script_pos
] = 0;
2117 g_list_script_buf
[g_list_script_pos
] = 0;
2119 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2120 grub_env_set(args
[1], buf
);
2124 check_free(device_name
, grub_free
);
2125 check_free(dev
, grub_device_close
);
2127 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2131 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2133 img_info
*next
= NULL
;
2134 img_info
*cur
= g_ventoy_img_list
;
2147 g_ventoy_img_list
= NULL
;
2148 g_ventoy_img_count
= 0;
2150 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2153 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2156 img_info
*cur
= g_ventoy_img_list
;
2160 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2162 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2165 img_id
= grub_strtol(args
[0], NULL
, 10);
2166 if (img_id
>= g_ventoy_img_count
)
2168 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2171 debug("Find image %ld name \n", img_id
);
2173 while (cur
&& img_id
> 0)
2181 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2184 debug("image name is %s\n", cur
->name
);
2186 grub_env_set(args
[1], cur
->name
);
2188 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2191 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2196 const char *id
= NULL
;
2197 img_info
*cur
= g_ventoy_img_list
;
2201 if (argc
< 1 || argc
> 2)
2203 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2206 id
= grub_env_get("chosen");
2208 pos
= grub_strstr(id
, "VID_");
2211 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2215 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2220 if (img_id
== cur
->id
)
2229 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2232 grub_env_set(args
[0], cur
->path
);
2236 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2237 grub_env_set(args
[1], value
);
2240 g_svd_replace_offset
= 0;
2242 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2245 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2252 device_name
= grub_file_get_device_name(filename
);
2264 pos2
= grub_strstr(pos
, ",");
2267 pos2
= grub_strstr(pos
, ")");
2275 disk
= grub_disk_open(pos
);
2278 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2279 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2280 grub_disk_close(disk
);
2287 grub_free(device_name
);
2291 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2293 eltorito_descriptor desc
;
2295 grub_memset(&desc
, 0, sizeof(desc
));
2296 grub_file_seek(file
, 17 * 2048);
2297 grub_file_read(file
, &desc
, sizeof(desc
));
2299 if (desc
.type
!= 0 || desc
.version
!= 1)
2304 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2305 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2313 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2317 grub_uint8_t buf
[512];
2318 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2320 grub_file_seek(file
, sector
* 2048);
2321 grub_file_read(file
, buf
, sizeof(buf
));
2323 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2325 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2329 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2334 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2336 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2338 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2342 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2344 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2349 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2351 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2353 if (buf
[36] == parttype
[i
])
2355 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2361 debug("%s does not contain efi eltorito\n", file
->name
);
2365 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2368 const char *fs
= NULL
;
2369 const char *cdprompt
= NULL
;
2371 grub_uint8_t chksum
= 0;
2374 disk
= file
->device
->disk
;
2375 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2377 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2378 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2379 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2381 pos
= grub_strstr(file
->name
, "/");
2387 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2389 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2391 param
->vtoy_img_size
= file
->size
;
2393 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2394 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2396 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2398 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2399 param
->vtoy_reserved
[4] = 0;
2400 if (g_ventoy_chain_type
== 1) /* Windows */
2402 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2403 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2405 param
->vtoy_reserved
[4] = 1;
2409 fs
= ventoy_get_env("ventoy_fs_probe");
2410 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2412 param
->vtoy_reserved
[3] = 1;
2415 /* calculate checksum */
2416 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2418 chksum
+= *((grub_uint8_t
*)param
+ i
);
2420 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2425 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2427 grub_uint32_t i
= 0;
2428 grub_uint64_t total
= 0;
2429 ventoy_img_chunk
*chunk
= NULL
;
2431 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2433 chunk
= chunklist
->chunk
+ i
;
2435 if (chunk
->disk_start_sector
<= start
)
2437 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2441 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2444 if (total
!= ((file
->size
+ 511) / 512))
2446 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2453 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2457 grub_uint32_t i
= 0;
2458 grub_uint32_t sector
= 0;
2459 grub_uint32_t count
= 0;
2460 grub_off_t size
= 0;
2461 grub_off_t read
= 0;
2463 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2464 if (fs_type
== ventoy_fs_exfat
)
2466 grub_fat_get_file_chunk(start
, file
, chunklist
);
2468 else if (fs_type
== ventoy_fs_ext
)
2470 grub_ext_get_file_chunk(start
, file
, chunklist
);
2474 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2475 file
->read_hook_data
= chunklist
;
2477 for (size
= file
->size
; size
> 0; size
-= read
)
2479 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2480 grub_file_read(file
, NULL
, read
);
2483 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2485 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2486 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2489 if (ventoy_fs_udf
== fs_type
)
2491 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2493 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2494 chunklist
->chunk
[i
].img_start_sector
= sector
;
2495 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2501 len
= (int)grub_strlen(file
->name
);
2502 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2503 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2504 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2505 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2507 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2509 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2519 chunklist
->chunk
[i
].img_start_sector
= sector
;
2520 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2528 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2532 grub_disk_addr_t start
;
2537 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2540 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2543 g_conf_replace_node
= NULL
;
2544 g_conf_replace_offset
= 0;
2546 if (g_img_chunk_list
.chunk
)
2548 grub_free(g_img_chunk_list
.chunk
);
2551 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2553 grub_file_close(file
);
2554 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2557 /* get image chunk data */
2558 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2559 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2560 if (NULL
== g_img_chunk_list
.chunk
)
2562 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2565 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2566 g_img_chunk_list
.cur_chunk
= 0;
2568 start
= file
->device
->disk
->partition
->start
;
2570 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2572 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2573 grub_file_close(file
);
2577 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2580 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2581 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2584 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2586 grub_uint64_t offset
= 0;
2587 grub_uint32_t align
= 0;
2588 grub_file_t file
= NULL
;
2589 conf_replace
*node
= NULL
;
2595 debug("select conf replace argc:%d\n", argc
);
2602 node
= ventoy_plugin_find_conf_replace(args
[1]);
2605 debug("Conf replace not found for %s\n", args
[1]);
2609 debug("Find conf replace for %s\n", args
[1]);
2611 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2614 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2618 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2619 grub_file_close(file
);
2621 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2624 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2628 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2630 if (align
> vtoy_max_replace_file_size
)
2632 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2636 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2637 g_conf_replace_new_len
= (int)file
->size
;
2638 g_conf_replace_new_len_align
= align
;
2640 g_conf_replace_node
= node
;
2641 g_conf_replace_offset
= offset
+ 2;
2643 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2648 grub_file_close(file
);
2650 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2653 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2658 char configfile
[128];
2659 install_template
*node
= NULL
;
2665 debug("select auto installation argc:%d\n", argc
);
2672 node
= ventoy_plugin_find_install_template(args
[0]);
2675 debug("Auto install template not found for %s\n", args
[0]);
2679 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2681 node
->cursel
= node
->autosel
- 1;
2682 debug("Auto install template auto select %d\n", node
->autosel
);
2686 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2692 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2693 " echo %s\n}\n", "123");
2695 for (i
= 0; i
< node
->templatenum
; i
++)
2697 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2699 node
->templatepath
[i
].path
);
2702 g_ventoy_menu_esc
= 1;
2703 g_ventoy_suppress_esc
= 1;
2705 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2706 grub_script_execute_sourcecode(configfile
);
2708 g_ventoy_menu_esc
= 0;
2709 g_ventoy_suppress_esc
= 0;
2713 node
->cursel
= g_ventoy_last_entry
- 1;
2715 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2718 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2723 char configfile
[128];
2724 persistence_config
*node
;
2730 debug("select persistence argc:%d\n", argc
);
2737 node
= ventoy_plugin_find_persistent(args
[0]);
2740 debug("Persistence image not found for %s\n", args
[0]);
2744 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2746 node
->cursel
= node
->autosel
- 1;
2747 debug("Persistence image auto select %d\n", node
->autosel
);
2751 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2757 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2758 " echo %s\n}\n", "123");
2760 for (i
= 0; i
< node
->backendnum
; i
++)
2762 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2764 node
->backendpath
[i
].path
);
2768 g_ventoy_menu_esc
= 1;
2769 g_ventoy_suppress_esc
= 1;
2771 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2772 grub_script_execute_sourcecode(configfile
);
2774 g_ventoy_menu_esc
= 0;
2775 g_ventoy_suppress_esc
= 0;
2779 node
->cursel
= g_ventoy_last_entry
- 1;
2781 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2784 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2787 ventoy_img_chunk
*cur
;
2793 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2795 cur
= g_img_chunk_list
.chunk
+ i
;
2796 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2797 cur
->img_start_sector
, cur
->img_end_sector
,
2798 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2802 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2805 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2809 ventoy_img_chunk_list chunklist
;
2814 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2817 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2820 /* get image chunk data */
2821 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2822 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2823 if (NULL
== chunklist
.chunk
)
2825 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2828 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2829 chunklist
.cur_chunk
= 0;
2831 ventoy_get_block_list(file
, &chunklist
, 0);
2833 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2835 grub_printf("########## UNSUPPORTED ###############\n");
2838 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2840 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2842 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2843 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2846 grub_printf("\n==================================\n");
2848 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2850 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2851 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2852 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2853 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2854 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2858 grub_free(chunklist
.chunk
);
2859 grub_file_close(file
);
2861 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2864 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2867 ventoy_grub_param_file_replace
*replace
= NULL
;
2875 replace
= &(g_grub_param
->file_replace
);
2876 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2878 replace
->old_name_cnt
= 0;
2879 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2881 replace
->old_name_cnt
++;
2882 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2885 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2888 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2891 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2899 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2900 grub_printf("%s", g_list_script_buf
);
2904 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2905 grub_printf("%s", g_tree_script_buf
);
2911 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2913 img_info
*cur
= g_ventoy_img_list
;
2921 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
2922 grub_printf("name:<%s>\n\n", cur
->name
);
2929 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2935 ventoy_plugin_dump_injection();
2940 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2946 ventoy_plugin_dump_auto_install();
2951 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2957 ventoy_plugin_dump_persistence();
2962 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2973 if (args
[0][0] == '0')
2975 return g_ventoy_memdisk_mode
? 0 : 1;
2977 else if (args
[0][0] == '1')
2979 return g_ventoy_iso_raw
? 0 : 1;
2981 else if (args
[0][0] == '2')
2983 return g_ventoy_iso_uefi_drv
? 0 : 1;
2989 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2991 static int configfile_mode
= 0;
2992 char memfile
[128] = {0};
2999 * args[0]: 0:normal 1:configfile
3000 * args[1]: 0:list_buf 1:tree_buf
3005 debug("Invalid argc %d\n", argc
);
3009 if (args
[0][0] == '0')
3011 if (args
[1][0] == '0')
3013 grub_script_execute_sourcecode(g_list_script_buf
);
3017 grub_script_execute_sourcecode(g_tree_script_buf
);
3022 if (configfile_mode
)
3024 debug("Now already in F3 mode %d\n", configfile_mode
);
3028 if (args
[1][0] == '0')
3030 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3031 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3035 g_ventoy_last_entry
= -1;
3036 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3037 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3040 configfile_mode
= 1;
3041 grub_script_execute_sourcecode(memfile
);
3042 configfile_mode
= 0;
3048 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3059 g_ventoy_case_insensitive
= 1;
3060 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3061 g_ventoy_case_insensitive
= 0;
3067 grub_file_close(file
);
3073 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3078 const char *isopath
= NULL
;
3080 ventoy_mbr_head mbr
;
3087 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3090 isopath
= grub_env_get("vtoy_iso_part");
3093 debug("isopath is null %p\n", isopath
);
3097 debug("isopath is %s\n", isopath
);
3099 for (id
= 0; id
< 30 && (find
== 0); id
++)
3101 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3102 if (grub_strstr(isopath
, hdname
))
3104 debug("skip %s ...\n", hdname
);
3108 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3110 disk
= grub_disk_open(hdname
);
3113 debug("%s not exist\n", hdname
);
3117 grub_memset(&mbr
, 0, sizeof(mbr
));
3118 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3120 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3122 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3123 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3126 grub_env_set(args
[0], hdname
);
3130 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3134 debug("read %s failed\n", hdname
);
3137 grub_disk_close(disk
);
3143 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3154 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3157 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3160 debug("failed to open file %s\n", args
[0]);
3164 buf
= grub_malloc(len
);
3171 grub_file_read(file
, buf
, len
- 1);
3173 ventoy_get_line(buf
);
3174 ventoy_set_env(args
[1], buf
);
3178 grub_check_free(buf
);
3179 grub_file_close(file
);
3184 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3189 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3190 "0 %llu linear /dev/ventoy %llu\n",
3191 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3196 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3198 char *device_name
= NULL
;
3199 grub_device_t dev
= NULL
;
3204 g_part_list_pos
= 0;
3205 grub_env_unset("vtoy_img_part_file");
3212 device_name
= grub_file_get_device_name(args
[0]);
3215 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3219 dev
= grub_device_open(device_name
);
3222 debug("grub_device_open failed, %s\n", device_name
);
3226 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3228 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3229 grub_env_set("vtoy_img_part_file", buf
);
3233 check_free(device_name
, grub_free
);
3234 check_free(dev
, grub_device_close
);
3240 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3251 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3254 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3257 debug("failed to open file %s\n", args
[0]);
3261 buf
= grub_malloc(file
->size
+ 1);
3267 buf
[file
->size
] = 0;
3268 grub_file_read(file
, buf
, file
->size
);
3270 if (grub_strstr(buf
, args
[1]))
3277 grub_check_free(buf
);
3278 grub_file_close(file
);
3283 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3289 ventoy_iso9660_vd pvd
;
3296 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3299 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3302 debug("failed to open file %s\n", args
[0]);
3306 grub_file_seek(file
, 16 * 2048);
3307 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3308 if (len
!= sizeof(pvd
))
3310 debug("failed to read pvd %d\n", len
);
3314 grub_memset(buf
, 0, sizeof(buf
));
3315 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3316 ventoy_set_env(args
[1], buf
);
3318 grub_memset(buf
, 0, sizeof(buf
));
3319 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3320 ventoy_set_env(args
[2], buf
);
3324 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3325 ventoy_set_env(args
[3], buf
);
3328 grub_file_close(file
);
3333 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3344 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3347 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3350 debug("failed to open file %s\n", args
[0]);
3354 grub_memset(buf
, 0, sizeof(buf
));
3355 grub_file_seek(file
, 16 * 2048 + 813);
3356 len
= (int)grub_file_read(file
, buf
, 17);
3359 debug("failed to read create date %d\n", len
);
3363 ventoy_set_env(args
[1], buf
);
3366 grub_file_close(file
);
3371 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3377 ventoy_env_hook_root(1);
3382 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3388 ventoy_env_hook_root(0);
3393 #ifdef GRUB_MACHINE_EFI
3394 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3399 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3405 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3406 if (var
&& *var
== 1)
3414 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3423 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3430 int image_sector_size
;
3432 ventoy_chain_head
*chain
;
3433 ventoy_img_chunk
*chunk
;
3434 ventoy_os_param
*osparam
;
3435 ventoy_image_location
*location
;
3436 ventoy_image_disk_region
*region
;
3437 struct grub_acpi_table_header
*acpi
;
3446 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3448 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3454 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3456 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3458 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3462 img_chunk_num
= chain
->img_chunk_num
;
3464 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3465 datalen
= sizeof(ventoy_os_param
) + loclen
;
3467 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3468 acpi
= grub_zalloc(buflen
);
3474 /* Step1: Fill acpi table header */
3475 grub_memcpy(acpi
->signature
, "VTOY", 4);
3476 acpi
->length
= buflen
;
3478 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3479 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3481 acpi
->creator_id
[0] = 1;
3482 acpi
->creator_rev
= 1;
3484 /* Step2: Fill data */
3485 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3486 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3487 osparam
->vtoy_img_location_addr
= 0;
3488 osparam
->vtoy_img_location_len
= loclen
;
3489 osparam
->chksum
= 0;
3490 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3492 location
= (ventoy_image_location
*)(osparam
+ 1);
3493 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3494 location
->image_sector_size
= image_sector_size
;
3495 location
->disk_sector_size
= chain
->disk_sector_size
;
3496 location
->region_count
= img_chunk_num
;
3498 region
= location
->regions
;
3499 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3500 if (512 == image_sector_size
)
3502 for (i
= 0; i
< img_chunk_num
; i
++)
3504 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3505 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3506 region
->disk_start_sector
= chunk
->disk_start_sector
;
3513 for (i
= 0; i
< img_chunk_num
; i
++)
3515 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3516 region
->image_start_sector
= chunk
->img_start_sector
;
3517 region
->disk_start_sector
= chunk
->disk_start_sector
;
3523 /* Step3: Fill acpi checksum */
3525 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3527 /* load acpi table */
3528 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3529 grub_script_execute_sourcecode(cmd
);
3533 VENTOY_CMD_RETURN(0);
3536 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3542 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3543 g_ventoy_last_entry
= -1;
3548 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3554 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3559 grub_uint64_t
ventoy_get_part1_size(ventoy_gpt_info
*gpt
)
3561 grub_uint64_t sectors
;
3563 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3565 sectors
= gpt
->PartTbl
[0].LastLBA
+ 1 - gpt
->PartTbl
[0].StartLBA
;
3569 sectors
= gpt
->MBR
.PartTbl
[0].SectorCount
;
3572 return sectors
* 512;
3575 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3577 const char *pos
= filename
+ 1;
3585 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3587 grub_strncpy((char *)data
, filename
, 128);
3598 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3601 char *device_name
= NULL
;
3602 grub_device_t dev
= NULL
;
3603 grub_fs_t fs
= NULL
;
3604 char buf
[128] = {0};
3610 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3614 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3616 device_name
= grub_file_get_device_name(args
[0]);
3619 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3623 dev
= grub_device_open(device_name
);
3626 debug("grub_device_open failed, %s\n", device_name
);
3630 fs
= grub_fs_probe(dev
);
3633 debug("grub_fs_probe failed, %s\n", device_name
);
3637 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3641 ventoy_set_env(args
[2], buf
);
3648 check_free(device_name
, grub_free
);
3649 check_free(dev
, grub_device_close
);
3654 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3664 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3665 if (!g_ventoy_part_info
)
3670 disk
= grub_disk_open(args
[0]);
3673 debug("Failed to open disk %s\n", args
[0]);
3677 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
3679 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3680 grub_disk_close(disk
);
3682 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3683 dev
= grub_device_open(name
);
3686 /* make sure that we are running in a correct Ventoy device */
3687 ret
= ventoy_check_device(dev
);
3688 grub_device_close(dev
);
3699 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3702 const char *vcfg
= NULL
;
3707 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
3710 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
3711 grub_env_set(args
[1], vcfg
);
3716 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
3724 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3727 grub_uint8_t zeroguid
[16] = {0};
3732 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3735 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3737 if (id
>= 1 && id
<= 128)
3739 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3747 if (id
>= 1 && id
<= 4)
3749 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3759 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3762 char *device_name
= NULL
;
3763 grub_device_t dev
= NULL
;
3764 grub_fs_t fs
= NULL
;
3771 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3775 device_name
= grub_file_get_device_name(args
[0]);
3778 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3782 dev
= grub_device_open(device_name
);
3785 debug("grub_device_open failed, %s\n", device_name
);
3789 fs
= grub_fs_probe(dev
);
3792 debug("grub_fs_probe failed, %s\n", device_name
);
3796 fs
->fs_label(dev
, &label
);
3799 ventoy_set_env(args
[1], label
);
3807 check_free(device_name
, grub_free
);
3808 check_free(dev
, grub_device_close
);
3813 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3817 grub_snprintf((char *)data
, 256, "%s", filename
);
3825 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3828 char *device_name
= NULL
;
3829 grub_device_t dev
= NULL
;
3830 grub_fs_t fs
= NULL
;
3831 char name
[256] ={0};
3837 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3841 device_name
= grub_file_get_device_name(args
[0]);
3844 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3848 dev
= grub_device_open(device_name
);
3851 debug("grub_device_open failed, %s\n", device_name
);
3855 fs
= grub_fs_probe(dev
);
3858 debug("grub_fs_probe failed, %s\n", device_name
);
3862 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3865 ventoy_set_env(args
[2], name
);
3872 check_free(device_name
, grub_free
);
3873 check_free(dev
, grub_device_close
);
3878 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3888 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3892 for (pos
= args
[0]; *pos
; pos
++)
3906 grub_env_set(args
[1], args
[0]);
3916 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3926 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
3931 len
= (int)grub_strlen(buf
);
3932 for (i
= len
; i
> 0; i
--)
3934 if (buf
[i
- 1] == '/')
3936 grub_env_set(args
[1], buf
+ i
);
3941 grub_env_set(args
[1], buf
);
3946 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3948 struct grub_video_mode_info info
;
3955 if (!g_video_mode_list
)
3957 ventoy_enum_video_mode();
3960 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3962 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3966 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3969 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3971 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3972 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3974 VENTOY_CMD_RETURN(0);
3977 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3979 struct grub_video_mode_info info
;
3986 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3988 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3992 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3995 grub_env_set(args
[0], buf
);
3997 VENTOY_CMD_RETURN(0);
4000 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4008 if (!g_video_mode_list
)
4013 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4014 if (id
< g_video_mode_num
)
4016 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4017 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4020 grub_env_set(args
[1], buf
);
4022 VENTOY_CMD_RETURN(0);
4025 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
4027 grub_uint64_t size
= 0;
4030 char fullpath
[256] = {0};
4033 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4036 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
4039 debug("grub_file_open failed <%s>\n", fullpath
);
4045 grub_file_close(file
);
4049 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
4053 char fullpath
[256] = {0};
4056 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
4059 file
= grub_file_open(fullpath
, type
);
4062 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
4069 int ventoy_is_file_exist(const char *fmt
, ...)
4074 char buf
[256] = {0};
4076 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
4080 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4083 grub_strncpy(pos
+ len
, "\" ]", 3);
4085 debug("script exec %s\n", buf
);
4087 if (0 == grub_script_execute_sourcecode(buf
))
4095 int ventoy_is_dir_exist(const char *fmt
, ...)
4100 char buf
[256] = {0};
4102 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
4106 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
4109 grub_strncpy(pos
+ len
, "\" ]", 3);
4111 debug("script exec %s\n", buf
);
4113 if (0 == grub_script_execute_sourcecode(buf
))
4121 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
4124 grub_uint8_t
*outbuf
;
4125 grub_uint8_t gzHdr
[10] =
4127 0x1F, 0x8B, /* magic */
4130 0,0,0,0, /* mtime */
4135 grub_memset(&s
, 0, sizeof(mz_stream
));
4137 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
4139 outbuf
= (grub_uint8_t
*)mem_out
;
4141 mem_out_len
-= sizeof(gzHdr
) + 8;
4142 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
4143 outbuf
+= sizeof(gzHdr
);
4145 s
.avail_in
= mem_in_len
;
4148 s
.avail_out
= mem_out_len
;
4149 s
.next_out
= outbuf
;
4151 mz_deflate(&s
, MZ_FINISH
);
4155 outbuf
+= s
.total_out
;
4156 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
4157 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
4159 return s
.total_out
+ sizeof(gzHdr
) + 8;
4162 static int ventoy_env_init(void)
4166 grub_env_set("vtdebug_flag", "");
4168 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4169 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4170 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4171 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4173 ventoy_filt_register(0, ventoy_wrapper_open
);
4175 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4178 g_grub_param
->grub_env_get
= grub_env_get
;
4179 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4180 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4181 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4182 grub_env_set("env_param", buf
);
4183 grub_env_set("ventoy_env_param", buf
);
4184 grub_env_export("ventoy_env_param");
4190 static cmd_para ventoy_cmds
[] =
4192 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4193 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4194 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4195 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4196 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4197 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4198 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4199 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4200 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4201 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4202 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4203 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4204 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4205 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4206 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4207 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4208 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4209 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4210 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4211 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4212 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4213 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4214 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4216 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4217 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4218 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4219 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4220 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4221 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4222 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4224 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4225 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4226 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4227 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4228 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4229 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4230 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4231 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4232 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4235 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4236 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4237 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4238 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4239 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4240 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4241 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4242 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4243 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4244 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4245 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4247 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4248 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4249 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4250 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4251 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4252 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4254 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4255 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4256 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4257 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4258 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4259 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4260 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4261 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4262 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4263 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4265 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4266 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4267 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4268 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4269 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4270 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4271 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4272 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4274 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4275 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4276 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4279 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4280 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4281 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4283 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4284 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4285 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4288 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4289 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4290 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4291 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4292 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4293 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4294 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4295 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4296 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4297 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4299 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4300 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4301 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4302 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4308 GRUB_MOD_INIT(ventoy
)
4311 cmd_para
*cur
= NULL
;
4315 ventoy_arch_mode_init();
4317 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4319 cur
= ventoy_cmds
+ i
;
4320 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4321 cur
->summary
, cur
->description
, cur
->parser
);
4325 GRUB_MOD_FINI(ventoy
)
4329 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4331 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);