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 char *g_tree_script_buf
= NULL
;
121 int g_tree_script_pos
= 0;
122 int g_tree_script_pre
= 0;
124 static char *g_list_script_buf
= NULL
;
125 static int g_list_script_pos
= 0;
127 static char *g_part_list_buf
= NULL
;
128 static int g_part_list_pos
= 0;
129 static grub_uint64_t g_part_end_max
= 0;
131 static int g_video_mode_max
= 0;
132 static int g_video_mode_num
= 0;
133 static ventoy_video_mode
*g_video_mode_list
= NULL
;
135 static int g_enumerate_time_checked
= 0;
136 static grub_uint64_t g_enumerate_start_time_ms
;
137 static grub_uint64_t g_enumerate_finish_time_ms
;
138 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
140 static int g_pager_flag
= 0;
141 static char g_old_pager
[32];
143 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
145 const char *g_menu_class
[img_type_max
] =
147 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
150 const char *g_menu_prefix
[img_type_max
] =
152 "iso", "wim", "efi", "img", "vhd", "vtoy"
155 static int g_vtoy_load_prompt
= 0;
156 static char g_vtoy_prompt_msg
[64];
158 static char g_json_case_mis_path
[32];
160 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
162 int ventoy_get_fs_type(const char *fs
)
166 return ventoy_fs_max
;
168 else if (grub_strncmp(fs
, "exfat", 5) == 0)
170 return ventoy_fs_exfat
;
172 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
174 return ventoy_fs_ntfs
;
176 else if (grub_strncmp(fs
, "ext", 3) == 0)
178 return ventoy_fs_ext
;
180 else if (grub_strncmp(fs
, "xfs", 3) == 0)
182 return ventoy_fs_xfs
;
184 else if (grub_strncmp(fs
, "udf", 3) == 0)
186 return ventoy_fs_udf
;
188 else if (grub_strncmp(fs
, "fat", 3) == 0)
190 return ventoy_fs_fat
;
193 return ventoy_fs_max
;
196 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
215 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
217 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
221 static int ventoy_control_get_flag(const char *key
)
223 const char *val
= ventoy_get_env(key
);
225 if (val
&& val
[0] == '1' && val
[1] == 0)
232 static grub_err_t
ventoy_fs_close(grub_file_t file
)
234 grub_file_close(g_old_file
);
235 grub_free(file
->data
);
243 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
249 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
254 for (i
= 0; i
< g_video_mode_num
; i
++)
256 if (g_video_mode_list
[i
].width
== info
->width
&&
257 g_video_mode_list
[i
].height
== info
->height
&&
258 g_video_mode_list
[i
].bpp
== info
->bpp
)
264 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
265 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
266 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
269 if (g_video_mode_num
== g_video_mode_max
)
271 g_video_mode_max
*= 2;
272 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
278 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
280 if (v1
->bpp
== v2
->bpp
)
282 if (v1
->width
== v2
->width
)
284 if (v1
->height
== v2
->height
)
290 return (v1
->height
< v2
->height
) ? -1 : 1;
295 return (v1
->width
< v2
->width
) ? -1 : 1;
300 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
304 static int ventoy_enum_video_mode(void)
307 grub_video_adapter_t adapter
;
308 grub_video_driver_id_t id
;
309 ventoy_video_mode mode
;
311 g_video_mode_num
= 0;
312 g_video_mode_max
= 1024;
313 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
314 if (!g_video_mode_list
)
319 #ifdef GRUB_MACHINE_PCBIOS
320 grub_dl_load ("vbe");
323 id
= grub_video_get_driver_id ();
325 FOR_VIDEO_ADAPTERS (adapter
)
327 if (!adapter
->iterate
||
328 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
329 adapter
->init() != GRUB_ERR_NONE
)))
334 adapter
->iterate(ventoy_video_hook
, NULL
);
336 if (adapter
->id
!= id
)
342 /* sort video mode */
343 for (i
= 0; i
< g_video_mode_num
; i
++)
344 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
346 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
348 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
349 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
350 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
354 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
357 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
361 static struct grub_fs vtoy_fs
=
366 .fs_read
= ventoy_fs_read
,
367 .fs_close
= ventoy_fs_close
,
377 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
383 file
->data
= grub_malloc(rawFile
->size
+ 4096);
389 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
390 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
392 g_old_file
= rawFile
;
394 file
->size
= rawFile
->size
+ len
;
395 file
->device
= rawFile
->device
;
397 file
->not_easily_seekable
= 1;
402 static int ventoy_check_decimal_var(const char *name
, long *value
)
404 const char *value_str
= NULL
;
406 value_str
= grub_env_get(name
);
407 if (NULL
== value_str
)
409 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
412 if (!ventoy_is_decimal(value_str
))
414 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
417 *value
= grub_strtol(value_str
, NULL
, 10);
419 return GRUB_ERR_NONE
;
422 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
424 grub_uint64_t sectors
;
426 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
428 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
432 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
435 return sectors
* 512;
438 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
444 grub_uint32_t offset
;
446 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
449 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
453 len
= (int)file
->size
;
455 data
= (char *)grub_malloc(file
->size
);
461 grub_file_read(file
, data
, file
->size
);
462 grub_file_close(file
);
464 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
465 grub_script_execute_sourcecode(exec
);
467 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
468 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
469 grub_file_close(file
);
471 grub_script_execute_sourcecode("loopback -d efiboot");
475 *direntoff
= offset
+ 2;
480 static int ventoy_set_check_result(int ret
)
484 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
485 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
486 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
490 grub_printf(VTOY_WARNING
"\n");
491 grub_printf(VTOY_WARNING
"\n");
492 grub_printf(VTOY_WARNING
"\n\n\n");
494 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
495 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
497 grub_printf("\n\nWill exit after 10 seconds ...... ");
505 static int ventoy_check_official_device(grub_device_t dev
)
509 grub_uint64_t offset
;
512 grub_uint8_t mbr
[512];
516 struct grub_partition
*partition
;
518 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
520 return ventoy_set_check_result(1 | 0x1000);
523 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
524 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
525 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
527 #ifndef GRUB_MACHINE_EFI
528 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
529 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
530 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
532 return ventoy_set_check_result(2 | 0x1000);
541 /* We must have partition 2 */
544 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
548 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
552 return ventoy_set_check_result(3 | 0x1000);
555 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
557 grub_file_close(file
);
558 return ventoy_set_check_result(4 | 0x1000);
561 partition
= dev
->disk
->partition
;
562 if (partition
->number
!= 0 || partition
->start
!= 2048)
564 return ventoy_set_check_result(5);
569 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
571 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
572 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
573 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
575 grub_file_close(file
);
576 return ventoy_set_check_result(6);
581 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
582 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
583 PartTbl
[1].SectorCount
!= 65536)
585 grub_file_close(file
);
586 return ventoy_set_check_result(6);
592 offset
= partition
->start
+ partition
->len
;
593 partition
= file
->device
->disk
->partition
;
594 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
596 grub_file_close(file
);
597 return ventoy_set_check_result(7);
601 grub_file_close(file
);
605 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
606 dev2
= grub_device_open(devname
);
609 return ventoy_set_check_result(8);
612 fs
= grub_fs_probe(dev2
);
615 grub_device_close(dev2
);
616 return ventoy_set_check_result(9);
619 fs
->fs_label(dev2
, &label
);
620 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
622 grub_device_close(dev2
);
623 return ventoy_set_check_result(10);
626 grub_device_close(dev2
);
630 disk
= grub_disk_open(dev
->disk
->name
);
633 return ventoy_set_check_result(11);
636 grub_memset(mbr
, 0, 512);
637 grub_disk_read(disk
, 0, 0, 512, mbr
);
638 grub_disk_close(disk
);
640 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
642 return ventoy_set_check_result(12);
645 return ventoy_set_check_result(0);
648 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
652 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
662 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
664 grub_uint64_t size
= 0;
667 char fullpath
[256] = {0};
670 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
673 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
676 debug("grub_file_open failed <%s>\n", fullpath
);
682 grub_file_close(file
);
686 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
690 char fullpath
[512] = {0};
693 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
696 file
= grub_file_open(fullpath
, type
);
699 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
706 int ventoy_is_dir_exist(const char *fmt
, ...)
713 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
717 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
720 grub_strncpy(pos
+ len
, "\" ]", 3);
722 debug("script exec %s\n", buf
);
724 if (0 == grub_script_execute_sourcecode(buf
))
732 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
735 grub_uint8_t
*outbuf
;
736 grub_uint8_t gzHdr
[10] =
738 0x1F, 0x8B, /* magic */
746 grub_memset(&s
, 0, sizeof(mz_stream
));
748 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
750 outbuf
= (grub_uint8_t
*)mem_out
;
752 mem_out_len
-= sizeof(gzHdr
) + 8;
753 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
754 outbuf
+= sizeof(gzHdr
);
756 s
.avail_in
= mem_in_len
;
759 s
.avail_out
= mem_out_len
;
762 mz_deflate(&s
, MZ_FINISH
);
766 outbuf
+= s
.total_out
;
767 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
768 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
770 return s
.total_out
+ sizeof(gzHdr
) + 8;
778 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
782 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
785 if (0 == grub_strcmp(args
[0], "on"))
788 grub_env_set("vtdebug_flag", "debug");
793 grub_env_set("vtdebug_flag", "");
796 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
799 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
803 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
805 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
806 grub_printf(" level:\r\n");
807 grub_printf(" 01/11: busybox / (+cat log)\r\n");
808 grub_printf(" 02/12: initrd / (+cat log)\r\n");
809 grub_printf(" 03/13: hook / (+cat log)\r\n");
811 grub_printf(" debug:\r\n");
812 grub_printf(" 0: debug is off\r\n");
813 grub_printf(" 1: debug is on\r\n");
815 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
818 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
820 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
822 g_ventoy_debug_level
= 1;
825 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
828 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
837 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
840 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
872 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
888 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
904 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
909 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
911 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
914 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
919 value_long
+= grub_strtol(args
[1], NULL
, 10);
921 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
922 grub_env_set(args
[0], buf
);
924 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
927 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
929 ulonglong value1
= 0;
930 ulonglong value2
= 0;
935 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
938 value1
= grub_strtoull(args
[0], NULL
, 10);
939 value2
= grub_strtoull(args
[1], NULL
, 10);
941 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
942 grub_env_set(args
[2], buf
);
944 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
947 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
962 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
965 debug("failed to open file <%s> for udf check\n", args
[0]);
969 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
971 grub_env_set(args
[1], buf
);
973 grub_file_close(file
);
979 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
987 g_wimboot_enable
= 0;
989 grub_check_free(g_wimiso_path
);
990 grub_check_free(g_wimiso_chunk_list
.chunk
);
992 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
998 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
999 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1000 if (NULL
== g_wimiso_chunk_list
.chunk
)
1002 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1005 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1006 g_wimiso_chunk_list
.cur_chunk
= 0;
1008 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1010 g_wimboot_enable
= 1;
1011 g_wimiso_path
= grub_strdup(args
[0]);
1012 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1013 grub_file_close(file
);
1018 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1028 ventoy_iso9660_override
*dirent
;
1037 totlen
= sizeof(ventoy_chain_head
);
1039 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1041 debug("failed to load efiboot template %d\n", len
);
1047 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1049 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1052 debug("failed to open file <%s>\n", args
[0]);
1056 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1061 totlen
+= ventoy_align_2k(file
->size
);
1063 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1064 dirent
->first_sector
= len
/ 2048;
1065 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1066 dirent
->size
= (grub_uint32_t
)file
->size
;
1067 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1069 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1071 #ifdef GRUB_MACHINE_EFI
1072 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1074 data
= (char *)grub_malloc(totlen
);
1077 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1079 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1080 grub_check_free(buf
);
1082 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1083 grub_file_close(file
);
1085 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1086 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1087 grub_env_set(name
, value
);
1089 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1090 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1091 grub_env_set(name
, value
);
1096 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1102 g_vtoy_load_prompt
= 0;
1103 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1105 if (argc
== 2 && args
[0][0] == '1')
1107 g_vtoy_load_prompt
= 1;
1108 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1111 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1114 int ventoy_need_prompt_load_file(void)
1116 return g_vtoy_load_prompt
;
1119 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1121 grub_uint64_t ro
= 0;
1122 grub_uint64_t div
= 0;
1123 grub_ssize_t left
= size
;
1124 char *cur
= (char *)buf
;
1126 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1129 while (left
>= VTOY_SIZE_2MB
)
1131 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1132 cur
+= VTOY_SIZE_2MB
;
1133 left
-= VTOY_SIZE_2MB
;
1135 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1136 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1142 grub_file_read(file
, cur
, left
);
1145 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1151 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1158 enum grub_file_type type
;
1169 if (grub_strcmp(args
[0], "nodecompress") == 0)
1171 type
= VENTOY_FILE_TYPE
;
1175 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1178 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1181 debug("failed to open file <%s>\n", args
[1]);
1185 #ifdef GRUB_MACHINE_EFI
1186 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1188 buf
= (char *)grub_malloc(file
->size
);
1193 grub_file_close(file
);
1197 if (g_vtoy_load_prompt
)
1199 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1203 grub_file_read(file
, buf
, file
->size
);
1206 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1207 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1208 grub_env_set(name
, value
);
1210 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1211 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1212 grub_env_set(name
, value
);
1214 grub_file_close(file
);
1220 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1238 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1241 debug("failed to open file <%s> for udf check\n", args
[0]);
1245 headlen
= sizeof(ventoy_chain_head
);
1247 #ifdef GRUB_MACHINE_EFI
1248 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1250 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1253 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1255 grub_file_read(file
, buf
+ headlen
, file
->size
);
1257 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1258 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1259 grub_env_set(name
, value
);
1261 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1262 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1263 grub_env_set(name
, value
);
1265 grub_file_close(file
);
1271 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1277 if (grub_iso9660_is_joliet())
1279 debug("This time has joliet process\n");
1288 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1297 if (args
[0][0] == '1')
1299 grub_iso9660_set_nojoliet(1);
1303 grub_iso9660_set_nojoliet(0);
1309 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1314 grub_uint8_t buf
[32];
1325 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1328 debug("failed to open file <%s> for udf check\n", args
[0]);
1332 for (i
= 16; i
< 32; i
++)
1334 grub_file_seek(file
, i
* 2048);
1335 grub_file_read(file
, buf
, sizeof(buf
));
1343 grub_file_seek(file
, i
* 2048);
1344 grub_file_read(file
, buf
, sizeof(buf
));
1346 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1349 grub_file_seek(file
, i
* 2048);
1350 grub_file_read(file
, buf
, sizeof(buf
));
1352 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1353 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1359 grub_file_close(file
);
1361 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1366 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1368 long value_long1
= 0;
1369 long value_long2
= 0;
1371 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1373 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1376 value_long1
= grub_strtol(args
[0], NULL
, 10);
1377 value_long2
= grub_strtol(args
[2], NULL
, 10);
1379 if (0 == grub_strcmp(args
[1], "eq"))
1381 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1383 else if (0 == grub_strcmp(args
[1], "ne"))
1385 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1387 else if (0 == grub_strcmp(args
[1], "gt"))
1389 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1391 else if (0 == grub_strcmp(args
[1], "lt"))
1393 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1395 else if (0 == grub_strcmp(args
[1], "ge"))
1397 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1399 else if (0 == grub_strcmp(args
[1], "le"))
1401 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1405 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1411 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1414 char buf
[128] = {0};
1418 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1421 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1422 pos
= grub_strstr(buf
, ",");
1428 grub_env_set(args
[1], buf
);
1430 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1433 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1439 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1445 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1448 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1450 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1451 if (0 == grub_script_execute_sourcecode(buf
))
1453 debug("file %s exist, ventoy_compatible YES\n", buf
);
1454 grub_env_set("ventoy_compatible", "YES");
1455 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1459 debug("file %s NOT exist\n", buf
);
1463 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1464 pos
= grub_strstr(buf
, ")");
1470 disk
= grub_disk_open(buf
);
1473 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1474 grub_disk_close(disk
);
1476 g_img_swap_tmp_buf
[703] = 0;
1477 for (i
= 318; i
< 703; i
++)
1479 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1480 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1482 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1483 grub_env_set("ventoy_compatible", "YES");
1484 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1490 debug("failed to open disk <%s>\n", buf
);
1493 grub_env_set("ventoy_compatible", "NO");
1494 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1497 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1503 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1505 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1508 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1513 if (0 == g_sort_case_sensitive
)
1515 if (grub_islower(c1
))
1517 c1
= c1
- 'a' + 'A';
1520 if (grub_islower(c2
))
1522 c2
= c2
- 'a' + 'A';
1535 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1541 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1543 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1546 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1551 if (0 == g_sort_case_sensitive
)
1553 if (grub_islower(c1
))
1555 c1
= c1
- 'a' + 'A';
1558 if (grub_islower(c2
))
1560 c2
= c2
- 'a' + 'A';
1573 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1575 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1577 grub_memcpy(img1
, img2
, sizeof(img_info
));
1578 img1
->next
= g_img_swap_tmp
.next
;
1579 img1
->prev
= g_img_swap_tmp
.prev
;
1581 g_img_swap_tmp
.next
= img2
->next
;
1582 g_img_swap_tmp
.prev
= img2
->prev
;
1583 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1586 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1590 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1598 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1600 ventoy_vlnk_part
*node
= NULL
;
1601 grub_uint32_t SelfSig
;
1602 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1604 /* skip Ventoy partition 1/2 */
1605 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1606 if (partition
->number
< 2 && SelfSig
== *pSig
)
1611 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1614 node
->disksig
= *pSig
;
1615 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1616 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1617 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1619 node
->next
= g_vlnk_part_list
;
1620 g_vlnk_part_list
= node
;
1626 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1633 disk
= grub_disk_open(name
);
1636 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1637 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1638 grub_disk_close(disk
);
1644 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1646 const char *fs
[ventoy_fs_max
+ 1] =
1648 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1653 cur
->dev
= grub_device_open(cur
->device
);
1658 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1664 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1669 char *disk
, *device
;
1670 grub_uint32_t readcrc
, calccrc
;
1671 ventoy_vlnk_part
*cur
;
1672 grub_fs_t fs
= NULL
;
1674 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1678 grub_printf("VLNK invalid guid\n");
1684 readcrc
= vlnk
->crc32
;
1686 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1687 if (readcrc
!= calccrc
)
1691 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1697 if (!g_vlnk_part_list
)
1699 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1702 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1704 if (cur
->disksig
== vlnk
->disk_signature
)
1708 if (cur
->partoffset
== vlnk
->part_offset
)
1711 device
= cur
->device
;
1713 if (cur
->probe
== 0)
1716 ventoy_vlnk_probe_fs(cur
);
1726 struct grub_file file
;
1728 grub_memset(&file
, 0, sizeof(file
));
1729 file
.device
= cur
->dev
;
1730 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1733 cur
->fs
->fs_close(&file
);
1734 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1743 grub_printf("\n==== VLNK Information ====\n"
1744 "Disk Signature: %08x\n"
1745 "Partition Offset: %llu\n"
1746 "File Path: <%s>\n\n",
1747 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1751 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1755 grub_printf("Disk Find: [ NO ]\n");
1760 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1764 grub_printf("Part Find: [ NO ]\n");
1766 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1769 grub_printf("VLNK File: <%s>\n", dst
);
1776 return (1 - filefind
);
1779 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1784 grub_file_t file
= NULL
;
1789 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1791 else if (dir
[0] == '/')
1793 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1797 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1800 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1806 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1807 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1808 grub_file_close(file
);
1810 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1812 rc
= grub_file_add_vlnk(src
, dst
);
1818 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1828 const menu_tip
*tip
;
1829 img_iterator_node
*tmp
;
1830 img_iterator_node
*new_node
;
1831 img_iterator_node
*node
= (img_iterator_node
*)data
;
1833 if (g_enumerate_time_checked
== 0)
1835 g_enumerate_finish_time_ms
= grub_get_time_ms();
1836 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1839 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1841 g_enumerate_time_checked
= 1;
1845 len
= grub_strlen(filename
);
1849 if (node
->level
+ 1 > g_img_max_search_level
)
1854 if ((len
== 1 && filename
[0] == '.') ||
1855 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1860 if (!ventoy_img_name_valid(filename
, len
))
1865 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1870 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1872 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1873 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1876 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1881 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1884 new_node
->level
= node
->level
+ 1;
1885 new_node
->plugin_list_index
= index
;
1886 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1888 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1891 debug("Directory %s ignored...\n", new_node
->dir
);
1892 grub_free(new_node
);
1896 new_node
->tail
= node
->tail
;
1898 new_node
->parent
= node
;
1899 if (!node
->firstchild
)
1901 node
->firstchild
= new_node
;
1904 if (g_img_iterator_tail
)
1906 g_img_iterator_tail
->next
= new_node
;
1907 g_img_iterator_tail
= new_node
;
1911 g_img_iterator_head
.next
= new_node
;
1912 g_img_iterator_tail
= new_node
;
1918 debug("Find a file %s\n", filename
);
1924 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1926 type
= img_type_iso
;
1928 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1930 type
= img_type_wim
;
1932 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1933 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1935 type
= img_type_vhd
;
1937 #ifdef GRUB_MACHINE_EFI
1938 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1940 type
= img_type_efi
;
1943 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1945 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1947 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1948 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1953 type
= img_type_img
;
1955 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1957 type
= img_type_vtoy
;
1959 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1961 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1963 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1964 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1973 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1978 if (g_plugin_image_list
)
1980 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1981 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1982 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1984 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1987 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1989 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1994 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
1996 if (grub_file_is_vlnk_suffix(filename
, len
))
1999 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2006 img
= grub_zalloc(sizeof(img_info
));
2010 img
->plugin_list_index
= index
;
2011 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2013 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2015 img
->size
= info
->size
;
2016 if (vlnk
|| 0 == img
->size
)
2018 if (node
->dir
[0] == '/')
2020 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2024 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2028 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2030 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2035 if (g_ventoy_img_list
)
2037 tail
= *(node
->tail
);
2043 g_ventoy_img_list
= img
;
2046 img
->id
= g_ventoy_img_count
;
2048 if (node
&& NULL
== node
->firstiso
)
2050 node
->firstiso
= img
;
2061 *((img_info
**)(node
->tail
)) = img
;
2062 g_ventoy_img_count
++;
2064 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2066 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2069 img
->tip1
= tip
->tip1
;
2070 img
->tip2
= tip
->tip2
;
2073 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2076 img
->class = g_menu_class
[type
];
2078 img
->menu_prefix
= g_menu_prefix
[type
];
2080 if (img_type_iso
== type
)
2082 if (ventoy_plugin_check_memdisk(img
->path
))
2084 img
->menu_prefix
= "miso";
2088 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2095 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2097 int len
= GRUB_UINT_MAX
;
2098 const char *value
= NULL
;
2099 char name
[32] = {0};
2100 char plat
[32] = {0};
2101 char guidstr
[32] = {0};
2102 ventoy_guid guid
= VENTOY_GUID
;
2103 const char *fmt1
= NULL
;
2104 const char *fmt2
= NULL
;
2105 const char *fmt3
= NULL
;
2106 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2107 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2108 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2109 const char fmtcode
[]={
2110 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2111 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2112 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2113 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2114 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2115 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2118 grub_memset(name
, 0, sizeof(name
));
2119 puint
[0] = grub_swap_bytes32(0x56454e54);
2120 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2121 puint
[2] = grub_swap_bytes32(0x45525349);
2122 puint
[1] = grub_swap_bytes32(0x4f595f56);
2123 value
= ventoy_get_env(name
);
2125 grub_memset(name
, 0, sizeof(name
));
2126 puint
[1] = grub_swap_bytes32(0x5f544f50);
2127 puint
[0] = grub_swap_bytes32(0x56544c45);
2128 fmt1
= ventoy_get_env(name
);
2134 grub_memset(name
, 0, sizeof(name
));
2135 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2136 puint
[0] = grub_swap_bytes32(0x56544c45);
2137 fmt2
= ventoy_get_env(name
);
2139 grub_memset(name
, 0, sizeof(name
));
2140 puint
[1] = grub_swap_bytes32(0x5f434c52);
2141 puint
[0] = grub_swap_bytes32(0x56544c45);
2142 fmt3
= ventoy_get_env(name
);
2144 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2146 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2148 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2149 #pragma GCC diagnostic push
2150 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2151 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2152 fmt1
? fmt1
: fmtdata
,
2153 fmt2
? fmt2
: fmtdata
+ 4,
2154 value
? value
: "", plat
, guidstr
,
2155 fmt3
? fmt3
: fmtdata
+ 6);
2156 #pragma GCC diagnostic pop
2158 grub_memset(name
, 0, sizeof(name
));
2159 puint
[0] = grub_swap_bytes32(0x76746f79);
2160 puint
[2] = grub_swap_bytes32(0x656e7365);
2161 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2162 ventoy_set_env(name
, guidstr
);
2167 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2171 grub_uint8_t md5
[16];
2175 grub_memset(input
, 0, sizeof(input
));
2177 grub_printf("Enter password: ");
2180 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2182 grub_password_get(input
, 128);
2183 if (grub_strcmp(pwd
->text
, input
) == 0)
2188 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2190 grub_password_get(input
, 128);
2191 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2192 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2197 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2199 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2200 grub_password_get(input
+ offset
, 128);
2202 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2203 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2209 grub_printf("Invalid password!\n\n");
2216 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2218 img_info
*minimg
= NULL
;
2219 img_info
*img
= (img_info
*)(node
->firstiso
);
2221 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2223 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2238 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2240 img_iterator_node
*Minchild
= NULL
;
2241 img_iterator_node
*child
= node
->firstchild
;
2243 while (child
&& child
->parent
== node
)
2245 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2249 child
= child
->next
;
2254 Minchild
->select
= 1;
2260 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2263 img_info
*img
= NULL
;
2264 const char *dir_class
= NULL
;
2265 const char *dir_alias
= NULL
;
2266 img_iterator_node
*child
= NULL
;
2267 const menu_tip
*tip
= NULL
;
2269 if (node
->isocnt
== 0 || node
->done
== 1)
2274 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2276 offset
= node
->parent
->dirlen
;
2279 if (node
== &g_img_iterator_head
)
2281 if (g_default_menu_mode
== 0)
2283 if (g_tree_view_menu_style
== 0)
2285 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2286 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2287 " echo 'return ...' \n"
2292 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2293 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2299 g_tree_script_pre
= g_tree_script_pos
;
2303 node
->dir
[node
->dirlen
- 1] = 0;
2304 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2307 dir_class
= "vtoydir";
2310 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2312 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2315 if (g_tree_view_menu_style
== 0)
2317 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2318 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2319 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2323 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2324 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2325 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2330 dir_alias
= node
->dir
+ offset
;
2332 if (g_tree_view_menu_style
== 0)
2334 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2335 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2336 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2340 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2341 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2342 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2346 if (g_tree_view_menu_style
== 0)
2348 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2349 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2350 " echo 'return ...' \n"
2355 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2356 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2362 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2364 ventoy_dynamic_tree_menu(child
);
2367 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2369 if (g_tree_view_menu_style
== 0)
2371 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2372 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2375 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2376 img
->unsupport
? "[***********] " : "",
2377 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2379 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2383 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2384 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2387 img
->unsupport
? "[***********] " : "",
2388 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2390 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2394 if (node
!= &g_img_iterator_head
)
2396 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2403 static int ventoy_set_default_menu(void)
2409 const char *strdata
= NULL
;
2410 img_info
*cur
= NULL
;
2411 img_info
*default_node
= NULL
;
2412 const char *default_image
= NULL
;
2414 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2415 if (default_image
&& default_image
[0] == '/')
2417 img_len
= grub_strlen(default_image
);
2419 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2421 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2433 if (0 == g_default_menu_mode
)
2435 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2439 def
= grub_strdup(default_image
);
2445 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2447 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2448 if (strdata
&& strdata
[0] == '/')
2450 pos
= def
+ grub_strlen(strdata
);
2461 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2464 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2468 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2476 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2478 img_info
*next
= NULL
;
2479 img_info
*cur
= g_ventoy_img_list
;
2492 g_ventoy_img_list
= NULL
;
2493 g_ventoy_img_count
= 0;
2495 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2498 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2501 img_info
*cur
= g_ventoy_img_list
;
2505 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2507 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2510 img_id
= grub_strtol(args
[0], NULL
, 10);
2511 if (img_id
>= g_ventoy_img_count
)
2513 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2516 debug("Find image %ld name \n", img_id
);
2518 while (cur
&& img_id
> 0)
2526 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2529 debug("image name is %s\n", cur
->name
);
2531 grub_env_set(args
[1], cur
->name
);
2533 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2536 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2540 img_info
*cur
= g_ventoy_img_list
;
2546 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2549 len
= (int)grub_strlen(args
[0]);
2553 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2562 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2565 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2566 grub_env_set("chosen", id
);
2567 grub_env_export("chosen");
2569 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2572 static char g_fake_vlnk_src
[512];
2573 static char g_fake_vlnk_dst
[512];
2574 static grub_uint64_t g_fake_vlnk_size
;
2575 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2581 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2583 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2584 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2586 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2588 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2591 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2597 g_fake_vlnk_src
[0] = 0;
2598 g_fake_vlnk_dst
[0] = 0;
2599 g_fake_vlnk_size
= 0;
2600 grub_file_vtoy_vlnk(NULL
, NULL
);
2602 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2606 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2610 const char *id
= NULL
;
2611 img_info
*cur
= NULL
;
2615 if (argc
< 1 || argc
> 2)
2617 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2620 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2622 grub_env_set(args
[0], grub_strchr(g_fake_vlnk_src
, '/'));
2625 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2626 grub_env_set(args
[1], value
);
2632 id
= grub_env_get("chosen");
2634 pos
= grub_strstr(id
, "VID_");
2637 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2641 cur
= g_ventoy_img_list
;
2646 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2649 grub_env_set(args
[0], cur
->path
);
2653 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2654 grub_env_set(args
[1], value
);
2658 g_svd_replace_offset
= 0;
2660 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2664 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2668 grub_device_t dev
= NULL
;
2669 img_info
*cur
= NULL
;
2670 img_info
*tail
= NULL
;
2671 img_info
*min
= NULL
;
2672 img_info
*head
= NULL
;
2673 const char *strdata
= NULL
;
2674 char *device_name
= NULL
;
2676 img_iterator_node
*node
= NULL
;
2677 img_iterator_node
*tmp
= NULL
;
2683 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2686 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2688 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2693 g_enumerate_time_checked
= 0;
2694 g_enumerate_start_time_ms
= grub_get_time_ms();
2696 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2697 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2699 g_filt_dot_underscore_file
= 1;
2702 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2703 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2705 g_sort_case_sensitive
= 1;
2708 device_name
= grub_file_get_device_name(args
[0]);
2714 g_enum_dev
= dev
= grub_device_open(device_name
);
2720 g_enum_fs
= fs
= grub_fs_probe(dev
);
2726 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2728 debug("unsupported fs:<%s>\n", fs
->name
);
2729 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2733 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2735 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2736 if (strdata
&& strdata
[0] == '1')
2738 g_default_menu_mode
= 1;
2741 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2743 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2745 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2746 if (strdata
&& strdata
[0] == '/')
2748 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2749 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2751 g_img_iterator_head
.dir
[len
++] = '/';
2753 g_img_iterator_head
.dirlen
= len
;
2757 g_img_iterator_head
.dirlen
= 1;
2758 grub_strcpy(g_img_iterator_head
.dir
, "/");
2761 g_img_iterator_head
.tail
= &tail
;
2763 if (g_img_max_search_level
< 0)
2765 g_img_max_search_level
= GRUB_INT_MAX
;
2766 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2767 if (strdata
&& ventoy_is_decimal(strdata
))
2769 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2773 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2774 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2775 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2776 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2777 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2778 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2780 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2782 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2785 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2786 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2788 g_tree_view_menu_style
= 1;
2791 ventoy_set_default_menu();
2793 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2795 ventoy_dynamic_tree_menu(node
);
2799 node
= g_img_iterator_head
.next
;
2807 /* sort image list by image name */
2808 while (g_ventoy_img_list
)
2810 min
= g_ventoy_img_list
;
2811 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2813 if (ventoy_cmp_img(min
, cur
) > 0)
2821 min
->prev
->next
= min
->next
;
2826 min
->next
->prev
= min
->prev
;
2829 if (min
== g_ventoy_img_list
)
2831 g_ventoy_img_list
= min
->next
;
2849 g_ventoy_img_list
= head
;
2851 if (g_default_menu_mode
== 1)
2853 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2854 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2855 " echo 'return ...' \n"
2859 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2861 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2862 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2865 cur
->unsupport
? "[***********] " : "",
2866 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2868 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2871 g_tree_script_buf
[g_tree_script_pos
] = 0;
2872 g_list_script_buf
[g_list_script_pos
] = 0;
2874 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2875 grub_env_set(args
[1], buf
);
2879 check_free(device_name
, grub_free
);
2880 check_free(dev
, grub_device_close
);
2882 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2885 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2892 device_name
= grub_file_get_device_name(filename
);
2904 pos2
= grub_strstr(pos
, ",");
2907 pos2
= grub_strstr(pos
, ")");
2915 disk
= grub_disk_open(pos
);
2918 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2919 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2920 grub_disk_close(disk
);
2927 grub_free(device_name
);
2931 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2933 eltorito_descriptor desc
;
2935 grub_memset(&desc
, 0, sizeof(desc
));
2936 grub_file_seek(file
, 17 * 2048);
2937 grub_file_read(file
, &desc
, sizeof(desc
));
2939 if (desc
.type
!= 0 || desc
.version
!= 1)
2944 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2945 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2953 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2955 grub_uint8_t buf
[512];
2957 grub_file_seek(file
, sector
* 2048);
2958 grub_file_read(file
, buf
, sizeof(buf
));
2960 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2961 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2963 return *((grub_uint32_t
*)(buf
+ 40));
2969 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2973 grub_uint8_t buf
[512];
2974 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2976 grub_file_seek(file
, sector
* 2048);
2977 grub_file_read(file
, buf
, sizeof(buf
));
2979 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2981 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2985 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2990 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2992 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2994 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2998 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3000 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3005 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3007 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3009 if (buf
[36] == parttype
[i
])
3011 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3017 debug("%s does not contain efi eltorito\n", file
->name
);
3021 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3024 const char *fs
= NULL
;
3025 const char *val
= NULL
;
3026 const char *cdprompt
= NULL
;
3028 grub_uint8_t chksum
= 0;
3031 disk
= file
->device
->disk
;
3032 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3034 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3035 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3036 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3038 pos
= grub_strstr(file
->name
, "/");
3044 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3046 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3048 param
->vtoy_img_size
= file
->size
;
3050 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3051 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3053 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3055 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3056 param
->vtoy_reserved
[4] = 0;
3057 if (g_ventoy_chain_type
== 1) /* Windows */
3059 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3060 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3062 param
->vtoy_reserved
[4] = 1;
3066 fs
= ventoy_get_env("ventoy_fs_probe");
3067 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3069 param
->vtoy_reserved
[3] = 1;
3072 param
->vtoy_reserved
[5] = 0;
3073 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3074 if (val
&& val
[0] == '1' && val
[1] == 0)
3076 param
->vtoy_reserved
[5] = 1;
3079 /* ventoy_disk_signature used for vlnk */
3080 param
->vtoy_reserved
[6] = file
->vlnk
;
3081 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3083 /* calculate checksum */
3084 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3086 chksum
+= *((grub_uint8_t
*)param
+ i
);
3088 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3093 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3095 grub_uint32_t i
= 0;
3096 grub_uint64_t total
= 0;
3097 grub_uint64_t fileblk
= 0;
3098 ventoy_img_chunk
*chunk
= NULL
;
3100 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3102 chunk
= chunklist
->chunk
+ i
;
3104 if (chunk
->disk_start_sector
<= start
)
3106 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3110 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3113 fileblk
= (file
->size
+ 511) / 512;
3115 if (total
!= fileblk
)
3117 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3118 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3120 debug("maybe img file to be processed.\n");
3130 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3134 grub_uint32_t i
= 0;
3135 grub_uint32_t sector
= 0;
3136 grub_uint32_t count
= 0;
3137 grub_off_t size
= 0;
3138 grub_off_t read
= 0;
3140 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3141 if (fs_type
== ventoy_fs_exfat
)
3143 grub_fat_get_file_chunk(start
, file
, chunklist
);
3145 else if (fs_type
== ventoy_fs_ext
)
3147 grub_ext_get_file_chunk(start
, file
, chunklist
);
3151 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
3152 file
->read_hook_data
= chunklist
;
3154 for (size
= file
->size
; size
> 0; size
-= read
)
3156 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3157 grub_file_read(file
, NULL
, read
);
3160 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3162 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3163 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3166 if (ventoy_fs_udf
== fs_type
)
3168 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3170 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3171 chunklist
->chunk
[i
].img_start_sector
= sector
;
3172 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3178 len
= (int)grub_strlen(file
->name
);
3179 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3180 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3181 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3182 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3184 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3186 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3196 chunklist
->chunk
[i
].img_start_sector
= sector
;
3197 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3205 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3209 grub_disk_addr_t start
;
3214 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3217 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3220 g_conf_replace_node
= NULL
;
3221 g_conf_replace_offset
= 0;
3223 if (g_img_chunk_list
.chunk
)
3225 grub_free(g_img_chunk_list
.chunk
);
3228 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3230 grub_file_close(file
);
3231 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3234 /* get image chunk data */
3235 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3236 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3237 if (NULL
== g_img_chunk_list
.chunk
)
3239 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3242 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3243 g_img_chunk_list
.cur_chunk
= 0;
3245 start
= file
->device
->disk
->partition
->start
;
3247 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3249 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3250 grub_file_close(file
);
3254 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3257 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3258 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3259 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3262 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3264 grub_uint64_t offset
= 0;
3265 grub_uint32_t align
= 0;
3266 grub_file_t file
= NULL
;
3267 conf_replace
*node
= NULL
;
3273 debug("select conf replace argc:%d\n", argc
);
3280 node
= ventoy_plugin_find_conf_replace(args
[1]);
3283 debug("Conf replace not found for %s\n", args
[1]);
3287 debug("Find conf replace for %s\n", args
[1]);
3289 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3292 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3293 grub_file_close(file
);
3295 else if (node
->img
> 0)
3301 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3305 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3308 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3312 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3314 if (align
> vtoy_max_replace_file_size
)
3316 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3320 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3321 g_conf_replace_new_len
= (int)file
->size
;
3322 g_conf_replace_new_len_align
= align
;
3324 g_conf_replace_node
= node
;
3325 g_conf_replace_offset
= offset
+ 2;
3329 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3330 g_grub_param
->img_replace
.old_name_cnt
= 1;
3331 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3334 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3339 grub_file_close(file
);
3341 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3344 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3350 char configfile
[128];
3351 install_template
*node
= NULL
;
3357 debug("select auto installation argc:%d\n", argc
);
3364 node
= ventoy_plugin_find_install_template(args
[0]);
3367 debug("Auto install template not found for %s\n", args
[0]);
3371 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3373 defidx
= node
->autosel
;
3374 if (node
->timeout
< 0)
3376 node
->cursel
= node
->autosel
- 1;
3377 debug("Auto install template auto select %d\n", node
->autosel
);
3382 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3388 if (node
->timeout
> 0)
3390 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3393 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3394 " echo %s\n}\n", "");
3396 for (i
= 0; i
< node
->templatenum
; i
++)
3398 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3400 node
->templatepath
[i
].path
);
3403 g_ventoy_menu_esc
= 1;
3404 g_ventoy_suppress_esc
= 1;
3405 g_ventoy_suppress_esc_default
= defidx
;
3407 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3408 grub_script_execute_sourcecode(configfile
);
3410 g_ventoy_menu_esc
= 0;
3411 g_ventoy_suppress_esc
= 0;
3412 g_ventoy_suppress_esc_default
= 1;
3416 node
->cursel
= g_ventoy_last_entry
- 1;
3418 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3421 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3427 char configfile
[128];
3428 persistence_config
*node
;
3434 debug("select persistence argc:%d\n", argc
);
3441 node
= ventoy_plugin_find_persistent(args
[0]);
3444 debug("Persistence image not found for %s\n", args
[0]);
3448 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3450 defidx
= node
->autosel
;
3451 if (node
->timeout
< 0)
3453 node
->cursel
= node
->autosel
- 1;
3454 debug("Persistence image auto select %d\n", node
->autosel
);
3459 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3465 if (node
->timeout
> 0)
3467 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3470 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3471 " echo %s\n}\n", "");
3473 for (i
= 0; i
< node
->backendnum
; i
++)
3475 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3477 node
->backendpath
[i
].path
);
3481 g_ventoy_menu_esc
= 1;
3482 g_ventoy_suppress_esc
= 1;
3483 g_ventoy_suppress_esc_default
= defidx
;
3485 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3486 grub_script_execute_sourcecode(configfile
);
3488 g_ventoy_menu_esc
= 0;
3489 g_ventoy_suppress_esc
= 0;
3490 g_ventoy_suppress_esc_default
= 1;
3494 node
->cursel
= g_ventoy_last_entry
- 1;
3496 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3499 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3502 ventoy_img_chunk
*cur
;
3508 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3510 cur
= g_img_chunk_list
.chunk
+ i
;
3511 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3512 cur
->img_start_sector
, cur
->img_end_sector
,
3513 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3517 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3520 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3524 ventoy_img_chunk_list chunklist
;
3529 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3532 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3535 /* get image chunk data */
3536 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3537 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3538 if (NULL
== chunklist
.chunk
)
3540 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3543 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3544 chunklist
.cur_chunk
= 0;
3546 ventoy_get_block_list(file
, &chunklist
, 0);
3548 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3550 grub_printf("########## UNSUPPORTED ###############\n");
3553 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3555 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3557 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3558 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3561 grub_printf("\n==================================\n");
3563 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3565 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3566 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3567 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3568 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3569 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3573 grub_free(chunklist
.chunk
);
3574 grub_file_close(file
);
3576 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3579 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3582 ventoy_grub_param_file_replace
*replace
= NULL
;
3590 replace
= &(g_grub_param
->file_replace
);
3591 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3593 replace
->old_name_cnt
= 0;
3594 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3596 replace
->old_name_cnt
++;
3597 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3600 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3603 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3606 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3609 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3615 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3616 grub_env_set(args
[0], buf
);
3619 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3622 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3630 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3631 grub_printf("%s", g_list_script_buf
);
3635 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3636 grub_printf("%s", g_tree_script_buf
);
3642 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3644 img_info
*cur
= g_ventoy_img_list
;
3652 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3653 grub_printf("name:<%s>\n\n", cur
->name
);
3660 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3666 ventoy_plugin_dump_injection();
3671 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3677 ventoy_plugin_dump_auto_install();
3682 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3688 ventoy_plugin_dump_persistence();
3693 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3704 if (args
[0][0] == '0')
3706 return g_ventoy_memdisk_mode
? 0 : 1;
3708 else if (args
[0][0] == '1')
3710 return g_ventoy_iso_raw
? 0 : 1;
3712 else if (args
[0][0] == '2')
3714 return g_ventoy_iso_uefi_drv
? 0 : 1;
3716 else if (args
[0][0] == '3')
3718 return g_ventoy_grub2_mode
? 0 : 1;
3720 else if (args
[0][0] == '4')
3722 return g_ventoy_wimboot_mode
? 0 : 1;
3728 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3730 static int configfile_mode
= 0;
3731 char memfile
[128] = {0};
3738 * args[0]: 0:normal 1:configfile
3739 * args[1]: 0:list_buf 1:tree_buf
3744 debug("Invalid argc %d\n", argc
);
3750 if (args
[0][0] == '0')
3752 if (args
[1][0] == '0')
3754 grub_script_execute_sourcecode(g_list_script_buf
);
3758 grub_script_execute_sourcecode(g_tree_script_buf
);
3763 if (configfile_mode
)
3765 debug("Now already in F3 mode %d\n", configfile_mode
);
3769 if (args
[1][0] == '0')
3771 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3772 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3776 g_ventoy_last_entry
= -1;
3777 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3778 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3781 configfile_mode
= 1;
3782 grub_script_execute_sourcecode(memfile
);
3783 configfile_mode
= 0;
3789 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3800 g_ventoy_case_insensitive
= 1;
3801 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3802 g_ventoy_case_insensitive
= 0;
3808 grub_file_close(file
);
3814 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3819 const char *isopath
= NULL
;
3821 ventoy_mbr_head mbr
;
3828 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3831 isopath
= grub_env_get("vtoy_iso_part");
3834 debug("isopath is null %p\n", isopath
);
3838 debug("isopath is %s\n", isopath
);
3840 for (id
= 0; id
< 30 && (find
== 0); id
++)
3842 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3843 if (grub_strstr(isopath
, hdname
))
3845 debug("skip %s ...\n", hdname
);
3849 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3851 disk
= grub_disk_open(hdname
);
3854 debug("%s not exist\n", hdname
);
3858 grub_memset(&mbr
, 0, sizeof(mbr
));
3859 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3861 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3863 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3864 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3867 grub_env_set(args
[0], hdname
);
3871 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3875 debug("read %s failed\n", hdname
);
3878 grub_disk_close(disk
);
3884 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3895 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3898 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3901 debug("failed to open file %s\n", args
[0]);
3905 buf
= grub_malloc(len
);
3912 grub_file_read(file
, buf
, len
- 1);
3914 ventoy_get_line(buf
);
3915 ventoy_set_env(args
[1], buf
);
3919 grub_check_free(buf
);
3920 grub_file_close(file
);
3925 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3927 grub_uint64_t end_max
= 0;
3928 int *pCnt
= (int *)data
;
3933 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3934 "0 %llu linear /dev/ventoy %llu\n",
3935 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3937 end_max
= (partition
->len
+ partition
->start
) * 512;
3938 if (end_max
> g_part_end_max
)
3940 g_part_end_max
= end_max
;
3946 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3949 char *device_name
= NULL
;
3950 grub_device_t dev
= NULL
;
3955 g_part_list_pos
= 0;
3957 grub_env_unset("vtoy_img_part_file");
3964 device_name
= grub_file_get_device_name(args
[0]);
3967 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3971 dev
= grub_device_open(device_name
);
3974 debug("grub_device_open failed, %s\n", device_name
);
3978 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3980 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3981 grub_env_set("vtoy_img_part_file", buf
);
3983 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3984 grub_env_set("vtoy_img_part_cnt", buf
);
3986 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
3987 grub_env_set("vtoy_img_max_part_end", buf
);
3991 check_free(device_name
, grub_free
);
3992 check_free(dev
, grub_device_close
);
3998 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4009 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4012 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4015 debug("failed to open file %s\n", args
[0]);
4019 buf
= grub_malloc(file
->size
+ 1);
4025 buf
[file
->size
] = 0;
4026 grub_file_read(file
, buf
, file
->size
);
4028 if (grub_strstr(buf
, args
[1]))
4035 grub_check_free(buf
);
4036 grub_file_close(file
);
4041 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4047 ventoy_iso9660_vd pvd
;
4054 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4057 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4060 debug("failed to open file %s\n", args
[0]);
4064 grub_file_seek(file
, 16 * 2048);
4065 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4066 if (len
!= sizeof(pvd
))
4068 debug("failed to read pvd %d\n", len
);
4072 grub_memset(buf
, 0, sizeof(buf
));
4073 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4074 ventoy_set_env(args
[1], buf
);
4076 grub_memset(buf
, 0, sizeof(buf
));
4077 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4078 ventoy_set_env(args
[2], buf
);
4082 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4083 ventoy_set_env(args
[3], buf
);
4086 grub_file_close(file
);
4091 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4102 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4105 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4108 debug("failed to open file %s\n", args
[0]);
4112 grub_memset(buf
, 0, sizeof(buf
));
4113 grub_file_seek(file
, 16 * 2048 + 813);
4114 len
= (int)grub_file_read(file
, buf
, 17);
4117 debug("failed to read create date %d\n", len
);
4121 ventoy_set_env(args
[1], buf
);
4124 grub_file_close(file
);
4129 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4135 ventoy_env_hook_root(1);
4140 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4146 ventoy_env_hook_root(0);
4151 #ifdef GRUB_MACHINE_EFI
4152 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4157 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4163 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4164 if (var
&& *var
== 1)
4172 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4181 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4186 grub_uint64_t FileSectors
= 0;
4187 ventoy_gpt_info
*gpt
= NULL
;
4188 ventoy_part_table
*pt
= NULL
;
4189 grub_uint8_t zeroguid
[16] = {0};
4194 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4197 debug("failed to open file %s\n", args
[0]);
4201 if (file
->size
% 512)
4203 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4207 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4213 FileSectors
= file
->size
/ 512;
4215 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4216 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4218 debug("This is EFI partition table\n");
4220 for (i
= 0; i
< 128; i
++)
4222 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4224 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4226 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4227 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4235 debug("This is MBR partition table\n");
4237 for (i
= 0; i
< 4; i
++)
4239 pt
= gpt
->MBR
.PartTbl
+ i
;
4240 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4242 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4243 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4244 (ulonglong
)FileSectors
);
4253 grub_file_close(file
);
4254 grub_check_free(gpt
);
4255 grub_errno
= GRUB_ERR_NONE
;
4259 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4268 for (i
= 0; i
< 500; i
++)
4270 ret
= grub_getkey_noblock();
4271 if (ret
== GRUB_TERM_NO_KEY
)
4280 grub_printf("\n\n Still have key input after clear.\n");
4288 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4295 int image_sector_size
;
4297 ventoy_chain_head
*chain
;
4298 ventoy_img_chunk
*chunk
;
4299 ventoy_os_param
*osparam
;
4300 ventoy_image_location
*location
;
4301 ventoy_image_disk_region
*region
;
4302 struct grub_acpi_table_header
*acpi
;
4311 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4313 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4319 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4321 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4323 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4327 img_chunk_num
= chain
->img_chunk_num
;
4329 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4330 datalen
= sizeof(ventoy_os_param
) + loclen
;
4332 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4333 acpi
= grub_zalloc(buflen
);
4339 /* Step1: Fill acpi table header */
4340 grub_memcpy(acpi
->signature
, "VTOY", 4);
4341 acpi
->length
= buflen
;
4343 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4344 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4346 acpi
->creator_id
[0] = 1;
4347 acpi
->creator_rev
= 1;
4349 /* Step2: Fill data */
4350 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4351 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4352 osparam
->vtoy_img_location_addr
= 0;
4353 osparam
->vtoy_img_location_len
= loclen
;
4354 osparam
->chksum
= 0;
4355 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4357 location
= (ventoy_image_location
*)(osparam
+ 1);
4358 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4359 location
->image_sector_size
= image_sector_size
;
4360 location
->disk_sector_size
= chain
->disk_sector_size
;
4361 location
->region_count
= img_chunk_num
;
4363 region
= location
->regions
;
4364 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4365 if (512 == image_sector_size
)
4367 for (i
= 0; i
< img_chunk_num
; i
++)
4369 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4370 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4371 region
->disk_start_sector
= chunk
->disk_start_sector
;
4378 for (i
= 0; i
< img_chunk_num
; i
++)
4380 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4381 region
->image_start_sector
= chunk
->img_start_sector
;
4382 region
->disk_start_sector
= chunk
->disk_start_sector
;
4388 /* Step3: Fill acpi checksum */
4390 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4392 /* load acpi table */
4393 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4394 grub_script_execute_sourcecode(cmd
);
4398 VENTOY_CMD_RETURN(0);
4401 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4407 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4408 g_ventoy_last_entry
= -1;
4413 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4419 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4424 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4426 const char *pos
= filename
+ 1;
4434 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4436 grub_strncpy((char *)data
, filename
, 128);
4447 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4450 char *device_name
= NULL
;
4451 grub_device_t dev
= NULL
;
4452 grub_fs_t fs
= NULL
;
4453 char buf
[128] = {0};
4459 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4463 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4465 device_name
= grub_file_get_device_name(args
[0]);
4468 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4472 dev
= grub_device_open(device_name
);
4475 debug("grub_device_open failed, %s\n", device_name
);
4479 fs
= grub_fs_probe(dev
);
4482 debug("grub_fs_probe failed, %s\n", device_name
);
4486 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4490 ventoy_set_env(args
[2], buf
);
4497 check_free(device_name
, grub_free
);
4498 check_free(dev
, grub_device_close
);
4503 int ventoy_load_part_table(const char *diskname
)
4510 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4511 if (!g_ventoy_part_info
)
4516 disk
= grub_disk_open(diskname
);
4519 debug("Failed to open disk %s\n", diskname
);
4523 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4525 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4526 grub_disk_close(disk
);
4528 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4529 dev
= grub_device_open(name
);
4532 /* Check for official Ventoy device */
4533 ret
= ventoy_check_official_device(dev
);
4534 grub_device_close(dev
);
4542 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4543 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4548 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4555 ret
= ventoy_load_part_table(args
[0]);
4561 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4562 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4567 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4570 const char *vcfg
= NULL
;
4575 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4578 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4579 grub_env_set(args
[1], vcfg
);
4584 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4592 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4595 grub_uint8_t zeroguid
[16] = {0};
4600 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4603 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4605 if (id
>= 1 && id
<= 128)
4607 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4615 if (id
>= 1 && id
<= 4)
4617 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4627 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4630 char *device_name
= NULL
;
4631 grub_device_t dev
= NULL
;
4632 grub_fs_t fs
= NULL
;
4637 debug("get fs label for %s\n", args
[0]);
4641 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4645 device_name
= grub_file_get_device_name(args
[0]);
4648 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4652 dev
= grub_device_open(device_name
);
4655 debug("grub_device_open failed, %s\n", device_name
);
4659 fs
= grub_fs_probe(dev
);
4660 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4662 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4666 fs
->fs_label(dev
, &label
);
4669 debug("label=<%s>\n", label
);
4670 ventoy_set_env(args
[1], label
);
4678 check_free(device_name
, grub_free
);
4679 check_free(dev
, grub_device_close
);
4684 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4688 grub_snprintf((char *)data
, 256, "%s", filename
);
4695 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4697 if (info
->dir
&& filename
&& filename
[0] != '.')
4699 grub_snprintf((char *)data
, 256, "%s", filename
);
4706 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4709 char *device_name
= NULL
;
4710 grub_device_t dev
= NULL
;
4711 grub_fs_t fs
= NULL
;
4712 char name
[256] ={0};
4716 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4720 device_name
= grub_file_get_device_name(args
[0]);
4723 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4727 dev
= grub_device_open(device_name
);
4730 debug("grub_device_open failed, %s\n", device_name
);
4734 fs
= grub_fs_probe(dev
);
4737 debug("grub_fs_probe failed, %s\n", device_name
);
4741 fs
->fs_dir(dev
, args
[1], hook
, name
);
4744 ventoy_set_env(args
[2], name
);
4751 check_free(device_name
, grub_free
);
4752 check_free(dev
, grub_device_close
);
4757 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4760 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4763 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4766 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4769 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4779 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4783 for (pos
= args
[0]; *pos
; pos
++)
4797 grub_env_set(args
[1], args
[0]);
4807 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4817 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4822 len
= (int)grub_strlen(buf
);
4823 for (i
= len
; i
> 0; i
--)
4825 if (buf
[i
- 1] == '/')
4827 grub_env_set(args
[1], buf
+ i
);
4832 grub_env_set(args
[1], buf
);
4837 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4839 struct grub_video_mode_info info
;
4846 if (!g_video_mode_list
)
4848 ventoy_enum_video_mode();
4851 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4853 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4857 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4860 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4862 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4863 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4865 VENTOY_CMD_RETURN(0);
4868 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4870 struct grub_video_mode_info info
;
4877 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4879 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4883 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4886 grub_env_set(args
[0], buf
);
4888 VENTOY_CMD_RETURN(0);
4891 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4899 if (!g_video_mode_list
)
4904 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4905 if (id
< g_video_mode_num
)
4907 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4908 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4911 grub_env_set(args
[1], buf
);
4913 VENTOY_CMD_RETURN(0);
4916 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4919 grub_uint32_t loadsector
= 0;
4922 grub_uint32_t boot_catlog
= 0;
4923 grub_uint8_t buf
[512];
4929 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4933 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4936 debug("failed to open %s\n", args
[0]);
4940 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4941 if (boot_catlog
== 0)
4943 debug("No bootcatlog found\n");
4944 grub_file_close(file
);
4948 grub_memset(buf
, 0, sizeof(buf
));
4949 grub_file_seek(file
, boot_catlog
* 2048);
4950 grub_file_read(file
, buf
, sizeof(buf
));
4951 grub_file_close(file
);
4953 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4955 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4957 if (buf
[i
+ 32] == 0x88)
4959 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4960 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4966 if (loadsector
== 0)
4968 debug("No EFI eltorito info found\n");
4972 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4973 grub_env_set(args
[1], value
);
4974 VENTOY_CMD_RETURN(0);
4977 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4982 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4984 if (pfsdir
->initrd
[0])
4989 curpos
= pfsdir
->curpos
;
4990 len
= grub_strlen(filename
);
4994 if ((len
== 1 && filename
[0] == '.') ||
4995 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5000 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5003 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5004 pfsdir
->curpos
= curpos
+ printlen
;
5005 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5006 pfsdir
->curpos
= curpos
;
5007 pfsdir
->fullpath
[curpos
] = 0;
5011 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5014 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5015 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5017 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5019 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5028 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5032 char *device_name
= NULL
;
5033 grub_device_t dev
= NULL
;
5034 grub_fs_t fs
= NULL
;
5035 replace_fs_dir
*pfsdir
= NULL
;
5041 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5045 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5051 device_name
= grub_file_get_device_name(args
[0]);
5057 dev
= grub_device_open(device_name
);
5063 fs
= grub_fs_probe(dev
);
5072 pfsdir
->fullpath
[0] = '/';
5073 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5075 if (pfsdir
->initrd
[0])
5077 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5079 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5081 if (pfsdir
->initrd
[i
] == '/')
5083 pfsdir
->initrd
[i
] = '\\';
5087 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5088 grub_env_set(args
[1], pos
);
5092 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5097 grub_check_free(pfsdir
);
5098 grub_check_free(device_name
);
5099 check_free(dev
, grub_device_close
);
5101 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5104 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5106 const char *pager
= NULL
;
5112 pager
= grub_env_get("pager");
5116 grub_env_set("pager", "1");
5118 else if (pager
[0] == '1')
5124 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5126 grub_env_set("pager", "1");
5129 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5132 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5138 if (g_pager_flag
== 1)
5140 grub_env_unset("pager");
5142 else if (g_pager_flag
== 2)
5144 grub_env_set("pager", g_old_pager
);
5147 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5150 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5152 if (g_json_case_mis_path
[0])
5157 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5159 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5165 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5168 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5170 if (g_json_case_mis_path
[0])
5175 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5177 if (grub_strcasecmp(filename
, "ventoy") == 0)
5179 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5180 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5181 if (g_json_case_mis_path
[0])
5191 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5194 char *device_name
= NULL
;
5195 grub_device_t dev
= NULL
;
5196 grub_fs_t fs
= NULL
;
5197 chk_case_fs_dir fs_dir
;
5203 device_name
= grub_file_get_device_name(args
[0]);
5209 dev
= grub_device_open(device_name
);
5215 fs
= grub_fs_probe(dev
);
5221 fstype
= ventoy_get_fs_type(fs
->name
);
5222 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5227 g_json_case_mis_path
[0] = 0;
5230 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5232 if (g_json_case_mis_path
[0])
5234 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5239 grub_check_free(device_name
);
5240 check_free(dev
, grub_device_close
);
5242 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5245 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5248 grub_partition_t part
;
5249 char priority_str
[3]; /* Maximum value 15 */
5253 if (argc
< 2 || argc
> 3)
5254 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5255 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5257 /* Open the disk if it exists */
5258 disk
= grub_disk_open (args
[0]);
5261 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5265 part
= grub_partition_probe (disk
, args
[1]);
5268 grub_disk_close (disk
);
5269 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5270 "No such partition");
5273 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5275 grub_disk_close (disk
);
5276 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5277 "Not a GPT partition");
5280 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5281 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5285 grub_env_set (args
[2], priority_str
);
5286 grub_env_export (args
[2]);
5290 grub_printf ("Priority is %s\n", priority_str
);
5293 grub_disk_close (disk
);
5294 return GRUB_ERR_NONE
;
5298 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5302 grub_file_t file
= NULL
;
5303 grub_uint32_t loadrba
= 0;
5304 grub_uint32_t boot_catlog
= 0;
5305 grub_uint8_t sector
[512];
5306 boot_info_table
*info
= NULL
;
5311 /* This also trigger a iso9660 fs parse */
5312 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5317 joliet
= grub_iso9660_is_joliet();
5323 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5326 debug("failed to open %s\n", args
[0]);
5330 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5331 if (boot_catlog
== 0)
5333 debug("no bootcatlog found %u\n", boot_catlog
);
5337 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5340 debug("no bios eltorito rba found %u\n", loadrba
);
5344 grub_file_seek(file
, loadrba
* 2048);
5345 grub_file_read(file
, sector
, 512);
5347 info
= (boot_info_table
*)sector
;
5348 if (info
->bi_data0
== 0x7c6ceafa &&
5349 info
->bi_data1
== 0x90900000 &&
5350 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5351 info
->bi_BootFileLocation
== loadrba
)
5353 debug("bootloader is syslinux, %u.\n", loadrba
);
5359 grub_file_close(file
);
5360 grub_errno
= GRUB_ERR_NONE
;
5364 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5367 ventoy_vlnk_part
*node
;
5373 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5375 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5376 ++n
, node
->device
, node
->disksig
,
5377 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5383 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5391 len
= (int)grub_strlen(args
[0]);
5392 if (grub_file_is_vlnk_suffix(args
[0], len
))
5401 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5404 const char *name
= NULL
;
5410 grub_env_unset(args
[1]);
5411 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5414 debug("VLNK SRC: <%s>\n", args
[0]);
5415 debug("VLNK DST: <%s>\n", name
);
5416 grub_env_set(args
[1], name
);
5424 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5428 grub_file_t file
= NULL
;
5439 len
= (int)grub_strlen(args
[0]);
5440 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5442 grub_printf("Invalid vlnk suffix\n");
5446 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5449 grub_printf("Failed to open %s\n", args
[0]);
5453 if (file
->size
!= 32768)
5455 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5459 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5460 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5462 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5467 check_free(file
, grub_file_close
);
5468 grub_errno
= GRUB_ERR_NONE
;
5472 int ventoy_env_init(void)
5476 grub_env_set("vtdebug_flag", "");
5478 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5479 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5480 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5481 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5483 ventoy_filt_register(0, ventoy_wrapper_open
);
5485 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5488 g_grub_param
->grub_env_get
= grub_env_get
;
5489 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5490 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5491 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5492 grub_env_set("env_param", buf
);
5493 grub_env_set("ventoy_env_param", buf
);
5495 grub_env_export("env_param");
5496 grub_env_export("ventoy_env_param");
5499 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5500 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5502 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5503 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5505 grub_env_export("vtoy_winpeshl_ini_addr");
5506 grub_env_export("vtoy_winpeshl_ini_size");
5508 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5509 grub_env_set("vtoy_chain_file_size", buf
);
5510 grub_env_export("vtoy_chain_file_size");
5512 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5513 grub_env_set("vtoy_chain_file_read", buf
);
5514 grub_env_export("vtoy_chain_file_read");
5521 static cmd_para ventoy_cmds
[] =
5523 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
5524 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
5525 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5526 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5527 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5528 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5529 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5530 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5531 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5532 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5533 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5534 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5535 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5536 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5537 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5538 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5539 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5540 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5541 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5542 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5543 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5544 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5545 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5546 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5547 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5548 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5549 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5551 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5552 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5553 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5554 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5555 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5556 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5557 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5559 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5560 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5561 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5562 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5563 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5564 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5565 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5566 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5567 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5568 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5571 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5572 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5573 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5574 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5575 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5576 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5577 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5578 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5579 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5580 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5581 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5583 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5584 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5585 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5586 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5587 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5588 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5589 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5591 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5592 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5593 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5594 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5595 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5596 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5597 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5598 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5599 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5600 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5602 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5603 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5604 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5605 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5606 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5607 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5608 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5609 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5610 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5612 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5613 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5614 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5615 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5618 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5619 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5620 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5622 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5623 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5624 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5627 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5628 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5629 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5630 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5631 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5632 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5633 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5634 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5635 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5636 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5637 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5638 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5640 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5641 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5642 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5643 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5644 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5645 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5646 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5647 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5648 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5649 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5650 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5651 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5653 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5654 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5655 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5656 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5657 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5658 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5659 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5660 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5661 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
5662 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
5663 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
5664 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
5665 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
5666 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
5669 int ventoy_register_all_cmd(void)
5672 cmd_para
*cur
= NULL
;
5674 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5676 cur
= ventoy_cmds
+ i
;
5677 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5678 cur
->summary
, cur
->description
, cur
->parser
);
5684 int ventoy_unregister_all_cmd(void)
5688 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5690 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);