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 char g_iso_vd_id_publisher
[130];
141 static char g_iso_vd_id_prepare
[130];
142 static char g_iso_vd_id_application
[130];
144 static int g_pager_flag
= 0;
145 static char g_old_pager
[32];
147 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
149 const char *g_menu_class
[img_type_max
] =
151 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
154 const char *g_menu_prefix
[img_type_max
] =
156 "iso", "wim", "efi", "img", "vhd", "vtoy"
159 static int g_vtoy_load_prompt
= 0;
160 static char g_vtoy_prompt_msg
[64];
162 static char g_json_case_mis_path
[32];
164 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
166 int ventoy_get_fs_type(const char *fs
)
170 return ventoy_fs_max
;
172 else if (grub_strncmp(fs
, "exfat", 5) == 0)
174 return ventoy_fs_exfat
;
176 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
178 return ventoy_fs_ntfs
;
180 else if (grub_strncmp(fs
, "ext", 3) == 0)
182 return ventoy_fs_ext
;
184 else if (grub_strncmp(fs
, "xfs", 3) == 0)
186 return ventoy_fs_xfs
;
188 else if (grub_strncmp(fs
, "udf", 3) == 0)
190 return ventoy_fs_udf
;
192 else if (grub_strncmp(fs
, "fat", 3) == 0)
194 return ventoy_fs_fat
;
197 return ventoy_fs_max
;
200 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
219 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
221 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
225 static int ventoy_control_get_flag(const char *key
)
227 const char *val
= ventoy_get_env(key
);
229 if (val
&& val
[0] == '1' && val
[1] == 0)
236 static grub_err_t
ventoy_fs_close(grub_file_t file
)
238 grub_file_close(g_old_file
);
239 grub_free(file
->data
);
247 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
253 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
258 for (i
= 0; i
< g_video_mode_num
; i
++)
260 if (g_video_mode_list
[i
].width
== info
->width
&&
261 g_video_mode_list
[i
].height
== info
->height
&&
262 g_video_mode_list
[i
].bpp
== info
->bpp
)
268 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
269 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
270 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
273 if (g_video_mode_num
== g_video_mode_max
)
275 g_video_mode_max
*= 2;
276 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
282 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
284 if (v1
->bpp
== v2
->bpp
)
286 if (v1
->width
== v2
->width
)
288 if (v1
->height
== v2
->height
)
294 return (v1
->height
< v2
->height
) ? -1 : 1;
299 return (v1
->width
< v2
->width
) ? -1 : 1;
304 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
308 static int ventoy_enum_video_mode(void)
311 grub_video_adapter_t adapter
;
312 grub_video_driver_id_t id
;
313 ventoy_video_mode mode
;
315 g_video_mode_num
= 0;
316 g_video_mode_max
= 1024;
317 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
318 if (!g_video_mode_list
)
323 #ifdef GRUB_MACHINE_PCBIOS
324 grub_dl_load ("vbe");
327 id
= grub_video_get_driver_id ();
329 FOR_VIDEO_ADAPTERS (adapter
)
331 if (!adapter
->iterate
||
332 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
333 adapter
->init() != GRUB_ERR_NONE
)))
338 adapter
->iterate(ventoy_video_hook
, NULL
);
340 if (adapter
->id
!= id
)
346 /* sort video mode */
347 for (i
= 0; i
< g_video_mode_num
; i
++)
348 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
350 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
352 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
353 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
354 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
358 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
361 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
365 static struct grub_fs vtoy_fs
=
370 .fs_read
= ventoy_fs_read
,
371 .fs_close
= ventoy_fs_close
,
381 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
387 file
->data
= grub_malloc(rawFile
->size
+ 4096);
393 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
394 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
396 g_old_file
= rawFile
;
398 file
->size
= rawFile
->size
+ len
;
399 file
->device
= rawFile
->device
;
401 file
->not_easily_seekable
= 1;
406 static int ventoy_check_decimal_var(const char *name
, long *value
)
408 const char *value_str
= NULL
;
410 value_str
= grub_env_get(name
);
411 if (NULL
== value_str
)
413 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
416 if (!ventoy_is_decimal(value_str
))
418 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
421 *value
= grub_strtol(value_str
, NULL
, 10);
423 return GRUB_ERR_NONE
;
426 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
428 grub_uint64_t sectors
;
430 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
432 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
436 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
439 return sectors
* 512;
442 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
448 grub_uint32_t offset
;
450 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
453 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
457 len
= (int)file
->size
;
459 data
= (char *)grub_malloc(file
->size
);
465 grub_file_read(file
, data
, file
->size
);
466 grub_file_close(file
);
468 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
469 grub_script_execute_sourcecode(exec
);
471 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
472 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
473 grub_file_close(file
);
475 grub_script_execute_sourcecode("loopback -d efiboot");
479 *direntoff
= offset
+ 2;
484 static int ventoy_set_check_result(int ret
)
488 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
489 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
490 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
494 grub_printf(VTOY_WARNING
"\n");
495 grub_printf(VTOY_WARNING
"\n");
496 grub_printf(VTOY_WARNING
"\n\n\n");
498 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
499 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
501 grub_printf("\n\nWill exit after 10 seconds ...... ");
509 static int ventoy_check_official_device(grub_device_t dev
)
513 grub_uint64_t offset
;
516 grub_uint8_t mbr
[512];
520 struct grub_partition
*partition
;
522 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
524 return ventoy_set_check_result(1 | 0x1000);
527 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
528 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
529 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
531 #ifndef GRUB_MACHINE_EFI
532 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
533 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
534 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
536 return ventoy_set_check_result(2 | 0x1000);
545 /* We must have partition 2 */
548 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
552 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
556 return ventoy_set_check_result(3 | 0x1000);
559 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
561 grub_file_close(file
);
562 return ventoy_set_check_result(4 | 0x1000);
565 partition
= dev
->disk
->partition
;
566 if (partition
->number
!= 0 || partition
->start
!= 2048)
568 return ventoy_set_check_result(5);
573 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
575 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
576 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
577 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
579 grub_file_close(file
);
580 return ventoy_set_check_result(6);
585 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
586 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
587 PartTbl
[1].SectorCount
!= 65536)
589 grub_file_close(file
);
590 return ventoy_set_check_result(6);
596 offset
= partition
->start
+ partition
->len
;
597 partition
= file
->device
->disk
->partition
;
598 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
600 grub_file_close(file
);
601 return ventoy_set_check_result(7);
605 grub_file_close(file
);
609 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
610 dev2
= grub_device_open(devname
);
613 return ventoy_set_check_result(8);
616 fs
= grub_fs_probe(dev2
);
619 grub_device_close(dev2
);
620 return ventoy_set_check_result(9);
623 fs
->fs_label(dev2
, &label
);
624 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
626 grub_device_close(dev2
);
627 return ventoy_set_check_result(10);
630 grub_device_close(dev2
);
634 disk
= grub_disk_open(dev
->disk
->name
);
637 return ventoy_set_check_result(11);
640 grub_memset(mbr
, 0, 512);
641 grub_disk_read(disk
, 0, 0, 512, mbr
);
642 grub_disk_close(disk
);
644 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
646 return ventoy_set_check_result(12);
649 return ventoy_set_check_result(0);
652 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
656 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
666 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
668 grub_uint64_t size
= 0;
671 char fullpath
[256] = {0};
674 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
677 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
680 debug("grub_file_open failed <%s>\n", fullpath
);
686 grub_file_close(file
);
690 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
694 char fullpath
[512] = {0};
697 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
700 file
= grub_file_open(fullpath
, type
);
703 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
710 int ventoy_is_dir_exist(const char *fmt
, ...)
717 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
721 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
724 grub_strncpy(pos
+ len
, "\" ]", 3);
726 debug("script exec %s\n", buf
);
728 if (0 == grub_script_execute_sourcecode(buf
))
736 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
739 grub_uint8_t
*outbuf
;
740 grub_uint8_t gzHdr
[10] =
742 0x1F, 0x8B, /* magic */
750 grub_memset(&s
, 0, sizeof(mz_stream
));
752 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
754 outbuf
= (grub_uint8_t
*)mem_out
;
756 mem_out_len
-= sizeof(gzHdr
) + 8;
757 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
758 outbuf
+= sizeof(gzHdr
);
760 s
.avail_in
= mem_in_len
;
763 s
.avail_out
= mem_out_len
;
766 mz_deflate(&s
, MZ_FINISH
);
770 outbuf
+= s
.total_out
;
771 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
772 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
774 return s
.total_out
+ sizeof(gzHdr
) + 8;
782 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
786 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
789 if (0 == grub_strcmp(args
[0], "on"))
792 grub_env_set("vtdebug_flag", "debug");
797 grub_env_set("vtdebug_flag", "");
800 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
803 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
807 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
809 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
810 grub_printf(" level:\r\n");
811 grub_printf(" 01/11: busybox / (+cat log)\r\n");
812 grub_printf(" 02/12: initrd / (+cat log)\r\n");
813 grub_printf(" 03/13: hook / (+cat log)\r\n");
815 grub_printf(" debug:\r\n");
816 grub_printf(" 0: debug is off\r\n");
817 grub_printf(" 1: debug is on\r\n");
819 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
822 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
824 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
826 g_ventoy_debug_level
= 1;
829 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
832 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
841 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
844 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
876 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
892 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
908 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
913 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
915 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
918 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
923 value_long
+= grub_strtol(args
[1], NULL
, 10);
925 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
926 grub_env_set(args
[0], buf
);
928 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
931 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
933 ulonglong value1
= 0;
934 ulonglong value2
= 0;
939 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
942 value1
= grub_strtoull(args
[0], NULL
, 10);
943 value2
= grub_strtoull(args
[1], NULL
, 10);
945 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
946 grub_env_set(args
[2], buf
);
948 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
951 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
966 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
969 debug("failed to open file <%s> for udf check\n", args
[0]);
973 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
975 grub_env_set(args
[1], buf
);
977 grub_file_close(file
);
983 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
991 g_wimboot_enable
= 0;
993 grub_check_free(g_wimiso_path
);
994 grub_check_free(g_wimiso_chunk_list
.chunk
);
996 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1002 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1003 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1004 if (NULL
== g_wimiso_chunk_list
.chunk
)
1006 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1009 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1010 g_wimiso_chunk_list
.cur_chunk
= 0;
1012 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1014 g_wimboot_enable
= 1;
1015 g_wimiso_path
= grub_strdup(args
[0]);
1016 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1017 grub_file_close(file
);
1022 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1032 ventoy_iso9660_override
*dirent
;
1041 totlen
= sizeof(ventoy_chain_head
);
1043 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1045 debug("failed to load efiboot template %d\n", len
);
1051 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1053 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1056 debug("failed to open file <%s>\n", args
[0]);
1060 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1065 totlen
+= ventoy_align_2k(file
->size
);
1067 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1068 dirent
->first_sector
= len
/ 2048;
1069 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1070 dirent
->size
= (grub_uint32_t
)file
->size
;
1071 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1073 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1075 #ifdef GRUB_MACHINE_EFI
1076 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1078 data
= (char *)grub_malloc(totlen
);
1081 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1083 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1084 grub_check_free(buf
);
1086 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1087 grub_file_close(file
);
1089 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1090 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1091 grub_env_set(name
, value
);
1093 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1094 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1095 grub_env_set(name
, value
);
1100 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1106 g_vtoy_load_prompt
= 0;
1107 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1109 if (argc
== 2 && args
[0][0] == '1')
1111 g_vtoy_load_prompt
= 1;
1112 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1115 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1118 int ventoy_need_prompt_load_file(void)
1120 return g_vtoy_load_prompt
;
1123 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1125 grub_uint64_t ro
= 0;
1126 grub_uint64_t div
= 0;
1127 grub_ssize_t left
= size
;
1128 char *cur
= (char *)buf
;
1130 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1133 while (left
>= VTOY_SIZE_2MB
)
1135 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1136 cur
+= VTOY_SIZE_2MB
;
1137 left
-= VTOY_SIZE_2MB
;
1139 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1140 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1146 grub_file_read(file
, cur
, left
);
1149 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1155 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1162 enum grub_file_type type
;
1173 if (grub_strcmp(args
[0], "nodecompress") == 0)
1175 type
= VENTOY_FILE_TYPE
;
1179 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1182 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1185 debug("failed to open file <%s>\n", args
[1]);
1189 #ifdef GRUB_MACHINE_EFI
1190 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1192 buf
= (char *)grub_malloc(file
->size
);
1197 grub_file_close(file
);
1201 if (g_vtoy_load_prompt
)
1203 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1207 grub_file_read(file
, buf
, file
->size
);
1210 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1211 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1212 grub_env_set(name
, value
);
1214 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1215 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1216 grub_env_set(name
, value
);
1218 grub_file_close(file
);
1224 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1242 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1245 debug("failed to open file <%s> for udf check\n", args
[0]);
1249 headlen
= sizeof(ventoy_chain_head
);
1251 #ifdef GRUB_MACHINE_EFI
1252 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1254 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1257 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1259 grub_file_read(file
, buf
+ headlen
, file
->size
);
1261 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1262 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1263 grub_env_set(name
, value
);
1265 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1266 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1267 grub_env_set(name
, value
);
1269 grub_file_close(file
);
1275 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1281 if (grub_iso9660_is_joliet())
1283 debug("This time has joliet process\n");
1292 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1301 if (args
[0][0] == '1')
1303 grub_iso9660_set_nojoliet(1);
1307 grub_iso9660_set_nojoliet(0);
1313 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1318 grub_uint8_t buf
[32];
1329 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1332 debug("failed to open file <%s> for udf check\n", args
[0]);
1336 for (i
= 16; i
< 32; i
++)
1338 grub_file_seek(file
, i
* 2048);
1339 grub_file_read(file
, buf
, sizeof(buf
));
1347 grub_file_seek(file
, i
* 2048);
1348 grub_file_read(file
, buf
, sizeof(buf
));
1350 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1353 grub_file_seek(file
, i
* 2048);
1354 grub_file_read(file
, buf
, sizeof(buf
));
1356 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1357 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1363 grub_file_close(file
);
1365 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1370 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1372 long value_long1
= 0;
1373 long value_long2
= 0;
1375 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1377 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1380 value_long1
= grub_strtol(args
[0], NULL
, 10);
1381 value_long2
= grub_strtol(args
[2], NULL
, 10);
1383 if (0 == grub_strcmp(args
[1], "eq"))
1385 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1387 else if (0 == grub_strcmp(args
[1], "ne"))
1389 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1391 else if (0 == grub_strcmp(args
[1], "gt"))
1393 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1395 else if (0 == grub_strcmp(args
[1], "lt"))
1397 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1399 else if (0 == grub_strcmp(args
[1], "ge"))
1401 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1403 else if (0 == grub_strcmp(args
[1], "le"))
1405 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1409 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1415 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1418 char buf
[128] = {0};
1422 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1425 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1426 pos
= grub_strstr(buf
, ",");
1432 grub_env_set(args
[1], buf
);
1434 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1437 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1443 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1449 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1452 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1454 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1455 if (0 == grub_script_execute_sourcecode(buf
))
1457 debug("file %s exist, ventoy_compatible YES\n", buf
);
1458 grub_env_set("ventoy_compatible", "YES");
1459 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1463 debug("file %s NOT exist\n", buf
);
1467 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1468 pos
= grub_strstr(buf
, ")");
1474 disk
= grub_disk_open(buf
);
1477 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1478 grub_disk_close(disk
);
1480 g_img_swap_tmp_buf
[703] = 0;
1481 for (i
= 318; i
< 703; i
++)
1483 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1484 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1486 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1487 grub_env_set("ventoy_compatible", "YES");
1488 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1494 debug("failed to open disk <%s>\n", buf
);
1497 grub_env_set("ventoy_compatible", "NO");
1498 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1501 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1507 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1509 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1512 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1517 if (0 == g_sort_case_sensitive
)
1519 if (grub_islower(c1
))
1521 c1
= c1
- 'a' + 'A';
1524 if (grub_islower(c2
))
1526 c2
= c2
- 'a' + 'A';
1539 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1545 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1547 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1550 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1555 if (0 == g_sort_case_sensitive
)
1557 if (grub_islower(c1
))
1559 c1
= c1
- 'a' + 'A';
1562 if (grub_islower(c2
))
1564 c2
= c2
- 'a' + 'A';
1577 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1579 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1581 grub_memcpy(img1
, img2
, sizeof(img_info
));
1582 img1
->next
= g_img_swap_tmp
.next
;
1583 img1
->prev
= g_img_swap_tmp
.prev
;
1585 g_img_swap_tmp
.next
= img2
->next
;
1586 g_img_swap_tmp
.prev
= img2
->prev
;
1587 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1590 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1594 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1602 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1604 ventoy_vlnk_part
*node
= NULL
;
1605 grub_uint32_t SelfSig
;
1606 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1608 /* skip Ventoy partition 1/2 */
1609 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1610 if (partition
->number
< 2 && SelfSig
== *pSig
)
1615 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1618 node
->disksig
= *pSig
;
1619 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1620 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1621 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1623 node
->next
= g_vlnk_part_list
;
1624 g_vlnk_part_list
= node
;
1630 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1637 disk
= grub_disk_open(name
);
1640 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1641 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1642 grub_disk_close(disk
);
1648 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1650 const char *fs
[ventoy_fs_max
+ 1] =
1652 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1657 cur
->dev
= grub_device_open(cur
->device
);
1662 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1668 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1673 char *disk
, *device
;
1674 grub_uint32_t readcrc
, calccrc
;
1675 ventoy_vlnk_part
*cur
;
1676 grub_fs_t fs
= NULL
;
1678 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1682 grub_printf("VLNK invalid guid\n");
1688 readcrc
= vlnk
->crc32
;
1690 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1691 if (readcrc
!= calccrc
)
1695 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1701 if (!g_vlnk_part_list
)
1703 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1706 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1708 if (cur
->disksig
== vlnk
->disk_signature
)
1712 if (cur
->partoffset
== vlnk
->part_offset
)
1715 device
= cur
->device
;
1717 if (cur
->probe
== 0)
1720 ventoy_vlnk_probe_fs(cur
);
1730 struct grub_file file
;
1732 grub_memset(&file
, 0, sizeof(file
));
1733 file
.device
= cur
->dev
;
1734 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1737 cur
->fs
->fs_close(&file
);
1738 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1747 grub_printf("\n==== VLNK Information ====\n"
1748 "Disk Signature: %08x\n"
1749 "Partition Offset: %llu\n"
1750 "File Path: <%s>\n\n",
1751 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1755 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1759 grub_printf("Disk Find: [ NO ]\n");
1764 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1768 grub_printf("Part Find: [ NO ]\n");
1770 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1773 grub_printf("VLNK File: <%s>\n", dst
);
1780 return (1 - filefind
);
1783 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1788 grub_file_t file
= NULL
;
1793 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1795 else if (dir
[0] == '/')
1797 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1801 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1804 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1810 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1811 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1812 grub_file_close(file
);
1814 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1816 rc
= grub_file_add_vlnk(src
, dst
);
1822 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1832 const menu_tip
*tip
;
1833 img_iterator_node
*tmp
;
1834 img_iterator_node
*new_node
;
1835 img_iterator_node
*node
= (img_iterator_node
*)data
;
1837 if (g_enumerate_time_checked
== 0)
1839 g_enumerate_finish_time_ms
= grub_get_time_ms();
1840 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1843 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1845 g_enumerate_time_checked
= 1;
1849 len
= grub_strlen(filename
);
1853 if (node
->level
+ 1 > g_img_max_search_level
)
1858 if ((len
== 1 && filename
[0] == '.') ||
1859 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1864 if (!ventoy_img_name_valid(filename
, len
))
1869 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1874 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1876 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1877 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1880 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1885 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1888 new_node
->level
= node
->level
+ 1;
1889 new_node
->plugin_list_index
= index
;
1890 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1892 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1895 debug("Directory %s ignored...\n", new_node
->dir
);
1896 grub_free(new_node
);
1900 new_node
->tail
= node
->tail
;
1902 new_node
->parent
= node
;
1903 if (!node
->firstchild
)
1905 node
->firstchild
= new_node
;
1908 if (g_img_iterator_tail
)
1910 g_img_iterator_tail
->next
= new_node
;
1911 g_img_iterator_tail
= new_node
;
1915 g_img_iterator_head
.next
= new_node
;
1916 g_img_iterator_tail
= new_node
;
1922 debug("Find a file %s\n", filename
);
1928 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1930 type
= img_type_iso
;
1932 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1934 type
= img_type_wim
;
1936 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1937 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1939 type
= img_type_vhd
;
1941 #ifdef GRUB_MACHINE_EFI
1942 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1944 type
= img_type_efi
;
1947 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1949 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1951 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1952 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1957 type
= img_type_img
;
1959 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1961 type
= img_type_vtoy
;
1963 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1965 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1967 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1968 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1977 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1982 if (g_plugin_image_list
)
1984 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1985 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1986 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1988 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1991 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1993 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1998 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2000 if (grub_file_is_vlnk_suffix(filename
, len
))
2003 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2010 img
= grub_zalloc(sizeof(img_info
));
2014 img
->plugin_list_index
= index
;
2015 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2017 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2019 img
->size
= info
->size
;
2020 if (vlnk
|| 0 == img
->size
)
2022 if (node
->dir
[0] == '/')
2024 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2028 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2032 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2034 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2039 if (g_ventoy_img_list
)
2041 tail
= *(node
->tail
);
2047 g_ventoy_img_list
= img
;
2050 img
->id
= g_ventoy_img_count
;
2052 if (node
&& NULL
== node
->firstiso
)
2054 node
->firstiso
= img
;
2065 *((img_info
**)(node
->tail
)) = img
;
2066 g_ventoy_img_count
++;
2068 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2070 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2073 img
->tip1
= tip
->tip1
;
2074 img
->tip2
= tip
->tip2
;
2077 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2080 img
->class = g_menu_class
[type
];
2082 img
->menu_prefix
= g_menu_prefix
[type
];
2084 if (img_type_iso
== type
)
2086 if (ventoy_plugin_check_memdisk(img
->path
))
2088 img
->menu_prefix
= "miso";
2092 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2099 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2101 int len
= GRUB_UINT_MAX
;
2102 const char *value
= NULL
;
2103 char name
[32] = {0};
2104 char plat
[32] = {0};
2105 char guidstr
[32] = {0};
2106 ventoy_guid guid
= VENTOY_GUID
;
2107 const char *fmt1
= NULL
;
2108 const char *fmt2
= NULL
;
2109 const char *fmt3
= NULL
;
2110 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2111 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2112 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2113 const char fmtcode
[]={
2114 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2115 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2116 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2117 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2118 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2119 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2122 grub_memset(name
, 0, sizeof(name
));
2123 puint
[0] = grub_swap_bytes32(0x56454e54);
2124 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2125 puint
[2] = grub_swap_bytes32(0x45525349);
2126 puint
[1] = grub_swap_bytes32(0x4f595f56);
2127 value
= ventoy_get_env(name
);
2129 grub_memset(name
, 0, sizeof(name
));
2130 puint
[1] = grub_swap_bytes32(0x5f544f50);
2131 puint
[0] = grub_swap_bytes32(0x56544c45);
2132 fmt1
= ventoy_get_env(name
);
2138 grub_memset(name
, 0, sizeof(name
));
2139 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2140 puint
[0] = grub_swap_bytes32(0x56544c45);
2141 fmt2
= ventoy_get_env(name
);
2143 grub_memset(name
, 0, sizeof(name
));
2144 puint
[1] = grub_swap_bytes32(0x5f434c52);
2145 puint
[0] = grub_swap_bytes32(0x56544c45);
2146 fmt3
= ventoy_get_env(name
);
2148 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2150 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2152 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2153 #pragma GCC diagnostic push
2154 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2155 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2156 fmt1
? fmt1
: fmtdata
,
2157 fmt2
? fmt2
: fmtdata
+ 4,
2158 value
? value
: "", plat
, guidstr
,
2159 fmt3
? fmt3
: fmtdata
+ 6);
2160 #pragma GCC diagnostic pop
2162 grub_memset(name
, 0, sizeof(name
));
2163 puint
[0] = grub_swap_bytes32(0x76746f79);
2164 puint
[2] = grub_swap_bytes32(0x656e7365);
2165 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2166 ventoy_set_env(name
, guidstr
);
2171 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2175 grub_uint8_t md5
[16];
2179 grub_memset(input
, 0, sizeof(input
));
2181 grub_printf("Enter password: ");
2184 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2186 grub_password_get(input
, 128);
2187 if (grub_strcmp(pwd
->text
, input
) == 0)
2192 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2194 grub_password_get(input
, 128);
2195 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2196 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2201 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2203 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2204 grub_password_get(input
+ offset
, 128);
2206 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2207 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2213 grub_printf("Invalid password!\n\n");
2220 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2222 img_info
*minimg
= NULL
;
2223 img_info
*img
= (img_info
*)(node
->firstiso
);
2225 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2227 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2242 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2244 img_iterator_node
*Minchild
= NULL
;
2245 img_iterator_node
*child
= node
->firstchild
;
2247 while (child
&& child
->parent
== node
)
2249 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2253 child
= child
->next
;
2258 Minchild
->select
= 1;
2264 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2267 img_info
*img
= NULL
;
2268 const char *dir_class
= NULL
;
2269 const char *dir_alias
= NULL
;
2270 img_iterator_node
*child
= NULL
;
2271 const menu_tip
*tip
= NULL
;
2273 if (node
->isocnt
== 0 || node
->done
== 1)
2278 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2280 offset
= node
->parent
->dirlen
;
2283 if (node
== &g_img_iterator_head
)
2285 if (g_default_menu_mode
== 0)
2287 if (g_tree_view_menu_style
== 0)
2289 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2290 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2291 " echo 'return ...' \n"
2296 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2297 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2303 g_tree_script_pre
= g_tree_script_pos
;
2307 node
->dir
[node
->dirlen
- 1] = 0;
2308 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2311 dir_class
= "vtoydir";
2314 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2316 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2319 if (g_tree_view_menu_style
== 0)
2321 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2322 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2323 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2327 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2328 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2329 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2334 dir_alias
= node
->dir
+ offset
;
2336 if (g_tree_view_menu_style
== 0)
2338 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2339 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2340 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2344 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2345 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2346 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2350 if (g_tree_view_menu_style
== 0)
2352 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2353 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2354 " echo 'return ...' \n"
2359 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2360 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2366 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2368 ventoy_dynamic_tree_menu(child
);
2371 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2373 if (g_tree_view_menu_style
== 0)
2375 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2376 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2379 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2380 img
->unsupport
? "[***********] " : "",
2381 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2383 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2387 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2388 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2391 img
->unsupport
? "[***********] " : "",
2392 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2394 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2398 if (node
!= &g_img_iterator_head
)
2400 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2407 static int ventoy_set_default_menu(void)
2413 const char *strdata
= NULL
;
2414 img_info
*cur
= NULL
;
2415 img_info
*default_node
= NULL
;
2416 const char *default_image
= NULL
;
2418 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2419 if (default_image
&& default_image
[0] == '/')
2421 img_len
= grub_strlen(default_image
);
2423 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2425 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2437 if (0 == g_default_menu_mode
)
2439 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2443 def
= grub_strdup(default_image
);
2449 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2451 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2452 if (strdata
&& strdata
[0] == '/')
2454 pos
= def
+ grub_strlen(strdata
);
2465 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2468 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2472 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2480 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2482 img_info
*next
= NULL
;
2483 img_info
*cur
= g_ventoy_img_list
;
2496 g_ventoy_img_list
= NULL
;
2497 g_ventoy_img_count
= 0;
2499 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2502 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2505 img_info
*cur
= g_ventoy_img_list
;
2509 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2511 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2514 img_id
= grub_strtol(args
[0], NULL
, 10);
2515 if (img_id
>= g_ventoy_img_count
)
2517 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2520 debug("Find image %ld name \n", img_id
);
2522 while (cur
&& img_id
> 0)
2530 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2533 debug("image name is %s\n", cur
->name
);
2535 grub_env_set(args
[1], cur
->name
);
2537 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2540 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2544 img_info
*cur
= g_ventoy_img_list
;
2550 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2553 len
= (int)grub_strlen(args
[0]);
2557 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2566 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2569 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2570 grub_env_set("chosen", id
);
2571 grub_env_export("chosen");
2573 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2576 static char g_fake_vlnk_src
[512];
2577 static char g_fake_vlnk_dst
[512];
2578 static grub_uint64_t g_fake_vlnk_size
;
2579 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2585 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2587 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2588 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2590 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2592 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2595 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2601 g_fake_vlnk_src
[0] = 0;
2602 g_fake_vlnk_dst
[0] = 0;
2603 g_fake_vlnk_size
= 0;
2604 grub_file_vtoy_vlnk(NULL
, NULL
);
2606 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2610 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2614 const char *id
= NULL
;
2615 img_info
*cur
= NULL
;
2619 if (argc
< 1 || argc
> 2)
2621 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2624 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2626 grub_env_set(args
[0], grub_strchr(g_fake_vlnk_src
, '/'));
2629 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2630 grub_env_set(args
[1], value
);
2636 id
= grub_env_get("chosen");
2638 pos
= grub_strstr(id
, "VID_");
2641 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2645 cur
= g_ventoy_img_list
;
2650 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2653 grub_env_set(args
[0], cur
->path
);
2657 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2658 grub_env_set(args
[1], value
);
2662 g_svd_replace_offset
= 0;
2664 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2668 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2672 grub_device_t dev
= NULL
;
2673 img_info
*cur
= NULL
;
2674 img_info
*tail
= NULL
;
2675 img_info
*min
= NULL
;
2676 img_info
*head
= NULL
;
2677 const char *strdata
= NULL
;
2678 char *device_name
= NULL
;
2680 img_iterator_node
*node
= NULL
;
2681 img_iterator_node
*tmp
= NULL
;
2687 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2690 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2692 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2697 g_enumerate_time_checked
= 0;
2698 g_enumerate_start_time_ms
= grub_get_time_ms();
2700 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2701 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2703 g_filt_dot_underscore_file
= 1;
2706 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2707 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2709 g_sort_case_sensitive
= 1;
2712 device_name
= grub_file_get_device_name(args
[0]);
2718 g_enum_dev
= dev
= grub_device_open(device_name
);
2724 g_enum_fs
= fs
= grub_fs_probe(dev
);
2730 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2732 debug("unsupported fs:<%s>\n", fs
->name
);
2733 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2737 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2739 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2740 if (strdata
&& strdata
[0] == '1')
2742 g_default_menu_mode
= 1;
2745 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2747 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2749 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2750 if (strdata
&& strdata
[0] == '/')
2752 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2753 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2755 g_img_iterator_head
.dir
[len
++] = '/';
2757 g_img_iterator_head
.dirlen
= len
;
2761 g_img_iterator_head
.dirlen
= 1;
2762 grub_strcpy(g_img_iterator_head
.dir
, "/");
2765 g_img_iterator_head
.tail
= &tail
;
2767 if (g_img_max_search_level
< 0)
2769 g_img_max_search_level
= GRUB_INT_MAX
;
2770 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2771 if (strdata
&& ventoy_is_decimal(strdata
))
2773 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2777 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2778 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2779 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2780 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2781 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2782 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2784 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2786 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2789 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2790 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2792 g_tree_view_menu_style
= 1;
2795 ventoy_set_default_menu();
2797 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2799 ventoy_dynamic_tree_menu(node
);
2803 node
= g_img_iterator_head
.next
;
2811 /* sort image list by image name */
2812 while (g_ventoy_img_list
)
2814 min
= g_ventoy_img_list
;
2815 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2817 if (ventoy_cmp_img(min
, cur
) > 0)
2825 min
->prev
->next
= min
->next
;
2830 min
->next
->prev
= min
->prev
;
2833 if (min
== g_ventoy_img_list
)
2835 g_ventoy_img_list
= min
->next
;
2853 g_ventoy_img_list
= head
;
2855 if (g_default_menu_mode
== 1)
2857 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2858 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2859 " echo 'return ...' \n"
2863 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2865 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2866 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2869 cur
->unsupport
? "[***********] " : "",
2870 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2872 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2875 g_tree_script_buf
[g_tree_script_pos
] = 0;
2876 g_list_script_buf
[g_list_script_pos
] = 0;
2878 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2879 grub_env_set(args
[1], buf
);
2883 check_free(device_name
, grub_free
);
2884 check_free(dev
, grub_device_close
);
2886 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2889 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2896 device_name
= grub_file_get_device_name(filename
);
2908 pos2
= grub_strstr(pos
, ",");
2911 pos2
= grub_strstr(pos
, ")");
2919 disk
= grub_disk_open(pos
);
2922 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2923 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2924 grub_disk_close(disk
);
2931 grub_free(device_name
);
2935 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2937 eltorito_descriptor desc
;
2939 grub_memset(&desc
, 0, sizeof(desc
));
2940 grub_file_seek(file
, 17 * 2048);
2941 grub_file_read(file
, &desc
, sizeof(desc
));
2943 if (desc
.type
!= 0 || desc
.version
!= 1)
2948 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2949 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2957 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2959 grub_uint8_t buf
[512];
2961 grub_file_seek(file
, sector
* 2048);
2962 grub_file_read(file
, buf
, sizeof(buf
));
2964 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2965 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2967 return *((grub_uint32_t
*)(buf
+ 40));
2973 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2977 grub_uint8_t buf
[512];
2978 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2980 grub_file_seek(file
, sector
* 2048);
2981 grub_file_read(file
, buf
, sizeof(buf
));
2983 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2985 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2989 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2994 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2996 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2998 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3002 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3004 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3009 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3011 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3013 if (buf
[36] == parttype
[i
])
3015 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3021 debug("%s does not contain efi eltorito\n", file
->name
);
3025 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3028 const char *fs
= NULL
;
3029 const char *val
= NULL
;
3030 const char *cdprompt
= NULL
;
3032 grub_uint8_t chksum
= 0;
3035 disk
= file
->device
->disk
;
3036 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3038 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3039 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3040 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3042 pos
= grub_strstr(file
->name
, "/");
3048 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3050 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3052 param
->vtoy_img_size
= file
->size
;
3054 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3055 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3057 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3059 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3060 param
->vtoy_reserved
[4] = 0;
3061 if (g_ventoy_chain_type
== 1) /* Windows */
3063 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3064 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3066 param
->vtoy_reserved
[4] = 1;
3070 fs
= ventoy_get_env("ventoy_fs_probe");
3071 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3073 param
->vtoy_reserved
[3] = 1;
3076 param
->vtoy_reserved
[5] = 0;
3077 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3078 if (val
&& val
[0] == '1' && val
[1] == 0)
3080 param
->vtoy_reserved
[5] = 1;
3083 /* ventoy_disk_signature used for vlnk */
3084 param
->vtoy_reserved
[6] = file
->vlnk
;
3085 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3087 /* calculate checksum */
3088 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3090 chksum
+= *((grub_uint8_t
*)param
+ i
);
3092 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3097 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3099 grub_uint32_t i
= 0;
3100 grub_uint64_t total
= 0;
3101 grub_uint64_t fileblk
= 0;
3102 ventoy_img_chunk
*chunk
= NULL
;
3104 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3106 chunk
= chunklist
->chunk
+ i
;
3108 if (chunk
->disk_start_sector
<= start
)
3110 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3114 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3117 fileblk
= (file
->size
+ 511) / 512;
3119 if (total
!= fileblk
)
3121 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3122 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3124 debug("maybe img file to be processed.\n");
3134 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3138 grub_uint32_t i
= 0;
3139 grub_uint32_t sector
= 0;
3140 grub_uint32_t count
= 0;
3141 grub_off_t size
= 0;
3142 grub_off_t read
= 0;
3144 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3145 if (fs_type
== ventoy_fs_exfat
)
3147 grub_fat_get_file_chunk(start
, file
, chunklist
);
3149 else if (fs_type
== ventoy_fs_ext
)
3151 grub_ext_get_file_chunk(start
, file
, chunklist
);
3155 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
3156 file
->read_hook_data
= chunklist
;
3158 for (size
= file
->size
; size
> 0; size
-= read
)
3160 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3161 grub_file_read(file
, NULL
, read
);
3164 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3166 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3167 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3170 if (ventoy_fs_udf
== fs_type
)
3172 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3174 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3175 chunklist
->chunk
[i
].img_start_sector
= sector
;
3176 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3182 len
= (int)grub_strlen(file
->name
);
3183 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3184 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3185 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3186 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3188 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3190 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3200 chunklist
->chunk
[i
].img_start_sector
= sector
;
3201 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3209 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3213 grub_disk_addr_t start
;
3218 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3221 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3224 g_conf_replace_node
= NULL
;
3225 g_conf_replace_offset
= 0;
3227 if (g_img_chunk_list
.chunk
)
3229 grub_free(g_img_chunk_list
.chunk
);
3232 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3234 grub_file_close(file
);
3235 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3238 /* get image chunk data */
3239 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3240 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3241 if (NULL
== g_img_chunk_list
.chunk
)
3243 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3246 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3247 g_img_chunk_list
.cur_chunk
= 0;
3249 start
= file
->device
->disk
->partition
->start
;
3251 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3253 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3254 grub_file_close(file
);
3258 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3261 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3262 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3263 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3266 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3268 grub_uint64_t offset
= 0;
3269 grub_uint32_t align
= 0;
3270 grub_file_t file
= NULL
;
3271 conf_replace
*node
= NULL
;
3277 debug("select conf replace argc:%d\n", argc
);
3284 node
= ventoy_plugin_find_conf_replace(args
[1]);
3287 debug("Conf replace not found for %s\n", args
[1]);
3291 debug("Find conf replace for %s\n", args
[1]);
3293 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3296 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3297 grub_file_close(file
);
3299 else if (node
->img
> 0)
3305 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3309 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3312 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3316 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3318 if (align
> vtoy_max_replace_file_size
)
3320 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3324 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3325 g_conf_replace_new_len
= (int)file
->size
;
3326 g_conf_replace_new_len_align
= align
;
3328 g_conf_replace_node
= node
;
3329 g_conf_replace_offset
= offset
+ 2;
3333 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3334 g_grub_param
->img_replace
.old_name_cnt
= 1;
3335 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3338 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3343 grub_file_close(file
);
3345 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3348 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3354 char configfile
[128];
3355 install_template
*node
= NULL
;
3361 debug("select auto installation argc:%d\n", argc
);
3368 node
= ventoy_plugin_find_install_template(args
[0]);
3371 debug("Auto install template not found for %s\n", args
[0]);
3375 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3377 defidx
= node
->autosel
;
3378 if (node
->timeout
< 0)
3380 node
->cursel
= node
->autosel
- 1;
3381 debug("Auto install template auto select %d\n", node
->autosel
);
3386 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3392 if (node
->timeout
> 0)
3394 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3397 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3398 " echo %s\n}\n", "");
3400 for (i
= 0; i
< node
->templatenum
; i
++)
3402 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3404 node
->templatepath
[i
].path
);
3407 g_ventoy_menu_esc
= 1;
3408 g_ventoy_suppress_esc
= 1;
3409 g_ventoy_suppress_esc_default
= defidx
;
3411 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3412 grub_script_execute_sourcecode(configfile
);
3414 g_ventoy_menu_esc
= 0;
3415 g_ventoy_suppress_esc
= 0;
3416 g_ventoy_suppress_esc_default
= 1;
3420 node
->cursel
= g_ventoy_last_entry
- 1;
3422 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3425 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3431 char configfile
[128];
3432 persistence_config
*node
;
3438 debug("select persistence argc:%d\n", argc
);
3445 node
= ventoy_plugin_find_persistent(args
[0]);
3448 debug("Persistence image not found for %s\n", args
[0]);
3452 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3454 defidx
= node
->autosel
;
3455 if (node
->timeout
< 0)
3457 node
->cursel
= node
->autosel
- 1;
3458 debug("Persistence image auto select %d\n", node
->autosel
);
3463 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3469 if (node
->timeout
> 0)
3471 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3474 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3475 " echo %s\n}\n", "");
3477 for (i
= 0; i
< node
->backendnum
; i
++)
3479 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3481 node
->backendpath
[i
].path
);
3485 g_ventoy_menu_esc
= 1;
3486 g_ventoy_suppress_esc
= 1;
3487 g_ventoy_suppress_esc_default
= defidx
;
3489 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3490 grub_script_execute_sourcecode(configfile
);
3492 g_ventoy_menu_esc
= 0;
3493 g_ventoy_suppress_esc
= 0;
3494 g_ventoy_suppress_esc_default
= 1;
3498 node
->cursel
= g_ventoy_last_entry
- 1;
3500 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3503 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3506 ventoy_img_chunk
*cur
;
3512 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3514 cur
= g_img_chunk_list
.chunk
+ i
;
3515 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3516 cur
->img_start_sector
, cur
->img_end_sector
,
3517 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3521 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3524 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3528 ventoy_img_chunk_list chunklist
;
3533 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3536 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3539 /* get image chunk data */
3540 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3541 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3542 if (NULL
== chunklist
.chunk
)
3544 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3547 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3548 chunklist
.cur_chunk
= 0;
3550 ventoy_get_block_list(file
, &chunklist
, 0);
3552 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3554 grub_printf("########## UNSUPPORTED ###############\n");
3557 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3559 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3561 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3562 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3565 grub_printf("\n==================================\n");
3567 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3569 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3570 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3571 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3572 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3573 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3577 grub_free(chunklist
.chunk
);
3578 grub_file_close(file
);
3580 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3583 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3586 ventoy_grub_param_file_replace
*replace
= NULL
;
3594 replace
= &(g_grub_param
->file_replace
);
3595 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3597 replace
->old_name_cnt
= 0;
3598 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3600 replace
->old_name_cnt
++;
3601 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3604 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3607 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3610 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3613 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3619 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3620 grub_env_set(args
[0], buf
);
3623 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3626 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3634 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3635 grub_printf("%s", g_list_script_buf
);
3639 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3640 grub_printf("%s", g_tree_script_buf
);
3646 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3648 img_info
*cur
= g_ventoy_img_list
;
3656 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3657 grub_printf("name:<%s>\n\n", cur
->name
);
3664 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3670 ventoy_plugin_dump_injection();
3675 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3681 ventoy_plugin_dump_auto_install();
3686 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3692 ventoy_plugin_dump_persistence();
3697 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3708 if (args
[0][0] == '0')
3710 return g_ventoy_memdisk_mode
? 0 : 1;
3712 else if (args
[0][0] == '1')
3714 return g_ventoy_iso_raw
? 0 : 1;
3716 else if (args
[0][0] == '2')
3718 return g_ventoy_iso_uefi_drv
? 0 : 1;
3720 else if (args
[0][0] == '3')
3722 return g_ventoy_grub2_mode
? 0 : 1;
3724 else if (args
[0][0] == '4')
3726 return g_ventoy_wimboot_mode
? 0 : 1;
3732 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3734 static int configfile_mode
= 0;
3735 char memfile
[128] = {0};
3742 * args[0]: 0:normal 1:configfile
3743 * args[1]: 0:list_buf 1:tree_buf
3748 debug("Invalid argc %d\n", argc
);
3754 if (args
[0][0] == '0')
3756 if (args
[1][0] == '0')
3758 grub_script_execute_sourcecode(g_list_script_buf
);
3762 grub_script_execute_sourcecode(g_tree_script_buf
);
3767 if (configfile_mode
)
3769 debug("Now already in F3 mode %d\n", configfile_mode
);
3773 if (args
[1][0] == '0')
3775 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3776 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3780 g_ventoy_last_entry
= -1;
3781 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3782 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3785 configfile_mode
= 1;
3786 grub_script_execute_sourcecode(memfile
);
3787 configfile_mode
= 0;
3793 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3804 g_ventoy_case_insensitive
= 1;
3805 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3806 g_ventoy_case_insensitive
= 0;
3812 grub_file_close(file
);
3818 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3823 const char *isopath
= NULL
;
3825 ventoy_mbr_head mbr
;
3832 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3835 isopath
= grub_env_get("vtoy_iso_part");
3838 debug("isopath is null %p\n", isopath
);
3842 debug("isopath is %s\n", isopath
);
3844 for (id
= 0; id
< 30 && (find
== 0); id
++)
3846 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3847 if (grub_strstr(isopath
, hdname
))
3849 debug("skip %s ...\n", hdname
);
3853 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3855 disk
= grub_disk_open(hdname
);
3858 debug("%s not exist\n", hdname
);
3862 grub_memset(&mbr
, 0, sizeof(mbr
));
3863 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3865 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3867 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3868 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3871 grub_env_set(args
[0], hdname
);
3875 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3879 debug("read %s failed\n", hdname
);
3882 grub_disk_close(disk
);
3888 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3899 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3902 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3905 debug("failed to open file %s\n", args
[0]);
3909 buf
= grub_malloc(len
);
3916 grub_file_read(file
, buf
, len
- 1);
3918 ventoy_get_line(buf
);
3919 ventoy_set_env(args
[1], buf
);
3923 grub_check_free(buf
);
3924 grub_file_close(file
);
3929 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3931 grub_uint64_t end_max
= 0;
3932 int *pCnt
= (int *)data
;
3937 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3938 "0 %llu linear /dev/ventoy %llu\n",
3939 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3941 end_max
= (partition
->len
+ partition
->start
) * 512;
3942 if (end_max
> g_part_end_max
)
3944 g_part_end_max
= end_max
;
3950 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3953 char *device_name
= NULL
;
3954 grub_device_t dev
= NULL
;
3959 g_part_list_pos
= 0;
3961 grub_env_unset("vtoy_img_part_file");
3968 device_name
= grub_file_get_device_name(args
[0]);
3971 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3975 dev
= grub_device_open(device_name
);
3978 debug("grub_device_open failed, %s\n", device_name
);
3982 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3984 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3985 grub_env_set("vtoy_img_part_file", buf
);
3987 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3988 grub_env_set("vtoy_img_part_cnt", buf
);
3990 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
3991 grub_env_set("vtoy_img_max_part_end", buf
);
3995 check_free(device_name
, grub_free
);
3996 check_free(dev
, grub_device_close
);
4002 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4013 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4016 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4019 debug("failed to open file %s\n", args
[0]);
4023 buf
= grub_malloc(file
->size
+ 1);
4029 buf
[file
->size
] = 0;
4030 grub_file_read(file
, buf
, file
->size
);
4032 if (grub_strstr(buf
, args
[1]))
4039 grub_check_free(buf
);
4040 grub_file_close(file
);
4045 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4051 ventoy_iso9660_vd pvd
;
4058 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4061 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4064 debug("failed to open file %s\n", args
[0]);
4068 grub_file_seek(file
, 16 * 2048);
4069 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4070 if (len
!= sizeof(pvd
))
4072 debug("failed to read pvd %d\n", len
);
4076 grub_memset(buf
, 0, sizeof(buf
));
4077 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4078 ventoy_set_env(args
[1], buf
);
4080 grub_memset(buf
, 0, sizeof(buf
));
4081 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4082 ventoy_set_env(args
[2], buf
);
4086 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4087 ventoy_set_env(args
[3], buf
);
4090 grub_file_close(file
);
4095 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4106 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4109 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4112 debug("failed to open file %s\n", args
[0]);
4116 grub_memset(buf
, 0, sizeof(buf
));
4117 grub_file_seek(file
, 16 * 2048 + 813);
4118 len
= (int)grub_file_read(file
, buf
, 17);
4121 debug("failed to read create date %d\n", len
);
4125 ventoy_set_env(args
[1], buf
);
4128 grub_file_close(file
);
4133 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4139 ventoy_env_hook_root(1);
4144 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4150 ventoy_env_hook_root(0);
4155 #ifdef GRUB_MACHINE_EFI
4156 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4161 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4167 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4168 if (var
&& *var
== 1)
4176 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4185 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4190 grub_uint64_t FileSectors
= 0;
4191 ventoy_gpt_info
*gpt
= NULL
;
4192 ventoy_part_table
*pt
= NULL
;
4193 grub_uint8_t zeroguid
[16] = {0};
4198 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4201 debug("failed to open file %s\n", args
[0]);
4205 if (file
->size
% 512)
4207 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4211 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4217 FileSectors
= file
->size
/ 512;
4219 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4220 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4222 debug("This is EFI partition table\n");
4224 for (i
= 0; i
< 128; i
++)
4226 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4228 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4230 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4231 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4239 debug("This is MBR partition table\n");
4241 for (i
= 0; i
< 4; i
++)
4243 pt
= gpt
->MBR
.PartTbl
+ i
;
4244 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4246 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4247 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4248 (ulonglong
)FileSectors
);
4257 grub_file_close(file
);
4258 grub_check_free(gpt
);
4259 grub_errno
= GRUB_ERR_NONE
;
4263 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4272 for (i
= 0; i
< 500; i
++)
4274 ret
= grub_getkey_noblock();
4275 if (ret
== GRUB_TERM_NO_KEY
)
4284 grub_printf("\n\n Still have key input after clear.\n");
4292 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4299 int image_sector_size
;
4301 ventoy_chain_head
*chain
;
4302 ventoy_img_chunk
*chunk
;
4303 ventoy_os_param
*osparam
;
4304 ventoy_image_location
*location
;
4305 ventoy_image_disk_region
*region
;
4306 struct grub_acpi_table_header
*acpi
;
4315 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4317 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4323 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4325 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4327 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4331 img_chunk_num
= chain
->img_chunk_num
;
4333 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4334 datalen
= sizeof(ventoy_os_param
) + loclen
;
4336 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4337 acpi
= grub_zalloc(buflen
);
4343 /* Step1: Fill acpi table header */
4344 grub_memcpy(acpi
->signature
, "VTOY", 4);
4345 acpi
->length
= buflen
;
4347 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4348 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4350 acpi
->creator_id
[0] = 1;
4351 acpi
->creator_rev
= 1;
4353 /* Step2: Fill data */
4354 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4355 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4356 osparam
->vtoy_img_location_addr
= 0;
4357 osparam
->vtoy_img_location_len
= loclen
;
4358 osparam
->chksum
= 0;
4359 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4361 location
= (ventoy_image_location
*)(osparam
+ 1);
4362 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4363 location
->image_sector_size
= image_sector_size
;
4364 location
->disk_sector_size
= chain
->disk_sector_size
;
4365 location
->region_count
= img_chunk_num
;
4367 region
= location
->regions
;
4368 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4369 if (512 == image_sector_size
)
4371 for (i
= 0; i
< img_chunk_num
; i
++)
4373 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4374 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4375 region
->disk_start_sector
= chunk
->disk_start_sector
;
4382 for (i
= 0; i
< img_chunk_num
; i
++)
4384 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4385 region
->image_start_sector
= chunk
->img_start_sector
;
4386 region
->disk_start_sector
= chunk
->disk_start_sector
;
4392 /* Step3: Fill acpi checksum */
4394 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4396 /* load acpi table */
4397 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4398 grub_script_execute_sourcecode(cmd
);
4402 VENTOY_CMD_RETURN(0);
4405 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4411 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4412 g_ventoy_last_entry
= -1;
4417 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4423 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4428 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4430 const char *pos
= filename
+ 1;
4438 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4440 grub_strncpy((char *)data
, filename
, 128);
4451 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4454 char *device_name
= NULL
;
4455 grub_device_t dev
= NULL
;
4456 grub_fs_t fs
= NULL
;
4457 char buf
[128] = {0};
4463 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4467 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4469 device_name
= grub_file_get_device_name(args
[0]);
4472 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4476 dev
= grub_device_open(device_name
);
4479 debug("grub_device_open failed, %s\n", device_name
);
4483 fs
= grub_fs_probe(dev
);
4486 debug("grub_fs_probe failed, %s\n", device_name
);
4490 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4494 ventoy_set_env(args
[2], buf
);
4501 check_free(device_name
, grub_free
);
4502 check_free(dev
, grub_device_close
);
4507 int ventoy_load_part_table(const char *diskname
)
4514 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4515 if (!g_ventoy_part_info
)
4520 disk
= grub_disk_open(diskname
);
4523 debug("Failed to open disk %s\n", diskname
);
4527 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4529 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4530 grub_disk_close(disk
);
4532 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4533 dev
= grub_device_open(name
);
4536 /* Check for official Ventoy device */
4537 ret
= ventoy_check_official_device(dev
);
4538 grub_device_close(dev
);
4546 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4547 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4552 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4559 ret
= ventoy_load_part_table(args
[0]);
4565 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4566 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4571 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4574 const char *vcfg
= NULL
;
4579 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4582 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4583 grub_env_set(args
[1], vcfg
);
4588 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4596 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4599 grub_uint8_t zeroguid
[16] = {0};
4604 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4607 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4609 if (id
>= 1 && id
<= 128)
4611 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4619 if (id
>= 1 && id
<= 4)
4621 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4631 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4634 char *device_name
= NULL
;
4635 grub_device_t dev
= NULL
;
4636 grub_fs_t fs
= NULL
;
4641 debug("get fs label for %s\n", args
[0]);
4645 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4649 device_name
= grub_file_get_device_name(args
[0]);
4652 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4656 dev
= grub_device_open(device_name
);
4659 debug("grub_device_open failed, %s\n", device_name
);
4663 fs
= grub_fs_probe(dev
);
4664 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4666 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4670 fs
->fs_label(dev
, &label
);
4673 debug("label=<%s>\n", label
);
4674 ventoy_set_env(args
[1], label
);
4682 check_free(device_name
, grub_free
);
4683 check_free(dev
, grub_device_close
);
4688 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4692 grub_snprintf((char *)data
, 256, "%s", filename
);
4699 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4701 if (info
->dir
&& filename
&& filename
[0] != '.')
4703 grub_snprintf((char *)data
, 256, "%s", filename
);
4710 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4713 char *device_name
= NULL
;
4714 grub_device_t dev
= NULL
;
4715 grub_fs_t fs
= NULL
;
4716 char name
[256] ={0};
4720 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4724 device_name
= grub_file_get_device_name(args
[0]);
4727 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4731 dev
= grub_device_open(device_name
);
4734 debug("grub_device_open failed, %s\n", device_name
);
4738 fs
= grub_fs_probe(dev
);
4741 debug("grub_fs_probe failed, %s\n", device_name
);
4745 fs
->fs_dir(dev
, args
[1], hook
, name
);
4748 ventoy_set_env(args
[2], name
);
4755 check_free(device_name
, grub_free
);
4756 check_free(dev
, grub_device_close
);
4761 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4764 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4767 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4770 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4773 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4783 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4787 for (pos
= args
[0]; *pos
; pos
++)
4801 grub_env_set(args
[1], args
[0]);
4811 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4821 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4826 len
= (int)grub_strlen(buf
);
4827 for (i
= len
; i
> 0; i
--)
4829 if (buf
[i
- 1] == '/')
4831 grub_env_set(args
[1], buf
+ i
);
4836 grub_env_set(args
[1], buf
);
4841 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4843 struct grub_video_mode_info info
;
4850 if (!g_video_mode_list
)
4852 ventoy_enum_video_mode();
4855 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4857 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4861 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4864 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4866 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4867 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4869 VENTOY_CMD_RETURN(0);
4872 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4874 struct grub_video_mode_info info
;
4881 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4883 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4887 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4890 grub_env_set(args
[0], buf
);
4892 VENTOY_CMD_RETURN(0);
4895 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4903 if (!g_video_mode_list
)
4908 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4909 if (id
< g_video_mode_num
)
4911 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4912 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4915 grub_env_set(args
[1], buf
);
4917 VENTOY_CMD_RETURN(0);
4920 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4923 grub_uint32_t loadsector
= 0;
4926 grub_uint32_t boot_catlog
= 0;
4927 grub_uint8_t buf
[512];
4933 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4937 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4940 debug("failed to open %s\n", args
[0]);
4944 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4945 if (boot_catlog
== 0)
4947 debug("No bootcatlog found\n");
4948 grub_file_close(file
);
4952 grub_memset(buf
, 0, sizeof(buf
));
4953 grub_file_seek(file
, boot_catlog
* 2048);
4954 grub_file_read(file
, buf
, sizeof(buf
));
4955 grub_file_close(file
);
4957 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4959 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4961 if (buf
[i
+ 32] == 0x88)
4963 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4964 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4970 if (loadsector
== 0)
4972 debug("No EFI eltorito info found\n");
4976 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4977 grub_env_set(args
[1], value
);
4978 VENTOY_CMD_RETURN(0);
4981 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4986 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4988 if (pfsdir
->initrd
[0])
4993 curpos
= pfsdir
->curpos
;
4994 len
= grub_strlen(filename
);
4998 if ((len
== 1 && filename
[0] == '.') ||
4999 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5004 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5007 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5008 pfsdir
->curpos
= curpos
+ printlen
;
5009 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5010 pfsdir
->curpos
= curpos
;
5011 pfsdir
->fullpath
[curpos
] = 0;
5015 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5018 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5019 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5021 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5023 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5032 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5036 char *device_name
= NULL
;
5037 grub_device_t dev
= NULL
;
5038 grub_fs_t fs
= NULL
;
5039 replace_fs_dir
*pfsdir
= NULL
;
5045 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5049 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5055 device_name
= grub_file_get_device_name(args
[0]);
5061 dev
= grub_device_open(device_name
);
5067 fs
= grub_fs_probe(dev
);
5076 pfsdir
->fullpath
[0] = '/';
5077 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5079 if (pfsdir
->initrd
[0])
5081 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5083 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5085 if (pfsdir
->initrd
[i
] == '/')
5087 pfsdir
->initrd
[i
] = '\\';
5091 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5092 grub_env_set(args
[1], pos
);
5096 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5101 grub_check_free(pfsdir
);
5102 grub_check_free(device_name
);
5103 check_free(dev
, grub_device_close
);
5105 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5108 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5110 const char *pager
= NULL
;
5116 pager
= grub_env_get("pager");
5120 grub_env_set("pager", "1");
5122 else if (pager
[0] == '1')
5128 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5130 grub_env_set("pager", "1");
5133 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5136 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5142 if (g_pager_flag
== 1)
5144 grub_env_unset("pager");
5146 else if (g_pager_flag
== 2)
5148 grub_env_set("pager", g_old_pager
);
5151 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5154 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5156 if (g_json_case_mis_path
[0])
5161 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5163 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5169 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5172 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5174 if (g_json_case_mis_path
[0])
5179 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5181 if (grub_strcasecmp(filename
, "ventoy") == 0)
5183 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5184 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5185 if (g_json_case_mis_path
[0])
5195 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5198 char *device_name
= NULL
;
5199 grub_device_t dev
= NULL
;
5200 grub_fs_t fs
= NULL
;
5201 chk_case_fs_dir fs_dir
;
5207 device_name
= grub_file_get_device_name(args
[0]);
5213 dev
= grub_device_open(device_name
);
5219 fs
= grub_fs_probe(dev
);
5225 fstype
= ventoy_get_fs_type(fs
->name
);
5226 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5231 g_json_case_mis_path
[0] = 0;
5234 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5236 if (g_json_case_mis_path
[0])
5238 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5243 grub_check_free(device_name
);
5244 check_free(dev
, grub_device_close
);
5246 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5249 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5252 grub_partition_t part
;
5253 char priority_str
[3]; /* Maximum value 15 */
5257 if (argc
< 2 || argc
> 3)
5258 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5259 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5261 /* Open the disk if it exists */
5262 disk
= grub_disk_open (args
[0]);
5265 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5269 part
= grub_partition_probe (disk
, args
[1]);
5272 grub_disk_close (disk
);
5273 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5274 "No such partition");
5277 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5279 grub_disk_close (disk
);
5280 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5281 "Not a GPT partition");
5284 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5285 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5289 grub_env_set (args
[2], priority_str
);
5290 grub_env_export (args
[2]);
5294 grub_printf ("Priority is %s\n", priority_str
);
5297 grub_disk_close (disk
);
5298 return GRUB_ERR_NONE
;
5302 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5306 grub_file_t file
= NULL
;
5307 grub_uint32_t loadrba
= 0;
5308 grub_uint32_t boot_catlog
= 0;
5309 grub_uint8_t sector
[512];
5310 boot_info_table
*info
= NULL
;
5315 /* This also trigger a iso9660 fs parse */
5316 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5321 joliet
= grub_iso9660_is_joliet();
5327 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5330 debug("failed to open %s\n", args
[0]);
5334 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5335 if (boot_catlog
== 0)
5337 debug("no bootcatlog found %u\n", boot_catlog
);
5341 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5344 debug("no bios eltorito rba found %u\n", loadrba
);
5348 grub_file_seek(file
, loadrba
* 2048);
5349 grub_file_read(file
, sector
, 512);
5351 info
= (boot_info_table
*)sector
;
5352 if (info
->bi_data0
== 0x7c6ceafa &&
5353 info
->bi_data1
== 0x90900000 &&
5354 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5355 info
->bi_BootFileLocation
== loadrba
)
5357 debug("bootloader is syslinux, %u.\n", loadrba
);
5363 grub_file_close(file
);
5364 grub_errno
= GRUB_ERR_NONE
;
5368 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5371 ventoy_vlnk_part
*node
;
5377 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5379 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5380 ++n
, node
->device
, node
->disksig
,
5381 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5387 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5395 len
= (int)grub_strlen(args
[0]);
5396 if (grub_file_is_vlnk_suffix(args
[0], len
))
5405 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5408 const char *name
= NULL
;
5414 grub_env_unset(args
[1]);
5415 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5418 debug("VLNK SRC: <%s>\n", args
[0]);
5419 debug("VLNK DST: <%s>\n", name
);
5420 grub_env_set(args
[1], name
);
5428 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5432 grub_file_t file
= NULL
;
5443 len
= (int)grub_strlen(args
[0]);
5444 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5446 grub_printf("Invalid vlnk suffix\n");
5450 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5453 grub_printf("Failed to open %s\n", args
[0]);
5457 if (file
->size
!= 32768)
5459 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5463 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5464 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5466 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5471 check_free(file
, grub_file_close
);
5472 grub_errno
= GRUB_ERR_NONE
;
5476 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5482 g_iso_vd_id_publisher
[0] = 0;
5483 g_iso_vd_id_prepare
[0] = 0;
5484 g_iso_vd_id_application
[0] = 0;
5489 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5493 grub_file_t file
= NULL
;
5498 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5501 grub_printf("Failed to open %s\n", args
[0]);
5505 grub_file_seek(file
, 16 * 2048 + offset
);
5506 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5509 grub_file_seek(file
, 16 * 2048 + offset
);
5510 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5513 grub_file_seek(file
, 16 * 2048 + offset
);
5514 grub_file_read(file
, g_iso_vd_id_application
, 128);
5518 check_free(file
, grub_file_close
);
5519 grub_errno
= GRUB_ERR_NONE
;
5523 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5526 char *id
= g_iso_vd_id_publisher
;
5531 if (args
[0][0] == '1')
5533 id
= g_iso_vd_id_prepare
;
5535 else if (args
[0][0] == '2')
5537 id
= g_iso_vd_id_application
;
5540 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5545 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5550 grub_errno
= GRUB_ERR_NONE
;
5554 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5559 g_ventoy_fn_mutex
= 0;
5560 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5562 g_ventoy_fn_mutex
= 1;
5565 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5568 int ventoy_env_init(void)
5572 grub_env_set("vtdebug_flag", "");
5574 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5575 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5576 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5577 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5579 ventoy_filt_register(0, ventoy_wrapper_open
);
5581 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5584 g_grub_param
->grub_env_get
= grub_env_get
;
5585 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5586 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5587 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5588 grub_env_set("env_param", buf
);
5589 grub_env_set("ventoy_env_param", buf
);
5591 grub_env_export("env_param");
5592 grub_env_export("ventoy_env_param");
5595 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5596 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5598 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5599 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5601 grub_env_export("vtoy_winpeshl_ini_addr");
5602 grub_env_export("vtoy_winpeshl_ini_size");
5604 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5605 grub_env_set("vtoy_chain_file_size", buf
);
5606 grub_env_export("vtoy_chain_file_size");
5608 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5609 grub_env_set("vtoy_chain_file_read", buf
);
5610 grub_env_export("vtoy_chain_file_read");
5617 static cmd_para ventoy_cmds
[] =
5619 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
5620 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
5621 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5622 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5623 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5624 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5625 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5626 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5627 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5628 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5629 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5630 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5631 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5632 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5633 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5634 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5635 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5636 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5637 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5638 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5639 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5640 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5641 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5642 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5643 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5644 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5645 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5647 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5648 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5649 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5650 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5651 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5652 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5653 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5655 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5656 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5657 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5658 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5659 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5660 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5661 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5662 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5663 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5664 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5667 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5668 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5669 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5670 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5671 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5672 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5673 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5674 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5675 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5676 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5677 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5679 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5680 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5681 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5682 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5683 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5684 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5685 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5687 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5688 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5689 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5690 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5691 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5692 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5693 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5694 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5695 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5696 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5698 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5699 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5700 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5701 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5702 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5703 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5704 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5705 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5706 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5708 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5709 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5710 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5711 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5714 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5715 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5716 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5718 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5719 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5720 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5723 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5724 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5725 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5726 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5727 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5728 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5729 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
5730 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5731 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
5732 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5733 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5734 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5735 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5736 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5738 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5739 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5740 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5741 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5742 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5743 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5744 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5745 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5746 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5747 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5748 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5749 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5751 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5752 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5753 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5754 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5755 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5756 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5757 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5758 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5759 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
5760 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
5761 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
5762 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
5763 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
5764 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
5765 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
5766 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
5767 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
5768 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
5771 int ventoy_register_all_cmd(void)
5774 cmd_para
*cur
= NULL
;
5776 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5778 cur
= ventoy_cmds
+ i
;
5779 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5780 cur
->summary
, cur
->description
, cur
->parser
);
5786 int ventoy_unregister_all_cmd(void)
5790 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5792 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);