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 static 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 static const char *g_menu_class
[] =
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 static 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
[256] = {0};
692 grub_vsnprintf(fullpath
, 255, 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
, 255, 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 static 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 grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2571 const char *id
= NULL
;
2572 img_info
*cur
= NULL
;
2576 if (argc
< 1 || argc
> 2)
2578 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2581 id
= grub_env_get("chosen");
2583 pos
= grub_strstr(id
, "VID_");
2586 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2590 cur
= g_ventoy_img_list
;
2595 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2598 grub_env_set(args
[0], cur
->path
);
2602 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2603 grub_env_set(args
[1], value
);
2606 g_svd_replace_offset
= 0;
2608 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2612 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2616 grub_device_t dev
= NULL
;
2617 img_info
*cur
= NULL
;
2618 img_info
*tail
= NULL
;
2619 img_info
*min
= NULL
;
2620 img_info
*head
= NULL
;
2621 const char *strdata
= NULL
;
2622 char *device_name
= NULL
;
2624 img_iterator_node
*node
= NULL
;
2625 img_iterator_node
*tmp
= NULL
;
2631 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2634 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2636 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2641 g_enumerate_time_checked
= 0;
2642 g_enumerate_start_time_ms
= grub_get_time_ms();
2644 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2645 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2647 g_filt_dot_underscore_file
= 1;
2650 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2651 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2653 g_sort_case_sensitive
= 1;
2656 device_name
= grub_file_get_device_name(args
[0]);
2662 g_enum_dev
= dev
= grub_device_open(device_name
);
2668 g_enum_fs
= fs
= grub_fs_probe(dev
);
2674 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2676 debug("unsupported fs:<%s>\n", fs
->name
);
2677 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2681 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2683 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2684 if (strdata
&& strdata
[0] == '1')
2686 g_default_menu_mode
= 1;
2689 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2691 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2693 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2694 if (strdata
&& strdata
[0] == '/')
2696 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2697 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2699 g_img_iterator_head
.dir
[len
++] = '/';
2701 g_img_iterator_head
.dirlen
= len
;
2705 g_img_iterator_head
.dirlen
= 1;
2706 grub_strcpy(g_img_iterator_head
.dir
, "/");
2709 g_img_iterator_head
.tail
= &tail
;
2711 if (g_img_max_search_level
< 0)
2713 g_img_max_search_level
= GRUB_INT_MAX
;
2714 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2715 if (strdata
&& ventoy_is_decimal(strdata
))
2717 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2721 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2722 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2723 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2724 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2725 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2726 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2728 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2730 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2733 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2734 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2736 g_tree_view_menu_style
= 1;
2739 ventoy_set_default_menu();
2741 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2743 ventoy_dynamic_tree_menu(node
);
2747 node
= g_img_iterator_head
.next
;
2755 /* sort image list by image name */
2756 while (g_ventoy_img_list
)
2758 min
= g_ventoy_img_list
;
2759 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2761 if (ventoy_cmp_img(min
, cur
) > 0)
2769 min
->prev
->next
= min
->next
;
2774 min
->next
->prev
= min
->prev
;
2777 if (min
== g_ventoy_img_list
)
2779 g_ventoy_img_list
= min
->next
;
2797 g_ventoy_img_list
= head
;
2799 if (g_default_menu_mode
== 1)
2801 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2802 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2803 " echo 'return ...' \n"
2807 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2809 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2810 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2813 cur
->unsupport
? "[***********] " : "",
2814 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2816 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2819 g_tree_script_buf
[g_tree_script_pos
] = 0;
2820 g_list_script_buf
[g_list_script_pos
] = 0;
2822 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2823 grub_env_set(args
[1], buf
);
2827 check_free(device_name
, grub_free
);
2828 check_free(dev
, grub_device_close
);
2830 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2833 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2840 device_name
= grub_file_get_device_name(filename
);
2852 pos2
= grub_strstr(pos
, ",");
2855 pos2
= grub_strstr(pos
, ")");
2863 disk
= grub_disk_open(pos
);
2866 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2867 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2868 grub_disk_close(disk
);
2875 grub_free(device_name
);
2879 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2881 eltorito_descriptor desc
;
2883 grub_memset(&desc
, 0, sizeof(desc
));
2884 grub_file_seek(file
, 17 * 2048);
2885 grub_file_read(file
, &desc
, sizeof(desc
));
2887 if (desc
.type
!= 0 || desc
.version
!= 1)
2892 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2893 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2901 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2903 grub_uint8_t buf
[512];
2905 grub_file_seek(file
, sector
* 2048);
2906 grub_file_read(file
, buf
, sizeof(buf
));
2908 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2909 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2911 return *((grub_uint32_t
*)(buf
+ 40));
2917 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2921 grub_uint8_t buf
[512];
2922 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2924 grub_file_seek(file
, sector
* 2048);
2925 grub_file_read(file
, buf
, sizeof(buf
));
2927 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2929 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2933 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2938 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2940 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2942 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2946 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2948 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2953 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2955 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2957 if (buf
[36] == parttype
[i
])
2959 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2965 debug("%s does not contain efi eltorito\n", file
->name
);
2969 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2972 const char *fs
= NULL
;
2973 const char *val
= NULL
;
2974 const char *cdprompt
= NULL
;
2976 grub_uint8_t chksum
= 0;
2979 disk
= file
->device
->disk
;
2980 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2982 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2983 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2984 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2986 pos
= grub_strstr(file
->name
, "/");
2992 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2994 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2996 param
->vtoy_img_size
= file
->size
;
2998 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2999 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3001 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3003 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3004 param
->vtoy_reserved
[4] = 0;
3005 if (g_ventoy_chain_type
== 1) /* Windows */
3007 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3008 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3010 param
->vtoy_reserved
[4] = 1;
3014 fs
= ventoy_get_env("ventoy_fs_probe");
3015 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3017 param
->vtoy_reserved
[3] = 1;
3020 param
->vtoy_reserved
[5] = 0;
3021 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3022 if (val
&& val
[0] == '1' && val
[1] == 0)
3024 param
->vtoy_reserved
[5] = 1;
3027 /* ventoy_disk_signature used for vlnk */
3028 param
->vtoy_reserved
[6] = file
->vlnk
;
3029 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3031 /* calculate checksum */
3032 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3034 chksum
+= *((grub_uint8_t
*)param
+ i
);
3036 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3041 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3043 grub_uint32_t i
= 0;
3044 grub_uint64_t total
= 0;
3045 grub_uint64_t fileblk
= 0;
3046 ventoy_img_chunk
*chunk
= NULL
;
3048 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3050 chunk
= chunklist
->chunk
+ i
;
3052 if (chunk
->disk_start_sector
<= start
)
3054 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3058 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3061 fileblk
= (file
->size
+ 511) / 512;
3063 if (total
!= fileblk
)
3065 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3066 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3068 debug("maybe img file to be processed.\n");
3078 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3082 grub_uint32_t i
= 0;
3083 grub_uint32_t sector
= 0;
3084 grub_uint32_t count
= 0;
3085 grub_off_t size
= 0;
3086 grub_off_t read
= 0;
3088 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3089 if (fs_type
== ventoy_fs_exfat
)
3091 grub_fat_get_file_chunk(start
, file
, chunklist
);
3093 else if (fs_type
== ventoy_fs_ext
)
3095 grub_ext_get_file_chunk(start
, file
, chunklist
);
3099 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
3100 file
->read_hook_data
= chunklist
;
3102 for (size
= file
->size
; size
> 0; size
-= read
)
3104 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3105 grub_file_read(file
, NULL
, read
);
3108 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3110 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3111 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3114 if (ventoy_fs_udf
== fs_type
)
3116 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3118 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3119 chunklist
->chunk
[i
].img_start_sector
= sector
;
3120 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3126 len
= (int)grub_strlen(file
->name
);
3127 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3128 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3129 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3130 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3132 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3134 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3144 chunklist
->chunk
[i
].img_start_sector
= sector
;
3145 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3153 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3157 grub_disk_addr_t start
;
3162 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3165 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3168 g_conf_replace_node
= NULL
;
3169 g_conf_replace_offset
= 0;
3171 if (g_img_chunk_list
.chunk
)
3173 grub_free(g_img_chunk_list
.chunk
);
3176 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3178 grub_file_close(file
);
3179 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3182 /* get image chunk data */
3183 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3184 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3185 if (NULL
== g_img_chunk_list
.chunk
)
3187 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3190 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3191 g_img_chunk_list
.cur_chunk
= 0;
3193 start
= file
->device
->disk
->partition
->start
;
3195 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3197 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3198 grub_file_close(file
);
3202 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3205 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3206 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3207 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3210 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3212 grub_uint64_t offset
= 0;
3213 grub_uint32_t align
= 0;
3214 grub_file_t file
= NULL
;
3215 conf_replace
*node
= NULL
;
3221 debug("select conf replace argc:%d\n", argc
);
3228 node
= ventoy_plugin_find_conf_replace(args
[1]);
3231 debug("Conf replace not found for %s\n", args
[1]);
3235 debug("Find conf replace for %s\n", args
[1]);
3237 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3240 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3241 grub_file_close(file
);
3243 else if (node
->img
> 0)
3249 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3253 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3256 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3260 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3262 if (align
> vtoy_max_replace_file_size
)
3264 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3268 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3269 g_conf_replace_new_len
= (int)file
->size
;
3270 g_conf_replace_new_len_align
= align
;
3272 g_conf_replace_node
= node
;
3273 g_conf_replace_offset
= offset
+ 2;
3277 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3278 g_grub_param
->img_replace
.old_name_cnt
= 1;
3279 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3282 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3287 grub_file_close(file
);
3289 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3292 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3298 char configfile
[128];
3299 install_template
*node
= NULL
;
3305 debug("select auto installation argc:%d\n", argc
);
3312 node
= ventoy_plugin_find_install_template(args
[0]);
3315 debug("Auto install template not found for %s\n", args
[0]);
3319 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3321 defidx
= node
->autosel
;
3322 if (node
->timeout
< 0)
3324 node
->cursel
= node
->autosel
- 1;
3325 debug("Auto install template auto select %d\n", node
->autosel
);
3330 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3336 if (node
->timeout
> 0)
3338 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3341 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3342 " echo %s\n}\n", "");
3344 for (i
= 0; i
< node
->templatenum
; i
++)
3346 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3348 node
->templatepath
[i
].path
);
3351 g_ventoy_menu_esc
= 1;
3352 g_ventoy_suppress_esc
= 1;
3353 g_ventoy_suppress_esc_default
= defidx
;
3355 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3356 grub_script_execute_sourcecode(configfile
);
3358 g_ventoy_menu_esc
= 0;
3359 g_ventoy_suppress_esc
= 0;
3360 g_ventoy_suppress_esc_default
= 1;
3364 node
->cursel
= g_ventoy_last_entry
- 1;
3366 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3369 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3375 char configfile
[128];
3376 persistence_config
*node
;
3382 debug("select persistence argc:%d\n", argc
);
3389 node
= ventoy_plugin_find_persistent(args
[0]);
3392 debug("Persistence image not found for %s\n", args
[0]);
3396 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3398 defidx
= node
->autosel
;
3399 if (node
->timeout
< 0)
3401 node
->cursel
= node
->autosel
- 1;
3402 debug("Persistence image auto select %d\n", node
->autosel
);
3407 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3413 if (node
->timeout
> 0)
3415 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3418 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3419 " echo %s\n}\n", "");
3421 for (i
= 0; i
< node
->backendnum
; i
++)
3423 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3425 node
->backendpath
[i
].path
);
3429 g_ventoy_menu_esc
= 1;
3430 g_ventoy_suppress_esc
= 1;
3431 g_ventoy_suppress_esc_default
= defidx
;
3433 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3434 grub_script_execute_sourcecode(configfile
);
3436 g_ventoy_menu_esc
= 0;
3437 g_ventoy_suppress_esc
= 0;
3438 g_ventoy_suppress_esc_default
= 1;
3442 node
->cursel
= g_ventoy_last_entry
- 1;
3444 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3447 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3450 ventoy_img_chunk
*cur
;
3456 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3458 cur
= g_img_chunk_list
.chunk
+ i
;
3459 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3460 cur
->img_start_sector
, cur
->img_end_sector
,
3461 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3465 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3468 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3472 ventoy_img_chunk_list chunklist
;
3477 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3480 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3483 /* get image chunk data */
3484 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3485 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3486 if (NULL
== chunklist
.chunk
)
3488 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3491 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3492 chunklist
.cur_chunk
= 0;
3494 ventoy_get_block_list(file
, &chunklist
, 0);
3496 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3498 grub_printf("########## UNSUPPORTED ###############\n");
3501 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3503 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3505 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3506 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3509 grub_printf("\n==================================\n");
3511 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3513 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3514 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3515 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3516 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3517 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3521 grub_free(chunklist
.chunk
);
3522 grub_file_close(file
);
3524 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3527 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3530 ventoy_grub_param_file_replace
*replace
= NULL
;
3538 replace
= &(g_grub_param
->file_replace
);
3539 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3541 replace
->old_name_cnt
= 0;
3542 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3544 replace
->old_name_cnt
++;
3545 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3548 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3551 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3554 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3557 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3563 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3564 grub_env_set(args
[0], buf
);
3567 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3570 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3578 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3579 grub_printf("%s", g_list_script_buf
);
3583 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3584 grub_printf("%s", g_tree_script_buf
);
3590 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3592 img_info
*cur
= g_ventoy_img_list
;
3600 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3601 grub_printf("name:<%s>\n\n", cur
->name
);
3608 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3614 ventoy_plugin_dump_injection();
3619 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3625 ventoy_plugin_dump_auto_install();
3630 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3636 ventoy_plugin_dump_persistence();
3641 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3652 if (args
[0][0] == '0')
3654 return g_ventoy_memdisk_mode
? 0 : 1;
3656 else if (args
[0][0] == '1')
3658 return g_ventoy_iso_raw
? 0 : 1;
3660 else if (args
[0][0] == '2')
3662 return g_ventoy_iso_uefi_drv
? 0 : 1;
3664 else if (args
[0][0] == '3')
3666 return g_ventoy_grub2_mode
? 0 : 1;
3668 else if (args
[0][0] == '4')
3670 return g_ventoy_wimboot_mode
? 0 : 1;
3676 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3678 static int configfile_mode
= 0;
3679 char memfile
[128] = {0};
3686 * args[0]: 0:normal 1:configfile
3687 * args[1]: 0:list_buf 1:tree_buf
3692 debug("Invalid argc %d\n", argc
);
3698 if (args
[0][0] == '0')
3700 if (args
[1][0] == '0')
3702 grub_script_execute_sourcecode(g_list_script_buf
);
3706 grub_script_execute_sourcecode(g_tree_script_buf
);
3711 if (configfile_mode
)
3713 debug("Now already in F3 mode %d\n", configfile_mode
);
3717 if (args
[1][0] == '0')
3719 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3720 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3724 g_ventoy_last_entry
= -1;
3725 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3726 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3729 configfile_mode
= 1;
3730 grub_script_execute_sourcecode(memfile
);
3731 configfile_mode
= 0;
3737 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3748 g_ventoy_case_insensitive
= 1;
3749 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3750 g_ventoy_case_insensitive
= 0;
3756 grub_file_close(file
);
3762 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3767 const char *isopath
= NULL
;
3769 ventoy_mbr_head mbr
;
3776 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3779 isopath
= grub_env_get("vtoy_iso_part");
3782 debug("isopath is null %p\n", isopath
);
3786 debug("isopath is %s\n", isopath
);
3788 for (id
= 0; id
< 30 && (find
== 0); id
++)
3790 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3791 if (grub_strstr(isopath
, hdname
))
3793 debug("skip %s ...\n", hdname
);
3797 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3799 disk
= grub_disk_open(hdname
);
3802 debug("%s not exist\n", hdname
);
3806 grub_memset(&mbr
, 0, sizeof(mbr
));
3807 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3809 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3811 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3812 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3815 grub_env_set(args
[0], hdname
);
3819 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3823 debug("read %s failed\n", hdname
);
3826 grub_disk_close(disk
);
3832 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3843 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3846 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3849 debug("failed to open file %s\n", args
[0]);
3853 buf
= grub_malloc(len
);
3860 grub_file_read(file
, buf
, len
- 1);
3862 ventoy_get_line(buf
);
3863 ventoy_set_env(args
[1], buf
);
3867 grub_check_free(buf
);
3868 grub_file_close(file
);
3873 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3875 grub_uint64_t end_max
= 0;
3876 int *pCnt
= (int *)data
;
3881 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3882 "0 %llu linear /dev/ventoy %llu\n",
3883 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3885 end_max
= (partition
->len
+ partition
->start
) * 512;
3886 if (end_max
> g_part_end_max
)
3888 g_part_end_max
= end_max
;
3894 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3897 char *device_name
= NULL
;
3898 grub_device_t dev
= NULL
;
3903 g_part_list_pos
= 0;
3905 grub_env_unset("vtoy_img_part_file");
3912 device_name
= grub_file_get_device_name(args
[0]);
3915 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3919 dev
= grub_device_open(device_name
);
3922 debug("grub_device_open failed, %s\n", device_name
);
3926 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3928 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3929 grub_env_set("vtoy_img_part_file", buf
);
3931 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3932 grub_env_set("vtoy_img_part_cnt", buf
);
3934 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
3935 grub_env_set("vtoy_img_max_part_end", buf
);
3939 check_free(device_name
, grub_free
);
3940 check_free(dev
, grub_device_close
);
3946 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3957 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3960 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3963 debug("failed to open file %s\n", args
[0]);
3967 buf
= grub_malloc(file
->size
+ 1);
3973 buf
[file
->size
] = 0;
3974 grub_file_read(file
, buf
, file
->size
);
3976 if (grub_strstr(buf
, args
[1]))
3983 grub_check_free(buf
);
3984 grub_file_close(file
);
3989 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3995 ventoy_iso9660_vd pvd
;
4002 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4005 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4008 debug("failed to open file %s\n", args
[0]);
4012 grub_file_seek(file
, 16 * 2048);
4013 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4014 if (len
!= sizeof(pvd
))
4016 debug("failed to read pvd %d\n", len
);
4020 grub_memset(buf
, 0, sizeof(buf
));
4021 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4022 ventoy_set_env(args
[1], buf
);
4024 grub_memset(buf
, 0, sizeof(buf
));
4025 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4026 ventoy_set_env(args
[2], buf
);
4030 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4031 ventoy_set_env(args
[3], buf
);
4034 grub_file_close(file
);
4039 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4050 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4053 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4056 debug("failed to open file %s\n", args
[0]);
4060 grub_memset(buf
, 0, sizeof(buf
));
4061 grub_file_seek(file
, 16 * 2048 + 813);
4062 len
= (int)grub_file_read(file
, buf
, 17);
4065 debug("failed to read create date %d\n", len
);
4069 ventoy_set_env(args
[1], buf
);
4072 grub_file_close(file
);
4077 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4083 ventoy_env_hook_root(1);
4088 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4094 ventoy_env_hook_root(0);
4099 #ifdef GRUB_MACHINE_EFI
4100 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4105 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4111 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4112 if (var
&& *var
== 1)
4120 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4129 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4134 grub_uint64_t FileSectors
= 0;
4135 ventoy_gpt_info
*gpt
= NULL
;
4136 ventoy_part_table
*pt
= NULL
;
4137 grub_uint8_t zeroguid
[16] = {0};
4142 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4145 debug("failed to open file %s\n", args
[0]);
4149 if (file
->size
% 512)
4151 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4155 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4161 FileSectors
= file
->size
/ 512;
4163 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4164 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4166 debug("This is EFI partition table\n");
4168 for (i
= 0; i
< 128; i
++)
4170 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4172 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4174 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4175 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4183 debug("This is MBR partition table\n");
4185 for (i
= 0; i
< 4; i
++)
4187 pt
= gpt
->MBR
.PartTbl
+ i
;
4188 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4190 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4191 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4192 (ulonglong
)FileSectors
);
4201 grub_file_close(file
);
4202 grub_check_free(gpt
);
4203 grub_errno
= GRUB_ERR_NONE
;
4207 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4216 for (i
= 0; i
< 500; i
++)
4218 ret
= grub_getkey_noblock();
4219 if (ret
== GRUB_TERM_NO_KEY
)
4228 grub_printf("\n\n Still have key input after clear.\n");
4236 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4243 int image_sector_size
;
4245 ventoy_chain_head
*chain
;
4246 ventoy_img_chunk
*chunk
;
4247 ventoy_os_param
*osparam
;
4248 ventoy_image_location
*location
;
4249 ventoy_image_disk_region
*region
;
4250 struct grub_acpi_table_header
*acpi
;
4259 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4261 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4267 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4269 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4271 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4275 img_chunk_num
= chain
->img_chunk_num
;
4277 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4278 datalen
= sizeof(ventoy_os_param
) + loclen
;
4280 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4281 acpi
= grub_zalloc(buflen
);
4287 /* Step1: Fill acpi table header */
4288 grub_memcpy(acpi
->signature
, "VTOY", 4);
4289 acpi
->length
= buflen
;
4291 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4292 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4294 acpi
->creator_id
[0] = 1;
4295 acpi
->creator_rev
= 1;
4297 /* Step2: Fill data */
4298 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4299 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4300 osparam
->vtoy_img_location_addr
= 0;
4301 osparam
->vtoy_img_location_len
= loclen
;
4302 osparam
->chksum
= 0;
4303 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4305 location
= (ventoy_image_location
*)(osparam
+ 1);
4306 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4307 location
->image_sector_size
= image_sector_size
;
4308 location
->disk_sector_size
= chain
->disk_sector_size
;
4309 location
->region_count
= img_chunk_num
;
4311 region
= location
->regions
;
4312 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4313 if (512 == image_sector_size
)
4315 for (i
= 0; i
< img_chunk_num
; i
++)
4317 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4318 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4319 region
->disk_start_sector
= chunk
->disk_start_sector
;
4326 for (i
= 0; i
< img_chunk_num
; i
++)
4328 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4329 region
->image_start_sector
= chunk
->img_start_sector
;
4330 region
->disk_start_sector
= chunk
->disk_start_sector
;
4336 /* Step3: Fill acpi checksum */
4338 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4340 /* load acpi table */
4341 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4342 grub_script_execute_sourcecode(cmd
);
4346 VENTOY_CMD_RETURN(0);
4349 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4355 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4356 g_ventoy_last_entry
= -1;
4361 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4367 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4372 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4374 const char *pos
= filename
+ 1;
4382 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4384 grub_strncpy((char *)data
, filename
, 128);
4395 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4398 char *device_name
= NULL
;
4399 grub_device_t dev
= NULL
;
4400 grub_fs_t fs
= NULL
;
4401 char buf
[128] = {0};
4407 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4411 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4413 device_name
= grub_file_get_device_name(args
[0]);
4416 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4420 dev
= grub_device_open(device_name
);
4423 debug("grub_device_open failed, %s\n", device_name
);
4427 fs
= grub_fs_probe(dev
);
4430 debug("grub_fs_probe failed, %s\n", device_name
);
4434 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4438 ventoy_set_env(args
[2], buf
);
4445 check_free(device_name
, grub_free
);
4446 check_free(dev
, grub_device_close
);
4451 int ventoy_load_part_table(const char *diskname
)
4458 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4459 if (!g_ventoy_part_info
)
4464 disk
= grub_disk_open(diskname
);
4467 debug("Failed to open disk %s\n", diskname
);
4471 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4473 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4474 grub_disk_close(disk
);
4476 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4477 dev
= grub_device_open(name
);
4480 /* Check for official Ventoy device */
4481 ret
= ventoy_check_official_device(dev
);
4482 grub_device_close(dev
);
4490 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4491 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4496 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4503 ret
= ventoy_load_part_table(args
[0]);
4509 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4510 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4515 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4518 const char *vcfg
= NULL
;
4523 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4526 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4527 grub_env_set(args
[1], vcfg
);
4532 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4540 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4543 grub_uint8_t zeroguid
[16] = {0};
4548 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4551 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4553 if (id
>= 1 && id
<= 128)
4555 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4563 if (id
>= 1 && id
<= 4)
4565 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4575 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4578 char *device_name
= NULL
;
4579 grub_device_t dev
= NULL
;
4580 grub_fs_t fs
= NULL
;
4585 debug("get fs label for %s\n", args
[0]);
4589 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4593 device_name
= grub_file_get_device_name(args
[0]);
4596 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4600 dev
= grub_device_open(device_name
);
4603 debug("grub_device_open failed, %s\n", device_name
);
4607 fs
= grub_fs_probe(dev
);
4608 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4610 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4614 fs
->fs_label(dev
, &label
);
4617 debug("label=<%s>\n", label
);
4618 ventoy_set_env(args
[1], label
);
4626 check_free(device_name
, grub_free
);
4627 check_free(dev
, grub_device_close
);
4632 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4636 grub_snprintf((char *)data
, 256, "%s", filename
);
4643 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4645 if (info
->dir
&& filename
&& filename
[0] != '.')
4647 grub_snprintf((char *)data
, 256, "%s", filename
);
4654 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4657 char *device_name
= NULL
;
4658 grub_device_t dev
= NULL
;
4659 grub_fs_t fs
= NULL
;
4660 char name
[256] ={0};
4664 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4668 device_name
= grub_file_get_device_name(args
[0]);
4671 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4675 dev
= grub_device_open(device_name
);
4678 debug("grub_device_open failed, %s\n", device_name
);
4682 fs
= grub_fs_probe(dev
);
4685 debug("grub_fs_probe failed, %s\n", device_name
);
4689 fs
->fs_dir(dev
, args
[1], hook
, name
);
4692 ventoy_set_env(args
[2], name
);
4699 check_free(device_name
, grub_free
);
4700 check_free(dev
, grub_device_close
);
4705 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4708 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4711 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4714 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4717 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4727 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4731 for (pos
= args
[0]; *pos
; pos
++)
4745 grub_env_set(args
[1], args
[0]);
4755 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4765 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4770 len
= (int)grub_strlen(buf
);
4771 for (i
= len
; i
> 0; i
--)
4773 if (buf
[i
- 1] == '/')
4775 grub_env_set(args
[1], buf
+ i
);
4780 grub_env_set(args
[1], buf
);
4785 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4787 struct grub_video_mode_info info
;
4794 if (!g_video_mode_list
)
4796 ventoy_enum_video_mode();
4799 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4801 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4805 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4808 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4810 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4811 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4813 VENTOY_CMD_RETURN(0);
4816 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4818 struct grub_video_mode_info info
;
4825 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4827 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4831 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4834 grub_env_set(args
[0], buf
);
4836 VENTOY_CMD_RETURN(0);
4839 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4847 if (!g_video_mode_list
)
4852 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4853 if (id
< g_video_mode_num
)
4855 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4856 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4859 grub_env_set(args
[1], buf
);
4861 VENTOY_CMD_RETURN(0);
4864 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4867 grub_uint32_t loadsector
= 0;
4870 grub_uint32_t boot_catlog
= 0;
4871 grub_uint8_t buf
[512];
4877 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4881 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4884 debug("failed to open %s\n", args
[0]);
4888 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4889 if (boot_catlog
== 0)
4891 debug("No bootcatlog found\n");
4892 grub_file_close(file
);
4896 grub_memset(buf
, 0, sizeof(buf
));
4897 grub_file_seek(file
, boot_catlog
* 2048);
4898 grub_file_read(file
, buf
, sizeof(buf
));
4899 grub_file_close(file
);
4901 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4903 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4905 if (buf
[i
+ 32] == 0x88)
4907 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4908 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4914 if (loadsector
== 0)
4916 debug("No EFI eltorito info found\n");
4920 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4921 grub_env_set(args
[1], value
);
4922 VENTOY_CMD_RETURN(0);
4925 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4930 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4932 if (pfsdir
->initrd
[0])
4937 curpos
= pfsdir
->curpos
;
4938 len
= grub_strlen(filename
);
4942 if ((len
== 1 && filename
[0] == '.') ||
4943 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4948 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4951 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4952 pfsdir
->curpos
= curpos
+ printlen
;
4953 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4954 pfsdir
->curpos
= curpos
;
4955 pfsdir
->fullpath
[curpos
] = 0;
4959 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4962 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4963 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4965 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4967 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4976 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4980 char *device_name
= NULL
;
4981 grub_device_t dev
= NULL
;
4982 grub_fs_t fs
= NULL
;
4983 replace_fs_dir
*pfsdir
= NULL
;
4989 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4993 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4999 device_name
= grub_file_get_device_name(args
[0]);
5005 dev
= grub_device_open(device_name
);
5011 fs
= grub_fs_probe(dev
);
5020 pfsdir
->fullpath
[0] = '/';
5021 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5023 if (pfsdir
->initrd
[0])
5025 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5027 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5029 if (pfsdir
->initrd
[i
] == '/')
5031 pfsdir
->initrd
[i
] = '\\';
5035 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5036 grub_env_set(args
[1], pos
);
5040 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5045 grub_check_free(pfsdir
);
5046 grub_check_free(device_name
);
5047 check_free(dev
, grub_device_close
);
5049 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5052 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5054 const char *pager
= NULL
;
5060 pager
= grub_env_get("pager");
5064 grub_env_set("pager", "1");
5066 else if (pager
[0] == '1')
5072 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5074 grub_env_set("pager", "1");
5077 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5080 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5086 if (g_pager_flag
== 1)
5088 grub_env_unset("pager");
5090 else if (g_pager_flag
== 2)
5092 grub_env_set("pager", g_old_pager
);
5095 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5098 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5100 if (g_json_case_mis_path
[0])
5105 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5107 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5113 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5116 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5118 if (g_json_case_mis_path
[0])
5123 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5125 if (grub_strcasecmp(filename
, "ventoy") == 0)
5127 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5128 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5129 if (g_json_case_mis_path
[0])
5139 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5142 char *device_name
= NULL
;
5143 grub_device_t dev
= NULL
;
5144 grub_fs_t fs
= NULL
;
5145 chk_case_fs_dir fs_dir
;
5151 device_name
= grub_file_get_device_name(args
[0]);
5157 dev
= grub_device_open(device_name
);
5163 fs
= grub_fs_probe(dev
);
5169 fstype
= ventoy_get_fs_type(fs
->name
);
5170 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5175 g_json_case_mis_path
[0] = 0;
5178 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5180 if (g_json_case_mis_path
[0])
5182 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5187 grub_check_free(device_name
);
5188 check_free(dev
, grub_device_close
);
5190 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5193 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5196 grub_partition_t part
;
5197 char priority_str
[3]; /* Maximum value 15 */
5201 if (argc
< 2 || argc
> 3)
5202 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5203 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5205 /* Open the disk if it exists */
5206 disk
= grub_disk_open (args
[0]);
5209 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5213 part
= grub_partition_probe (disk
, args
[1]);
5216 grub_disk_close (disk
);
5217 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5218 "No such partition");
5221 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5223 grub_disk_close (disk
);
5224 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5225 "Not a GPT partition");
5228 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5229 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5233 grub_env_set (args
[2], priority_str
);
5234 grub_env_export (args
[2]);
5238 grub_printf ("Priority is %s\n", priority_str
);
5241 grub_disk_close (disk
);
5242 return GRUB_ERR_NONE
;
5246 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5250 grub_file_t file
= NULL
;
5251 grub_uint32_t loadrba
= 0;
5252 grub_uint32_t boot_catlog
= 0;
5253 grub_uint8_t sector
[512];
5254 boot_info_table
*info
= NULL
;
5259 /* This also trigger a iso9660 fs parse */
5260 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5265 joliet
= grub_iso9660_is_joliet();
5271 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5274 debug("failed to open %s\n", args
[0]);
5278 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5279 if (boot_catlog
== 0)
5281 debug("no bootcatlog found %u\n", boot_catlog
);
5285 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5288 debug("no bios eltorito rba found %u\n", loadrba
);
5292 grub_file_seek(file
, loadrba
* 2048);
5293 grub_file_read(file
, sector
, 512);
5295 info
= (boot_info_table
*)sector
;
5296 if (info
->bi_data0
== 0x7c6ceafa &&
5297 info
->bi_data1
== 0x90900000 &&
5298 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5299 info
->bi_BootFileLocation
== loadrba
)
5301 debug("bootloader is syslinux, %u.\n", loadrba
);
5307 grub_file_close(file
);
5308 grub_errno
= GRUB_ERR_NONE
;
5312 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5315 ventoy_vlnk_part
*node
;
5321 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5323 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5324 ++n
, node
->device
, node
->disksig
,
5325 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5331 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5339 len
= (int)grub_strlen(args
[0]);
5340 if (grub_file_is_vlnk_suffix(args
[0], len
))
5349 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5352 const char *name
= NULL
;
5358 grub_env_unset(args
[1]);
5359 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5362 debug("VLNK SRC: <%s>\n", args
[0]);
5363 debug("VLNK DST: <%s>\n", name
);
5364 grub_env_set(args
[1], name
);
5372 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5376 grub_file_t file
= NULL
;
5387 len
= (int)grub_strlen(args
[0]);
5388 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5390 grub_printf("Invalid vlnk suffix\n");
5394 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5397 grub_printf("Failed to open %s\n", args
[0]);
5401 if (file
->size
!= 32768)
5403 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5407 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5408 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5410 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5415 check_free(file
, grub_file_close
);
5416 grub_errno
= GRUB_ERR_NONE
;
5420 int ventoy_env_init(void)
5424 grub_env_set("vtdebug_flag", "");
5426 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5427 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5428 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5429 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5431 ventoy_filt_register(0, ventoy_wrapper_open
);
5433 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5436 g_grub_param
->grub_env_get
= grub_env_get
;
5437 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5438 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5439 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5440 grub_env_set("env_param", buf
);
5441 grub_env_set("ventoy_env_param", buf
);
5443 grub_env_export("env_param");
5444 grub_env_export("ventoy_env_param");
5447 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5448 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5450 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5451 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5453 grub_env_export("vtoy_winpeshl_ini_addr");
5454 grub_env_export("vtoy_winpeshl_ini_size");
5456 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5457 grub_env_set("vtoy_chain_file_size", buf
);
5458 grub_env_export("vtoy_chain_file_size");
5460 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5461 grub_env_set("vtoy_chain_file_read", buf
);
5462 grub_env_export("vtoy_chain_file_read");
5469 static cmd_para ventoy_cmds
[] =
5471 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5472 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5473 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5474 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5475 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5476 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5477 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5478 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5479 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5480 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5481 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5482 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5483 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5484 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5485 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5486 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5487 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5488 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5489 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5490 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5491 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5492 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5493 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5494 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5495 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5497 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5498 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5499 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5500 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5501 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5502 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5503 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5505 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5506 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5507 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5508 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5509 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5510 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5511 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5512 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5513 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5514 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5517 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5518 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5519 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5520 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5521 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5522 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5523 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5524 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5525 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5526 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5527 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5529 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5530 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5531 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5532 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5533 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5534 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5535 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5537 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5538 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5539 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5540 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5541 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5542 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5543 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5544 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5545 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5546 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5548 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5549 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5550 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5551 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5552 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5553 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5554 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5555 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5556 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5558 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5559 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5560 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5561 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5564 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5565 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5566 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5568 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5569 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5570 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5573 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5574 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5575 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5576 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5577 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5578 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5579 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5580 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5581 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5582 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5583 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5584 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5586 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5587 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5588 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5589 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5590 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5591 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5592 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5593 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5594 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5595 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5596 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5597 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5599 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5600 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5601 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5602 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5603 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5604 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5605 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5606 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5607 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
5608 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
5609 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
5610 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
5613 int ventoy_register_all_cmd(void)
5616 cmd_para
*cur
= NULL
;
5618 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5620 cur
= ventoy_cmds
+ i
;
5621 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5622 cur
->summary
, cur
->description
, cur
->parser
);
5628 int ventoy_unregister_all_cmd(void)
5632 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5634 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);