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 initrd_info
*g_initrd_img_list
= NULL
;
55 initrd_info
*g_initrd_img_tail
= NULL
;
56 int g_initrd_img_count
= 0;
57 int g_valid_initrd_count
= 0;
58 int g_default_menu_mode
= 0;
59 int g_filt_dot_underscore_file
= 0;
60 int g_sort_case_sensitive
= 0;
61 int g_tree_view_menu_style
= 0;
62 static grub_file_t g_old_file
;
63 static int g_ventoy_last_entry_back
;
66 char g_img_swap_tmp_buf
[1024];
67 img_info g_img_swap_tmp
;
68 img_info
*g_ventoy_img_list
= NULL
;
70 int g_ventoy_img_count
= 0;
72 grub_device_t g_enum_dev
= NULL
;
73 grub_fs_t g_enum_fs
= NULL
;
74 int g_img_max_search_level
= -1;
75 img_iterator_node g_img_iterator_head
;
76 img_iterator_node
*g_img_iterator_tail
= NULL
;
78 grub_uint8_t g_ventoy_break_level
= 0;
79 grub_uint8_t g_ventoy_debug_level
= 0;
80 grub_uint8_t g_ventoy_chain_type
= 0;
82 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
83 grub_uint32_t g_ventoy_cpio_size
= 0;
84 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
85 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
87 int g_plugin_image_list
= 0;
89 ventoy_grub_param
*g_grub_param
= NULL
;
91 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
93 ventoy_img_chunk_list g_img_chunk_list
;
95 int g_wimboot_enable
= 0;
96 ventoy_img_chunk_list g_wimiso_chunk_list
;
97 char *g_wimiso_path
= NULL
;
99 int g_vhdboot_enable
= 0;
101 grub_uint64_t g_conf_replace_offset
= 0;
102 grub_uint64_t g_svd_replace_offset
= 0;
103 conf_replace
*g_conf_replace_node
= NULL
;
104 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
105 int g_conf_replace_new_len
= 0;
106 int g_conf_replace_new_len_align
= 0;
108 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
109 grub_uint64_t g_ventoy_disk_size
= 0;
110 grub_uint64_t g_ventoy_disk_part_size
[2];
112 static char *g_tree_script_buf
= NULL
;
113 static int g_tree_script_pos
= 0;
115 static char *g_list_script_buf
= NULL
;
116 static int g_list_script_pos
= 0;
118 static char *g_part_list_buf
= NULL
;
119 static int g_part_list_pos
= 0;
121 static int g_video_mode_max
= 0;
122 static int g_video_mode_num
= 0;
123 static ventoy_video_mode
*g_video_mode_list
= NULL
;
125 static int g_enumerate_time_checked
= 0;
126 static grub_uint64_t g_enumerate_start_time_ms
;
127 static grub_uint64_t g_enumerate_finish_time_ms
;
128 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
130 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
132 static const char *g_menu_class
[] =
134 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
137 const char *g_menu_prefix
[img_type_max
] =
139 "iso", "wim", "efi", "img", "vhd", "vtoy"
142 static int g_vtoy_load_prompt
= 0;
143 static char g_vtoy_prompt_msg
[64];
145 static int ventoy_get_fs_type(const char *fs
)
149 return ventoy_fs_max
;
151 else if (grub_strncmp(fs
, "exfat", 5) == 0)
153 return ventoy_fs_exfat
;
155 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
157 return ventoy_fs_ntfs
;
159 else if (grub_strncmp(fs
, "ext", 3) == 0)
161 return ventoy_fs_ext
;
163 else if (grub_strncmp(fs
, "xfs", 3) == 0)
165 return ventoy_fs_xfs
;
167 else if (grub_strncmp(fs
, "udf", 3) == 0)
169 return ventoy_fs_udf
;
171 else if (grub_strncmp(fs
, "fat", 3) == 0)
173 return ventoy_fs_fat
;
176 return ventoy_fs_max
;
179 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
198 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
200 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
204 static int ventoy_control_get_flag(const char *key
)
206 const char *val
= ventoy_get_env(key
);
208 if (val
&& val
[0] == '1' && val
[1] == 0)
215 static grub_err_t
ventoy_fs_close(grub_file_t file
)
217 grub_file_close(g_old_file
);
218 grub_free(file
->data
);
226 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
232 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
237 for (i
= 0; i
< g_video_mode_num
; i
++)
239 if (g_video_mode_list
[i
].width
== info
->width
&&
240 g_video_mode_list
[i
].height
== info
->height
&&
241 g_video_mode_list
[i
].bpp
== info
->bpp
)
247 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
248 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
249 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
252 if (g_video_mode_num
== g_video_mode_max
)
254 g_video_mode_max
*= 2;
255 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
261 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
263 if (v1
->bpp
== v2
->bpp
)
265 if (v1
->width
== v2
->width
)
267 if (v1
->height
== v2
->height
)
273 return (v1
->height
< v2
->height
) ? -1 : 1;
278 return (v1
->width
< v2
->width
) ? -1 : 1;
283 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
287 static int ventoy_enum_video_mode(void)
290 grub_video_adapter_t adapter
;
291 grub_video_driver_id_t id
;
292 ventoy_video_mode mode
;
294 g_video_mode_num
= 0;
295 g_video_mode_max
= 1024;
296 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
297 if (!g_video_mode_list
)
302 #ifdef GRUB_MACHINE_PCBIOS
303 grub_dl_load ("vbe");
306 id
= grub_video_get_driver_id ();
308 FOR_VIDEO_ADAPTERS (adapter
)
310 if (!adapter
->iterate
||
311 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
312 adapter
->init() != GRUB_ERR_NONE
)))
317 adapter
->iterate(ventoy_video_hook
, NULL
);
319 if (adapter
->id
!= id
)
325 /* sort video mode */
326 for (i
= 0; i
< g_video_mode_num
; i
++)
327 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
329 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
331 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
332 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
333 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
337 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
340 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
344 static struct grub_fs vtoy_fs
=
349 .fs_read
= ventoy_fs_read
,
350 .fs_close
= ventoy_fs_close
,
360 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
366 file
->data
= grub_malloc(rawFile
->size
+ 4096);
372 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
373 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
375 g_old_file
= rawFile
;
377 file
->size
= rawFile
->size
+ len
;
378 file
->device
= rawFile
->device
;
380 file
->not_easily_seekable
= 1;
385 static int ventoy_check_decimal_var(const char *name
, long *value
)
387 const char *value_str
= NULL
;
389 value_str
= grub_env_get(name
);
390 if (NULL
== value_str
)
392 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
395 if (!ventoy_is_decimal(value_str
))
397 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
400 *value
= grub_strtol(value_str
, NULL
, 10);
402 return GRUB_ERR_NONE
;
405 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
407 grub_uint64_t sectors
;
409 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
411 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
415 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
418 return sectors
* 512;
421 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
427 grub_uint32_t offset
;
429 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
432 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
436 len
= (int)file
->size
;
438 data
= (char *)grub_malloc(file
->size
);
444 grub_file_read(file
, data
, file
->size
);
445 grub_file_close(file
);
447 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
448 grub_script_execute_sourcecode(exec
);
450 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
451 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
452 grub_file_close(file
);
454 grub_script_execute_sourcecode("loopback -d efiboot");
458 *direntoff
= offset
+ 2;
463 static int ventoy_set_check_result(int ret
)
467 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
468 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
469 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
473 grub_printf(VTOY_WARNING
"\n");
474 grub_printf(VTOY_WARNING
"\n");
475 grub_printf(VTOY_WARNING
"\n\n\n");
477 grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret
);
478 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
480 grub_printf("\n\nWill exit after 10 seconds ...... ");
488 static int ventoy_check_official_device(grub_device_t dev
)
492 grub_uint64_t offset
;
497 struct grub_partition
*partition
;
499 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
501 return ventoy_set_check_result(1 | 0x1000);
504 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
505 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
506 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
508 #ifndef GRUB_MACHINE_EFI
509 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
510 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
511 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
513 return ventoy_set_check_result(2 | 0x1000);
522 /* We must have partition 2 */
525 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
529 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
533 return ventoy_set_check_result(3 | 0x1000);
536 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
538 grub_file_close(file
);
539 return ventoy_set_check_result(4 | 0x1000);
542 partition
= dev
->disk
->partition
;
543 if (partition
->number
!= 0 || partition
->start
!= 2048)
545 return ventoy_set_check_result(5);
550 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
552 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
553 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
554 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
556 grub_file_close(file
);
557 return ventoy_set_check_result(6);
562 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
563 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
564 PartTbl
[1].SectorCount
!= 65536)
566 grub_file_close(file
);
567 return ventoy_set_check_result(6);
573 offset
= partition
->start
+ partition
->len
;
574 partition
= file
->device
->disk
->partition
;
575 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
577 grub_file_close(file
);
578 return ventoy_set_check_result(7);
582 grub_file_close(file
);
586 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
587 dev2
= grub_device_open(devname
);
590 return ventoy_set_check_result(8);
593 fs
= grub_fs_probe(dev2
);
596 grub_device_close(dev2
);
597 return ventoy_set_check_result(9);
600 fs
->fs_label(dev2
, &label
);
601 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
603 grub_device_close(dev2
);
604 return ventoy_set_check_result(10);
607 grub_device_close(dev2
);
610 return ventoy_set_check_result(0);
613 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
617 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
627 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
629 grub_uint64_t size
= 0;
632 char fullpath
[256] = {0};
635 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
638 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
641 debug("grub_file_open failed <%s>\n", fullpath
);
647 grub_file_close(file
);
651 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
655 char fullpath
[256] = {0};
658 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
661 file
= grub_file_open(fullpath
, type
);
664 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
671 int ventoy_is_file_exist(const char *fmt
, ...)
678 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
682 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
685 grub_strncpy(pos
+ len
, "\" ]", 3);
687 debug("script exec %s\n", buf
);
689 if (0 == grub_script_execute_sourcecode(buf
))
697 int ventoy_is_dir_exist(const char *fmt
, ...)
704 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
708 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
711 grub_strncpy(pos
+ len
, "\" ]", 3);
713 debug("script exec %s\n", buf
);
715 if (0 == grub_script_execute_sourcecode(buf
))
723 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
726 grub_uint8_t
*outbuf
;
727 grub_uint8_t gzHdr
[10] =
729 0x1F, 0x8B, /* magic */
737 grub_memset(&s
, 0, sizeof(mz_stream
));
739 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
741 outbuf
= (grub_uint8_t
*)mem_out
;
743 mem_out_len
-= sizeof(gzHdr
) + 8;
744 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
745 outbuf
+= sizeof(gzHdr
);
747 s
.avail_in
= mem_in_len
;
750 s
.avail_out
= mem_out_len
;
753 mz_deflate(&s
, MZ_FINISH
);
757 outbuf
+= s
.total_out
;
758 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
759 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
761 return s
.total_out
+ sizeof(gzHdr
) + 8;
769 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
773 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
776 if (0 == grub_strcmp(args
[0], "on"))
779 grub_env_set("vtdebug_flag", "debug");
784 grub_env_set("vtdebug_flag", "");
787 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
790 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
794 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
796 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
797 grub_printf(" level:\r\n");
798 grub_printf(" 01/11: busybox / (+cat log)\r\n");
799 grub_printf(" 02/12: initrd / (+cat log)\r\n");
800 grub_printf(" 03/13: hook / (+cat log)\r\n");
802 grub_printf(" debug:\r\n");
803 grub_printf(" 0: debug is off\r\n");
804 grub_printf(" 1: debug is on\r\n");
806 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
809 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
811 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
813 g_ventoy_debug_level
= 1;
816 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
819 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
828 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
831 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
863 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
868 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
870 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
873 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
878 value_long
+= grub_strtol(args
[1], NULL
, 10);
880 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
881 grub_env_set(args
[0], buf
);
883 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
886 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
888 ulonglong value1
= 0;
889 ulonglong value2
= 0;
894 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
897 value1
= grub_strtoull(args
[0], NULL
, 10);
898 value2
= grub_strtoull(args
[1], NULL
, 10);
900 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
901 grub_env_set(args
[2], buf
);
903 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
906 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
921 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
924 debug("failed to open file <%s> for udf check\n", args
[0]);
928 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
930 grub_env_set(args
[1], buf
);
932 grub_file_close(file
);
938 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
946 g_wimboot_enable
= 0;
947 grub_check_free(g_wimiso_path
);
948 grub_check_free(g_wimiso_chunk_list
.chunk
);
950 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
956 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
957 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
958 if (NULL
== g_wimiso_chunk_list
.chunk
)
960 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
963 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
964 g_wimiso_chunk_list
.cur_chunk
= 0;
966 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
968 g_wimboot_enable
= 1;
969 g_wimiso_path
= grub_strdup(args
[0]);
971 grub_file_close(file
);
976 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
986 ventoy_iso9660_override
*dirent
;
995 totlen
= sizeof(ventoy_chain_head
);
997 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
999 debug("failed to load efiboot template %d\n", len
);
1005 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1007 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1010 debug("failed to open file <%s>\n", args
[0]);
1014 totlen
+= ventoy_align_2k(file
->size
);
1016 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1017 dirent
->first_sector
= len
/ 2048;
1018 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1019 dirent
->size
= (grub_uint32_t
)file
->size
;
1020 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1022 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1024 #ifdef GRUB_MACHINE_EFI
1025 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1027 data
= (char *)grub_malloc(totlen
);
1030 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1032 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1033 grub_check_free(buf
);
1035 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1036 grub_file_close(file
);
1038 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1039 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1040 grub_env_set(name
, value
);
1042 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1043 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1044 grub_env_set(name
, value
);
1049 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1055 g_vtoy_load_prompt
= 0;
1056 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1058 if (argc
== 2 && args
[0][0] == '1')
1060 g_vtoy_load_prompt
= 1;
1061 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1064 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1067 int ventoy_need_prompt_load_file(void)
1069 return g_vtoy_load_prompt
;
1072 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1074 grub_uint64_t ro
= 0;
1075 grub_uint64_t div
= 0;
1076 grub_ssize_t left
= size
;
1077 char *cur
= (char *)buf
;
1079 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1082 while (left
>= VTOY_SIZE_2MB
)
1084 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1085 cur
+= VTOY_SIZE_2MB
;
1086 left
-= VTOY_SIZE_2MB
;
1088 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1089 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1095 grub_file_read(file
, cur
, left
);
1098 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1104 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1111 enum grub_file_type type
;
1122 if (grub_strcmp(args
[0], "nodecompress") == 0)
1124 type
= VENTOY_FILE_TYPE
;
1128 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1131 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1134 debug("failed to open file <%s>\n", args
[1]);
1138 #ifdef GRUB_MACHINE_EFI
1139 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1141 buf
= (char *)grub_malloc(file
->size
);
1146 grub_file_close(file
);
1150 if (g_vtoy_load_prompt
)
1152 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1156 grub_file_read(file
, buf
, file
->size
);
1159 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1160 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1161 grub_env_set(name
, value
);
1163 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1164 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1165 grub_env_set(name
, value
);
1167 grub_file_close(file
);
1173 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1191 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1194 debug("failed to open file <%s> for udf check\n", args
[0]);
1198 headlen
= sizeof(ventoy_chain_head
);
1200 #ifdef GRUB_MACHINE_EFI
1201 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1203 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1206 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1208 grub_file_read(file
, buf
+ headlen
, file
->size
);
1210 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
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
[1]);
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_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1233 if (args
[0][0] == '1')
1235 grub_iso9660_set_nojoliet(1);
1239 grub_iso9660_set_nojoliet(0);
1245 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1250 grub_uint8_t buf
[32];
1261 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1264 debug("failed to open file <%s> for udf check\n", args
[0]);
1268 for (i
= 16; i
< 32; i
++)
1270 grub_file_seek(file
, i
* 2048);
1271 grub_file_read(file
, buf
, sizeof(buf
));
1279 grub_file_seek(file
, i
* 2048);
1280 grub_file_read(file
, buf
, sizeof(buf
));
1282 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1285 grub_file_seek(file
, i
* 2048);
1286 grub_file_read(file
, buf
, sizeof(buf
));
1288 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1289 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1295 grub_file_close(file
);
1297 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1302 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1304 long value_long1
= 0;
1305 long value_long2
= 0;
1307 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1309 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1312 value_long1
= grub_strtol(args
[0], NULL
, 10);
1313 value_long2
= grub_strtol(args
[2], NULL
, 10);
1315 if (0 == grub_strcmp(args
[1], "eq"))
1317 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1319 else if (0 == grub_strcmp(args
[1], "ne"))
1321 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1323 else if (0 == grub_strcmp(args
[1], "gt"))
1325 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1327 else if (0 == grub_strcmp(args
[1], "lt"))
1329 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1331 else if (0 == grub_strcmp(args
[1], "ge"))
1333 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1335 else if (0 == grub_strcmp(args
[1], "le"))
1337 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1341 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1347 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1350 char buf
[128] = {0};
1354 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1357 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1358 pos
= grub_strstr(buf
, ",");
1364 grub_env_set(args
[1], buf
);
1366 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1369 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1375 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1381 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1384 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1386 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1387 if (0 == grub_script_execute_sourcecode(buf
))
1389 debug("file %s exist, ventoy_compatible YES\n", buf
);
1390 grub_env_set("ventoy_compatible", "YES");
1391 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1395 debug("file %s NOT exist\n", buf
);
1399 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1400 pos
= grub_strstr(buf
, ")");
1406 disk
= grub_disk_open(buf
);
1409 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1410 grub_disk_close(disk
);
1412 g_img_swap_tmp_buf
[703] = 0;
1413 for (i
= 318; i
< 703; i
++)
1415 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1416 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1418 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1419 grub_env_set("ventoy_compatible", "YES");
1420 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1426 debug("failed to open disk <%s>\n", buf
);
1429 grub_env_set("ventoy_compatible", "NO");
1430 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1433 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1439 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1441 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1444 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1449 if (0 == g_sort_case_sensitive
)
1451 if (grub_islower(c1
))
1453 c1
= c1
- 'a' + 'A';
1456 if (grub_islower(c2
))
1458 c2
= c2
- 'a' + 'A';
1471 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1477 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1479 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1482 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1487 if (0 == g_sort_case_sensitive
)
1489 if (grub_islower(c1
))
1491 c1
= c1
- 'a' + 'A';
1494 if (grub_islower(c2
))
1496 c2
= c2
- 'a' + 'A';
1509 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1511 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1513 grub_memcpy(img1
, img2
, sizeof(img_info
));
1514 img1
->next
= g_img_swap_tmp
.next
;
1515 img1
->prev
= g_img_swap_tmp
.prev
;
1517 g_img_swap_tmp
.next
= img2
->next
;
1518 g_img_swap_tmp
.prev
= img2
->prev
;
1519 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1522 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1526 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1534 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1543 img_iterator_node
*tmp
;
1544 img_iterator_node
*new_node
;
1545 img_iterator_node
*node
= (img_iterator_node
*)data
;
1547 if (g_enumerate_time_checked
== 0)
1549 g_enumerate_finish_time_ms
= grub_get_time_ms();
1550 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1553 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1555 g_enumerate_time_checked
= 1;
1559 len
= grub_strlen(filename
);
1563 if (node
->level
+ 1 > g_img_max_search_level
)
1568 if ((len
== 1 && filename
[0] == '.') ||
1569 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1574 if (!ventoy_img_name_valid(filename
, len
))
1579 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1584 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1586 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1587 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1590 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1595 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1598 new_node
->level
= node
->level
+ 1;
1599 new_node
->plugin_list_index
= index
;
1600 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1602 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1605 debug("Directory %s ignored...\n", new_node
->dir
);
1606 grub_free(new_node
);
1610 new_node
->tail
= node
->tail
;
1612 new_node
->parent
= node
;
1613 if (!node
->firstchild
)
1615 node
->firstchild
= new_node
;
1618 if (g_img_iterator_tail
)
1620 g_img_iterator_tail
->next
= new_node
;
1621 g_img_iterator_tail
= new_node
;
1625 g_img_iterator_head
.next
= new_node
;
1626 g_img_iterator_tail
= new_node
;
1632 debug("Find a file %s\n", filename
);
1638 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1640 type
= img_type_iso
;
1642 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1644 type
= img_type_wim
;
1646 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1647 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1649 type
= img_type_vhd
;
1651 #ifdef GRUB_MACHINE_EFI
1652 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1654 type
= img_type_efi
;
1657 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1659 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1661 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1662 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1667 type
= img_type_img
;
1669 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1671 type
= img_type_vtoy
;
1673 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1675 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1677 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1678 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1687 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1692 if (g_plugin_image_list
)
1694 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1695 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1696 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1698 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1701 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1703 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1708 img
= grub_zalloc(sizeof(img_info
));
1712 img
->plugin_list_index
= index
;
1713 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1715 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1717 img
->size
= info
->size
;
1720 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1723 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1725 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1730 if (g_ventoy_img_list
)
1732 tail
= *(node
->tail
);
1738 g_ventoy_img_list
= img
;
1741 img
->id
= g_ventoy_img_count
;
1743 if (node
&& NULL
== node
->firstiso
)
1745 node
->firstiso
= img
;
1756 *((img_info
**)(node
->tail
)) = img
;
1757 g_ventoy_img_count
++;
1759 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1760 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1763 img
->class = g_menu_class
[type
];
1765 img
->menu_prefix
= g_menu_prefix
[type
];
1767 if (img_type_iso
== type
)
1769 if (ventoy_plugin_check_memdisk(img
->path
))
1771 img
->menu_prefix
= "miso";
1775 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1782 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1784 int len
= GRUB_UINT_MAX
;
1785 const char *value
= NULL
;
1786 char name
[32] = {0};
1787 char plat
[32] = {0};
1788 char guidstr
[32] = {0};
1789 ventoy_guid guid
= VENTOY_GUID
;
1790 const char *fmt1
= NULL
;
1791 const char *fmt2
= NULL
;
1792 const char *fmt3
= NULL
;
1793 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1794 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1795 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1796 const char fmtcode
[]={
1797 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1798 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1799 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1800 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1801 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1802 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1805 grub_memset(name
, 0, sizeof(name
));
1806 puint
[0] = grub_swap_bytes32(0x56454e54);
1807 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1808 puint
[2] = grub_swap_bytes32(0x45525349);
1809 puint
[1] = grub_swap_bytes32(0x4f595f56);
1810 value
= ventoy_get_env(name
);
1812 grub_memset(name
, 0, sizeof(name
));
1813 puint
[1] = grub_swap_bytes32(0x5f544f50);
1814 puint
[0] = grub_swap_bytes32(0x56544c45);
1815 fmt1
= ventoy_get_env(name
);
1821 grub_memset(name
, 0, sizeof(name
));
1822 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1823 puint
[0] = grub_swap_bytes32(0x56544c45);
1824 fmt2
= ventoy_get_env(name
);
1826 grub_memset(name
, 0, sizeof(name
));
1827 puint
[1] = grub_swap_bytes32(0x5f434c52);
1828 puint
[0] = grub_swap_bytes32(0x56544c45);
1829 fmt3
= ventoy_get_env(name
);
1831 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1833 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1835 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1836 #pragma GCC diagnostic push
1837 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1838 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1839 fmt1
? fmt1
: fmtdata
,
1840 fmt2
? fmt2
: fmtdata
+ 4,
1841 value
? value
: "", plat
, guidstr
,
1842 fmt3
? fmt3
: fmtdata
+ 6);
1843 #pragma GCC diagnostic pop
1845 grub_memset(name
, 0, sizeof(name
));
1846 puint
[0] = grub_swap_bytes32(0x76746f79);
1847 puint
[2] = grub_swap_bytes32(0x656e7365);
1848 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1849 ventoy_set_env(name
, guidstr
);
1854 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1858 grub_uint8_t md5
[16];
1862 grub_memset(input
, 0, sizeof(input
));
1864 grub_printf("Enter password: ");
1867 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1869 grub_password_get(input
, 128);
1870 if (grub_strcmp(pwd
->text
, input
) == 0)
1875 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1877 grub_password_get(input
, 128);
1878 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1879 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1884 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1886 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1887 grub_password_get(input
+ offset
, 128);
1889 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1890 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1896 grub_printf("Invalid password!\n\n");
1903 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1905 img_info
*minimg
= NULL
;
1906 img_info
*img
= (img_info
*)(node
->firstiso
);
1908 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1910 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1925 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1927 img_iterator_node
*Minchild
= NULL
;
1928 img_iterator_node
*child
= node
->firstchild
;
1930 while (child
&& child
->parent
== node
)
1932 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1936 child
= child
->next
;
1941 Minchild
->select
= 1;
1947 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1950 img_info
*img
= NULL
;
1951 const char *dir_class
= NULL
;
1952 const char *dir_alias
= NULL
;
1953 img_iterator_node
*child
= NULL
;
1955 if (node
->isocnt
== 0 || node
->done
== 1)
1960 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1962 offset
= node
->parent
->dirlen
;
1965 if (node
== &g_img_iterator_head
)
1967 if (g_default_menu_mode
== 0)
1969 if (g_tree_view_menu_style
== 0)
1971 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1972 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1973 " echo 'return ...' \n"
1978 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1979 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1987 node
->dir
[node
->dirlen
- 1] = 0;
1988 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
1991 dir_class
= "vtoydir";
1994 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1997 if (g_tree_view_menu_style
== 0)
1999 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2000 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2001 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2005 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2006 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2007 dir_alias
, dir_class
, node
->dir
+ offset
);
2012 dir_alias
= node
->dir
+ offset
;
2014 if (g_tree_view_menu_style
== 0)
2016 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2017 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2018 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2022 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2023 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2024 dir_alias
, dir_class
, node
->dir
+ offset
);
2028 if (g_tree_view_menu_style
== 0)
2030 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2031 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2032 " echo 'return ...' \n"
2037 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2038 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2044 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2046 ventoy_dynamic_tree_menu(child
);
2049 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2051 if (g_tree_view_menu_style
== 0)
2053 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2054 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2057 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2058 img
->unsupport
? "[***********] " : "",
2059 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2061 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2065 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2066 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2069 img
->unsupport
? "[***********] " : "",
2070 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2072 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2076 if (node
!= &g_img_iterator_head
)
2078 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2085 static int ventoy_set_default_menu(void)
2091 const char *strdata
= NULL
;
2092 img_info
*cur
= NULL
;
2093 img_info
*default_node
= NULL
;
2094 const char *default_image
= NULL
;
2096 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2097 if (default_image
&& default_image
[0] == '/')
2099 img_len
= grub_strlen(default_image
);
2101 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2103 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2115 if (0 == g_default_menu_mode
)
2117 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
2121 def
= grub_strdup(default_image
);
2127 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2129 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2130 if (strdata
&& strdata
[0] == '/')
2132 pos
= def
+ grub_strlen(strdata
);
2143 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2146 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2150 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
2158 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2160 img_info
*next
= NULL
;
2161 img_info
*cur
= g_ventoy_img_list
;
2174 g_ventoy_img_list
= NULL
;
2175 g_ventoy_img_count
= 0;
2177 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2180 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2183 img_info
*cur
= g_ventoy_img_list
;
2187 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2189 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2192 img_id
= grub_strtol(args
[0], NULL
, 10);
2193 if (img_id
>= g_ventoy_img_count
)
2195 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2198 debug("Find image %ld name \n", img_id
);
2200 while (cur
&& img_id
> 0)
2208 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2211 debug("image name is %s\n", cur
->name
);
2213 grub_env_set(args
[1], cur
->name
);
2215 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2218 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2222 img_info
*cur
= g_ventoy_img_list
;
2228 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2231 len
= (int)grub_strlen(args
[0]);
2235 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2244 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2247 grub_snprintf(id
, sizeof(id
), "VID_%d", cur
->id
);
2248 grub_env_set("chosen", id
);
2249 grub_env_export("chosen");
2251 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2254 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2259 const char *id
= NULL
;
2260 img_info
*cur
= g_ventoy_img_list
;
2264 if (argc
< 1 || argc
> 2)
2266 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2269 id
= grub_env_get("chosen");
2271 pos
= grub_strstr(id
, "VID_");
2274 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2278 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2283 if (img_id
== cur
->id
)
2292 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2295 grub_env_set(args
[0], cur
->path
);
2299 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2300 grub_env_set(args
[1], value
);
2303 g_svd_replace_offset
= 0;
2305 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2309 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2313 grub_device_t dev
= NULL
;
2314 img_info
*cur
= NULL
;
2315 img_info
*tail
= NULL
;
2316 const char *strdata
= NULL
;
2317 char *device_name
= NULL
;
2319 img_iterator_node
*node
= NULL
;
2320 img_iterator_node
*tmp
= NULL
;
2326 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2329 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2331 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2336 g_enumerate_time_checked
= 0;
2337 g_enumerate_start_time_ms
= grub_get_time_ms();
2339 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2340 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2342 g_filt_dot_underscore_file
= 1;
2345 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2346 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2348 g_sort_case_sensitive
= 1;
2351 device_name
= grub_file_get_device_name(args
[0]);
2357 g_enum_dev
= dev
= grub_device_open(device_name
);
2363 g_enum_fs
= fs
= grub_fs_probe(dev
);
2369 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2371 debug("unsupported fs:<%s>\n", fs
->name
);
2372 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2376 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2378 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2379 if (strdata
&& strdata
[0] == '1')
2381 g_default_menu_mode
= 1;
2384 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2386 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2388 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2389 if (strdata
&& strdata
[0] == '/')
2391 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2392 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2394 g_img_iterator_head
.dir
[len
++] = '/';
2396 g_img_iterator_head
.dirlen
= len
;
2400 g_img_iterator_head
.dirlen
= 1;
2401 grub_strcpy(g_img_iterator_head
.dir
, "/");
2404 g_img_iterator_head
.tail
= &tail
;
2406 if (g_img_max_search_level
< 0)
2408 g_img_max_search_level
= GRUB_INT_MAX
;
2409 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2410 if (strdata
&& ventoy_is_decimal(strdata
))
2412 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2416 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2417 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2418 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2419 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2420 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2421 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2423 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2425 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2428 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2429 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2431 g_tree_view_menu_style
= 1;
2434 ventoy_set_default_menu();
2436 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2438 ventoy_dynamic_tree_menu(node
);
2442 node
= g_img_iterator_head
.next
;
2450 /* sort image list by image name */
2451 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2453 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2455 if (ventoy_cmp_img(cur
, tail
) > 0)
2457 ventoy_swap_img(cur
, tail
);
2462 if (g_default_menu_mode
== 1)
2464 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2465 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2466 " echo 'return ...' \n"
2470 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2472 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2473 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2476 cur
->unsupport
? "[***********] " : "",
2477 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2479 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2482 g_tree_script_buf
[g_tree_script_pos
] = 0;
2483 g_list_script_buf
[g_list_script_pos
] = 0;
2485 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2486 grub_env_set(args
[1], buf
);
2490 check_free(device_name
, grub_free
);
2491 check_free(dev
, grub_device_close
);
2493 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2496 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2503 device_name
= grub_file_get_device_name(filename
);
2515 pos2
= grub_strstr(pos
, ",");
2518 pos2
= grub_strstr(pos
, ")");
2526 disk
= grub_disk_open(pos
);
2529 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2530 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2531 grub_disk_close(disk
);
2538 grub_free(device_name
);
2542 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2544 eltorito_descriptor desc
;
2546 grub_memset(&desc
, 0, sizeof(desc
));
2547 grub_file_seek(file
, 17 * 2048);
2548 grub_file_read(file
, &desc
, sizeof(desc
));
2550 if (desc
.type
!= 0 || desc
.version
!= 1)
2555 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2556 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2564 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2568 grub_uint8_t buf
[512];
2569 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2571 grub_file_seek(file
, sector
* 2048);
2572 grub_file_read(file
, buf
, sizeof(buf
));
2574 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2576 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2580 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2585 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2587 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2589 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2593 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2595 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2600 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2602 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2604 if (buf
[36] == parttype
[i
])
2606 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2612 debug("%s does not contain efi eltorito\n", file
->name
);
2616 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2619 const char *fs
= NULL
;
2620 const char *cdprompt
= NULL
;
2622 grub_uint8_t chksum
= 0;
2625 disk
= file
->device
->disk
;
2626 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2628 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2629 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2630 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2632 pos
= grub_strstr(file
->name
, "/");
2638 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2640 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2642 param
->vtoy_img_size
= file
->size
;
2644 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2645 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2647 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2649 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2650 param
->vtoy_reserved
[4] = 0;
2651 if (g_ventoy_chain_type
== 1) /* Windows */
2653 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2654 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2656 param
->vtoy_reserved
[4] = 1;
2660 fs
= ventoy_get_env("ventoy_fs_probe");
2661 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2663 param
->vtoy_reserved
[3] = 1;
2666 /* calculate checksum */
2667 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2669 chksum
+= *((grub_uint8_t
*)param
+ i
);
2671 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2676 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2678 grub_uint32_t i
= 0;
2679 grub_uint64_t total
= 0;
2680 grub_uint64_t fileblk
= 0;
2681 ventoy_img_chunk
*chunk
= NULL
;
2683 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2685 chunk
= chunklist
->chunk
+ i
;
2687 if (chunk
->disk_start_sector
<= start
)
2689 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2693 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2696 fileblk
= (file
->size
+ 511) / 512;
2698 if (total
!= fileblk
)
2700 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2701 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2703 debug("maybe img file to be processed.\n");
2713 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2717 grub_uint32_t i
= 0;
2718 grub_uint32_t sector
= 0;
2719 grub_uint32_t count
= 0;
2720 grub_off_t size
= 0;
2721 grub_off_t read
= 0;
2723 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2724 if (fs_type
== ventoy_fs_exfat
)
2726 grub_fat_get_file_chunk(start
, file
, chunklist
);
2728 else if (fs_type
== ventoy_fs_ext
)
2730 grub_ext_get_file_chunk(start
, file
, chunklist
);
2734 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2735 file
->read_hook_data
= chunklist
;
2737 for (size
= file
->size
; size
> 0; size
-= read
)
2739 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2740 grub_file_read(file
, NULL
, read
);
2743 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2745 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2746 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2749 if (ventoy_fs_udf
== fs_type
)
2751 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2753 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2754 chunklist
->chunk
[i
].img_start_sector
= sector
;
2755 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2761 len
= (int)grub_strlen(file
->name
);
2762 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2763 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2764 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2765 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2767 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2769 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2779 chunklist
->chunk
[i
].img_start_sector
= sector
;
2780 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2788 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2792 grub_disk_addr_t start
;
2797 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2800 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2803 g_conf_replace_node
= NULL
;
2804 g_conf_replace_offset
= 0;
2806 if (g_img_chunk_list
.chunk
)
2808 grub_free(g_img_chunk_list
.chunk
);
2811 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2813 grub_file_close(file
);
2814 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2817 /* get image chunk data */
2818 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2819 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2820 if (NULL
== g_img_chunk_list
.chunk
)
2822 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2825 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2826 g_img_chunk_list
.cur_chunk
= 0;
2828 start
= file
->device
->disk
->partition
->start
;
2830 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2832 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2833 grub_file_close(file
);
2837 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2840 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2841 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2844 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2846 grub_uint64_t offset
= 0;
2847 grub_uint32_t align
= 0;
2848 grub_file_t file
= NULL
;
2849 conf_replace
*node
= NULL
;
2855 debug("select conf replace argc:%d\n", argc
);
2862 node
= ventoy_plugin_find_conf_replace(args
[1]);
2865 debug("Conf replace not found for %s\n", args
[1]);
2869 debug("Find conf replace for %s\n", args
[1]);
2871 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2874 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2878 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2879 grub_file_close(file
);
2881 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2884 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2888 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2890 if (align
> vtoy_max_replace_file_size
)
2892 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2896 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2897 g_conf_replace_new_len
= (int)file
->size
;
2898 g_conf_replace_new_len_align
= align
;
2900 g_conf_replace_node
= node
;
2901 g_conf_replace_offset
= offset
+ 2;
2903 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2908 grub_file_close(file
);
2910 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2913 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2918 char configfile
[128];
2919 install_template
*node
= NULL
;
2925 debug("select auto installation argc:%d\n", argc
);
2932 node
= ventoy_plugin_find_install_template(args
[0]);
2935 debug("Auto install template not found for %s\n", args
[0]);
2939 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2941 node
->cursel
= node
->autosel
- 1;
2942 debug("Auto install template auto select %d\n", node
->autosel
);
2946 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2952 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2953 " echo %s\n}\n", "123");
2955 for (i
= 0; i
< node
->templatenum
; i
++)
2957 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2959 node
->templatepath
[i
].path
);
2962 g_ventoy_menu_esc
= 1;
2963 g_ventoy_suppress_esc
= 1;
2965 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2966 grub_script_execute_sourcecode(configfile
);
2968 g_ventoy_menu_esc
= 0;
2969 g_ventoy_suppress_esc
= 0;
2973 node
->cursel
= g_ventoy_last_entry
- 1;
2975 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2978 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2983 char configfile
[128];
2984 persistence_config
*node
;
2990 debug("select persistence argc:%d\n", argc
);
2997 node
= ventoy_plugin_find_persistent(args
[0]);
3000 debug("Persistence image not found for %s\n", args
[0]);
3004 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3006 node
->cursel
= node
->autosel
- 1;
3007 debug("Persistence image auto select %d\n", node
->autosel
);
3011 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3017 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3018 " echo %s\n}\n", "123");
3020 for (i
= 0; i
< node
->backendnum
; i
++)
3022 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3024 node
->backendpath
[i
].path
);
3028 g_ventoy_menu_esc
= 1;
3029 g_ventoy_suppress_esc
= 1;
3031 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3032 grub_script_execute_sourcecode(configfile
);
3034 g_ventoy_menu_esc
= 0;
3035 g_ventoy_suppress_esc
= 0;
3039 node
->cursel
= g_ventoy_last_entry
- 1;
3041 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3044 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3047 ventoy_img_chunk
*cur
;
3053 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3055 cur
= g_img_chunk_list
.chunk
+ i
;
3056 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3057 cur
->img_start_sector
, cur
->img_end_sector
,
3058 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3062 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3065 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3069 ventoy_img_chunk_list chunklist
;
3074 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3077 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3080 /* get image chunk data */
3081 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3082 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3083 if (NULL
== chunklist
.chunk
)
3085 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3088 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3089 chunklist
.cur_chunk
= 0;
3091 ventoy_get_block_list(file
, &chunklist
, 0);
3093 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3095 grub_printf("########## UNSUPPORTED ###############\n");
3098 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3100 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3102 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3103 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3106 grub_printf("\n==================================\n");
3108 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3110 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3111 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3112 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3113 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3114 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3118 grub_free(chunklist
.chunk
);
3119 grub_file_close(file
);
3121 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3124 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3127 ventoy_grub_param_file_replace
*replace
= NULL
;
3135 replace
= &(g_grub_param
->file_replace
);
3136 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3138 replace
->old_name_cnt
= 0;
3139 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3141 replace
->old_name_cnt
++;
3142 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3145 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3148 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3151 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3159 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3160 grub_printf("%s", g_list_script_buf
);
3164 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3165 grub_printf("%s", g_tree_script_buf
);
3171 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3173 img_info
*cur
= g_ventoy_img_list
;
3181 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3182 grub_printf("name:<%s>\n\n", cur
->name
);
3189 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3195 ventoy_plugin_dump_injection();
3200 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3206 ventoy_plugin_dump_auto_install();
3211 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3217 ventoy_plugin_dump_persistence();
3222 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3233 if (args
[0][0] == '0')
3235 return g_ventoy_memdisk_mode
? 0 : 1;
3237 else if (args
[0][0] == '1')
3239 return g_ventoy_iso_raw
? 0 : 1;
3241 else if (args
[0][0] == '2')
3243 return g_ventoy_iso_uefi_drv
? 0 : 1;
3245 else if (args
[0][0] == '3')
3247 return g_ventoy_grub2_mode
? 0 : 1;
3249 else if (args
[0][0] == '4')
3251 return g_ventoy_wimboot_mode
? 0 : 1;
3257 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3259 static int configfile_mode
= 0;
3260 char memfile
[128] = {0};
3267 * args[0]: 0:normal 1:configfile
3268 * args[1]: 0:list_buf 1:tree_buf
3273 debug("Invalid argc %d\n", argc
);
3279 if (args
[0][0] == '0')
3281 if (args
[1][0] == '0')
3283 grub_script_execute_sourcecode(g_list_script_buf
);
3287 grub_script_execute_sourcecode(g_tree_script_buf
);
3292 if (configfile_mode
)
3294 debug("Now already in F3 mode %d\n", configfile_mode
);
3298 if (args
[1][0] == '0')
3300 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3301 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3305 g_ventoy_last_entry
= -1;
3306 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3307 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3310 configfile_mode
= 1;
3311 grub_script_execute_sourcecode(memfile
);
3312 configfile_mode
= 0;
3318 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3329 g_ventoy_case_insensitive
= 1;
3330 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3331 g_ventoy_case_insensitive
= 0;
3337 grub_file_close(file
);
3343 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3348 const char *isopath
= NULL
;
3350 ventoy_mbr_head mbr
;
3357 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3360 isopath
= grub_env_get("vtoy_iso_part");
3363 debug("isopath is null %p\n", isopath
);
3367 debug("isopath is %s\n", isopath
);
3369 for (id
= 0; id
< 30 && (find
== 0); id
++)
3371 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3372 if (grub_strstr(isopath
, hdname
))
3374 debug("skip %s ...\n", hdname
);
3378 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3380 disk
= grub_disk_open(hdname
);
3383 debug("%s not exist\n", hdname
);
3387 grub_memset(&mbr
, 0, sizeof(mbr
));
3388 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3390 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3392 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3393 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3396 grub_env_set(args
[0], hdname
);
3400 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3404 debug("read %s failed\n", hdname
);
3407 grub_disk_close(disk
);
3413 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3424 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3427 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3430 debug("failed to open file %s\n", args
[0]);
3434 buf
= grub_malloc(len
);
3441 grub_file_read(file
, buf
, len
- 1);
3443 ventoy_get_line(buf
);
3444 ventoy_set_env(args
[1], buf
);
3448 grub_check_free(buf
);
3449 grub_file_close(file
);
3454 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3459 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3460 "0 %llu linear /dev/ventoy %llu\n",
3461 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3466 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3468 char *device_name
= NULL
;
3469 grub_device_t dev
= NULL
;
3474 g_part_list_pos
= 0;
3475 grub_env_unset("vtoy_img_part_file");
3482 device_name
= grub_file_get_device_name(args
[0]);
3485 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3489 dev
= grub_device_open(device_name
);
3492 debug("grub_device_open failed, %s\n", device_name
);
3496 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3498 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3499 grub_env_set("vtoy_img_part_file", buf
);
3503 check_free(device_name
, grub_free
);
3504 check_free(dev
, grub_device_close
);
3510 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3521 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3524 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3527 debug("failed to open file %s\n", args
[0]);
3531 buf
= grub_malloc(file
->size
+ 1);
3537 buf
[file
->size
] = 0;
3538 grub_file_read(file
, buf
, file
->size
);
3540 if (grub_strstr(buf
, args
[1]))
3547 grub_check_free(buf
);
3548 grub_file_close(file
);
3553 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3559 ventoy_iso9660_vd pvd
;
3566 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3569 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3572 debug("failed to open file %s\n", args
[0]);
3576 grub_file_seek(file
, 16 * 2048);
3577 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3578 if (len
!= sizeof(pvd
))
3580 debug("failed to read pvd %d\n", len
);
3584 grub_memset(buf
, 0, sizeof(buf
));
3585 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3586 ventoy_set_env(args
[1], buf
);
3588 grub_memset(buf
, 0, sizeof(buf
));
3589 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3590 ventoy_set_env(args
[2], buf
);
3594 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3595 ventoy_set_env(args
[3], buf
);
3598 grub_file_close(file
);
3603 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3614 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3617 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3620 debug("failed to open file %s\n", args
[0]);
3624 grub_memset(buf
, 0, sizeof(buf
));
3625 grub_file_seek(file
, 16 * 2048 + 813);
3626 len
= (int)grub_file_read(file
, buf
, 17);
3629 debug("failed to read create date %d\n", len
);
3633 ventoy_set_env(args
[1], buf
);
3636 grub_file_close(file
);
3641 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3647 ventoy_env_hook_root(1);
3652 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3658 ventoy_env_hook_root(0);
3663 #ifdef GRUB_MACHINE_EFI
3664 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3669 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3675 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3676 if (var
&& *var
== 1)
3684 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3693 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3698 grub_uint64_t FileSectors
= 0;
3699 ventoy_gpt_info
*gpt
= NULL
;
3700 ventoy_part_table
*pt
= NULL
;
3701 grub_uint8_t zeroguid
[16] = {0};
3706 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3709 debug("failed to open file %s\n", args
[0]);
3713 if (file
->size
% 512)
3715 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3719 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3725 FileSectors
= file
->size
/ 512;
3727 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3728 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3730 debug("This is EFI partition table\n");
3732 for (i
= 0; i
< 128; i
++)
3734 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3736 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3738 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3739 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3747 debug("This is MBR partition table\n");
3749 for (i
= 0; i
< 4; i
++)
3751 pt
= gpt
->MBR
.PartTbl
+ i
;
3752 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3754 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3755 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3756 (ulonglong
)FileSectors
);
3765 grub_file_close(file
);
3766 grub_check_free(gpt
);
3767 grub_errno
= GRUB_ERR_NONE
;
3771 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3780 for (i
= 0; i
< 500; i
++)
3782 ret
= grub_getkey_noblock();
3783 if (ret
== GRUB_TERM_NO_KEY
)
3792 grub_printf("\n\n Still have key input after clear.\n");
3800 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3807 int image_sector_size
;
3809 ventoy_chain_head
*chain
;
3810 ventoy_img_chunk
*chunk
;
3811 ventoy_os_param
*osparam
;
3812 ventoy_image_location
*location
;
3813 ventoy_image_disk_region
*region
;
3814 struct grub_acpi_table_header
*acpi
;
3823 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3825 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3831 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3833 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3835 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3839 img_chunk_num
= chain
->img_chunk_num
;
3841 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3842 datalen
= sizeof(ventoy_os_param
) + loclen
;
3844 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3845 acpi
= grub_zalloc(buflen
);
3851 /* Step1: Fill acpi table header */
3852 grub_memcpy(acpi
->signature
, "VTOY", 4);
3853 acpi
->length
= buflen
;
3855 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3856 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3858 acpi
->creator_id
[0] = 1;
3859 acpi
->creator_rev
= 1;
3861 /* Step2: Fill data */
3862 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3863 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3864 osparam
->vtoy_img_location_addr
= 0;
3865 osparam
->vtoy_img_location_len
= loclen
;
3866 osparam
->chksum
= 0;
3867 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3869 location
= (ventoy_image_location
*)(osparam
+ 1);
3870 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3871 location
->image_sector_size
= image_sector_size
;
3872 location
->disk_sector_size
= chain
->disk_sector_size
;
3873 location
->region_count
= img_chunk_num
;
3875 region
= location
->regions
;
3876 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3877 if (512 == image_sector_size
)
3879 for (i
= 0; i
< img_chunk_num
; i
++)
3881 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3882 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3883 region
->disk_start_sector
= chunk
->disk_start_sector
;
3890 for (i
= 0; i
< img_chunk_num
; i
++)
3892 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3893 region
->image_start_sector
= chunk
->img_start_sector
;
3894 region
->disk_start_sector
= chunk
->disk_start_sector
;
3900 /* Step3: Fill acpi checksum */
3902 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3904 /* load acpi table */
3905 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3906 grub_script_execute_sourcecode(cmd
);
3910 VENTOY_CMD_RETURN(0);
3913 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3919 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3920 g_ventoy_last_entry
= -1;
3925 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3931 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3936 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3938 const char *pos
= filename
+ 1;
3946 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3948 grub_strncpy((char *)data
, filename
, 128);
3959 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3962 char *device_name
= NULL
;
3963 grub_device_t dev
= NULL
;
3964 grub_fs_t fs
= NULL
;
3965 char buf
[128] = {0};
3971 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3975 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3977 device_name
= grub_file_get_device_name(args
[0]);
3980 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3984 dev
= grub_device_open(device_name
);
3987 debug("grub_device_open failed, %s\n", device_name
);
3991 fs
= grub_fs_probe(dev
);
3994 debug("grub_fs_probe failed, %s\n", device_name
);
3998 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4002 ventoy_set_env(args
[2], buf
);
4009 check_free(device_name
, grub_free
);
4010 check_free(dev
, grub_device_close
);
4015 int ventoy_load_part_table(const char *diskname
)
4022 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4023 if (!g_ventoy_part_info
)
4028 disk
= grub_disk_open(diskname
);
4031 debug("Failed to open disk %s\n", diskname
);
4035 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4037 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4038 grub_disk_close(disk
);
4040 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4041 dev
= grub_device_open(name
);
4044 /* Check for official Ventoy device */
4045 ret
= ventoy_check_official_device(dev
);
4046 grub_device_close(dev
);
4054 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4055 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4060 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4067 ret
= ventoy_load_part_table(args
[0]);
4073 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4074 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4079 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4082 const char *vcfg
= NULL
;
4087 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4090 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4091 grub_env_set(args
[1], vcfg
);
4096 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4104 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4107 grub_uint8_t zeroguid
[16] = {0};
4112 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4115 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4117 if (id
>= 1 && id
<= 128)
4119 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4127 if (id
>= 1 && id
<= 4)
4129 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4139 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4142 char *device_name
= NULL
;
4143 grub_device_t dev
= NULL
;
4144 grub_fs_t fs
= NULL
;
4149 debug("get fs label for %s\n", args
[0]);
4153 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4157 device_name
= grub_file_get_device_name(args
[0]);
4160 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4164 dev
= grub_device_open(device_name
);
4167 debug("grub_device_open failed, %s\n", device_name
);
4171 fs
= grub_fs_probe(dev
);
4172 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4174 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4178 fs
->fs_label(dev
, &label
);
4181 debug("label=<%s>\n", label
);
4182 ventoy_set_env(args
[1], label
);
4190 check_free(device_name
, grub_free
);
4191 check_free(dev
, grub_device_close
);
4196 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4200 grub_snprintf((char *)data
, 256, "%s", filename
);
4208 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4211 char *device_name
= NULL
;
4212 grub_device_t dev
= NULL
;
4213 grub_fs_t fs
= NULL
;
4214 char name
[256] ={0};
4220 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
4224 device_name
= grub_file_get_device_name(args
[0]);
4227 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4231 dev
= grub_device_open(device_name
);
4234 debug("grub_device_open failed, %s\n", device_name
);
4238 fs
= grub_fs_probe(dev
);
4241 debug("grub_fs_probe failed, %s\n", device_name
);
4245 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
4248 ventoy_set_env(args
[2], name
);
4255 check_free(device_name
, grub_free
);
4256 check_free(dev
, grub_device_close
);
4261 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4271 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4275 for (pos
= args
[0]; *pos
; pos
++)
4289 grub_env_set(args
[1], args
[0]);
4299 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4309 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4314 len
= (int)grub_strlen(buf
);
4315 for (i
= len
; i
> 0; i
--)
4317 if (buf
[i
- 1] == '/')
4319 grub_env_set(args
[1], buf
+ i
);
4324 grub_env_set(args
[1], buf
);
4329 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4331 struct grub_video_mode_info info
;
4338 if (!g_video_mode_list
)
4340 ventoy_enum_video_mode();
4343 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4345 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4349 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4352 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4354 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4355 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4357 VENTOY_CMD_RETURN(0);
4360 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4362 struct grub_video_mode_info info
;
4369 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4371 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4375 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4378 grub_env_set(args
[0], buf
);
4380 VENTOY_CMD_RETURN(0);
4383 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4391 if (!g_video_mode_list
)
4396 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4397 if (id
< g_video_mode_num
)
4399 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4400 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4403 grub_env_set(args
[1], buf
);
4405 VENTOY_CMD_RETURN(0);
4408 int ventoy_env_init(void)
4412 grub_env_set("vtdebug_flag", "");
4414 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4415 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4416 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4417 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4419 ventoy_filt_register(0, ventoy_wrapper_open
);
4421 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4424 g_grub_param
->grub_env_get
= grub_env_get
;
4425 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4426 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4427 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4428 grub_env_set("env_param", buf
);
4429 grub_env_set("ventoy_env_param", buf
);
4431 grub_env_export("env_param");
4432 grub_env_export("ventoy_env_param");
4435 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
4436 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
4438 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
4439 grub_env_set("vtoy_winpeshl_ini_size", buf
);
4441 grub_env_export("vtoy_winpeshl_ini_addr");
4442 grub_env_export("vtoy_winpeshl_ini_size");
4444 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
4445 grub_env_set("vtoy_chain_file_size", buf
);
4446 grub_env_export("vtoy_chain_file_size");
4448 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
4449 grub_env_set("vtoy_chain_file_read", buf
);
4450 grub_env_export("vtoy_chain_file_read");
4455 static cmd_para ventoy_cmds
[] =
4457 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4458 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4459 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4460 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4461 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4462 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4463 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4464 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4465 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4466 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4467 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4468 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4469 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4470 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4471 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4472 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4473 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4474 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4475 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4476 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4477 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4478 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4479 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4480 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4482 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4483 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4484 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4485 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4486 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4487 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4488 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4490 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4491 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4492 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4493 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4494 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4495 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4496 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4497 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4498 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4501 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4502 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4503 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4504 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4505 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4506 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4507 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4508 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4509 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4510 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4511 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4513 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4514 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4515 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4516 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4517 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4518 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4520 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4521 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4522 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4523 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4524 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4525 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4526 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4527 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4528 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4529 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4531 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4532 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4533 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
4534 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4535 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4536 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4537 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4538 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4539 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4541 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4542 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4543 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4546 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4547 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4548 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4550 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4551 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4552 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4555 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4556 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4557 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4558 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4559 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
4560 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4561 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4562 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4563 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4564 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4565 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4567 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4568 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4569 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4570 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4571 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
4572 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
4573 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
4574 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
4575 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
4579 int ventoy_register_all_cmd(void)
4582 cmd_para
*cur
= NULL
;
4584 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4586 cur
= ventoy_cmds
+ i
;
4587 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4588 cur
->summary
, cur
->description
, cur
->parser
);
4594 int ventoy_unregister_all_cmd(void)
4598 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4600 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);