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
*pSig
= (grub_uint32_t
*)data
;
1602 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1605 node
->disksig
= *pSig
;
1606 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1607 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1608 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1610 node
->next
= g_vlnk_part_list
;
1611 g_vlnk_part_list
= node
;
1617 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1624 disk
= grub_disk_open(name
);
1627 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1629 /* skip ventoy device self */
1630 if (sig
!= *(grub_uint32_t
*)data
)
1632 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1635 grub_disk_close(disk
);
1641 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1643 const char *fs
[ventoy_fs_max
+ 1] =
1645 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1650 cur
->dev
= grub_device_open(cur
->device
);
1655 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1661 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1666 char *disk
, *device
;
1667 grub_uint32_t readcrc
, calccrc
;
1668 ventoy_vlnk_part
*cur
;
1669 grub_fs_t fs
= NULL
;
1671 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1675 grub_printf("VLNK invalid guid\n");
1681 readcrc
= vlnk
->crc32
;
1683 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1684 if (readcrc
!= calccrc
)
1688 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1694 if (!g_vlnk_part_list
)
1696 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8);
1699 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1701 if (cur
->disksig
== vlnk
->disk_signature
)
1705 if (cur
->partoffset
== vlnk
->part_offset
)
1708 device
= cur
->device
;
1710 if (cur
->probe
== 0)
1713 ventoy_vlnk_probe_fs(cur
);
1723 struct grub_file file
;
1725 grub_memset(&file
, 0, sizeof(file
));
1726 file
.device
= cur
->dev
;
1727 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1730 cur
->fs
->fs_close(&file
);
1731 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1740 grub_printf("\n==== VLNK Information ====\n"
1741 "Disk Signature: %08x\n"
1742 "Partition Offset: %llu\n"
1743 "File Path: <%s>\n\n",
1744 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1748 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1752 grub_printf("Disk Find: [ NO ]\n");
1757 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1761 grub_printf("Part Find: [ NO ]\n");
1763 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1766 grub_printf("VLNK File: <%s>\n", dst
);
1773 return (1 - filefind
);
1776 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1781 grub_file_t file
= NULL
;
1786 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1788 else if (dir
[0] == '/')
1790 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1794 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1797 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1803 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1804 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1805 grub_file_close(file
);
1807 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1809 rc
= grub_file_add_vlnk(src
, dst
);
1815 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1825 const menu_tip
*tip
;
1826 img_iterator_node
*tmp
;
1827 img_iterator_node
*new_node
;
1828 img_iterator_node
*node
= (img_iterator_node
*)data
;
1830 if (g_enumerate_time_checked
== 0)
1832 g_enumerate_finish_time_ms
= grub_get_time_ms();
1833 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1836 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1838 g_enumerate_time_checked
= 1;
1842 len
= grub_strlen(filename
);
1846 if (node
->level
+ 1 > g_img_max_search_level
)
1851 if ((len
== 1 && filename
[0] == '.') ||
1852 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1857 if (!ventoy_img_name_valid(filename
, len
))
1862 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1867 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1869 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1870 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1873 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1878 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1881 new_node
->level
= node
->level
+ 1;
1882 new_node
->plugin_list_index
= index
;
1883 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1885 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1888 debug("Directory %s ignored...\n", new_node
->dir
);
1889 grub_free(new_node
);
1893 new_node
->tail
= node
->tail
;
1895 new_node
->parent
= node
;
1896 if (!node
->firstchild
)
1898 node
->firstchild
= new_node
;
1901 if (g_img_iterator_tail
)
1903 g_img_iterator_tail
->next
= new_node
;
1904 g_img_iterator_tail
= new_node
;
1908 g_img_iterator_head
.next
= new_node
;
1909 g_img_iterator_tail
= new_node
;
1915 debug("Find a file %s\n", filename
);
1921 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1923 type
= img_type_iso
;
1925 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1927 type
= img_type_wim
;
1929 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1930 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1932 type
= img_type_vhd
;
1934 #ifdef GRUB_MACHINE_EFI
1935 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1937 type
= img_type_efi
;
1940 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1942 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1944 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1945 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1950 type
= img_type_img
;
1952 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1954 type
= img_type_vtoy
;
1956 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1958 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1960 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1961 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1970 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1975 if (g_plugin_image_list
)
1977 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1978 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1979 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1981 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1984 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1986 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1991 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
1993 if (grub_file_is_vlnk_suffix(filename
, len
))
1996 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2003 img
= grub_zalloc(sizeof(img_info
));
2007 img
->plugin_list_index
= index
;
2008 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2010 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2012 img
->size
= info
->size
;
2013 if (vlnk
|| 0 == img
->size
)
2015 if (node
->dir
[0] == '/')
2017 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2021 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2025 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2027 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2032 if (g_ventoy_img_list
)
2034 tail
= *(node
->tail
);
2040 g_ventoy_img_list
= img
;
2043 img
->id
= g_ventoy_img_count
;
2045 if (node
&& NULL
== node
->firstiso
)
2047 node
->firstiso
= img
;
2058 *((img_info
**)(node
->tail
)) = img
;
2059 g_ventoy_img_count
++;
2061 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2063 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2066 img
->tip1
= tip
->tip1
;
2067 img
->tip2
= tip
->tip2
;
2070 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2073 img
->class = g_menu_class
[type
];
2075 img
->menu_prefix
= g_menu_prefix
[type
];
2077 if (img_type_iso
== type
)
2079 if (ventoy_plugin_check_memdisk(img
->path
))
2081 img
->menu_prefix
= "miso";
2085 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2092 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2094 int len
= GRUB_UINT_MAX
;
2095 const char *value
= NULL
;
2096 char name
[32] = {0};
2097 char plat
[32] = {0};
2098 char guidstr
[32] = {0};
2099 ventoy_guid guid
= VENTOY_GUID
;
2100 const char *fmt1
= NULL
;
2101 const char *fmt2
= NULL
;
2102 const char *fmt3
= NULL
;
2103 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2104 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2105 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2106 const char fmtcode
[]={
2107 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2108 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2109 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2110 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2111 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2112 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2115 grub_memset(name
, 0, sizeof(name
));
2116 puint
[0] = grub_swap_bytes32(0x56454e54);
2117 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2118 puint
[2] = grub_swap_bytes32(0x45525349);
2119 puint
[1] = grub_swap_bytes32(0x4f595f56);
2120 value
= ventoy_get_env(name
);
2122 grub_memset(name
, 0, sizeof(name
));
2123 puint
[1] = grub_swap_bytes32(0x5f544f50);
2124 puint
[0] = grub_swap_bytes32(0x56544c45);
2125 fmt1
= ventoy_get_env(name
);
2131 grub_memset(name
, 0, sizeof(name
));
2132 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2133 puint
[0] = grub_swap_bytes32(0x56544c45);
2134 fmt2
= ventoy_get_env(name
);
2136 grub_memset(name
, 0, sizeof(name
));
2137 puint
[1] = grub_swap_bytes32(0x5f434c52);
2138 puint
[0] = grub_swap_bytes32(0x56544c45);
2139 fmt3
= ventoy_get_env(name
);
2141 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2143 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2145 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2146 #pragma GCC diagnostic push
2147 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2148 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2149 fmt1
? fmt1
: fmtdata
,
2150 fmt2
? fmt2
: fmtdata
+ 4,
2151 value
? value
: "", plat
, guidstr
,
2152 fmt3
? fmt3
: fmtdata
+ 6);
2153 #pragma GCC diagnostic pop
2155 grub_memset(name
, 0, sizeof(name
));
2156 puint
[0] = grub_swap_bytes32(0x76746f79);
2157 puint
[2] = grub_swap_bytes32(0x656e7365);
2158 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2159 ventoy_set_env(name
, guidstr
);
2164 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2168 grub_uint8_t md5
[16];
2172 grub_memset(input
, 0, sizeof(input
));
2174 grub_printf("Enter password: ");
2177 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2179 grub_password_get(input
, 128);
2180 if (grub_strcmp(pwd
->text
, input
) == 0)
2185 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2187 grub_password_get(input
, 128);
2188 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2189 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2194 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2196 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2197 grub_password_get(input
+ offset
, 128);
2199 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2200 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2206 grub_printf("Invalid password!\n\n");
2213 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2215 img_info
*minimg
= NULL
;
2216 img_info
*img
= (img_info
*)(node
->firstiso
);
2218 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2220 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2235 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2237 img_iterator_node
*Minchild
= NULL
;
2238 img_iterator_node
*child
= node
->firstchild
;
2240 while (child
&& child
->parent
== node
)
2242 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2246 child
= child
->next
;
2251 Minchild
->select
= 1;
2257 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2260 img_info
*img
= NULL
;
2261 const char *dir_class
= NULL
;
2262 const char *dir_alias
= NULL
;
2263 img_iterator_node
*child
= NULL
;
2264 const menu_tip
*tip
= NULL
;
2266 if (node
->isocnt
== 0 || node
->done
== 1)
2271 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2273 offset
= node
->parent
->dirlen
;
2276 if (node
== &g_img_iterator_head
)
2278 if (g_default_menu_mode
== 0)
2280 if (g_tree_view_menu_style
== 0)
2282 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2283 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2284 " echo 'return ...' \n"
2289 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2290 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2298 node
->dir
[node
->dirlen
- 1] = 0;
2299 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2302 dir_class
= "vtoydir";
2305 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2307 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2310 if (g_tree_view_menu_style
== 0)
2312 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2313 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2314 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2318 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2319 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2320 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2325 dir_alias
= node
->dir
+ offset
;
2327 if (g_tree_view_menu_style
== 0)
2329 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2330 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2331 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2335 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2336 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2337 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2341 if (g_tree_view_menu_style
== 0)
2343 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2344 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2345 " echo 'return ...' \n"
2350 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2351 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2357 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2359 ventoy_dynamic_tree_menu(child
);
2362 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2364 if (g_tree_view_menu_style
== 0)
2366 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2367 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2370 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2371 img
->unsupport
? "[***********] " : "",
2372 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2374 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2378 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2379 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2382 img
->unsupport
? "[***********] " : "",
2383 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2385 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2389 if (node
!= &g_img_iterator_head
)
2391 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2398 static int ventoy_set_default_menu(void)
2404 const char *strdata
= NULL
;
2405 img_info
*cur
= NULL
;
2406 img_info
*default_node
= NULL
;
2407 const char *default_image
= NULL
;
2409 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2410 if (default_image
&& default_image
[0] == '/')
2412 img_len
= grub_strlen(default_image
);
2414 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2416 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2428 if (0 == g_default_menu_mode
)
2430 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2434 def
= grub_strdup(default_image
);
2440 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2442 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2443 if (strdata
&& strdata
[0] == '/')
2445 pos
= def
+ grub_strlen(strdata
);
2456 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2459 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2463 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2471 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2473 img_info
*next
= NULL
;
2474 img_info
*cur
= g_ventoy_img_list
;
2487 g_ventoy_img_list
= NULL
;
2488 g_ventoy_img_count
= 0;
2490 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2493 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2496 img_info
*cur
= g_ventoy_img_list
;
2500 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2502 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2505 img_id
= grub_strtol(args
[0], NULL
, 10);
2506 if (img_id
>= g_ventoy_img_count
)
2508 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2511 debug("Find image %ld name \n", img_id
);
2513 while (cur
&& img_id
> 0)
2521 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2524 debug("image name is %s\n", cur
->name
);
2526 grub_env_set(args
[1], cur
->name
);
2528 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2531 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2535 img_info
*cur
= g_ventoy_img_list
;
2541 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2544 len
= (int)grub_strlen(args
[0]);
2548 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2557 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2560 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2561 grub_env_set("chosen", id
);
2562 grub_env_export("chosen");
2564 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2567 static char g_fake_vlnk_src
[512];
2568 static char g_fake_vlnk_dst
[512];
2569 static grub_uint64_t g_fake_vlnk_size
;
2570 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2576 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2578 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2579 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2581 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2583 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2586 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2592 g_fake_vlnk_src
[0] = 0;
2593 g_fake_vlnk_dst
[0] = 0;
2594 g_fake_vlnk_size
= 0;
2595 grub_file_vtoy_vlnk(NULL
, NULL
);
2597 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2601 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2605 const char *id
= NULL
;
2606 img_info
*cur
= NULL
;
2610 if (argc
< 1 || argc
> 2)
2612 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2615 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2617 grub_env_set(args
[0], grub_strchr(g_fake_vlnk_src
, '/'));
2620 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2621 grub_env_set(args
[1], value
);
2627 id
= grub_env_get("chosen");
2629 pos
= grub_strstr(id
, "VID_");
2632 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2636 cur
= g_ventoy_img_list
;
2641 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2644 grub_env_set(args
[0], cur
->path
);
2648 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2649 grub_env_set(args
[1], value
);
2653 g_svd_replace_offset
= 0;
2655 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2659 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2663 grub_device_t dev
= NULL
;
2664 img_info
*cur
= NULL
;
2665 img_info
*tail
= NULL
;
2666 img_info
*min
= NULL
;
2667 img_info
*head
= NULL
;
2668 const char *strdata
= NULL
;
2669 char *device_name
= NULL
;
2671 img_iterator_node
*node
= NULL
;
2672 img_iterator_node
*tmp
= NULL
;
2678 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2681 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2683 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2688 g_enumerate_time_checked
= 0;
2689 g_enumerate_start_time_ms
= grub_get_time_ms();
2691 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2692 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2694 g_filt_dot_underscore_file
= 1;
2697 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2698 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2700 g_sort_case_sensitive
= 1;
2703 device_name
= grub_file_get_device_name(args
[0]);
2709 g_enum_dev
= dev
= grub_device_open(device_name
);
2715 g_enum_fs
= fs
= grub_fs_probe(dev
);
2721 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2723 debug("unsupported fs:<%s>\n", fs
->name
);
2724 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2728 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2730 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2731 if (strdata
&& strdata
[0] == '1')
2733 g_default_menu_mode
= 1;
2736 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2738 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2740 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2741 if (strdata
&& strdata
[0] == '/')
2743 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2744 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2746 g_img_iterator_head
.dir
[len
++] = '/';
2748 g_img_iterator_head
.dirlen
= len
;
2752 g_img_iterator_head
.dirlen
= 1;
2753 grub_strcpy(g_img_iterator_head
.dir
, "/");
2756 g_img_iterator_head
.tail
= &tail
;
2758 if (g_img_max_search_level
< 0)
2760 g_img_max_search_level
= GRUB_INT_MAX
;
2761 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2762 if (strdata
&& ventoy_is_decimal(strdata
))
2764 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2768 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2769 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2770 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2771 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2772 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2773 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2775 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2777 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2780 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2781 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2783 g_tree_view_menu_style
= 1;
2786 ventoy_set_default_menu();
2788 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2790 ventoy_dynamic_tree_menu(node
);
2794 node
= g_img_iterator_head
.next
;
2802 /* sort image list by image name */
2803 while (g_ventoy_img_list
)
2805 min
= g_ventoy_img_list
;
2806 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2808 if (ventoy_cmp_img(min
, cur
) > 0)
2816 min
->prev
->next
= min
->next
;
2821 min
->next
->prev
= min
->prev
;
2824 if (min
== g_ventoy_img_list
)
2826 g_ventoy_img_list
= min
->next
;
2844 g_ventoy_img_list
= head
;
2846 if (g_default_menu_mode
== 1)
2848 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2849 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2850 " echo 'return ...' \n"
2854 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2856 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2857 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2860 cur
->unsupport
? "[***********] " : "",
2861 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2863 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2866 g_tree_script_buf
[g_tree_script_pos
] = 0;
2867 g_list_script_buf
[g_list_script_pos
] = 0;
2869 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2870 grub_env_set(args
[1], buf
);
2874 check_free(device_name
, grub_free
);
2875 check_free(dev
, grub_device_close
);
2877 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2880 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2887 device_name
= grub_file_get_device_name(filename
);
2899 pos2
= grub_strstr(pos
, ",");
2902 pos2
= grub_strstr(pos
, ")");
2910 disk
= grub_disk_open(pos
);
2913 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2914 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2915 grub_disk_close(disk
);
2922 grub_free(device_name
);
2926 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2928 eltorito_descriptor desc
;
2930 grub_memset(&desc
, 0, sizeof(desc
));
2931 grub_file_seek(file
, 17 * 2048);
2932 grub_file_read(file
, &desc
, sizeof(desc
));
2934 if (desc
.type
!= 0 || desc
.version
!= 1)
2939 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2940 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2948 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2950 grub_uint8_t buf
[512];
2952 grub_file_seek(file
, sector
* 2048);
2953 grub_file_read(file
, buf
, sizeof(buf
));
2955 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2956 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2958 return *((grub_uint32_t
*)(buf
+ 40));
2964 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2968 grub_uint8_t buf
[512];
2969 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2971 grub_file_seek(file
, sector
* 2048);
2972 grub_file_read(file
, buf
, sizeof(buf
));
2974 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2976 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2980 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2985 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2987 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2989 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2993 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2995 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3000 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3002 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3004 if (buf
[36] == parttype
[i
])
3006 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3012 debug("%s does not contain efi eltorito\n", file
->name
);
3016 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3019 const char *fs
= NULL
;
3020 const char *val
= NULL
;
3021 const char *cdprompt
= NULL
;
3023 grub_uint8_t chksum
= 0;
3026 disk
= file
->device
->disk
;
3027 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3029 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3030 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3031 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3033 pos
= grub_strstr(file
->name
, "/");
3039 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3041 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3043 param
->vtoy_img_size
= file
->size
;
3045 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3046 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3048 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3050 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3051 param
->vtoy_reserved
[4] = 0;
3052 if (g_ventoy_chain_type
== 1) /* Windows */
3054 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3055 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3057 param
->vtoy_reserved
[4] = 1;
3061 fs
= ventoy_get_env("ventoy_fs_probe");
3062 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3064 param
->vtoy_reserved
[3] = 1;
3067 param
->vtoy_reserved
[5] = 0;
3068 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3069 if (val
&& val
[0] == '1' && val
[1] == 0)
3071 param
->vtoy_reserved
[5] = 1;
3074 /* ventoy_disk_signature used for vlnk */
3075 param
->vtoy_reserved
[6] = file
->vlnk
;
3076 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3078 /* calculate checksum */
3079 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3081 chksum
+= *((grub_uint8_t
*)param
+ i
);
3083 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3088 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3090 grub_uint32_t i
= 0;
3091 grub_uint64_t total
= 0;
3092 grub_uint64_t fileblk
= 0;
3093 ventoy_img_chunk
*chunk
= NULL
;
3095 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3097 chunk
= chunklist
->chunk
+ i
;
3099 if (chunk
->disk_start_sector
<= start
)
3101 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3105 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3108 fileblk
= (file
->size
+ 511) / 512;
3110 if (total
!= fileblk
)
3112 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3113 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3115 debug("maybe img file to be processed.\n");
3125 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3129 grub_uint32_t i
= 0;
3130 grub_uint32_t sector
= 0;
3131 grub_uint32_t count
= 0;
3132 grub_off_t size
= 0;
3133 grub_off_t read
= 0;
3135 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3136 if (fs_type
== ventoy_fs_exfat
)
3138 grub_fat_get_file_chunk(start
, file
, chunklist
);
3140 else if (fs_type
== ventoy_fs_ext
)
3142 grub_ext_get_file_chunk(start
, file
, chunklist
);
3146 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
3147 file
->read_hook_data
= chunklist
;
3149 for (size
= file
->size
; size
> 0; size
-= read
)
3151 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3152 grub_file_read(file
, NULL
, read
);
3155 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3157 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3158 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3161 if (ventoy_fs_udf
== fs_type
)
3163 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3165 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3166 chunklist
->chunk
[i
].img_start_sector
= sector
;
3167 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3173 len
= (int)grub_strlen(file
->name
);
3174 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3175 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3176 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3177 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3179 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3181 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3191 chunklist
->chunk
[i
].img_start_sector
= sector
;
3192 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3200 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3204 grub_disk_addr_t start
;
3209 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3212 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3215 g_conf_replace_node
= NULL
;
3216 g_conf_replace_offset
= 0;
3218 if (g_img_chunk_list
.chunk
)
3220 grub_free(g_img_chunk_list
.chunk
);
3223 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3225 grub_file_close(file
);
3226 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3229 /* get image chunk data */
3230 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3231 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3232 if (NULL
== g_img_chunk_list
.chunk
)
3234 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3237 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3238 g_img_chunk_list
.cur_chunk
= 0;
3240 start
= file
->device
->disk
->partition
->start
;
3242 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3244 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3245 grub_file_close(file
);
3249 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3252 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3253 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3254 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3257 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3259 grub_uint64_t offset
= 0;
3260 grub_uint32_t align
= 0;
3261 grub_file_t file
= NULL
;
3262 conf_replace
*node
= NULL
;
3268 debug("select conf replace argc:%d\n", argc
);
3275 node
= ventoy_plugin_find_conf_replace(args
[1]);
3278 debug("Conf replace not found for %s\n", args
[1]);
3282 debug("Find conf replace for %s\n", args
[1]);
3284 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3287 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3288 grub_file_close(file
);
3290 else if (node
->img
> 0)
3296 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3300 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3303 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3307 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3309 if (align
> vtoy_max_replace_file_size
)
3311 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3315 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3316 g_conf_replace_new_len
= (int)file
->size
;
3317 g_conf_replace_new_len_align
= align
;
3319 g_conf_replace_node
= node
;
3320 g_conf_replace_offset
= offset
+ 2;
3324 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3325 g_grub_param
->img_replace
.old_name_cnt
= 1;
3326 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3329 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3334 grub_file_close(file
);
3336 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3339 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3345 char configfile
[128];
3346 install_template
*node
= NULL
;
3352 debug("select auto installation argc:%d\n", argc
);
3359 node
= ventoy_plugin_find_install_template(args
[0]);
3362 debug("Auto install template not found for %s\n", args
[0]);
3366 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3368 defidx
= node
->autosel
;
3369 if (node
->timeout
< 0)
3371 node
->cursel
= node
->autosel
- 1;
3372 debug("Auto install template auto select %d\n", node
->autosel
);
3377 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3383 if (node
->timeout
> 0)
3385 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3388 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3389 " echo %s\n}\n", "");
3391 for (i
= 0; i
< node
->templatenum
; i
++)
3393 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3395 node
->templatepath
[i
].path
);
3398 g_ventoy_menu_esc
= 1;
3399 g_ventoy_suppress_esc
= 1;
3400 g_ventoy_suppress_esc_default
= defidx
;
3402 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3403 grub_script_execute_sourcecode(configfile
);
3405 g_ventoy_menu_esc
= 0;
3406 g_ventoy_suppress_esc
= 0;
3407 g_ventoy_suppress_esc_default
= 1;
3411 node
->cursel
= g_ventoy_last_entry
- 1;
3413 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3416 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3422 char configfile
[128];
3423 persistence_config
*node
;
3429 debug("select persistence argc:%d\n", argc
);
3436 node
= ventoy_plugin_find_persistent(args
[0]);
3439 debug("Persistence image not found for %s\n", args
[0]);
3443 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3445 defidx
= node
->autosel
;
3446 if (node
->timeout
< 0)
3448 node
->cursel
= node
->autosel
- 1;
3449 debug("Persistence image auto select %d\n", node
->autosel
);
3454 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3460 if (node
->timeout
> 0)
3462 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3465 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3466 " echo %s\n}\n", "");
3468 for (i
= 0; i
< node
->backendnum
; i
++)
3470 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3472 node
->backendpath
[i
].path
);
3476 g_ventoy_menu_esc
= 1;
3477 g_ventoy_suppress_esc
= 1;
3478 g_ventoy_suppress_esc_default
= defidx
;
3480 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3481 grub_script_execute_sourcecode(configfile
);
3483 g_ventoy_menu_esc
= 0;
3484 g_ventoy_suppress_esc
= 0;
3485 g_ventoy_suppress_esc_default
= 1;
3489 node
->cursel
= g_ventoy_last_entry
- 1;
3491 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3494 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3497 ventoy_img_chunk
*cur
;
3503 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3505 cur
= g_img_chunk_list
.chunk
+ i
;
3506 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3507 cur
->img_start_sector
, cur
->img_end_sector
,
3508 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3512 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3515 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3519 ventoy_img_chunk_list chunklist
;
3524 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3527 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3530 /* get image chunk data */
3531 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3532 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3533 if (NULL
== chunklist
.chunk
)
3535 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3538 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3539 chunklist
.cur_chunk
= 0;
3541 ventoy_get_block_list(file
, &chunklist
, 0);
3543 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3545 grub_printf("########## UNSUPPORTED ###############\n");
3548 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3550 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3552 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3553 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3556 grub_printf("\n==================================\n");
3558 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3560 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3561 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3562 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3563 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3564 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3568 grub_free(chunklist
.chunk
);
3569 grub_file_close(file
);
3571 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3574 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3577 ventoy_grub_param_file_replace
*replace
= NULL
;
3585 replace
= &(g_grub_param
->file_replace
);
3586 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3588 replace
->old_name_cnt
= 0;
3589 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3591 replace
->old_name_cnt
++;
3592 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3595 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3598 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3601 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3604 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3610 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3611 grub_env_set(args
[0], buf
);
3614 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3617 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3625 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3626 grub_printf("%s", g_list_script_buf
);
3630 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3631 grub_printf("%s", g_tree_script_buf
);
3637 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3639 img_info
*cur
= g_ventoy_img_list
;
3647 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3648 grub_printf("name:<%s>\n\n", cur
->name
);
3655 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3661 ventoy_plugin_dump_injection();
3666 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3672 ventoy_plugin_dump_auto_install();
3677 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3683 ventoy_plugin_dump_persistence();
3688 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3699 if (args
[0][0] == '0')
3701 return g_ventoy_memdisk_mode
? 0 : 1;
3703 else if (args
[0][0] == '1')
3705 return g_ventoy_iso_raw
? 0 : 1;
3707 else if (args
[0][0] == '2')
3709 return g_ventoy_iso_uefi_drv
? 0 : 1;
3711 else if (args
[0][0] == '3')
3713 return g_ventoy_grub2_mode
? 0 : 1;
3715 else if (args
[0][0] == '4')
3717 return g_ventoy_wimboot_mode
? 0 : 1;
3723 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3725 static int configfile_mode
= 0;
3726 char memfile
[128] = {0};
3733 * args[0]: 0:normal 1:configfile
3734 * args[1]: 0:list_buf 1:tree_buf
3739 debug("Invalid argc %d\n", argc
);
3745 if (args
[0][0] == '0')
3747 if (args
[1][0] == '0')
3749 grub_script_execute_sourcecode(g_list_script_buf
);
3753 grub_script_execute_sourcecode(g_tree_script_buf
);
3758 if (configfile_mode
)
3760 debug("Now already in F3 mode %d\n", configfile_mode
);
3764 if (args
[1][0] == '0')
3766 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3767 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3771 g_ventoy_last_entry
= -1;
3772 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3773 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3776 configfile_mode
= 1;
3777 grub_script_execute_sourcecode(memfile
);
3778 configfile_mode
= 0;
3784 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3795 g_ventoy_case_insensitive
= 1;
3796 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3797 g_ventoy_case_insensitive
= 0;
3803 grub_file_close(file
);
3809 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3814 const char *isopath
= NULL
;
3816 ventoy_mbr_head mbr
;
3823 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3826 isopath
= grub_env_get("vtoy_iso_part");
3829 debug("isopath is null %p\n", isopath
);
3833 debug("isopath is %s\n", isopath
);
3835 for (id
= 0; id
< 30 && (find
== 0); id
++)
3837 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3838 if (grub_strstr(isopath
, hdname
))
3840 debug("skip %s ...\n", hdname
);
3844 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3846 disk
= grub_disk_open(hdname
);
3849 debug("%s not exist\n", hdname
);
3853 grub_memset(&mbr
, 0, sizeof(mbr
));
3854 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3856 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3858 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3859 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3862 grub_env_set(args
[0], hdname
);
3866 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3870 debug("read %s failed\n", hdname
);
3873 grub_disk_close(disk
);
3879 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3890 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3893 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3896 debug("failed to open file %s\n", args
[0]);
3900 buf
= grub_malloc(len
);
3907 grub_file_read(file
, buf
, len
- 1);
3909 ventoy_get_line(buf
);
3910 ventoy_set_env(args
[1], buf
);
3914 grub_check_free(buf
);
3915 grub_file_close(file
);
3920 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3922 grub_uint64_t end_max
= 0;
3923 int *pCnt
= (int *)data
;
3928 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3929 "0 %llu linear /dev/ventoy %llu\n",
3930 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3932 end_max
= (partition
->len
+ partition
->start
) * 512;
3933 if (end_max
> g_part_end_max
)
3935 g_part_end_max
= end_max
;
3941 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3944 char *device_name
= NULL
;
3945 grub_device_t dev
= NULL
;
3950 g_part_list_pos
= 0;
3952 grub_env_unset("vtoy_img_part_file");
3959 device_name
= grub_file_get_device_name(args
[0]);
3962 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3966 dev
= grub_device_open(device_name
);
3969 debug("grub_device_open failed, %s\n", device_name
);
3973 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3975 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3976 grub_env_set("vtoy_img_part_file", buf
);
3978 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3979 grub_env_set("vtoy_img_part_cnt", buf
);
3981 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
3982 grub_env_set("vtoy_img_max_part_end", buf
);
3986 check_free(device_name
, grub_free
);
3987 check_free(dev
, grub_device_close
);
3993 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4004 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4007 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4010 debug("failed to open file %s\n", args
[0]);
4014 buf
= grub_malloc(file
->size
+ 1);
4020 buf
[file
->size
] = 0;
4021 grub_file_read(file
, buf
, file
->size
);
4023 if (grub_strstr(buf
, args
[1]))
4030 grub_check_free(buf
);
4031 grub_file_close(file
);
4036 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4042 ventoy_iso9660_vd pvd
;
4049 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4052 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4055 debug("failed to open file %s\n", args
[0]);
4059 grub_file_seek(file
, 16 * 2048);
4060 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4061 if (len
!= sizeof(pvd
))
4063 debug("failed to read pvd %d\n", len
);
4067 grub_memset(buf
, 0, sizeof(buf
));
4068 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4069 ventoy_set_env(args
[1], buf
);
4071 grub_memset(buf
, 0, sizeof(buf
));
4072 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4073 ventoy_set_env(args
[2], buf
);
4077 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4078 ventoy_set_env(args
[3], buf
);
4081 grub_file_close(file
);
4086 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4097 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4100 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4103 debug("failed to open file %s\n", args
[0]);
4107 grub_memset(buf
, 0, sizeof(buf
));
4108 grub_file_seek(file
, 16 * 2048 + 813);
4109 len
= (int)grub_file_read(file
, buf
, 17);
4112 debug("failed to read create date %d\n", len
);
4116 ventoy_set_env(args
[1], buf
);
4119 grub_file_close(file
);
4124 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4130 ventoy_env_hook_root(1);
4135 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4141 ventoy_env_hook_root(0);
4146 #ifdef GRUB_MACHINE_EFI
4147 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4152 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4158 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4159 if (var
&& *var
== 1)
4167 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4176 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4181 grub_uint64_t FileSectors
= 0;
4182 ventoy_gpt_info
*gpt
= NULL
;
4183 ventoy_part_table
*pt
= NULL
;
4184 grub_uint8_t zeroguid
[16] = {0};
4189 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4192 debug("failed to open file %s\n", args
[0]);
4196 if (file
->size
% 512)
4198 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4202 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4208 FileSectors
= file
->size
/ 512;
4210 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4211 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4213 debug("This is EFI partition table\n");
4215 for (i
= 0; i
< 128; i
++)
4217 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4219 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4221 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4222 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4230 debug("This is MBR partition table\n");
4232 for (i
= 0; i
< 4; i
++)
4234 pt
= gpt
->MBR
.PartTbl
+ i
;
4235 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4237 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4238 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4239 (ulonglong
)FileSectors
);
4248 grub_file_close(file
);
4249 grub_check_free(gpt
);
4250 grub_errno
= GRUB_ERR_NONE
;
4254 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4263 for (i
= 0; i
< 500; i
++)
4265 ret
= grub_getkey_noblock();
4266 if (ret
== GRUB_TERM_NO_KEY
)
4275 grub_printf("\n\n Still have key input after clear.\n");
4283 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4290 int image_sector_size
;
4292 ventoy_chain_head
*chain
;
4293 ventoy_img_chunk
*chunk
;
4294 ventoy_os_param
*osparam
;
4295 ventoy_image_location
*location
;
4296 ventoy_image_disk_region
*region
;
4297 struct grub_acpi_table_header
*acpi
;
4306 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4308 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4314 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4316 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4318 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4322 img_chunk_num
= chain
->img_chunk_num
;
4324 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4325 datalen
= sizeof(ventoy_os_param
) + loclen
;
4327 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4328 acpi
= grub_zalloc(buflen
);
4334 /* Step1: Fill acpi table header */
4335 grub_memcpy(acpi
->signature
, "VTOY", 4);
4336 acpi
->length
= buflen
;
4338 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4339 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4341 acpi
->creator_id
[0] = 1;
4342 acpi
->creator_rev
= 1;
4344 /* Step2: Fill data */
4345 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4346 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4347 osparam
->vtoy_img_location_addr
= 0;
4348 osparam
->vtoy_img_location_len
= loclen
;
4349 osparam
->chksum
= 0;
4350 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4352 location
= (ventoy_image_location
*)(osparam
+ 1);
4353 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4354 location
->image_sector_size
= image_sector_size
;
4355 location
->disk_sector_size
= chain
->disk_sector_size
;
4356 location
->region_count
= img_chunk_num
;
4358 region
= location
->regions
;
4359 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4360 if (512 == image_sector_size
)
4362 for (i
= 0; i
< img_chunk_num
; i
++)
4364 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4365 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4366 region
->disk_start_sector
= chunk
->disk_start_sector
;
4373 for (i
= 0; i
< img_chunk_num
; i
++)
4375 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4376 region
->image_start_sector
= chunk
->img_start_sector
;
4377 region
->disk_start_sector
= chunk
->disk_start_sector
;
4383 /* Step3: Fill acpi checksum */
4385 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4387 /* load acpi table */
4388 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4389 grub_script_execute_sourcecode(cmd
);
4393 VENTOY_CMD_RETURN(0);
4396 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4402 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4403 g_ventoy_last_entry
= -1;
4408 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4414 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4419 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4421 const char *pos
= filename
+ 1;
4429 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4431 grub_strncpy((char *)data
, filename
, 128);
4442 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4445 char *device_name
= NULL
;
4446 grub_device_t dev
= NULL
;
4447 grub_fs_t fs
= NULL
;
4448 char buf
[128] = {0};
4454 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4458 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4460 device_name
= grub_file_get_device_name(args
[0]);
4463 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4467 dev
= grub_device_open(device_name
);
4470 debug("grub_device_open failed, %s\n", device_name
);
4474 fs
= grub_fs_probe(dev
);
4477 debug("grub_fs_probe failed, %s\n", device_name
);
4481 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4485 ventoy_set_env(args
[2], buf
);
4492 check_free(device_name
, grub_free
);
4493 check_free(dev
, grub_device_close
);
4498 int ventoy_load_part_table(const char *diskname
)
4505 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4506 if (!g_ventoy_part_info
)
4511 disk
= grub_disk_open(diskname
);
4514 debug("Failed to open disk %s\n", diskname
);
4518 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4520 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4521 grub_disk_close(disk
);
4523 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4524 dev
= grub_device_open(name
);
4527 /* Check for official Ventoy device */
4528 ret
= ventoy_check_official_device(dev
);
4529 grub_device_close(dev
);
4537 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4538 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4543 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4550 ret
= ventoy_load_part_table(args
[0]);
4556 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4557 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4562 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4565 const char *vcfg
= NULL
;
4570 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4573 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4574 grub_env_set(args
[1], vcfg
);
4579 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4587 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4590 grub_uint8_t zeroguid
[16] = {0};
4595 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4598 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4600 if (id
>= 1 && id
<= 128)
4602 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4610 if (id
>= 1 && id
<= 4)
4612 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4622 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4625 char *device_name
= NULL
;
4626 grub_device_t dev
= NULL
;
4627 grub_fs_t fs
= NULL
;
4632 debug("get fs label for %s\n", args
[0]);
4636 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4640 device_name
= grub_file_get_device_name(args
[0]);
4643 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4647 dev
= grub_device_open(device_name
);
4650 debug("grub_device_open failed, %s\n", device_name
);
4654 fs
= grub_fs_probe(dev
);
4655 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4657 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4661 fs
->fs_label(dev
, &label
);
4664 debug("label=<%s>\n", label
);
4665 ventoy_set_env(args
[1], label
);
4673 check_free(device_name
, grub_free
);
4674 check_free(dev
, grub_device_close
);
4679 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4683 grub_snprintf((char *)data
, 256, "%s", filename
);
4690 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4692 if (info
->dir
&& filename
&& filename
[0] != '.')
4694 grub_snprintf((char *)data
, 256, "%s", filename
);
4701 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4704 char *device_name
= NULL
;
4705 grub_device_t dev
= NULL
;
4706 grub_fs_t fs
= NULL
;
4707 char name
[256] ={0};
4711 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4715 device_name
= grub_file_get_device_name(args
[0]);
4718 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4722 dev
= grub_device_open(device_name
);
4725 debug("grub_device_open failed, %s\n", device_name
);
4729 fs
= grub_fs_probe(dev
);
4732 debug("grub_fs_probe failed, %s\n", device_name
);
4736 fs
->fs_dir(dev
, args
[1], hook
, name
);
4739 ventoy_set_env(args
[2], name
);
4746 check_free(device_name
, grub_free
);
4747 check_free(dev
, grub_device_close
);
4752 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4755 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4758 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4761 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4764 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4774 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4778 for (pos
= args
[0]; *pos
; pos
++)
4792 grub_env_set(args
[1], args
[0]);
4802 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4812 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4817 len
= (int)grub_strlen(buf
);
4818 for (i
= len
; i
> 0; i
--)
4820 if (buf
[i
- 1] == '/')
4822 grub_env_set(args
[1], buf
+ i
);
4827 grub_env_set(args
[1], buf
);
4832 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4834 struct grub_video_mode_info info
;
4841 if (!g_video_mode_list
)
4843 ventoy_enum_video_mode();
4846 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4848 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4852 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4855 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4857 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4858 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4860 VENTOY_CMD_RETURN(0);
4863 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4865 struct grub_video_mode_info info
;
4872 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4874 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4878 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4881 grub_env_set(args
[0], buf
);
4883 VENTOY_CMD_RETURN(0);
4886 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4894 if (!g_video_mode_list
)
4899 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4900 if (id
< g_video_mode_num
)
4902 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4903 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4906 grub_env_set(args
[1], buf
);
4908 VENTOY_CMD_RETURN(0);
4911 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4914 grub_uint32_t loadsector
= 0;
4917 grub_uint32_t boot_catlog
= 0;
4918 grub_uint8_t buf
[512];
4924 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4928 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4931 debug("failed to open %s\n", args
[0]);
4935 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4936 if (boot_catlog
== 0)
4938 debug("No bootcatlog found\n");
4939 grub_file_close(file
);
4943 grub_memset(buf
, 0, sizeof(buf
));
4944 grub_file_seek(file
, boot_catlog
* 2048);
4945 grub_file_read(file
, buf
, sizeof(buf
));
4946 grub_file_close(file
);
4948 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4950 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4952 if (buf
[i
+ 32] == 0x88)
4954 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4955 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4961 if (loadsector
== 0)
4963 debug("No EFI eltorito info found\n");
4967 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4968 grub_env_set(args
[1], value
);
4969 VENTOY_CMD_RETURN(0);
4972 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4977 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4979 if (pfsdir
->initrd
[0])
4984 curpos
= pfsdir
->curpos
;
4985 len
= grub_strlen(filename
);
4989 if ((len
== 1 && filename
[0] == '.') ||
4990 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4995 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4998 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4999 pfsdir
->curpos
= curpos
+ printlen
;
5000 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5001 pfsdir
->curpos
= curpos
;
5002 pfsdir
->fullpath
[curpos
] = 0;
5006 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5009 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5010 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5012 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5014 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5023 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5027 char *device_name
= NULL
;
5028 grub_device_t dev
= NULL
;
5029 grub_fs_t fs
= NULL
;
5030 replace_fs_dir
*pfsdir
= NULL
;
5036 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5040 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5046 device_name
= grub_file_get_device_name(args
[0]);
5052 dev
= grub_device_open(device_name
);
5058 fs
= grub_fs_probe(dev
);
5067 pfsdir
->fullpath
[0] = '/';
5068 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5070 if (pfsdir
->initrd
[0])
5072 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5074 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5076 if (pfsdir
->initrd
[i
] == '/')
5078 pfsdir
->initrd
[i
] = '\\';
5082 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5083 grub_env_set(args
[1], pos
);
5087 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5092 grub_check_free(pfsdir
);
5093 grub_check_free(device_name
);
5094 check_free(dev
, grub_device_close
);
5096 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5099 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5101 const char *pager
= NULL
;
5107 pager
= grub_env_get("pager");
5111 grub_env_set("pager", "1");
5113 else if (pager
[0] == '1')
5119 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5121 grub_env_set("pager", "1");
5124 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5127 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5133 if (g_pager_flag
== 1)
5135 grub_env_unset("pager");
5137 else if (g_pager_flag
== 2)
5139 grub_env_set("pager", g_old_pager
);
5142 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5145 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5147 if (g_json_case_mis_path
[0])
5152 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5154 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5160 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5163 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5165 if (g_json_case_mis_path
[0])
5170 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5172 if (grub_strcasecmp(filename
, "ventoy") == 0)
5174 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5175 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5176 if (g_json_case_mis_path
[0])
5186 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5189 char *device_name
= NULL
;
5190 grub_device_t dev
= NULL
;
5191 grub_fs_t fs
= NULL
;
5192 chk_case_fs_dir fs_dir
;
5198 device_name
= grub_file_get_device_name(args
[0]);
5204 dev
= grub_device_open(device_name
);
5210 fs
= grub_fs_probe(dev
);
5216 fstype
= ventoy_get_fs_type(fs
->name
);
5217 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5222 g_json_case_mis_path
[0] = 0;
5225 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5227 if (g_json_case_mis_path
[0])
5229 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5234 grub_check_free(device_name
);
5235 check_free(dev
, grub_device_close
);
5237 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5240 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5243 grub_partition_t part
;
5244 char priority_str
[3]; /* Maximum value 15 */
5248 if (argc
< 2 || argc
> 3)
5249 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5250 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5252 /* Open the disk if it exists */
5253 disk
= grub_disk_open (args
[0]);
5256 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5260 part
= grub_partition_probe (disk
, args
[1]);
5263 grub_disk_close (disk
);
5264 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5265 "No such partition");
5268 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5270 grub_disk_close (disk
);
5271 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5272 "Not a GPT partition");
5275 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5276 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5280 grub_env_set (args
[2], priority_str
);
5281 grub_env_export (args
[2]);
5285 grub_printf ("Priority is %s\n", priority_str
);
5288 grub_disk_close (disk
);
5289 return GRUB_ERR_NONE
;
5293 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5297 grub_file_t file
= NULL
;
5298 grub_uint32_t loadrba
= 0;
5299 grub_uint32_t boot_catlog
= 0;
5300 grub_uint8_t sector
[512];
5301 boot_info_table
*info
= NULL
;
5306 /* This also trigger a iso9660 fs parse */
5307 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5312 joliet
= grub_iso9660_is_joliet();
5318 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5321 debug("failed to open %s\n", args
[0]);
5325 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5326 if (boot_catlog
== 0)
5328 debug("no bootcatlog found %u\n", boot_catlog
);
5332 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5335 debug("no bios eltorito rba found %u\n", loadrba
);
5339 grub_file_seek(file
, loadrba
* 2048);
5340 grub_file_read(file
, sector
, 512);
5342 info
= (boot_info_table
*)sector
;
5343 if (info
->bi_data0
== 0x7c6ceafa &&
5344 info
->bi_data1
== 0x90900000 &&
5345 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5346 info
->bi_BootFileLocation
== loadrba
)
5348 debug("bootloader is syslinux, %u.\n", loadrba
);
5354 grub_file_close(file
);
5355 grub_errno
= GRUB_ERR_NONE
;
5359 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5362 ventoy_vlnk_part
*node
;
5368 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5370 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5371 ++n
, node
->device
, node
->disksig
,
5372 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5378 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5386 len
= (int)grub_strlen(args
[0]);
5387 if (grub_file_is_vlnk_suffix(args
[0], len
))
5396 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5399 const char *name
= NULL
;
5405 grub_env_unset(args
[1]);
5406 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5409 debug("VLNK SRC: <%s>\n", args
[0]);
5410 debug("VLNK DST: <%s>\n", name
);
5411 grub_env_set(args
[1], name
);
5419 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5423 grub_file_t file
= NULL
;
5434 len
= (int)grub_strlen(args
[0]);
5435 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5437 grub_printf("Invalid vlnk suffix\n");
5441 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5444 grub_printf("Failed to open %s\n", args
[0]);
5448 if (file
->size
!= 32768)
5450 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5454 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5455 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5457 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5462 check_free(file
, grub_file_close
);
5463 grub_errno
= GRUB_ERR_NONE
;
5467 int ventoy_env_init(void)
5471 grub_env_set("vtdebug_flag", "");
5473 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5474 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5475 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5476 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5478 ventoy_filt_register(0, ventoy_wrapper_open
);
5480 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5483 g_grub_param
->grub_env_get
= grub_env_get
;
5484 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5485 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5486 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5487 grub_env_set("env_param", buf
);
5488 grub_env_set("ventoy_env_param", buf
);
5490 grub_env_export("env_param");
5491 grub_env_export("ventoy_env_param");
5494 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5495 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5497 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5498 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5500 grub_env_export("vtoy_winpeshl_ini_addr");
5501 grub_env_export("vtoy_winpeshl_ini_size");
5503 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5504 grub_env_set("vtoy_chain_file_size", buf
);
5505 grub_env_export("vtoy_chain_file_size");
5507 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5508 grub_env_set("vtoy_chain_file_read", buf
);
5509 grub_env_export("vtoy_chain_file_read");
5516 static cmd_para ventoy_cmds
[] =
5518 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
5519 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
5520 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5521 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5522 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5523 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5524 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5525 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5526 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5527 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5528 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5529 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5530 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5531 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5532 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5533 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5534 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5535 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5536 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5537 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5538 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5539 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5540 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5541 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5542 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5543 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5544 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5546 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5547 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5548 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5549 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5550 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5551 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5552 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5554 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5555 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5556 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5557 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5558 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5559 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5560 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5561 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5562 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5563 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5566 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5567 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5568 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5569 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5570 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5571 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5572 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5573 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5574 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5575 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5576 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5578 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5579 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5580 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5581 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5582 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5583 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5584 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5586 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5587 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5588 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5589 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5590 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5591 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5592 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5593 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5594 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5595 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5597 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5598 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5599 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5600 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5601 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5602 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5603 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5604 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5605 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5607 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5608 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5609 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5610 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5613 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5614 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5615 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5617 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5618 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5619 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5622 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5623 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5624 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5625 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5626 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5627 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5628 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5629 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5630 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5631 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5632 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5633 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5635 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5636 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5637 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5638 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5639 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5640 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5641 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5642 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5643 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5644 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5645 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5646 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5648 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5649 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5650 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5651 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5652 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5653 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5654 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5655 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5656 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
5657 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
5658 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
5659 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
5660 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
5661 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
5664 int ventoy_register_all_cmd(void)
5667 cmd_para
*cur
= NULL
;
5669 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5671 cur
= ventoy_cmds
+ i
;
5672 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5673 cur
->summary
, cur
->description
, cur
->parser
);
5679 int ventoy_unregister_all_cmd(void)
5683 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5685 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);