1 /******************************************************************************
4 * Copyright (c) 2021, 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 static grub_uint8_t g_check_mbr_data
[] = {
55 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
61 initrd_info
*g_initrd_img_list
= NULL
;
62 initrd_info
*g_initrd_img_tail
= NULL
;
63 int g_initrd_img_count
= 0;
64 int g_valid_initrd_count
= 0;
65 int g_default_menu_mode
= 0;
66 int g_filt_dot_underscore_file
= 0;
67 int g_sort_case_sensitive
= 0;
68 int g_tree_view_menu_style
= 0;
69 static grub_file_t g_old_file
;
70 static int g_ventoy_last_entry_back
;
73 char g_img_swap_tmp_buf
[1024];
74 img_info g_img_swap_tmp
;
75 img_info
*g_ventoy_img_list
= NULL
;
77 int g_ventoy_img_count
= 0;
79 grub_device_t g_enum_dev
= NULL
;
80 grub_fs_t g_enum_fs
= NULL
;
81 int g_img_max_search_level
= -1;
82 img_iterator_node g_img_iterator_head
;
83 img_iterator_node
*g_img_iterator_tail
= NULL
;
85 grub_uint8_t g_ventoy_break_level
= 0;
86 grub_uint8_t g_ventoy_debug_level
= 0;
87 grub_uint8_t g_ventoy_chain_type
= 0;
89 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
90 grub_uint32_t g_ventoy_cpio_size
= 0;
91 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
92 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
94 int g_plugin_image_list
= 0;
96 ventoy_grub_param
*g_grub_param
= NULL
;
98 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
100 ventoy_img_chunk_list g_img_chunk_list
;
102 int g_wimboot_enable
= 0;
103 ventoy_img_chunk_list g_wimiso_chunk_list
;
104 char *g_wimiso_path
= NULL
;
105 grub_uint32_t g_wimiso_size
= 0;
107 int g_vhdboot_enable
= 0;
109 grub_uint64_t g_conf_replace_offset
= 0;
110 grub_uint64_t g_svd_replace_offset
= 0;
111 conf_replace
*g_conf_replace_node
= NULL
;
112 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
113 int g_conf_replace_new_len
= 0;
114 int g_conf_replace_new_len_align
= 0;
116 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
117 grub_uint64_t g_ventoy_disk_size
= 0;
118 grub_uint64_t g_ventoy_disk_part_size
[2];
120 static char *g_tree_script_buf
= NULL
;
121 static int g_tree_script_pos
= 0;
123 static char *g_list_script_buf
= NULL
;
124 static int g_list_script_pos
= 0;
126 static char *g_part_list_buf
= NULL
;
127 static int g_part_list_pos
= 0;
128 static grub_uint64_t g_part_end_max
= 0;
130 static int g_video_mode_max
= 0;
131 static int g_video_mode_num
= 0;
132 static ventoy_video_mode
*g_video_mode_list
= NULL
;
134 static int g_enumerate_time_checked
= 0;
135 static grub_uint64_t g_enumerate_start_time_ms
;
136 static grub_uint64_t g_enumerate_finish_time_ms
;
137 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
139 static int g_pager_flag
= 0;
140 static char g_old_pager
[32];
142 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
144 const char *g_menu_class
[img_type_max
] =
146 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
149 const char *g_menu_prefix
[img_type_max
] =
151 "iso", "wim", "efi", "img", "vhd", "vtoy"
154 static int g_vtoy_load_prompt
= 0;
155 static char g_vtoy_prompt_msg
[64];
157 static char g_json_case_mis_path
[32];
159 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
161 int ventoy_get_fs_type(const char *fs
)
165 return ventoy_fs_max
;
167 else if (grub_strncmp(fs
, "exfat", 5) == 0)
169 return ventoy_fs_exfat
;
171 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
173 return ventoy_fs_ntfs
;
175 else if (grub_strncmp(fs
, "ext", 3) == 0)
177 return ventoy_fs_ext
;
179 else if (grub_strncmp(fs
, "xfs", 3) == 0)
181 return ventoy_fs_xfs
;
183 else if (grub_strncmp(fs
, "udf", 3) == 0)
185 return ventoy_fs_udf
;
187 else if (grub_strncmp(fs
, "fat", 3) == 0)
189 return ventoy_fs_fat
;
192 return ventoy_fs_max
;
195 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
214 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
216 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
220 static int ventoy_control_get_flag(const char *key
)
222 const char *val
= ventoy_get_env(key
);
224 if (val
&& val
[0] == '1' && val
[1] == 0)
231 static grub_err_t
ventoy_fs_close(grub_file_t file
)
233 grub_file_close(g_old_file
);
234 grub_free(file
->data
);
242 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
248 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
253 for (i
= 0; i
< g_video_mode_num
; i
++)
255 if (g_video_mode_list
[i
].width
== info
->width
&&
256 g_video_mode_list
[i
].height
== info
->height
&&
257 g_video_mode_list
[i
].bpp
== info
->bpp
)
263 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
264 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
265 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
268 if (g_video_mode_num
== g_video_mode_max
)
270 g_video_mode_max
*= 2;
271 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
277 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
279 if (v1
->bpp
== v2
->bpp
)
281 if (v1
->width
== v2
->width
)
283 if (v1
->height
== v2
->height
)
289 return (v1
->height
< v2
->height
) ? -1 : 1;
294 return (v1
->width
< v2
->width
) ? -1 : 1;
299 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
303 static int ventoy_enum_video_mode(void)
306 grub_video_adapter_t adapter
;
307 grub_video_driver_id_t id
;
308 ventoy_video_mode mode
;
310 g_video_mode_num
= 0;
311 g_video_mode_max
= 1024;
312 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
313 if (!g_video_mode_list
)
318 #ifdef GRUB_MACHINE_PCBIOS
319 grub_dl_load ("vbe");
322 id
= grub_video_get_driver_id ();
324 FOR_VIDEO_ADAPTERS (adapter
)
326 if (!adapter
->iterate
||
327 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
328 adapter
->init() != GRUB_ERR_NONE
)))
333 adapter
->iterate(ventoy_video_hook
, NULL
);
335 if (adapter
->id
!= id
)
341 /* sort video mode */
342 for (i
= 0; i
< g_video_mode_num
; i
++)
343 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
345 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
347 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
348 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
349 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
353 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
356 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
360 static struct grub_fs vtoy_fs
=
365 .fs_read
= ventoy_fs_read
,
366 .fs_close
= ventoy_fs_close
,
376 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
382 file
->data
= grub_malloc(rawFile
->size
+ 4096);
388 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
389 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
391 g_old_file
= rawFile
;
393 file
->size
= rawFile
->size
+ len
;
394 file
->device
= rawFile
->device
;
396 file
->not_easily_seekable
= 1;
401 static int ventoy_check_decimal_var(const char *name
, long *value
)
403 const char *value_str
= NULL
;
405 value_str
= grub_env_get(name
);
406 if (NULL
== value_str
)
408 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
411 if (!ventoy_is_decimal(value_str
))
413 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
416 *value
= grub_strtol(value_str
, NULL
, 10);
418 return GRUB_ERR_NONE
;
421 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
423 grub_uint64_t sectors
;
425 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
427 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
431 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
434 return sectors
* 512;
437 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
443 grub_uint32_t offset
;
445 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
448 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
452 len
= (int)file
->size
;
454 data
= (char *)grub_malloc(file
->size
);
460 grub_file_read(file
, data
, file
->size
);
461 grub_file_close(file
);
463 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
464 grub_script_execute_sourcecode(exec
);
466 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
467 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
468 grub_file_close(file
);
470 grub_script_execute_sourcecode("loopback -d efiboot");
474 *direntoff
= offset
+ 2;
479 static int ventoy_set_check_result(int ret
)
483 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
484 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
485 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
489 grub_printf(VTOY_WARNING
"\n");
490 grub_printf(VTOY_WARNING
"\n");
491 grub_printf(VTOY_WARNING
"\n\n\n");
493 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
494 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
496 grub_printf("\n\nWill exit after 10 seconds ...... ");
504 static int ventoy_check_official_device(grub_device_t dev
)
508 grub_uint64_t offset
;
511 grub_uint8_t mbr
[512];
515 struct grub_partition
*partition
;
517 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
519 return ventoy_set_check_result(1 | 0x1000);
522 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
523 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
524 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
526 #ifndef GRUB_MACHINE_EFI
527 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
528 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
529 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
531 return ventoy_set_check_result(2 | 0x1000);
540 /* We must have partition 2 */
543 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
547 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
551 return ventoy_set_check_result(3 | 0x1000);
554 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
556 grub_file_close(file
);
557 return ventoy_set_check_result(4 | 0x1000);
560 partition
= dev
->disk
->partition
;
561 if (partition
->number
!= 0 || partition
->start
!= 2048)
563 return ventoy_set_check_result(5);
568 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
570 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
571 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
572 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
574 grub_file_close(file
);
575 return ventoy_set_check_result(6);
580 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
581 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
582 PartTbl
[1].SectorCount
!= 65536)
584 grub_file_close(file
);
585 return ventoy_set_check_result(6);
591 offset
= partition
->start
+ partition
->len
;
592 partition
= file
->device
->disk
->partition
;
593 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
595 grub_file_close(file
);
596 return ventoy_set_check_result(7);
600 grub_file_close(file
);
604 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
605 dev2
= grub_device_open(devname
);
608 return ventoy_set_check_result(8);
611 fs
= grub_fs_probe(dev2
);
614 grub_device_close(dev2
);
615 return ventoy_set_check_result(9);
618 fs
->fs_label(dev2
, &label
);
619 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
621 grub_device_close(dev2
);
622 return ventoy_set_check_result(10);
625 grub_device_close(dev2
);
629 disk
= grub_disk_open(dev
->disk
->name
);
632 return ventoy_set_check_result(11);
635 grub_memset(mbr
, 0, 512);
636 grub_disk_read(disk
, 0, 0, 512, mbr
);
637 grub_disk_close(disk
);
639 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
641 return ventoy_set_check_result(12);
644 return ventoy_set_check_result(0);
647 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
651 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
661 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
663 grub_uint64_t size
= 0;
666 char fullpath
[256] = {0};
669 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
672 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
675 debug("grub_file_open failed <%s>\n", fullpath
);
681 grub_file_close(file
);
685 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
689 char fullpath
[512] = {0};
692 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
695 file
= grub_file_open(fullpath
, type
);
698 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
705 int ventoy_is_dir_exist(const char *fmt
, ...)
712 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
716 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
719 grub_strncpy(pos
+ len
, "\" ]", 3);
721 debug("script exec %s\n", buf
);
723 if (0 == grub_script_execute_sourcecode(buf
))
731 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
734 grub_uint8_t
*outbuf
;
735 grub_uint8_t gzHdr
[10] =
737 0x1F, 0x8B, /* magic */
745 grub_memset(&s
, 0, sizeof(mz_stream
));
747 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
749 outbuf
= (grub_uint8_t
*)mem_out
;
751 mem_out_len
-= sizeof(gzHdr
) + 8;
752 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
753 outbuf
+= sizeof(gzHdr
);
755 s
.avail_in
= mem_in_len
;
758 s
.avail_out
= mem_out_len
;
761 mz_deflate(&s
, MZ_FINISH
);
765 outbuf
+= s
.total_out
;
766 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
767 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
769 return s
.total_out
+ sizeof(gzHdr
) + 8;
777 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
781 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
784 if (0 == grub_strcmp(args
[0], "on"))
787 grub_env_set("vtdebug_flag", "debug");
792 grub_env_set("vtdebug_flag", "");
795 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
798 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
802 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
804 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
805 grub_printf(" level:\r\n");
806 grub_printf(" 01/11: busybox / (+cat log)\r\n");
807 grub_printf(" 02/12: initrd / (+cat log)\r\n");
808 grub_printf(" 03/13: hook / (+cat log)\r\n");
810 grub_printf(" debug:\r\n");
811 grub_printf(" 0: debug is off\r\n");
812 grub_printf(" 1: debug is on\r\n");
814 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
817 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
819 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
821 g_ventoy_debug_level
= 1;
824 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
827 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
836 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
839 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
871 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
887 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
903 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
908 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
910 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
913 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
918 value_long
+= grub_strtol(args
[1], NULL
, 10);
920 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
921 grub_env_set(args
[0], buf
);
923 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
926 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
928 ulonglong value1
= 0;
929 ulonglong value2
= 0;
934 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
937 value1
= grub_strtoull(args
[0], NULL
, 10);
938 value2
= grub_strtoull(args
[1], NULL
, 10);
940 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
941 grub_env_set(args
[2], buf
);
943 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
946 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
961 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
964 debug("failed to open file <%s> for udf check\n", args
[0]);
968 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
970 grub_env_set(args
[1], buf
);
972 grub_file_close(file
);
978 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
986 g_wimboot_enable
= 0;
988 grub_check_free(g_wimiso_path
);
989 grub_check_free(g_wimiso_chunk_list
.chunk
);
991 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
997 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
998 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
999 if (NULL
== g_wimiso_chunk_list
.chunk
)
1001 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1004 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1005 g_wimiso_chunk_list
.cur_chunk
= 0;
1007 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1009 g_wimboot_enable
= 1;
1010 g_wimiso_path
= grub_strdup(args
[0]);
1011 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1012 grub_file_close(file
);
1017 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1027 ventoy_iso9660_override
*dirent
;
1036 totlen
= sizeof(ventoy_chain_head
);
1038 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1040 debug("failed to load efiboot template %d\n", len
);
1046 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1048 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1051 debug("failed to open file <%s>\n", args
[0]);
1055 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1060 totlen
+= ventoy_align_2k(file
->size
);
1062 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1063 dirent
->first_sector
= len
/ 2048;
1064 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1065 dirent
->size
= (grub_uint32_t
)file
->size
;
1066 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1068 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1070 #ifdef GRUB_MACHINE_EFI
1071 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1073 data
= (char *)grub_malloc(totlen
);
1076 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1078 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1079 grub_check_free(buf
);
1081 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1082 grub_file_close(file
);
1084 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1085 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1086 grub_env_set(name
, value
);
1088 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1089 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1090 grub_env_set(name
, value
);
1095 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1101 g_vtoy_load_prompt
= 0;
1102 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1104 if (argc
== 2 && args
[0][0] == '1')
1106 g_vtoy_load_prompt
= 1;
1107 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1110 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1113 int ventoy_need_prompt_load_file(void)
1115 return g_vtoy_load_prompt
;
1118 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1120 grub_uint64_t ro
= 0;
1121 grub_uint64_t div
= 0;
1122 grub_ssize_t left
= size
;
1123 char *cur
= (char *)buf
;
1125 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1128 while (left
>= VTOY_SIZE_2MB
)
1130 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1131 cur
+= VTOY_SIZE_2MB
;
1132 left
-= VTOY_SIZE_2MB
;
1134 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1135 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1141 grub_file_read(file
, cur
, left
);
1144 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1150 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1157 enum grub_file_type type
;
1168 if (grub_strcmp(args
[0], "nodecompress") == 0)
1170 type
= VENTOY_FILE_TYPE
;
1174 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1177 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1180 debug("failed to open file <%s>\n", args
[1]);
1184 #ifdef GRUB_MACHINE_EFI
1185 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1187 buf
= (char *)grub_malloc(file
->size
);
1192 grub_file_close(file
);
1196 if (g_vtoy_load_prompt
)
1198 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1202 grub_file_read(file
, buf
, file
->size
);
1205 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1206 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1207 grub_env_set(name
, value
);
1209 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1210 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1211 grub_env_set(name
, value
);
1213 grub_file_close(file
);
1219 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1237 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1240 debug("failed to open file <%s> for udf check\n", args
[0]);
1244 headlen
= sizeof(ventoy_chain_head
);
1246 #ifdef GRUB_MACHINE_EFI
1247 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1249 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1252 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1254 grub_file_read(file
, buf
+ headlen
, file
->size
);
1256 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1257 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1258 grub_env_set(name
, value
);
1260 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1261 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1262 grub_env_set(name
, value
);
1264 grub_file_close(file
);
1270 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1276 if (grub_iso9660_is_joliet())
1278 debug("This time has joliet process\n");
1287 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1296 if (args
[0][0] == '1')
1298 grub_iso9660_set_nojoliet(1);
1302 grub_iso9660_set_nojoliet(0);
1308 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1313 grub_uint8_t buf
[32];
1324 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1327 debug("failed to open file <%s> for udf check\n", args
[0]);
1331 for (i
= 16; i
< 32; i
++)
1333 grub_file_seek(file
, i
* 2048);
1334 grub_file_read(file
, buf
, sizeof(buf
));
1342 grub_file_seek(file
, i
* 2048);
1343 grub_file_read(file
, buf
, sizeof(buf
));
1345 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1348 grub_file_seek(file
, i
* 2048);
1349 grub_file_read(file
, buf
, sizeof(buf
));
1351 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1352 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1358 grub_file_close(file
);
1360 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1365 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1367 long value_long1
= 0;
1368 long value_long2
= 0;
1370 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1372 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1375 value_long1
= grub_strtol(args
[0], NULL
, 10);
1376 value_long2
= grub_strtol(args
[2], NULL
, 10);
1378 if (0 == grub_strcmp(args
[1], "eq"))
1380 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1382 else if (0 == grub_strcmp(args
[1], "ne"))
1384 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1386 else if (0 == grub_strcmp(args
[1], "gt"))
1388 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1390 else if (0 == grub_strcmp(args
[1], "lt"))
1392 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1394 else if (0 == grub_strcmp(args
[1], "ge"))
1396 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1398 else if (0 == grub_strcmp(args
[1], "le"))
1400 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1404 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1410 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1413 char buf
[128] = {0};
1417 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1420 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1421 pos
= grub_strstr(buf
, ",");
1427 grub_env_set(args
[1], buf
);
1429 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1432 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1438 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1444 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1447 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1449 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1450 if (0 == grub_script_execute_sourcecode(buf
))
1452 debug("file %s exist, ventoy_compatible YES\n", buf
);
1453 grub_env_set("ventoy_compatible", "YES");
1454 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1458 debug("file %s NOT exist\n", buf
);
1462 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1463 pos
= grub_strstr(buf
, ")");
1469 disk
= grub_disk_open(buf
);
1472 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1473 grub_disk_close(disk
);
1475 g_img_swap_tmp_buf
[703] = 0;
1476 for (i
= 318; i
< 703; i
++)
1478 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1479 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1481 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1482 grub_env_set("ventoy_compatible", "YES");
1483 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1489 debug("failed to open disk <%s>\n", buf
);
1492 grub_env_set("ventoy_compatible", "NO");
1493 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1496 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1502 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1504 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1507 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1512 if (0 == g_sort_case_sensitive
)
1514 if (grub_islower(c1
))
1516 c1
= c1
- 'a' + 'A';
1519 if (grub_islower(c2
))
1521 c2
= c2
- 'a' + 'A';
1534 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1540 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1542 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1545 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1550 if (0 == g_sort_case_sensitive
)
1552 if (grub_islower(c1
))
1554 c1
= c1
- 'a' + 'A';
1557 if (grub_islower(c2
))
1559 c2
= c2
- 'a' + 'A';
1572 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1574 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1576 grub_memcpy(img1
, img2
, sizeof(img_info
));
1577 img1
->next
= g_img_swap_tmp
.next
;
1578 img1
->prev
= g_img_swap_tmp
.prev
;
1580 g_img_swap_tmp
.next
= img2
->next
;
1581 g_img_swap_tmp
.prev
= img2
->prev
;
1582 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1585 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1589 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1597 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1599 ventoy_vlnk_part
*node
= NULL
;
1600 grub_uint32_t SelfSig
;
1601 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1603 /* skip Ventoy partition 1/2 */
1604 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1605 if (partition
->number
< 2 && SelfSig
== *pSig
)
1610 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1613 node
->disksig
= *pSig
;
1614 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1615 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1616 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1618 node
->next
= g_vlnk_part_list
;
1619 g_vlnk_part_list
= node
;
1625 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1632 disk
= grub_disk_open(name
);
1635 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1636 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1637 grub_disk_close(disk
);
1643 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1645 const char *fs
[ventoy_fs_max
+ 1] =
1647 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1652 cur
->dev
= grub_device_open(cur
->device
);
1657 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1663 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1668 char *disk
, *device
;
1669 grub_uint32_t readcrc
, calccrc
;
1670 ventoy_vlnk_part
*cur
;
1671 grub_fs_t fs
= NULL
;
1673 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1677 grub_printf("VLNK invalid guid\n");
1683 readcrc
= vlnk
->crc32
;
1685 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1686 if (readcrc
!= calccrc
)
1690 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1696 if (!g_vlnk_part_list
)
1698 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1701 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1703 if (cur
->disksig
== vlnk
->disk_signature
)
1707 if (cur
->partoffset
== vlnk
->part_offset
)
1710 device
= cur
->device
;
1712 if (cur
->probe
== 0)
1715 ventoy_vlnk_probe_fs(cur
);
1725 struct grub_file file
;
1727 grub_memset(&file
, 0, sizeof(file
));
1728 file
.device
= cur
->dev
;
1729 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1732 cur
->fs
->fs_close(&file
);
1733 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1742 grub_printf("\n==== VLNK Information ====\n"
1743 "Disk Signature: %08x\n"
1744 "Partition Offset: %llu\n"
1745 "File Path: <%s>\n\n",
1746 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1750 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1754 grub_printf("Disk Find: [ NO ]\n");
1759 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1763 grub_printf("Part Find: [ NO ]\n");
1765 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1768 grub_printf("VLNK File: <%s>\n", dst
);
1775 return (1 - filefind
);
1778 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1783 grub_file_t file
= NULL
;
1788 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1790 else if (dir
[0] == '/')
1792 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1796 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1799 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1805 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1806 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1807 grub_file_close(file
);
1809 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1811 rc
= grub_file_add_vlnk(src
, dst
);
1817 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1827 const menu_tip
*tip
;
1828 img_iterator_node
*tmp
;
1829 img_iterator_node
*new_node
;
1830 img_iterator_node
*node
= (img_iterator_node
*)data
;
1832 if (g_enumerate_time_checked
== 0)
1834 g_enumerate_finish_time_ms
= grub_get_time_ms();
1835 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1838 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1840 g_enumerate_time_checked
= 1;
1844 len
= grub_strlen(filename
);
1848 if (node
->level
+ 1 > g_img_max_search_level
)
1853 if ((len
== 1 && filename
[0] == '.') ||
1854 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1859 if (!ventoy_img_name_valid(filename
, len
))
1864 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1869 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1871 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1872 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1875 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1880 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1883 new_node
->level
= node
->level
+ 1;
1884 new_node
->plugin_list_index
= index
;
1885 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1887 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1890 debug("Directory %s ignored...\n", new_node
->dir
);
1891 grub_free(new_node
);
1895 new_node
->tail
= node
->tail
;
1897 new_node
->parent
= node
;
1898 if (!node
->firstchild
)
1900 node
->firstchild
= new_node
;
1903 if (g_img_iterator_tail
)
1905 g_img_iterator_tail
->next
= new_node
;
1906 g_img_iterator_tail
= new_node
;
1910 g_img_iterator_head
.next
= new_node
;
1911 g_img_iterator_tail
= new_node
;
1917 debug("Find a file %s\n", filename
);
1923 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1925 type
= img_type_iso
;
1927 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1929 type
= img_type_wim
;
1931 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1932 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1934 type
= img_type_vhd
;
1936 #ifdef GRUB_MACHINE_EFI
1937 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1939 type
= img_type_efi
;
1942 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1944 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1946 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1947 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1952 type
= img_type_img
;
1954 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1956 type
= img_type_vtoy
;
1958 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1960 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1962 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1963 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1972 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1977 if (g_plugin_image_list
)
1979 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1980 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1981 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1983 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1986 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1988 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1993 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
1995 if (grub_file_is_vlnk_suffix(filename
, len
))
1998 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2005 img
= grub_zalloc(sizeof(img_info
));
2009 img
->plugin_list_index
= index
;
2010 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2012 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2014 img
->size
= info
->size
;
2015 if (vlnk
|| 0 == img
->size
)
2017 if (node
->dir
[0] == '/')
2019 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2023 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2027 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2029 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2034 if (g_ventoy_img_list
)
2036 tail
= *(node
->tail
);
2042 g_ventoy_img_list
= img
;
2045 img
->id
= g_ventoy_img_count
;
2047 if (node
&& NULL
== node
->firstiso
)
2049 node
->firstiso
= img
;
2060 *((img_info
**)(node
->tail
)) = img
;
2061 g_ventoy_img_count
++;
2063 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2065 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2068 img
->tip1
= tip
->tip1
;
2069 img
->tip2
= tip
->tip2
;
2072 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2075 img
->class = g_menu_class
[type
];
2077 img
->menu_prefix
= g_menu_prefix
[type
];
2079 if (img_type_iso
== type
)
2081 if (ventoy_plugin_check_memdisk(img
->path
))
2083 img
->menu_prefix
= "miso";
2087 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2094 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2096 int len
= GRUB_UINT_MAX
;
2097 const char *value
= NULL
;
2098 char name
[32] = {0};
2099 char plat
[32] = {0};
2100 char guidstr
[32] = {0};
2101 ventoy_guid guid
= VENTOY_GUID
;
2102 const char *fmt1
= NULL
;
2103 const char *fmt2
= NULL
;
2104 const char *fmt3
= NULL
;
2105 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2106 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2107 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2108 const char fmtcode
[]={
2109 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2110 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2111 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2112 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2113 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2114 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2117 grub_memset(name
, 0, sizeof(name
));
2118 puint
[0] = grub_swap_bytes32(0x56454e54);
2119 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2120 puint
[2] = grub_swap_bytes32(0x45525349);
2121 puint
[1] = grub_swap_bytes32(0x4f595f56);
2122 value
= ventoy_get_env(name
);
2124 grub_memset(name
, 0, sizeof(name
));
2125 puint
[1] = grub_swap_bytes32(0x5f544f50);
2126 puint
[0] = grub_swap_bytes32(0x56544c45);
2127 fmt1
= ventoy_get_env(name
);
2133 grub_memset(name
, 0, sizeof(name
));
2134 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2135 puint
[0] = grub_swap_bytes32(0x56544c45);
2136 fmt2
= ventoy_get_env(name
);
2138 grub_memset(name
, 0, sizeof(name
));
2139 puint
[1] = grub_swap_bytes32(0x5f434c52);
2140 puint
[0] = grub_swap_bytes32(0x56544c45);
2141 fmt3
= ventoy_get_env(name
);
2143 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2145 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2147 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2148 #pragma GCC diagnostic push
2149 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2150 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2151 fmt1
? fmt1
: fmtdata
,
2152 fmt2
? fmt2
: fmtdata
+ 4,
2153 value
? value
: "", plat
, guidstr
,
2154 fmt3
? fmt3
: fmtdata
+ 6);
2155 #pragma GCC diagnostic pop
2157 grub_memset(name
, 0, sizeof(name
));
2158 puint
[0] = grub_swap_bytes32(0x76746f79);
2159 puint
[2] = grub_swap_bytes32(0x656e7365);
2160 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2161 ventoy_set_env(name
, guidstr
);
2166 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2170 grub_uint8_t md5
[16];
2174 grub_memset(input
, 0, sizeof(input
));
2176 grub_printf("Enter password: ");
2179 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2181 grub_password_get(input
, 128);
2182 if (grub_strcmp(pwd
->text
, input
) == 0)
2187 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2189 grub_password_get(input
, 128);
2190 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2191 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2196 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2198 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2199 grub_password_get(input
+ offset
, 128);
2201 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2202 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2208 grub_printf("Invalid password!\n\n");
2215 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2217 img_info
*minimg
= NULL
;
2218 img_info
*img
= (img_info
*)(node
->firstiso
);
2220 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2222 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2237 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2239 img_iterator_node
*Minchild
= NULL
;
2240 img_iterator_node
*child
= node
->firstchild
;
2242 while (child
&& child
->parent
== node
)
2244 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2248 child
= child
->next
;
2253 Minchild
->select
= 1;
2259 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2262 img_info
*img
= NULL
;
2263 const char *dir_class
= NULL
;
2264 const char *dir_alias
= NULL
;
2265 img_iterator_node
*child
= NULL
;
2266 const menu_tip
*tip
= NULL
;
2268 if (node
->isocnt
== 0 || node
->done
== 1)
2273 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2275 offset
= node
->parent
->dirlen
;
2278 if (node
== &g_img_iterator_head
)
2280 if (g_default_menu_mode
== 0)
2282 if (g_tree_view_menu_style
== 0)
2284 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2285 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2286 " echo 'return ...' \n"
2291 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2292 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2300 node
->dir
[node
->dirlen
- 1] = 0;
2301 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2304 dir_class
= "vtoydir";
2307 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2309 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2312 if (g_tree_view_menu_style
== 0)
2314 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2315 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2316 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2320 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2321 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2322 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2327 dir_alias
= node
->dir
+ offset
;
2329 if (g_tree_view_menu_style
== 0)
2331 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2332 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2333 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2337 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2338 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2339 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2343 if (g_tree_view_menu_style
== 0)
2345 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2346 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2347 " echo 'return ...' \n"
2352 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2353 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2359 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2361 ventoy_dynamic_tree_menu(child
);
2364 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2366 if (g_tree_view_menu_style
== 0)
2368 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2369 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2372 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2373 img
->unsupport
? "[***********] " : "",
2374 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2376 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2380 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2381 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2384 img
->unsupport
? "[***********] " : "",
2385 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2387 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2391 if (node
!= &g_img_iterator_head
)
2393 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2400 static int ventoy_set_default_menu(void)
2406 const char *strdata
= NULL
;
2407 img_info
*cur
= NULL
;
2408 img_info
*default_node
= NULL
;
2409 const char *default_image
= NULL
;
2411 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2412 if (default_image
&& default_image
[0] == '/')
2414 img_len
= grub_strlen(default_image
);
2416 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2418 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2430 if (0 == g_default_menu_mode
)
2432 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2436 def
= grub_strdup(default_image
);
2442 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2444 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2445 if (strdata
&& strdata
[0] == '/')
2447 pos
= def
+ grub_strlen(strdata
);
2458 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2461 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2465 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2473 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2475 img_info
*next
= NULL
;
2476 img_info
*cur
= g_ventoy_img_list
;
2489 g_ventoy_img_list
= NULL
;
2490 g_ventoy_img_count
= 0;
2492 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2495 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2498 img_info
*cur
= g_ventoy_img_list
;
2502 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2504 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2507 img_id
= grub_strtol(args
[0], NULL
, 10);
2508 if (img_id
>= g_ventoy_img_count
)
2510 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2513 debug("Find image %ld name \n", img_id
);
2515 while (cur
&& img_id
> 0)
2523 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2526 debug("image name is %s\n", cur
->name
);
2528 grub_env_set(args
[1], cur
->name
);
2530 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2533 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2537 img_info
*cur
= g_ventoy_img_list
;
2543 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2546 len
= (int)grub_strlen(args
[0]);
2550 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2559 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2562 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2563 grub_env_set("chosen", id
);
2564 grub_env_export("chosen");
2566 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2569 static char g_fake_vlnk_src
[512];
2570 static char g_fake_vlnk_dst
[512];
2571 static grub_uint64_t g_fake_vlnk_size
;
2572 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2578 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2580 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2581 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2583 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2585 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2588 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2594 g_fake_vlnk_src
[0] = 0;
2595 g_fake_vlnk_dst
[0] = 0;
2596 g_fake_vlnk_size
= 0;
2597 grub_file_vtoy_vlnk(NULL
, NULL
);
2599 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2603 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2607 const char *id
= NULL
;
2608 img_info
*cur
= NULL
;
2612 if (argc
< 1 || argc
> 2)
2614 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2617 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2619 grub_env_set(args
[0], grub_strchr(g_fake_vlnk_src
, '/'));
2622 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2623 grub_env_set(args
[1], value
);
2629 id
= grub_env_get("chosen");
2631 pos
= grub_strstr(id
, "VID_");
2634 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2638 cur
= g_ventoy_img_list
;
2643 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2646 grub_env_set(args
[0], cur
->path
);
2650 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2651 grub_env_set(args
[1], value
);
2655 g_svd_replace_offset
= 0;
2657 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2661 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2665 grub_device_t dev
= NULL
;
2666 img_info
*cur
= NULL
;
2667 img_info
*tail
= NULL
;
2668 img_info
*min
= NULL
;
2669 img_info
*head
= NULL
;
2670 const char *strdata
= NULL
;
2671 char *device_name
= NULL
;
2673 img_iterator_node
*node
= NULL
;
2674 img_iterator_node
*tmp
= NULL
;
2680 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2683 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2685 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2690 g_enumerate_time_checked
= 0;
2691 g_enumerate_start_time_ms
= grub_get_time_ms();
2693 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2694 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2696 g_filt_dot_underscore_file
= 1;
2699 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2700 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2702 g_sort_case_sensitive
= 1;
2705 device_name
= grub_file_get_device_name(args
[0]);
2711 g_enum_dev
= dev
= grub_device_open(device_name
);
2717 g_enum_fs
= fs
= grub_fs_probe(dev
);
2723 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2725 debug("unsupported fs:<%s>\n", fs
->name
);
2726 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2730 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2732 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2733 if (strdata
&& strdata
[0] == '1')
2735 g_default_menu_mode
= 1;
2738 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2740 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2742 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2743 if (strdata
&& strdata
[0] == '/')
2745 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2746 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2748 g_img_iterator_head
.dir
[len
++] = '/';
2750 g_img_iterator_head
.dirlen
= len
;
2754 g_img_iterator_head
.dirlen
= 1;
2755 grub_strcpy(g_img_iterator_head
.dir
, "/");
2758 g_img_iterator_head
.tail
= &tail
;
2760 if (g_img_max_search_level
< 0)
2762 g_img_max_search_level
= GRUB_INT_MAX
;
2763 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2764 if (strdata
&& ventoy_is_decimal(strdata
))
2766 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2770 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2771 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2772 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2773 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2774 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2775 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2777 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2779 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2782 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2783 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2785 g_tree_view_menu_style
= 1;
2788 ventoy_set_default_menu();
2790 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2792 ventoy_dynamic_tree_menu(node
);
2796 node
= g_img_iterator_head
.next
;
2804 /* sort image list by image name */
2805 while (g_ventoy_img_list
)
2807 min
= g_ventoy_img_list
;
2808 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2810 if (ventoy_cmp_img(min
, cur
) > 0)
2818 min
->prev
->next
= min
->next
;
2823 min
->next
->prev
= min
->prev
;
2826 if (min
== g_ventoy_img_list
)
2828 g_ventoy_img_list
= min
->next
;
2846 g_ventoy_img_list
= head
;
2848 if (g_default_menu_mode
== 1)
2850 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2851 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2852 " echo 'return ...' \n"
2856 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2858 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2859 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2862 cur
->unsupport
? "[***********] " : "",
2863 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2865 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2868 g_tree_script_buf
[g_tree_script_pos
] = 0;
2869 g_list_script_buf
[g_list_script_pos
] = 0;
2871 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2872 grub_env_set(args
[1], buf
);
2876 check_free(device_name
, grub_free
);
2877 check_free(dev
, grub_device_close
);
2879 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2882 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2889 device_name
= grub_file_get_device_name(filename
);
2901 pos2
= grub_strstr(pos
, ",");
2904 pos2
= grub_strstr(pos
, ")");
2912 disk
= grub_disk_open(pos
);
2915 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2916 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2917 grub_disk_close(disk
);
2924 grub_free(device_name
);
2928 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2930 eltorito_descriptor desc
;
2932 grub_memset(&desc
, 0, sizeof(desc
));
2933 grub_file_seek(file
, 17 * 2048);
2934 grub_file_read(file
, &desc
, sizeof(desc
));
2936 if (desc
.type
!= 0 || desc
.version
!= 1)
2941 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2942 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2950 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2952 grub_uint8_t buf
[512];
2954 grub_file_seek(file
, sector
* 2048);
2955 grub_file_read(file
, buf
, sizeof(buf
));
2957 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2958 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2960 return *((grub_uint32_t
*)(buf
+ 40));
2966 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2970 grub_uint8_t buf
[512];
2971 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2973 grub_file_seek(file
, sector
* 2048);
2974 grub_file_read(file
, buf
, sizeof(buf
));
2976 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2978 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2982 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2987 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2989 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2991 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2995 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2997 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3002 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3004 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3006 if (buf
[36] == parttype
[i
])
3008 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3014 debug("%s does not contain efi eltorito\n", file
->name
);
3018 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3021 const char *fs
= NULL
;
3022 const char *val
= NULL
;
3023 const char *cdprompt
= NULL
;
3025 grub_uint8_t chksum
= 0;
3028 disk
= file
->device
->disk
;
3029 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3031 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3032 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3033 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3035 pos
= grub_strstr(file
->name
, "/");
3041 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3043 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3045 param
->vtoy_img_size
= file
->size
;
3047 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3048 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3050 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3052 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3053 param
->vtoy_reserved
[4] = 0;
3054 if (g_ventoy_chain_type
== 1) /* Windows */
3056 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3057 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3059 param
->vtoy_reserved
[4] = 1;
3063 fs
= ventoy_get_env("ventoy_fs_probe");
3064 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3066 param
->vtoy_reserved
[3] = 1;
3069 param
->vtoy_reserved
[5] = 0;
3070 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3071 if (val
&& val
[0] == '1' && val
[1] == 0)
3073 param
->vtoy_reserved
[5] = 1;
3076 /* ventoy_disk_signature used for vlnk */
3077 param
->vtoy_reserved
[6] = file
->vlnk
;
3078 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3080 /* calculate checksum */
3081 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3083 chksum
+= *((grub_uint8_t
*)param
+ i
);
3085 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3090 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3092 grub_uint32_t i
= 0;
3093 grub_uint64_t total
= 0;
3094 grub_uint64_t fileblk
= 0;
3095 ventoy_img_chunk
*chunk
= NULL
;
3097 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3099 chunk
= chunklist
->chunk
+ i
;
3101 if (chunk
->disk_start_sector
<= start
)
3103 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3107 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3110 fileblk
= (file
->size
+ 511) / 512;
3112 if (total
!= fileblk
)
3114 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3115 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3117 debug("maybe img file to be processed.\n");
3127 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3131 grub_uint32_t i
= 0;
3132 grub_uint32_t sector
= 0;
3133 grub_uint32_t count
= 0;
3134 grub_off_t size
= 0;
3135 grub_off_t read
= 0;
3137 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3138 if (fs_type
== ventoy_fs_exfat
)
3140 grub_fat_get_file_chunk(start
, file
, chunklist
);
3142 else if (fs_type
== ventoy_fs_ext
)
3144 grub_ext_get_file_chunk(start
, file
, chunklist
);
3148 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
3149 file
->read_hook_data
= chunklist
;
3151 for (size
= file
->size
; size
> 0; size
-= read
)
3153 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3154 grub_file_read(file
, NULL
, read
);
3157 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3159 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3160 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3163 if (ventoy_fs_udf
== fs_type
)
3165 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3167 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3168 chunklist
->chunk
[i
].img_start_sector
= sector
;
3169 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3175 len
= (int)grub_strlen(file
->name
);
3176 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3177 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3178 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3179 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3181 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3183 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3193 chunklist
->chunk
[i
].img_start_sector
= sector
;
3194 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3202 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3206 grub_disk_addr_t start
;
3211 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3214 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3217 g_conf_replace_node
= NULL
;
3218 g_conf_replace_offset
= 0;
3220 if (g_img_chunk_list
.chunk
)
3222 grub_free(g_img_chunk_list
.chunk
);
3225 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3227 grub_file_close(file
);
3228 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3231 /* get image chunk data */
3232 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3233 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3234 if (NULL
== g_img_chunk_list
.chunk
)
3236 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3239 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3240 g_img_chunk_list
.cur_chunk
= 0;
3242 start
= file
->device
->disk
->partition
->start
;
3244 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3246 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3247 grub_file_close(file
);
3251 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3254 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3255 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3256 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3259 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3261 grub_uint64_t offset
= 0;
3262 grub_uint32_t align
= 0;
3263 grub_file_t file
= NULL
;
3264 conf_replace
*node
= NULL
;
3270 debug("select conf replace argc:%d\n", argc
);
3277 node
= ventoy_plugin_find_conf_replace(args
[1]);
3280 debug("Conf replace not found for %s\n", args
[1]);
3284 debug("Find conf replace for %s\n", args
[1]);
3286 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3289 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3290 grub_file_close(file
);
3292 else if (node
->img
> 0)
3298 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3302 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3305 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3309 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3311 if (align
> vtoy_max_replace_file_size
)
3313 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3317 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3318 g_conf_replace_new_len
= (int)file
->size
;
3319 g_conf_replace_new_len_align
= align
;
3321 g_conf_replace_node
= node
;
3322 g_conf_replace_offset
= offset
+ 2;
3326 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3327 g_grub_param
->img_replace
.old_name_cnt
= 1;
3328 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3331 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3336 grub_file_close(file
);
3338 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3341 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3347 char configfile
[128];
3348 install_template
*node
= NULL
;
3354 debug("select auto installation argc:%d\n", argc
);
3361 node
= ventoy_plugin_find_install_template(args
[0]);
3364 debug("Auto install template not found for %s\n", args
[0]);
3368 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3370 defidx
= node
->autosel
;
3371 if (node
->timeout
< 0)
3373 node
->cursel
= node
->autosel
- 1;
3374 debug("Auto install template auto select %d\n", node
->autosel
);
3379 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3385 if (node
->timeout
> 0)
3387 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3390 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3391 " echo %s\n}\n", "");
3393 for (i
= 0; i
< node
->templatenum
; i
++)
3395 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3397 node
->templatepath
[i
].path
);
3400 g_ventoy_menu_esc
= 1;
3401 g_ventoy_suppress_esc
= 1;
3402 g_ventoy_suppress_esc_default
= defidx
;
3404 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3405 grub_script_execute_sourcecode(configfile
);
3407 g_ventoy_menu_esc
= 0;
3408 g_ventoy_suppress_esc
= 0;
3409 g_ventoy_suppress_esc_default
= 1;
3413 node
->cursel
= g_ventoy_last_entry
- 1;
3415 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3418 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3424 char configfile
[128];
3425 persistence_config
*node
;
3431 debug("select persistence argc:%d\n", argc
);
3438 node
= ventoy_plugin_find_persistent(args
[0]);
3441 debug("Persistence image not found for %s\n", args
[0]);
3445 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3447 defidx
= node
->autosel
;
3448 if (node
->timeout
< 0)
3450 node
->cursel
= node
->autosel
- 1;
3451 debug("Persistence image auto select %d\n", node
->autosel
);
3456 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3462 if (node
->timeout
> 0)
3464 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3467 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3468 " echo %s\n}\n", "");
3470 for (i
= 0; i
< node
->backendnum
; i
++)
3472 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3474 node
->backendpath
[i
].path
);
3478 g_ventoy_menu_esc
= 1;
3479 g_ventoy_suppress_esc
= 1;
3480 g_ventoy_suppress_esc_default
= defidx
;
3482 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3483 grub_script_execute_sourcecode(configfile
);
3485 g_ventoy_menu_esc
= 0;
3486 g_ventoy_suppress_esc
= 0;
3487 g_ventoy_suppress_esc_default
= 1;
3491 node
->cursel
= g_ventoy_last_entry
- 1;
3493 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3496 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3499 ventoy_img_chunk
*cur
;
3505 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3507 cur
= g_img_chunk_list
.chunk
+ i
;
3508 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3509 cur
->img_start_sector
, cur
->img_end_sector
,
3510 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3514 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3517 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3521 ventoy_img_chunk_list chunklist
;
3526 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3529 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3532 /* get image chunk data */
3533 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3534 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3535 if (NULL
== chunklist
.chunk
)
3537 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3540 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3541 chunklist
.cur_chunk
= 0;
3543 ventoy_get_block_list(file
, &chunklist
, 0);
3545 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3547 grub_printf("########## UNSUPPORTED ###############\n");
3550 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3552 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3554 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3555 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3558 grub_printf("\n==================================\n");
3560 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3562 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3563 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3564 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3565 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3566 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3570 grub_free(chunklist
.chunk
);
3571 grub_file_close(file
);
3573 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3576 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3579 ventoy_grub_param_file_replace
*replace
= NULL
;
3587 replace
= &(g_grub_param
->file_replace
);
3588 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3590 replace
->old_name_cnt
= 0;
3591 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3593 replace
->old_name_cnt
++;
3594 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3597 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3600 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3603 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3606 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3612 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3613 grub_env_set(args
[0], buf
);
3616 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3619 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3627 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3628 grub_printf("%s", g_list_script_buf
);
3632 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3633 grub_printf("%s", g_tree_script_buf
);
3639 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3641 img_info
*cur
= g_ventoy_img_list
;
3649 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3650 grub_printf("name:<%s>\n\n", cur
->name
);
3657 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3663 ventoy_plugin_dump_injection();
3668 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3674 ventoy_plugin_dump_auto_install();
3679 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3685 ventoy_plugin_dump_persistence();
3690 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3701 if (args
[0][0] == '0')
3703 return g_ventoy_memdisk_mode
? 0 : 1;
3705 else if (args
[0][0] == '1')
3707 return g_ventoy_iso_raw
? 0 : 1;
3709 else if (args
[0][0] == '2')
3711 return g_ventoy_iso_uefi_drv
? 0 : 1;
3713 else if (args
[0][0] == '3')
3715 return g_ventoy_grub2_mode
? 0 : 1;
3717 else if (args
[0][0] == '4')
3719 return g_ventoy_wimboot_mode
? 0 : 1;
3725 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3727 static int configfile_mode
= 0;
3728 char memfile
[128] = {0};
3735 * args[0]: 0:normal 1:configfile
3736 * args[1]: 0:list_buf 1:tree_buf
3741 debug("Invalid argc %d\n", argc
);
3747 if (args
[0][0] == '0')
3749 if (args
[1][0] == '0')
3751 grub_script_execute_sourcecode(g_list_script_buf
);
3755 grub_script_execute_sourcecode(g_tree_script_buf
);
3760 if (configfile_mode
)
3762 debug("Now already in F3 mode %d\n", configfile_mode
);
3766 if (args
[1][0] == '0')
3768 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3769 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3773 g_ventoy_last_entry
= -1;
3774 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3775 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3778 configfile_mode
= 1;
3779 grub_script_execute_sourcecode(memfile
);
3780 configfile_mode
= 0;
3786 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3797 g_ventoy_case_insensitive
= 1;
3798 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3799 g_ventoy_case_insensitive
= 0;
3805 grub_file_close(file
);
3811 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3816 const char *isopath
= NULL
;
3818 ventoy_mbr_head mbr
;
3825 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3828 isopath
= grub_env_get("vtoy_iso_part");
3831 debug("isopath is null %p\n", isopath
);
3835 debug("isopath is %s\n", isopath
);
3837 for (id
= 0; id
< 30 && (find
== 0); id
++)
3839 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3840 if (grub_strstr(isopath
, hdname
))
3842 debug("skip %s ...\n", hdname
);
3846 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3848 disk
= grub_disk_open(hdname
);
3851 debug("%s not exist\n", hdname
);
3855 grub_memset(&mbr
, 0, sizeof(mbr
));
3856 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3858 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3860 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3861 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3864 grub_env_set(args
[0], hdname
);
3868 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3872 debug("read %s failed\n", hdname
);
3875 grub_disk_close(disk
);
3881 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3892 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3895 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3898 debug("failed to open file %s\n", args
[0]);
3902 buf
= grub_malloc(len
);
3909 grub_file_read(file
, buf
, len
- 1);
3911 ventoy_get_line(buf
);
3912 ventoy_set_env(args
[1], buf
);
3916 grub_check_free(buf
);
3917 grub_file_close(file
);
3922 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3924 grub_uint64_t end_max
= 0;
3925 int *pCnt
= (int *)data
;
3930 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3931 "0 %llu linear /dev/ventoy %llu\n",
3932 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3934 end_max
= (partition
->len
+ partition
->start
) * 512;
3935 if (end_max
> g_part_end_max
)
3937 g_part_end_max
= end_max
;
3943 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3946 char *device_name
= NULL
;
3947 grub_device_t dev
= NULL
;
3952 g_part_list_pos
= 0;
3954 grub_env_unset("vtoy_img_part_file");
3961 device_name
= grub_file_get_device_name(args
[0]);
3964 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3968 dev
= grub_device_open(device_name
);
3971 debug("grub_device_open failed, %s\n", device_name
);
3975 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3977 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3978 grub_env_set("vtoy_img_part_file", buf
);
3980 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3981 grub_env_set("vtoy_img_part_cnt", buf
);
3983 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
3984 grub_env_set("vtoy_img_max_part_end", buf
);
3988 check_free(device_name
, grub_free
);
3989 check_free(dev
, grub_device_close
);
3995 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4006 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4009 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4012 debug("failed to open file %s\n", args
[0]);
4016 buf
= grub_malloc(file
->size
+ 1);
4022 buf
[file
->size
] = 0;
4023 grub_file_read(file
, buf
, file
->size
);
4025 if (grub_strstr(buf
, args
[1]))
4032 grub_check_free(buf
);
4033 grub_file_close(file
);
4038 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4044 ventoy_iso9660_vd pvd
;
4051 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4054 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4057 debug("failed to open file %s\n", args
[0]);
4061 grub_file_seek(file
, 16 * 2048);
4062 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4063 if (len
!= sizeof(pvd
))
4065 debug("failed to read pvd %d\n", len
);
4069 grub_memset(buf
, 0, sizeof(buf
));
4070 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4071 ventoy_set_env(args
[1], buf
);
4073 grub_memset(buf
, 0, sizeof(buf
));
4074 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4075 ventoy_set_env(args
[2], buf
);
4079 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4080 ventoy_set_env(args
[3], buf
);
4083 grub_file_close(file
);
4088 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4099 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4102 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4105 debug("failed to open file %s\n", args
[0]);
4109 grub_memset(buf
, 0, sizeof(buf
));
4110 grub_file_seek(file
, 16 * 2048 + 813);
4111 len
= (int)grub_file_read(file
, buf
, 17);
4114 debug("failed to read create date %d\n", len
);
4118 ventoy_set_env(args
[1], buf
);
4121 grub_file_close(file
);
4126 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4132 ventoy_env_hook_root(1);
4137 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4143 ventoy_env_hook_root(0);
4148 #ifdef GRUB_MACHINE_EFI
4149 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4154 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4160 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4161 if (var
&& *var
== 1)
4169 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4178 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4183 grub_uint64_t FileSectors
= 0;
4184 ventoy_gpt_info
*gpt
= NULL
;
4185 ventoy_part_table
*pt
= NULL
;
4186 grub_uint8_t zeroguid
[16] = {0};
4191 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4194 debug("failed to open file %s\n", args
[0]);
4198 if (file
->size
% 512)
4200 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4204 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4210 FileSectors
= file
->size
/ 512;
4212 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4213 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4215 debug("This is EFI partition table\n");
4217 for (i
= 0; i
< 128; i
++)
4219 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4221 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4223 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4224 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4232 debug("This is MBR partition table\n");
4234 for (i
= 0; i
< 4; i
++)
4236 pt
= gpt
->MBR
.PartTbl
+ i
;
4237 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4239 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4240 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4241 (ulonglong
)FileSectors
);
4250 grub_file_close(file
);
4251 grub_check_free(gpt
);
4252 grub_errno
= GRUB_ERR_NONE
;
4256 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4265 for (i
= 0; i
< 500; i
++)
4267 ret
= grub_getkey_noblock();
4268 if (ret
== GRUB_TERM_NO_KEY
)
4277 grub_printf("\n\n Still have key input after clear.\n");
4285 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4292 int image_sector_size
;
4294 ventoy_chain_head
*chain
;
4295 ventoy_img_chunk
*chunk
;
4296 ventoy_os_param
*osparam
;
4297 ventoy_image_location
*location
;
4298 ventoy_image_disk_region
*region
;
4299 struct grub_acpi_table_header
*acpi
;
4308 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4310 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4316 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4318 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4320 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4324 img_chunk_num
= chain
->img_chunk_num
;
4326 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4327 datalen
= sizeof(ventoy_os_param
) + loclen
;
4329 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4330 acpi
= grub_zalloc(buflen
);
4336 /* Step1: Fill acpi table header */
4337 grub_memcpy(acpi
->signature
, "VTOY", 4);
4338 acpi
->length
= buflen
;
4340 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4341 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4343 acpi
->creator_id
[0] = 1;
4344 acpi
->creator_rev
= 1;
4346 /* Step2: Fill data */
4347 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4348 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4349 osparam
->vtoy_img_location_addr
= 0;
4350 osparam
->vtoy_img_location_len
= loclen
;
4351 osparam
->chksum
= 0;
4352 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4354 location
= (ventoy_image_location
*)(osparam
+ 1);
4355 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4356 location
->image_sector_size
= image_sector_size
;
4357 location
->disk_sector_size
= chain
->disk_sector_size
;
4358 location
->region_count
= img_chunk_num
;
4360 region
= location
->regions
;
4361 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4362 if (512 == image_sector_size
)
4364 for (i
= 0; i
< img_chunk_num
; i
++)
4366 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4367 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4368 region
->disk_start_sector
= chunk
->disk_start_sector
;
4375 for (i
= 0; i
< img_chunk_num
; i
++)
4377 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4378 region
->image_start_sector
= chunk
->img_start_sector
;
4379 region
->disk_start_sector
= chunk
->disk_start_sector
;
4385 /* Step3: Fill acpi checksum */
4387 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4389 /* load acpi table */
4390 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4391 grub_script_execute_sourcecode(cmd
);
4395 VENTOY_CMD_RETURN(0);
4398 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4404 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4405 g_ventoy_last_entry
= -1;
4410 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4416 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4421 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4423 const char *pos
= filename
+ 1;
4431 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4433 grub_strncpy((char *)data
, filename
, 128);
4444 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4447 char *device_name
= NULL
;
4448 grub_device_t dev
= NULL
;
4449 grub_fs_t fs
= NULL
;
4450 char buf
[128] = {0};
4456 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4460 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4462 device_name
= grub_file_get_device_name(args
[0]);
4465 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4469 dev
= grub_device_open(device_name
);
4472 debug("grub_device_open failed, %s\n", device_name
);
4476 fs
= grub_fs_probe(dev
);
4479 debug("grub_fs_probe failed, %s\n", device_name
);
4483 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4487 ventoy_set_env(args
[2], buf
);
4494 check_free(device_name
, grub_free
);
4495 check_free(dev
, grub_device_close
);
4500 int ventoy_load_part_table(const char *diskname
)
4507 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4508 if (!g_ventoy_part_info
)
4513 disk
= grub_disk_open(diskname
);
4516 debug("Failed to open disk %s\n", diskname
);
4520 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4522 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4523 grub_disk_close(disk
);
4525 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4526 dev
= grub_device_open(name
);
4529 /* Check for official Ventoy device */
4530 ret
= ventoy_check_official_device(dev
);
4531 grub_device_close(dev
);
4539 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4540 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4545 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4552 ret
= ventoy_load_part_table(args
[0]);
4558 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4559 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4564 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4567 const char *vcfg
= NULL
;
4572 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4575 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4576 grub_env_set(args
[1], vcfg
);
4581 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4589 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4592 grub_uint8_t zeroguid
[16] = {0};
4597 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4600 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4602 if (id
>= 1 && id
<= 128)
4604 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4612 if (id
>= 1 && id
<= 4)
4614 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4624 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4627 char *device_name
= NULL
;
4628 grub_device_t dev
= NULL
;
4629 grub_fs_t fs
= NULL
;
4634 debug("get fs label for %s\n", args
[0]);
4638 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4642 device_name
= grub_file_get_device_name(args
[0]);
4645 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4649 dev
= grub_device_open(device_name
);
4652 debug("grub_device_open failed, %s\n", device_name
);
4656 fs
= grub_fs_probe(dev
);
4657 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4659 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4663 fs
->fs_label(dev
, &label
);
4666 debug("label=<%s>\n", label
);
4667 ventoy_set_env(args
[1], label
);
4675 check_free(device_name
, grub_free
);
4676 check_free(dev
, grub_device_close
);
4681 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4685 grub_snprintf((char *)data
, 256, "%s", filename
);
4692 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4694 if (info
->dir
&& filename
&& filename
[0] != '.')
4696 grub_snprintf((char *)data
, 256, "%s", filename
);
4703 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4706 char *device_name
= NULL
;
4707 grub_device_t dev
= NULL
;
4708 grub_fs_t fs
= NULL
;
4709 char name
[256] ={0};
4713 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4717 device_name
= grub_file_get_device_name(args
[0]);
4720 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4724 dev
= grub_device_open(device_name
);
4727 debug("grub_device_open failed, %s\n", device_name
);
4731 fs
= grub_fs_probe(dev
);
4734 debug("grub_fs_probe failed, %s\n", device_name
);
4738 fs
->fs_dir(dev
, args
[1], hook
, name
);
4741 ventoy_set_env(args
[2], name
);
4748 check_free(device_name
, grub_free
);
4749 check_free(dev
, grub_device_close
);
4754 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4757 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4760 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4763 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4766 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4776 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4780 for (pos
= args
[0]; *pos
; pos
++)
4794 grub_env_set(args
[1], args
[0]);
4804 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4814 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4819 len
= (int)grub_strlen(buf
);
4820 for (i
= len
; i
> 0; i
--)
4822 if (buf
[i
- 1] == '/')
4824 grub_env_set(args
[1], buf
+ i
);
4829 grub_env_set(args
[1], buf
);
4834 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4836 struct grub_video_mode_info info
;
4843 if (!g_video_mode_list
)
4845 ventoy_enum_video_mode();
4848 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4850 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4854 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4857 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4859 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4860 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4862 VENTOY_CMD_RETURN(0);
4865 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4867 struct grub_video_mode_info info
;
4874 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4876 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4880 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4883 grub_env_set(args
[0], buf
);
4885 VENTOY_CMD_RETURN(0);
4888 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4896 if (!g_video_mode_list
)
4901 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4902 if (id
< g_video_mode_num
)
4904 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4905 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4908 grub_env_set(args
[1], buf
);
4910 VENTOY_CMD_RETURN(0);
4913 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4916 grub_uint32_t loadsector
= 0;
4919 grub_uint32_t boot_catlog
= 0;
4920 grub_uint8_t buf
[512];
4926 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4930 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4933 debug("failed to open %s\n", args
[0]);
4937 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4938 if (boot_catlog
== 0)
4940 debug("No bootcatlog found\n");
4941 grub_file_close(file
);
4945 grub_memset(buf
, 0, sizeof(buf
));
4946 grub_file_seek(file
, boot_catlog
* 2048);
4947 grub_file_read(file
, buf
, sizeof(buf
));
4948 grub_file_close(file
);
4950 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4952 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4954 if (buf
[i
+ 32] == 0x88)
4956 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4957 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4963 if (loadsector
== 0)
4965 debug("No EFI eltorito info found\n");
4969 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4970 grub_env_set(args
[1], value
);
4971 VENTOY_CMD_RETURN(0);
4974 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4979 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4981 if (pfsdir
->initrd
[0])
4986 curpos
= pfsdir
->curpos
;
4987 len
= grub_strlen(filename
);
4991 if ((len
== 1 && filename
[0] == '.') ||
4992 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4997 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5000 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5001 pfsdir
->curpos
= curpos
+ printlen
;
5002 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5003 pfsdir
->curpos
= curpos
;
5004 pfsdir
->fullpath
[curpos
] = 0;
5008 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5011 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5012 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5014 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5016 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5025 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5029 char *device_name
= NULL
;
5030 grub_device_t dev
= NULL
;
5031 grub_fs_t fs
= NULL
;
5032 replace_fs_dir
*pfsdir
= NULL
;
5038 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5042 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5048 device_name
= grub_file_get_device_name(args
[0]);
5054 dev
= grub_device_open(device_name
);
5060 fs
= grub_fs_probe(dev
);
5069 pfsdir
->fullpath
[0] = '/';
5070 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5072 if (pfsdir
->initrd
[0])
5074 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5076 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5078 if (pfsdir
->initrd
[i
] == '/')
5080 pfsdir
->initrd
[i
] = '\\';
5084 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5085 grub_env_set(args
[1], pos
);
5089 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5094 grub_check_free(pfsdir
);
5095 grub_check_free(device_name
);
5096 check_free(dev
, grub_device_close
);
5098 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5101 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5103 const char *pager
= NULL
;
5109 pager
= grub_env_get("pager");
5113 grub_env_set("pager", "1");
5115 else if (pager
[0] == '1')
5121 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5123 grub_env_set("pager", "1");
5126 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5129 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5135 if (g_pager_flag
== 1)
5137 grub_env_unset("pager");
5139 else if (g_pager_flag
== 2)
5141 grub_env_set("pager", g_old_pager
);
5144 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5147 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5149 if (g_json_case_mis_path
[0])
5154 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5156 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5162 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5165 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5167 if (g_json_case_mis_path
[0])
5172 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5174 if (grub_strcasecmp(filename
, "ventoy") == 0)
5176 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5177 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5178 if (g_json_case_mis_path
[0])
5188 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5191 char *device_name
= NULL
;
5192 grub_device_t dev
= NULL
;
5193 grub_fs_t fs
= NULL
;
5194 chk_case_fs_dir fs_dir
;
5200 device_name
= grub_file_get_device_name(args
[0]);
5206 dev
= grub_device_open(device_name
);
5212 fs
= grub_fs_probe(dev
);
5218 fstype
= ventoy_get_fs_type(fs
->name
);
5219 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5224 g_json_case_mis_path
[0] = 0;
5227 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5229 if (g_json_case_mis_path
[0])
5231 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5236 grub_check_free(device_name
);
5237 check_free(dev
, grub_device_close
);
5239 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5242 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5245 grub_partition_t part
;
5246 char priority_str
[3]; /* Maximum value 15 */
5250 if (argc
< 2 || argc
> 3)
5251 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5252 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5254 /* Open the disk if it exists */
5255 disk
= grub_disk_open (args
[0]);
5258 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5262 part
= grub_partition_probe (disk
, args
[1]);
5265 grub_disk_close (disk
);
5266 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5267 "No such partition");
5270 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5272 grub_disk_close (disk
);
5273 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5274 "Not a GPT partition");
5277 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5278 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5282 grub_env_set (args
[2], priority_str
);
5283 grub_env_export (args
[2]);
5287 grub_printf ("Priority is %s\n", priority_str
);
5290 grub_disk_close (disk
);
5291 return GRUB_ERR_NONE
;
5295 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5299 grub_file_t file
= NULL
;
5300 grub_uint32_t loadrba
= 0;
5301 grub_uint32_t boot_catlog
= 0;
5302 grub_uint8_t sector
[512];
5303 boot_info_table
*info
= NULL
;
5308 /* This also trigger a iso9660 fs parse */
5309 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5314 joliet
= grub_iso9660_is_joliet();
5320 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5323 debug("failed to open %s\n", args
[0]);
5327 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5328 if (boot_catlog
== 0)
5330 debug("no bootcatlog found %u\n", boot_catlog
);
5334 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5337 debug("no bios eltorito rba found %u\n", loadrba
);
5341 grub_file_seek(file
, loadrba
* 2048);
5342 grub_file_read(file
, sector
, 512);
5344 info
= (boot_info_table
*)sector
;
5345 if (info
->bi_data0
== 0x7c6ceafa &&
5346 info
->bi_data1
== 0x90900000 &&
5347 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5348 info
->bi_BootFileLocation
== loadrba
)
5350 debug("bootloader is syslinux, %u.\n", loadrba
);
5356 grub_file_close(file
);
5357 grub_errno
= GRUB_ERR_NONE
;
5361 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5364 ventoy_vlnk_part
*node
;
5370 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5372 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5373 ++n
, node
->device
, node
->disksig
,
5374 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5380 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5388 len
= (int)grub_strlen(args
[0]);
5389 if (grub_file_is_vlnk_suffix(args
[0], len
))
5398 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5401 const char *name
= NULL
;
5407 grub_env_unset(args
[1]);
5408 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5411 debug("VLNK SRC: <%s>\n", args
[0]);
5412 debug("VLNK DST: <%s>\n", name
);
5413 grub_env_set(args
[1], name
);
5421 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5425 grub_file_t file
= NULL
;
5436 len
= (int)grub_strlen(args
[0]);
5437 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5439 grub_printf("Invalid vlnk suffix\n");
5443 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5446 grub_printf("Failed to open %s\n", args
[0]);
5450 if (file
->size
!= 32768)
5452 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5456 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5457 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5459 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5464 check_free(file
, grub_file_close
);
5465 grub_errno
= GRUB_ERR_NONE
;
5469 int ventoy_env_init(void)
5473 grub_env_set("vtdebug_flag", "");
5475 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5476 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5477 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5478 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5480 ventoy_filt_register(0, ventoy_wrapper_open
);
5482 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5485 g_grub_param
->grub_env_get
= grub_env_get
;
5486 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5487 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5488 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5489 grub_env_set("env_param", buf
);
5490 grub_env_set("ventoy_env_param", buf
);
5492 grub_env_export("env_param");
5493 grub_env_export("ventoy_env_param");
5496 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5497 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5499 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5500 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5502 grub_env_export("vtoy_winpeshl_ini_addr");
5503 grub_env_export("vtoy_winpeshl_ini_size");
5505 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5506 grub_env_set("vtoy_chain_file_size", buf
);
5507 grub_env_export("vtoy_chain_file_size");
5509 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5510 grub_env_set("vtoy_chain_file_read", buf
);
5511 grub_env_export("vtoy_chain_file_read");
5518 static cmd_para ventoy_cmds
[] =
5520 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
5521 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
5522 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5523 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5524 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5525 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5526 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5527 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5528 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5529 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5530 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5531 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5532 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5533 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5534 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5535 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5536 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5537 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5538 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5539 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5540 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5541 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5542 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5543 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5544 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5545 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5546 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5548 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5549 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5550 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5551 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5552 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5553 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5554 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5556 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5557 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5558 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5559 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5560 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5561 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5562 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5563 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5564 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5565 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5568 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5569 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5570 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5571 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5572 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5573 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5574 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5575 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5576 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5577 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5578 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5580 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5581 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5582 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5583 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5584 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5585 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5586 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5588 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5589 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5590 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5591 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5592 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5593 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5594 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5595 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5596 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5597 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5599 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5600 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5601 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5602 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5603 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5604 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5605 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5606 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5607 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5609 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5610 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5611 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5612 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5615 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5616 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5617 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5619 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5620 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5621 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5624 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5625 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5626 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5627 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5628 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5629 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5630 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5631 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5632 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5633 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5634 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5635 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5637 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5638 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5639 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5640 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5641 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5642 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5643 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5644 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5645 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5646 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5647 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5648 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5650 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5651 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5652 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5653 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5654 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5655 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5656 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5657 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5658 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
5659 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
5660 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
5661 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
5662 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
5663 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
5666 int ventoy_register_all_cmd(void)
5669 cmd_para
*cur
= NULL
;
5671 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5673 cur
= ventoy_cmds
+ i
;
5674 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5675 cur
->summary
, cur
->description
, cur
->parser
);
5681 int ventoy_unregister_all_cmd(void)
5685 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5687 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);