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_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3154 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3160 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3161 grub_env_set(args
[0], buf
);
3164 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3167 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3175 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3176 grub_printf("%s", g_list_script_buf
);
3180 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3181 grub_printf("%s", g_tree_script_buf
);
3187 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3189 img_info
*cur
= g_ventoy_img_list
;
3197 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3198 grub_printf("name:<%s>\n\n", cur
->name
);
3205 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3211 ventoy_plugin_dump_injection();
3216 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3222 ventoy_plugin_dump_auto_install();
3227 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3233 ventoy_plugin_dump_persistence();
3238 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3249 if (args
[0][0] == '0')
3251 return g_ventoy_memdisk_mode
? 0 : 1;
3253 else if (args
[0][0] == '1')
3255 return g_ventoy_iso_raw
? 0 : 1;
3257 else if (args
[0][0] == '2')
3259 return g_ventoy_iso_uefi_drv
? 0 : 1;
3261 else if (args
[0][0] == '3')
3263 return g_ventoy_grub2_mode
? 0 : 1;
3265 else if (args
[0][0] == '4')
3267 return g_ventoy_wimboot_mode
? 0 : 1;
3273 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3275 static int configfile_mode
= 0;
3276 char memfile
[128] = {0};
3283 * args[0]: 0:normal 1:configfile
3284 * args[1]: 0:list_buf 1:tree_buf
3289 debug("Invalid argc %d\n", argc
);
3295 if (args
[0][0] == '0')
3297 if (args
[1][0] == '0')
3299 grub_script_execute_sourcecode(g_list_script_buf
);
3303 grub_script_execute_sourcecode(g_tree_script_buf
);
3308 if (configfile_mode
)
3310 debug("Now already in F3 mode %d\n", configfile_mode
);
3314 if (args
[1][0] == '0')
3316 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3317 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3321 g_ventoy_last_entry
= -1;
3322 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3323 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3326 configfile_mode
= 1;
3327 grub_script_execute_sourcecode(memfile
);
3328 configfile_mode
= 0;
3334 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3345 g_ventoy_case_insensitive
= 1;
3346 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3347 g_ventoy_case_insensitive
= 0;
3353 grub_file_close(file
);
3359 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3364 const char *isopath
= NULL
;
3366 ventoy_mbr_head mbr
;
3373 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3376 isopath
= grub_env_get("vtoy_iso_part");
3379 debug("isopath is null %p\n", isopath
);
3383 debug("isopath is %s\n", isopath
);
3385 for (id
= 0; id
< 30 && (find
== 0); id
++)
3387 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3388 if (grub_strstr(isopath
, hdname
))
3390 debug("skip %s ...\n", hdname
);
3394 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3396 disk
= grub_disk_open(hdname
);
3399 debug("%s not exist\n", hdname
);
3403 grub_memset(&mbr
, 0, sizeof(mbr
));
3404 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3406 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3408 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3409 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3412 grub_env_set(args
[0], hdname
);
3416 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3420 debug("read %s failed\n", hdname
);
3423 grub_disk_close(disk
);
3429 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3440 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3443 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3446 debug("failed to open file %s\n", args
[0]);
3450 buf
= grub_malloc(len
);
3457 grub_file_read(file
, buf
, len
- 1);
3459 ventoy_get_line(buf
);
3460 ventoy_set_env(args
[1], buf
);
3464 grub_check_free(buf
);
3465 grub_file_close(file
);
3470 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3475 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3476 "0 %llu linear /dev/ventoy %llu\n",
3477 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3482 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3484 char *device_name
= NULL
;
3485 grub_device_t dev
= NULL
;
3490 g_part_list_pos
= 0;
3491 grub_env_unset("vtoy_img_part_file");
3498 device_name
= grub_file_get_device_name(args
[0]);
3501 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3505 dev
= grub_device_open(device_name
);
3508 debug("grub_device_open failed, %s\n", device_name
);
3512 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3514 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3515 grub_env_set("vtoy_img_part_file", buf
);
3519 check_free(device_name
, grub_free
);
3520 check_free(dev
, grub_device_close
);
3526 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3537 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3540 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3543 debug("failed to open file %s\n", args
[0]);
3547 buf
= grub_malloc(file
->size
+ 1);
3553 buf
[file
->size
] = 0;
3554 grub_file_read(file
, buf
, file
->size
);
3556 if (grub_strstr(buf
, args
[1]))
3563 grub_check_free(buf
);
3564 grub_file_close(file
);
3569 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3575 ventoy_iso9660_vd pvd
;
3582 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3585 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3588 debug("failed to open file %s\n", args
[0]);
3592 grub_file_seek(file
, 16 * 2048);
3593 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3594 if (len
!= sizeof(pvd
))
3596 debug("failed to read pvd %d\n", len
);
3600 grub_memset(buf
, 0, sizeof(buf
));
3601 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3602 ventoy_set_env(args
[1], buf
);
3604 grub_memset(buf
, 0, sizeof(buf
));
3605 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3606 ventoy_set_env(args
[2], buf
);
3610 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3611 ventoy_set_env(args
[3], buf
);
3614 grub_file_close(file
);
3619 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3630 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3633 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3636 debug("failed to open file %s\n", args
[0]);
3640 grub_memset(buf
, 0, sizeof(buf
));
3641 grub_file_seek(file
, 16 * 2048 + 813);
3642 len
= (int)grub_file_read(file
, buf
, 17);
3645 debug("failed to read create date %d\n", len
);
3649 ventoy_set_env(args
[1], buf
);
3652 grub_file_close(file
);
3657 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3663 ventoy_env_hook_root(1);
3668 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3674 ventoy_env_hook_root(0);
3679 #ifdef GRUB_MACHINE_EFI
3680 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3685 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3691 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3692 if (var
&& *var
== 1)
3700 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3709 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3714 grub_uint64_t FileSectors
= 0;
3715 ventoy_gpt_info
*gpt
= NULL
;
3716 ventoy_part_table
*pt
= NULL
;
3717 grub_uint8_t zeroguid
[16] = {0};
3722 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3725 debug("failed to open file %s\n", args
[0]);
3729 if (file
->size
% 512)
3731 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3735 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3741 FileSectors
= file
->size
/ 512;
3743 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3744 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3746 debug("This is EFI partition table\n");
3748 for (i
= 0; i
< 128; i
++)
3750 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3752 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3754 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3755 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3763 debug("This is MBR partition table\n");
3765 for (i
= 0; i
< 4; i
++)
3767 pt
= gpt
->MBR
.PartTbl
+ i
;
3768 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3770 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3771 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3772 (ulonglong
)FileSectors
);
3781 grub_file_close(file
);
3782 grub_check_free(gpt
);
3783 grub_errno
= GRUB_ERR_NONE
;
3787 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3796 for (i
= 0; i
< 500; i
++)
3798 ret
= grub_getkey_noblock();
3799 if (ret
== GRUB_TERM_NO_KEY
)
3808 grub_printf("\n\n Still have key input after clear.\n");
3816 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3823 int image_sector_size
;
3825 ventoy_chain_head
*chain
;
3826 ventoy_img_chunk
*chunk
;
3827 ventoy_os_param
*osparam
;
3828 ventoy_image_location
*location
;
3829 ventoy_image_disk_region
*region
;
3830 struct grub_acpi_table_header
*acpi
;
3839 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3841 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3847 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3849 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3851 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3855 img_chunk_num
= chain
->img_chunk_num
;
3857 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3858 datalen
= sizeof(ventoy_os_param
) + loclen
;
3860 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3861 acpi
= grub_zalloc(buflen
);
3867 /* Step1: Fill acpi table header */
3868 grub_memcpy(acpi
->signature
, "VTOY", 4);
3869 acpi
->length
= buflen
;
3871 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3872 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3874 acpi
->creator_id
[0] = 1;
3875 acpi
->creator_rev
= 1;
3877 /* Step2: Fill data */
3878 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3879 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3880 osparam
->vtoy_img_location_addr
= 0;
3881 osparam
->vtoy_img_location_len
= loclen
;
3882 osparam
->chksum
= 0;
3883 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3885 location
= (ventoy_image_location
*)(osparam
+ 1);
3886 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3887 location
->image_sector_size
= image_sector_size
;
3888 location
->disk_sector_size
= chain
->disk_sector_size
;
3889 location
->region_count
= img_chunk_num
;
3891 region
= location
->regions
;
3892 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3893 if (512 == image_sector_size
)
3895 for (i
= 0; i
< img_chunk_num
; i
++)
3897 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3898 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3899 region
->disk_start_sector
= chunk
->disk_start_sector
;
3906 for (i
= 0; i
< img_chunk_num
; i
++)
3908 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3909 region
->image_start_sector
= chunk
->img_start_sector
;
3910 region
->disk_start_sector
= chunk
->disk_start_sector
;
3916 /* Step3: Fill acpi checksum */
3918 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3920 /* load acpi table */
3921 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3922 grub_script_execute_sourcecode(cmd
);
3926 VENTOY_CMD_RETURN(0);
3929 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3935 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3936 g_ventoy_last_entry
= -1;
3941 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3947 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3952 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3954 const char *pos
= filename
+ 1;
3962 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3964 grub_strncpy((char *)data
, filename
, 128);
3975 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3978 char *device_name
= NULL
;
3979 grub_device_t dev
= NULL
;
3980 grub_fs_t fs
= NULL
;
3981 char buf
[128] = {0};
3987 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3991 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3993 device_name
= grub_file_get_device_name(args
[0]);
3996 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4000 dev
= grub_device_open(device_name
);
4003 debug("grub_device_open failed, %s\n", device_name
);
4007 fs
= grub_fs_probe(dev
);
4010 debug("grub_fs_probe failed, %s\n", device_name
);
4014 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4018 ventoy_set_env(args
[2], buf
);
4025 check_free(device_name
, grub_free
);
4026 check_free(dev
, grub_device_close
);
4031 int ventoy_load_part_table(const char *diskname
)
4038 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4039 if (!g_ventoy_part_info
)
4044 disk
= grub_disk_open(diskname
);
4047 debug("Failed to open disk %s\n", diskname
);
4051 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4053 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4054 grub_disk_close(disk
);
4056 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4057 dev
= grub_device_open(name
);
4060 /* Check for official Ventoy device */
4061 ret
= ventoy_check_official_device(dev
);
4062 grub_device_close(dev
);
4070 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4071 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4076 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4083 ret
= ventoy_load_part_table(args
[0]);
4089 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4090 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4095 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4098 const char *vcfg
= NULL
;
4103 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4106 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4107 grub_env_set(args
[1], vcfg
);
4112 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4120 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4123 grub_uint8_t zeroguid
[16] = {0};
4128 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4131 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4133 if (id
>= 1 && id
<= 128)
4135 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4143 if (id
>= 1 && id
<= 4)
4145 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4155 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4158 char *device_name
= NULL
;
4159 grub_device_t dev
= NULL
;
4160 grub_fs_t fs
= NULL
;
4165 debug("get fs label for %s\n", args
[0]);
4169 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4173 device_name
= grub_file_get_device_name(args
[0]);
4176 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4180 dev
= grub_device_open(device_name
);
4183 debug("grub_device_open failed, %s\n", device_name
);
4187 fs
= grub_fs_probe(dev
);
4188 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4190 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4194 fs
->fs_label(dev
, &label
);
4197 debug("label=<%s>\n", label
);
4198 ventoy_set_env(args
[1], label
);
4206 check_free(device_name
, grub_free
);
4207 check_free(dev
, grub_device_close
);
4212 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4216 grub_snprintf((char *)data
, 256, "%s", filename
);
4223 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4225 if (info
->dir
&& filename
&& filename
[0] != '.')
4227 grub_snprintf((char *)data
, 256, "%s", filename
);
4234 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4237 char *device_name
= NULL
;
4238 grub_device_t dev
= NULL
;
4239 grub_fs_t fs
= NULL
;
4240 char name
[256] ={0};
4244 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4248 device_name
= grub_file_get_device_name(args
[0]);
4251 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4255 dev
= grub_device_open(device_name
);
4258 debug("grub_device_open failed, %s\n", device_name
);
4262 fs
= grub_fs_probe(dev
);
4265 debug("grub_fs_probe failed, %s\n", device_name
);
4269 fs
->fs_dir(dev
, args
[1], hook
, name
);
4272 ventoy_set_env(args
[2], name
);
4279 check_free(device_name
, grub_free
);
4280 check_free(dev
, grub_device_close
);
4285 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4288 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4291 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4294 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4297 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4307 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4311 for (pos
= args
[0]; *pos
; pos
++)
4325 grub_env_set(args
[1], args
[0]);
4335 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4345 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4350 len
= (int)grub_strlen(buf
);
4351 for (i
= len
; i
> 0; i
--)
4353 if (buf
[i
- 1] == '/')
4355 grub_env_set(args
[1], buf
+ i
);
4360 grub_env_set(args
[1], buf
);
4365 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4367 struct grub_video_mode_info info
;
4374 if (!g_video_mode_list
)
4376 ventoy_enum_video_mode();
4379 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4381 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4385 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4388 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4390 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4391 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4393 VENTOY_CMD_RETURN(0);
4396 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4398 struct grub_video_mode_info info
;
4405 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4407 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4411 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4414 grub_env_set(args
[0], buf
);
4416 VENTOY_CMD_RETURN(0);
4419 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4427 if (!g_video_mode_list
)
4432 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4433 if (id
< g_video_mode_num
)
4435 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4436 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4439 grub_env_set(args
[1], buf
);
4441 VENTOY_CMD_RETURN(0);
4444 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4447 grub_uint32_t loadsector
= 0;
4450 grub_uint32_t boot_catlog
= 0;
4451 grub_uint8_t buf
[512];
4457 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4461 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4464 debug("failed to open %s\n", args
[0]);
4468 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4469 if (boot_catlog
== 0)
4471 debug("No bootcatlog found\n");
4472 grub_file_close(file
);
4476 grub_memset(buf
, 0, sizeof(buf
));
4477 grub_file_seek(file
, boot_catlog
* 2048);
4478 grub_file_read(file
, buf
, sizeof(buf
));
4479 grub_file_close(file
);
4481 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4483 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4485 if (buf
[i
+ 32] == 0x88)
4487 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4488 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4494 if (loadsector
== 0)
4496 debug("No EFI eltorito info found\n");
4500 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4501 grub_env_set(args
[1], value
);
4502 VENTOY_CMD_RETURN(0);
4505 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4510 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4512 if (pfsdir
->initrd
[0])
4517 curpos
= pfsdir
->curpos
;
4518 len
= grub_strlen(filename
);
4522 if ((len
== 1 && filename
[0] == '.') ||
4523 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4528 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4531 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4532 pfsdir
->curpos
= curpos
+ printlen
;
4533 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4534 pfsdir
->curpos
= curpos
;
4535 pfsdir
->fullpath
[curpos
] = 0;
4539 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4542 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4543 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4545 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4547 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4556 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4560 char *device_name
= NULL
;
4561 grub_device_t dev
= NULL
;
4562 grub_fs_t fs
= NULL
;
4563 replace_fs_dir
*pfsdir
= NULL
;
4569 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4573 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4579 device_name
= grub_file_get_device_name(args
[0]);
4585 dev
= grub_device_open(device_name
);
4591 fs
= grub_fs_probe(dev
);
4600 pfsdir
->fullpath
[0] = '/';
4601 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4603 if (pfsdir
->initrd
[0])
4605 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4607 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4609 if (pfsdir
->initrd
[i
] == '/')
4611 pfsdir
->initrd
[i
] = '\\';
4615 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4616 grub_env_set(args
[1], pos
);
4620 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4625 grub_check_free(pfsdir
);
4626 grub_check_free(device_name
);
4627 check_free(dev
, grub_device_close
);
4629 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4632 int ventoy_env_init(void)
4636 grub_env_set("vtdebug_flag", "");
4638 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4639 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4640 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4641 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4643 ventoy_filt_register(0, ventoy_wrapper_open
);
4645 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4648 g_grub_param
->grub_env_get
= grub_env_get
;
4649 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4650 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4651 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4652 grub_env_set("env_param", buf
);
4653 grub_env_set("ventoy_env_param", buf
);
4655 grub_env_export("env_param");
4656 grub_env_export("ventoy_env_param");
4659 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
4660 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
4662 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
4663 grub_env_set("vtoy_winpeshl_ini_size", buf
);
4665 grub_env_export("vtoy_winpeshl_ini_addr");
4666 grub_env_export("vtoy_winpeshl_ini_size");
4668 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
4669 grub_env_set("vtoy_chain_file_size", buf
);
4670 grub_env_export("vtoy_chain_file_size");
4672 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
4673 grub_env_set("vtoy_chain_file_read", buf
);
4674 grub_env_export("vtoy_chain_file_read");
4679 static cmd_para ventoy_cmds
[] =
4681 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4682 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4683 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4684 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4685 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4686 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4687 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4688 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4689 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4690 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4691 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4692 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4693 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4694 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4695 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4696 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4697 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4698 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4699 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4700 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4701 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4702 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4703 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4704 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4706 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4707 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4708 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4709 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4710 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4711 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4712 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4714 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4715 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4716 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4717 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4718 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
4719 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4720 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4721 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4722 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4723 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4726 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4727 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4728 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4729 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4730 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4731 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4732 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4733 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4734 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4735 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4736 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4738 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4739 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4740 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4741 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4742 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4743 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4745 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4746 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4747 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4748 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4749 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4750 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4751 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4752 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4753 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4754 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4756 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4757 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4758 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
4759 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4760 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4761 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4762 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4763 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4764 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4766 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4767 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
4768 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4769 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4772 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4773 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4774 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4776 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4777 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4778 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4781 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4782 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4783 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4784 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4785 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
4786 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4787 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4788 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4789 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4790 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4791 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4793 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4794 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4795 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4796 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4797 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
4798 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
4799 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
4800 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
4801 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
4802 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
4804 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
4805 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
4808 int ventoy_register_all_cmd(void)
4811 cmd_para
*cur
= NULL
;
4813 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4815 cur
= ventoy_cmds
+ i
;
4816 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4817 cur
->summary
, cur
->description
, cur
->parser
);
4823 int ventoy_unregister_all_cmd(void)
4827 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4829 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);