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 int g_pager_flag
= 0;
131 static char g_old_pager
[32];
133 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
135 static const char *g_menu_class
[] =
137 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
140 const char *g_menu_prefix
[img_type_max
] =
142 "iso", "wim", "efi", "img", "vhd", "vtoy"
145 static int g_vtoy_load_prompt
= 0;
146 static char g_vtoy_prompt_msg
[64];
148 static int ventoy_get_fs_type(const char *fs
)
152 return ventoy_fs_max
;
154 else if (grub_strncmp(fs
, "exfat", 5) == 0)
156 return ventoy_fs_exfat
;
158 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
160 return ventoy_fs_ntfs
;
162 else if (grub_strncmp(fs
, "ext", 3) == 0)
164 return ventoy_fs_ext
;
166 else if (grub_strncmp(fs
, "xfs", 3) == 0)
168 return ventoy_fs_xfs
;
170 else if (grub_strncmp(fs
, "udf", 3) == 0)
172 return ventoy_fs_udf
;
174 else if (grub_strncmp(fs
, "fat", 3) == 0)
176 return ventoy_fs_fat
;
179 return ventoy_fs_max
;
182 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
201 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
203 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
207 static int ventoy_control_get_flag(const char *key
)
209 const char *val
= ventoy_get_env(key
);
211 if (val
&& val
[0] == '1' && val
[1] == 0)
218 static grub_err_t
ventoy_fs_close(grub_file_t file
)
220 grub_file_close(g_old_file
);
221 grub_free(file
->data
);
229 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
235 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
240 for (i
= 0; i
< g_video_mode_num
; i
++)
242 if (g_video_mode_list
[i
].width
== info
->width
&&
243 g_video_mode_list
[i
].height
== info
->height
&&
244 g_video_mode_list
[i
].bpp
== info
->bpp
)
250 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
251 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
252 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
255 if (g_video_mode_num
== g_video_mode_max
)
257 g_video_mode_max
*= 2;
258 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
264 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
266 if (v1
->bpp
== v2
->bpp
)
268 if (v1
->width
== v2
->width
)
270 if (v1
->height
== v2
->height
)
276 return (v1
->height
< v2
->height
) ? -1 : 1;
281 return (v1
->width
< v2
->width
) ? -1 : 1;
286 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
290 static int ventoy_enum_video_mode(void)
293 grub_video_adapter_t adapter
;
294 grub_video_driver_id_t id
;
295 ventoy_video_mode mode
;
297 g_video_mode_num
= 0;
298 g_video_mode_max
= 1024;
299 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
300 if (!g_video_mode_list
)
305 #ifdef GRUB_MACHINE_PCBIOS
306 grub_dl_load ("vbe");
309 id
= grub_video_get_driver_id ();
311 FOR_VIDEO_ADAPTERS (adapter
)
313 if (!adapter
->iterate
||
314 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
315 adapter
->init() != GRUB_ERR_NONE
)))
320 adapter
->iterate(ventoy_video_hook
, NULL
);
322 if (adapter
->id
!= id
)
328 /* sort video mode */
329 for (i
= 0; i
< g_video_mode_num
; i
++)
330 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
332 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
334 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
335 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
336 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
340 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
343 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
347 static struct grub_fs vtoy_fs
=
352 .fs_read
= ventoy_fs_read
,
353 .fs_close
= ventoy_fs_close
,
363 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
369 file
->data
= grub_malloc(rawFile
->size
+ 4096);
375 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
376 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
378 g_old_file
= rawFile
;
380 file
->size
= rawFile
->size
+ len
;
381 file
->device
= rawFile
->device
;
383 file
->not_easily_seekable
= 1;
388 static int ventoy_check_decimal_var(const char *name
, long *value
)
390 const char *value_str
= NULL
;
392 value_str
= grub_env_get(name
);
393 if (NULL
== value_str
)
395 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
398 if (!ventoy_is_decimal(value_str
))
400 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
403 *value
= grub_strtol(value_str
, NULL
, 10);
405 return GRUB_ERR_NONE
;
408 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
410 grub_uint64_t sectors
;
412 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
414 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
418 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
421 return sectors
* 512;
424 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
430 grub_uint32_t offset
;
432 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
435 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
439 len
= (int)file
->size
;
441 data
= (char *)grub_malloc(file
->size
);
447 grub_file_read(file
, data
, file
->size
);
448 grub_file_close(file
);
450 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
451 grub_script_execute_sourcecode(exec
);
453 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
454 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
455 grub_file_close(file
);
457 grub_script_execute_sourcecode("loopback -d efiboot");
461 *direntoff
= offset
+ 2;
466 static int ventoy_set_check_result(int ret
)
470 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
471 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
472 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
476 grub_printf(VTOY_WARNING
"\n");
477 grub_printf(VTOY_WARNING
"\n");
478 grub_printf(VTOY_WARNING
"\n\n\n");
480 grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret
);
481 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
483 grub_printf("\n\nWill exit after 10 seconds ...... ");
491 static int ventoy_check_official_device(grub_device_t dev
)
495 grub_uint64_t offset
;
500 struct grub_partition
*partition
;
502 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
504 return ventoy_set_check_result(1 | 0x1000);
507 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
508 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
509 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
511 #ifndef GRUB_MACHINE_EFI
512 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
513 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
514 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
516 return ventoy_set_check_result(2 | 0x1000);
525 /* We must have partition 2 */
528 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
532 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
536 return ventoy_set_check_result(3 | 0x1000);
539 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
541 grub_file_close(file
);
542 return ventoy_set_check_result(4 | 0x1000);
545 partition
= dev
->disk
->partition
;
546 if (partition
->number
!= 0 || partition
->start
!= 2048)
548 return ventoy_set_check_result(5);
553 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
555 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
556 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
557 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
559 grub_file_close(file
);
560 return ventoy_set_check_result(6);
565 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
566 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
567 PartTbl
[1].SectorCount
!= 65536)
569 grub_file_close(file
);
570 return ventoy_set_check_result(6);
576 offset
= partition
->start
+ partition
->len
;
577 partition
= file
->device
->disk
->partition
;
578 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
580 grub_file_close(file
);
581 return ventoy_set_check_result(7);
585 grub_file_close(file
);
589 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
590 dev2
= grub_device_open(devname
);
593 return ventoy_set_check_result(8);
596 fs
= grub_fs_probe(dev2
);
599 grub_device_close(dev2
);
600 return ventoy_set_check_result(9);
603 fs
->fs_label(dev2
, &label
);
604 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
606 grub_device_close(dev2
);
607 return ventoy_set_check_result(10);
610 grub_device_close(dev2
);
613 return ventoy_set_check_result(0);
616 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
620 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
630 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
632 grub_uint64_t size
= 0;
635 char fullpath
[256] = {0};
638 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
641 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
644 debug("grub_file_open failed <%s>\n", fullpath
);
650 grub_file_close(file
);
654 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
658 char fullpath
[256] = {0};
661 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
664 file
= grub_file_open(fullpath
, type
);
667 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
674 int ventoy_is_file_exist(const char *fmt
, ...)
681 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
685 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
688 grub_strncpy(pos
+ len
, "\" ]", 3);
690 debug("script exec %s\n", buf
);
692 if (0 == grub_script_execute_sourcecode(buf
))
700 int ventoy_is_dir_exist(const char *fmt
, ...)
707 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
711 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
714 grub_strncpy(pos
+ len
, "\" ]", 3);
716 debug("script exec %s\n", buf
);
718 if (0 == grub_script_execute_sourcecode(buf
))
726 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
729 grub_uint8_t
*outbuf
;
730 grub_uint8_t gzHdr
[10] =
732 0x1F, 0x8B, /* magic */
740 grub_memset(&s
, 0, sizeof(mz_stream
));
742 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
744 outbuf
= (grub_uint8_t
*)mem_out
;
746 mem_out_len
-= sizeof(gzHdr
) + 8;
747 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
748 outbuf
+= sizeof(gzHdr
);
750 s
.avail_in
= mem_in_len
;
753 s
.avail_out
= mem_out_len
;
756 mz_deflate(&s
, MZ_FINISH
);
760 outbuf
+= s
.total_out
;
761 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
762 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
764 return s
.total_out
+ sizeof(gzHdr
) + 8;
772 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
776 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
779 if (0 == grub_strcmp(args
[0], "on"))
782 grub_env_set("vtdebug_flag", "debug");
787 grub_env_set("vtdebug_flag", "");
790 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
793 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
797 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
799 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
800 grub_printf(" level:\r\n");
801 grub_printf(" 01/11: busybox / (+cat log)\r\n");
802 grub_printf(" 02/12: initrd / (+cat log)\r\n");
803 grub_printf(" 03/13: hook / (+cat log)\r\n");
805 grub_printf(" debug:\r\n");
806 grub_printf(" 0: debug is off\r\n");
807 grub_printf(" 1: debug is on\r\n");
809 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
812 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
814 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
816 g_ventoy_debug_level
= 1;
819 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
822 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
831 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
834 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
866 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
871 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
873 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
876 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
881 value_long
+= grub_strtol(args
[1], NULL
, 10);
883 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
884 grub_env_set(args
[0], buf
);
886 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
889 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
891 ulonglong value1
= 0;
892 ulonglong value2
= 0;
897 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
900 value1
= grub_strtoull(args
[0], NULL
, 10);
901 value2
= grub_strtoull(args
[1], NULL
, 10);
903 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
904 grub_env_set(args
[2], buf
);
906 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
909 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
924 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
927 debug("failed to open file <%s> for udf check\n", args
[0]);
931 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
933 grub_env_set(args
[1], buf
);
935 grub_file_close(file
);
941 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
949 g_wimboot_enable
= 0;
950 grub_check_free(g_wimiso_path
);
951 grub_check_free(g_wimiso_chunk_list
.chunk
);
953 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
959 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
960 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
961 if (NULL
== g_wimiso_chunk_list
.chunk
)
963 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
966 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
967 g_wimiso_chunk_list
.cur_chunk
= 0;
969 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
971 g_wimboot_enable
= 1;
972 g_wimiso_path
= grub_strdup(args
[0]);
974 grub_file_close(file
);
979 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
989 ventoy_iso9660_override
*dirent
;
998 totlen
= sizeof(ventoy_chain_head
);
1000 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1002 debug("failed to load efiboot template %d\n", len
);
1008 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1010 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1013 debug("failed to open file <%s>\n", args
[0]);
1017 totlen
+= ventoy_align_2k(file
->size
);
1019 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1020 dirent
->first_sector
= len
/ 2048;
1021 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1022 dirent
->size
= (grub_uint32_t
)file
->size
;
1023 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1025 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1027 #ifdef GRUB_MACHINE_EFI
1028 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1030 data
= (char *)grub_malloc(totlen
);
1033 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1035 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1036 grub_check_free(buf
);
1038 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1039 grub_file_close(file
);
1041 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1042 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1043 grub_env_set(name
, value
);
1045 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1046 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1047 grub_env_set(name
, value
);
1052 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1058 g_vtoy_load_prompt
= 0;
1059 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1061 if (argc
== 2 && args
[0][0] == '1')
1063 g_vtoy_load_prompt
= 1;
1064 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1067 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1070 int ventoy_need_prompt_load_file(void)
1072 return g_vtoy_load_prompt
;
1075 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1077 grub_uint64_t ro
= 0;
1078 grub_uint64_t div
= 0;
1079 grub_ssize_t left
= size
;
1080 char *cur
= (char *)buf
;
1082 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1085 while (left
>= VTOY_SIZE_2MB
)
1087 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1088 cur
+= VTOY_SIZE_2MB
;
1089 left
-= VTOY_SIZE_2MB
;
1091 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1092 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1098 grub_file_read(file
, cur
, left
);
1101 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1107 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1114 enum grub_file_type type
;
1125 if (grub_strcmp(args
[0], "nodecompress") == 0)
1127 type
= VENTOY_FILE_TYPE
;
1131 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1134 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1137 debug("failed to open file <%s>\n", args
[1]);
1141 #ifdef GRUB_MACHINE_EFI
1142 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1144 buf
= (char *)grub_malloc(file
->size
);
1149 grub_file_close(file
);
1153 if (g_vtoy_load_prompt
)
1155 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1159 grub_file_read(file
, buf
, file
->size
);
1162 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1163 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1164 grub_env_set(name
, value
);
1166 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1167 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1168 grub_env_set(name
, value
);
1170 grub_file_close(file
);
1176 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1194 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1197 debug("failed to open file <%s> for udf check\n", args
[0]);
1201 headlen
= sizeof(ventoy_chain_head
);
1203 #ifdef GRUB_MACHINE_EFI
1204 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1206 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1209 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1211 grub_file_read(file
, buf
+ headlen
, file
->size
);
1213 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1214 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1215 grub_env_set(name
, value
);
1217 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1218 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1219 grub_env_set(name
, value
);
1221 grub_file_close(file
);
1227 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1233 if (grub_iso9660_is_joliet())
1235 debug("This time has joliet process\n");
1244 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1253 if (args
[0][0] == '1')
1255 grub_iso9660_set_nojoliet(1);
1259 grub_iso9660_set_nojoliet(0);
1265 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1270 grub_uint8_t buf
[32];
1281 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1284 debug("failed to open file <%s> for udf check\n", args
[0]);
1288 for (i
= 16; i
< 32; i
++)
1290 grub_file_seek(file
, i
* 2048);
1291 grub_file_read(file
, buf
, sizeof(buf
));
1299 grub_file_seek(file
, i
* 2048);
1300 grub_file_read(file
, buf
, sizeof(buf
));
1302 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1305 grub_file_seek(file
, i
* 2048);
1306 grub_file_read(file
, buf
, sizeof(buf
));
1308 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1309 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1315 grub_file_close(file
);
1317 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1322 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1324 long value_long1
= 0;
1325 long value_long2
= 0;
1327 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1329 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1332 value_long1
= grub_strtol(args
[0], NULL
, 10);
1333 value_long2
= grub_strtol(args
[2], NULL
, 10);
1335 if (0 == grub_strcmp(args
[1], "eq"))
1337 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1339 else if (0 == grub_strcmp(args
[1], "ne"))
1341 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1343 else if (0 == grub_strcmp(args
[1], "gt"))
1345 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1347 else if (0 == grub_strcmp(args
[1], "lt"))
1349 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1351 else if (0 == grub_strcmp(args
[1], "ge"))
1353 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1355 else if (0 == grub_strcmp(args
[1], "le"))
1357 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1361 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1367 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1370 char buf
[128] = {0};
1374 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1377 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1378 pos
= grub_strstr(buf
, ",");
1384 grub_env_set(args
[1], buf
);
1386 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1389 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1395 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1401 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1404 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1406 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1407 if (0 == grub_script_execute_sourcecode(buf
))
1409 debug("file %s exist, ventoy_compatible YES\n", buf
);
1410 grub_env_set("ventoy_compatible", "YES");
1411 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1415 debug("file %s NOT exist\n", buf
);
1419 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1420 pos
= grub_strstr(buf
, ")");
1426 disk
= grub_disk_open(buf
);
1429 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1430 grub_disk_close(disk
);
1432 g_img_swap_tmp_buf
[703] = 0;
1433 for (i
= 318; i
< 703; i
++)
1435 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1436 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1438 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1439 grub_env_set("ventoy_compatible", "YES");
1440 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1446 debug("failed to open disk <%s>\n", buf
);
1449 grub_env_set("ventoy_compatible", "NO");
1450 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1453 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1459 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1461 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1464 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1469 if (0 == g_sort_case_sensitive
)
1471 if (grub_islower(c1
))
1473 c1
= c1
- 'a' + 'A';
1476 if (grub_islower(c2
))
1478 c2
= c2
- 'a' + 'A';
1491 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1497 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1499 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1502 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1507 if (0 == g_sort_case_sensitive
)
1509 if (grub_islower(c1
))
1511 c1
= c1
- 'a' + 'A';
1514 if (grub_islower(c2
))
1516 c2
= c2
- 'a' + 'A';
1529 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1531 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1533 grub_memcpy(img1
, img2
, sizeof(img_info
));
1534 img1
->next
= g_img_swap_tmp
.next
;
1535 img1
->prev
= g_img_swap_tmp
.prev
;
1537 g_img_swap_tmp
.next
= img2
->next
;
1538 g_img_swap_tmp
.prev
= img2
->prev
;
1539 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1542 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1546 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1554 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1563 img_iterator_node
*tmp
;
1564 img_iterator_node
*new_node
;
1565 img_iterator_node
*node
= (img_iterator_node
*)data
;
1567 if (g_enumerate_time_checked
== 0)
1569 g_enumerate_finish_time_ms
= grub_get_time_ms();
1570 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1573 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1575 g_enumerate_time_checked
= 1;
1579 len
= grub_strlen(filename
);
1583 if (node
->level
+ 1 > g_img_max_search_level
)
1588 if ((len
== 1 && filename
[0] == '.') ||
1589 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1594 if (!ventoy_img_name_valid(filename
, len
))
1599 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1604 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1606 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1607 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1610 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1615 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1618 new_node
->level
= node
->level
+ 1;
1619 new_node
->plugin_list_index
= index
;
1620 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1622 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1625 debug("Directory %s ignored...\n", new_node
->dir
);
1626 grub_free(new_node
);
1630 new_node
->tail
= node
->tail
;
1632 new_node
->parent
= node
;
1633 if (!node
->firstchild
)
1635 node
->firstchild
= new_node
;
1638 if (g_img_iterator_tail
)
1640 g_img_iterator_tail
->next
= new_node
;
1641 g_img_iterator_tail
= new_node
;
1645 g_img_iterator_head
.next
= new_node
;
1646 g_img_iterator_tail
= new_node
;
1652 debug("Find a file %s\n", filename
);
1658 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1660 type
= img_type_iso
;
1662 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1664 type
= img_type_wim
;
1666 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1667 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1669 type
= img_type_vhd
;
1671 #ifdef GRUB_MACHINE_EFI
1672 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1674 type
= img_type_efi
;
1677 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1679 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1681 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1682 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1687 type
= img_type_img
;
1689 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1691 type
= img_type_vtoy
;
1693 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1695 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1697 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1698 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1707 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1712 if (g_plugin_image_list
)
1714 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1715 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1716 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1718 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1721 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1723 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1728 img
= grub_zalloc(sizeof(img_info
));
1732 img
->plugin_list_index
= index
;
1733 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1735 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1737 img
->size
= info
->size
;
1740 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1743 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1745 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1750 if (g_ventoy_img_list
)
1752 tail
= *(node
->tail
);
1758 g_ventoy_img_list
= img
;
1761 img
->id
= g_ventoy_img_count
;
1763 if (node
&& NULL
== node
->firstiso
)
1765 node
->firstiso
= img
;
1776 *((img_info
**)(node
->tail
)) = img
;
1777 g_ventoy_img_count
++;
1779 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1780 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1783 img
->class = g_menu_class
[type
];
1785 img
->menu_prefix
= g_menu_prefix
[type
];
1787 if (img_type_iso
== type
)
1789 if (ventoy_plugin_check_memdisk(img
->path
))
1791 img
->menu_prefix
= "miso";
1795 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1802 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1804 int len
= GRUB_UINT_MAX
;
1805 const char *value
= NULL
;
1806 char name
[32] = {0};
1807 char plat
[32] = {0};
1808 char guidstr
[32] = {0};
1809 ventoy_guid guid
= VENTOY_GUID
;
1810 const char *fmt1
= NULL
;
1811 const char *fmt2
= NULL
;
1812 const char *fmt3
= NULL
;
1813 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1814 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1815 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1816 const char fmtcode
[]={
1817 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1818 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1819 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1820 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1821 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1822 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1825 grub_memset(name
, 0, sizeof(name
));
1826 puint
[0] = grub_swap_bytes32(0x56454e54);
1827 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1828 puint
[2] = grub_swap_bytes32(0x45525349);
1829 puint
[1] = grub_swap_bytes32(0x4f595f56);
1830 value
= ventoy_get_env(name
);
1832 grub_memset(name
, 0, sizeof(name
));
1833 puint
[1] = grub_swap_bytes32(0x5f544f50);
1834 puint
[0] = grub_swap_bytes32(0x56544c45);
1835 fmt1
= ventoy_get_env(name
);
1841 grub_memset(name
, 0, sizeof(name
));
1842 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1843 puint
[0] = grub_swap_bytes32(0x56544c45);
1844 fmt2
= ventoy_get_env(name
);
1846 grub_memset(name
, 0, sizeof(name
));
1847 puint
[1] = grub_swap_bytes32(0x5f434c52);
1848 puint
[0] = grub_swap_bytes32(0x56544c45);
1849 fmt3
= ventoy_get_env(name
);
1851 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1853 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1855 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1856 #pragma GCC diagnostic push
1857 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1858 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1859 fmt1
? fmt1
: fmtdata
,
1860 fmt2
? fmt2
: fmtdata
+ 4,
1861 value
? value
: "", plat
, guidstr
,
1862 fmt3
? fmt3
: fmtdata
+ 6);
1863 #pragma GCC diagnostic pop
1865 grub_memset(name
, 0, sizeof(name
));
1866 puint
[0] = grub_swap_bytes32(0x76746f79);
1867 puint
[2] = grub_swap_bytes32(0x656e7365);
1868 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1869 ventoy_set_env(name
, guidstr
);
1874 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1878 grub_uint8_t md5
[16];
1882 grub_memset(input
, 0, sizeof(input
));
1884 grub_printf("Enter password: ");
1887 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1889 grub_password_get(input
, 128);
1890 if (grub_strcmp(pwd
->text
, input
) == 0)
1895 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1897 grub_password_get(input
, 128);
1898 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1899 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1904 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1906 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1907 grub_password_get(input
+ offset
, 128);
1909 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1910 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1916 grub_printf("Invalid password!\n\n");
1923 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1925 img_info
*minimg
= NULL
;
1926 img_info
*img
= (img_info
*)(node
->firstiso
);
1928 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1930 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1945 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1947 img_iterator_node
*Minchild
= NULL
;
1948 img_iterator_node
*child
= node
->firstchild
;
1950 while (child
&& child
->parent
== node
)
1952 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1956 child
= child
->next
;
1961 Minchild
->select
= 1;
1967 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1970 img_info
*img
= NULL
;
1971 const char *dir_class
= NULL
;
1972 const char *dir_alias
= NULL
;
1973 img_iterator_node
*child
= NULL
;
1975 if (node
->isocnt
== 0 || node
->done
== 1)
1980 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1982 offset
= node
->parent
->dirlen
;
1985 if (node
== &g_img_iterator_head
)
1987 if (g_default_menu_mode
== 0)
1989 if (g_tree_view_menu_style
== 0)
1991 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1992 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1993 " echo 'return ...' \n"
1998 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1999 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2007 node
->dir
[node
->dirlen
- 1] = 0;
2008 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2011 dir_class
= "vtoydir";
2014 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2017 if (g_tree_view_menu_style
== 0)
2019 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2020 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2021 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2025 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2026 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2027 dir_alias
, dir_class
, node
->dir
+ offset
);
2032 dir_alias
= node
->dir
+ offset
;
2034 if (g_tree_view_menu_style
== 0)
2036 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2037 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2038 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2042 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2043 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2044 dir_alias
, dir_class
, node
->dir
+ offset
);
2048 if (g_tree_view_menu_style
== 0)
2050 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2051 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2052 " echo 'return ...' \n"
2057 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2058 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2064 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2066 ventoy_dynamic_tree_menu(child
);
2069 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2071 if (g_tree_view_menu_style
== 0)
2073 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2074 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2077 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2078 img
->unsupport
? "[***********] " : "",
2079 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2081 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2085 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2086 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2089 img
->unsupport
? "[***********] " : "",
2090 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2092 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2096 if (node
!= &g_img_iterator_head
)
2098 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2105 static int ventoy_set_default_menu(void)
2111 const char *strdata
= NULL
;
2112 img_info
*cur
= NULL
;
2113 img_info
*default_node
= NULL
;
2114 const char *default_image
= NULL
;
2116 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2117 if (default_image
&& default_image
[0] == '/')
2119 img_len
= grub_strlen(default_image
);
2121 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2123 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2135 if (0 == g_default_menu_mode
)
2137 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
2141 def
= grub_strdup(default_image
);
2147 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2149 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2150 if (strdata
&& strdata
[0] == '/')
2152 pos
= def
+ grub_strlen(strdata
);
2163 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2166 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2170 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
2178 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2180 img_info
*next
= NULL
;
2181 img_info
*cur
= g_ventoy_img_list
;
2194 g_ventoy_img_list
= NULL
;
2195 g_ventoy_img_count
= 0;
2197 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2200 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2203 img_info
*cur
= g_ventoy_img_list
;
2207 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2209 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2212 img_id
= grub_strtol(args
[0], NULL
, 10);
2213 if (img_id
>= g_ventoy_img_count
)
2215 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2218 debug("Find image %ld name \n", img_id
);
2220 while (cur
&& img_id
> 0)
2228 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2231 debug("image name is %s\n", cur
->name
);
2233 grub_env_set(args
[1], cur
->name
);
2235 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2238 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2242 img_info
*cur
= g_ventoy_img_list
;
2248 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2251 len
= (int)grub_strlen(args
[0]);
2255 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2264 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2267 grub_snprintf(id
, sizeof(id
), "VID_%d", cur
->id
);
2268 grub_env_set("chosen", id
);
2269 grub_env_export("chosen");
2271 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2274 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2279 const char *id
= NULL
;
2280 img_info
*cur
= g_ventoy_img_list
;
2284 if (argc
< 1 || argc
> 2)
2286 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2289 id
= grub_env_get("chosen");
2291 pos
= grub_strstr(id
, "VID_");
2294 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2298 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2303 if (img_id
== cur
->id
)
2312 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2315 grub_env_set(args
[0], cur
->path
);
2319 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2320 grub_env_set(args
[1], value
);
2323 g_svd_replace_offset
= 0;
2325 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2329 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2333 grub_device_t dev
= NULL
;
2334 img_info
*cur
= NULL
;
2335 img_info
*tail
= NULL
;
2336 const char *strdata
= NULL
;
2337 char *device_name
= NULL
;
2339 img_iterator_node
*node
= NULL
;
2340 img_iterator_node
*tmp
= NULL
;
2346 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2349 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2351 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2356 g_enumerate_time_checked
= 0;
2357 g_enumerate_start_time_ms
= grub_get_time_ms();
2359 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2360 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2362 g_filt_dot_underscore_file
= 1;
2365 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2366 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2368 g_sort_case_sensitive
= 1;
2371 device_name
= grub_file_get_device_name(args
[0]);
2377 g_enum_dev
= dev
= grub_device_open(device_name
);
2383 g_enum_fs
= fs
= grub_fs_probe(dev
);
2389 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2391 debug("unsupported fs:<%s>\n", fs
->name
);
2392 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2396 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2398 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2399 if (strdata
&& strdata
[0] == '1')
2401 g_default_menu_mode
= 1;
2404 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2406 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2408 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2409 if (strdata
&& strdata
[0] == '/')
2411 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2412 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2414 g_img_iterator_head
.dir
[len
++] = '/';
2416 g_img_iterator_head
.dirlen
= len
;
2420 g_img_iterator_head
.dirlen
= 1;
2421 grub_strcpy(g_img_iterator_head
.dir
, "/");
2424 g_img_iterator_head
.tail
= &tail
;
2426 if (g_img_max_search_level
< 0)
2428 g_img_max_search_level
= GRUB_INT_MAX
;
2429 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2430 if (strdata
&& ventoy_is_decimal(strdata
))
2432 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2436 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2437 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2438 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2439 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2440 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2441 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2443 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2445 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2448 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2449 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2451 g_tree_view_menu_style
= 1;
2454 ventoy_set_default_menu();
2456 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2458 ventoy_dynamic_tree_menu(node
);
2462 node
= g_img_iterator_head
.next
;
2470 /* sort image list by image name */
2471 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2473 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2475 if (ventoy_cmp_img(cur
, tail
) > 0)
2477 ventoy_swap_img(cur
, tail
);
2482 if (g_default_menu_mode
== 1)
2484 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2485 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2486 " echo 'return ...' \n"
2490 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2492 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2493 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2496 cur
->unsupport
? "[***********] " : "",
2497 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2499 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2502 g_tree_script_buf
[g_tree_script_pos
] = 0;
2503 g_list_script_buf
[g_list_script_pos
] = 0;
2505 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2506 grub_env_set(args
[1], buf
);
2510 check_free(device_name
, grub_free
);
2511 check_free(dev
, grub_device_close
);
2513 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2516 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2523 device_name
= grub_file_get_device_name(filename
);
2535 pos2
= grub_strstr(pos
, ",");
2538 pos2
= grub_strstr(pos
, ")");
2546 disk
= grub_disk_open(pos
);
2549 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2550 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2551 grub_disk_close(disk
);
2558 grub_free(device_name
);
2562 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2564 eltorito_descriptor desc
;
2566 grub_memset(&desc
, 0, sizeof(desc
));
2567 grub_file_seek(file
, 17 * 2048);
2568 grub_file_read(file
, &desc
, sizeof(desc
));
2570 if (desc
.type
!= 0 || desc
.version
!= 1)
2575 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2576 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2584 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2588 grub_uint8_t buf
[512];
2589 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2591 grub_file_seek(file
, sector
* 2048);
2592 grub_file_read(file
, buf
, sizeof(buf
));
2594 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2596 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2600 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2605 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2607 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2609 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2613 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2615 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2620 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2622 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2624 if (buf
[36] == parttype
[i
])
2626 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2632 debug("%s does not contain efi eltorito\n", file
->name
);
2636 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2639 const char *fs
= NULL
;
2640 const char *cdprompt
= NULL
;
2642 grub_uint8_t chksum
= 0;
2645 disk
= file
->device
->disk
;
2646 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2648 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2649 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2650 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2652 pos
= grub_strstr(file
->name
, "/");
2658 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2660 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2662 param
->vtoy_img_size
= file
->size
;
2664 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2665 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2667 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2669 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2670 param
->vtoy_reserved
[4] = 0;
2671 if (g_ventoy_chain_type
== 1) /* Windows */
2673 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2674 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2676 param
->vtoy_reserved
[4] = 1;
2680 fs
= ventoy_get_env("ventoy_fs_probe");
2681 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2683 param
->vtoy_reserved
[3] = 1;
2686 /* calculate checksum */
2687 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2689 chksum
+= *((grub_uint8_t
*)param
+ i
);
2691 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2696 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2698 grub_uint32_t i
= 0;
2699 grub_uint64_t total
= 0;
2700 grub_uint64_t fileblk
= 0;
2701 ventoy_img_chunk
*chunk
= NULL
;
2703 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2705 chunk
= chunklist
->chunk
+ i
;
2707 if (chunk
->disk_start_sector
<= start
)
2709 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2713 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2716 fileblk
= (file
->size
+ 511) / 512;
2718 if (total
!= fileblk
)
2720 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2721 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2723 debug("maybe img file to be processed.\n");
2733 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2737 grub_uint32_t i
= 0;
2738 grub_uint32_t sector
= 0;
2739 grub_uint32_t count
= 0;
2740 grub_off_t size
= 0;
2741 grub_off_t read
= 0;
2743 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2744 if (fs_type
== ventoy_fs_exfat
)
2746 grub_fat_get_file_chunk(start
, file
, chunklist
);
2748 else if (fs_type
== ventoy_fs_ext
)
2750 grub_ext_get_file_chunk(start
, file
, chunklist
);
2754 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2755 file
->read_hook_data
= chunklist
;
2757 for (size
= file
->size
; size
> 0; size
-= read
)
2759 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2760 grub_file_read(file
, NULL
, read
);
2763 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2765 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2766 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2769 if (ventoy_fs_udf
== fs_type
)
2771 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2773 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2774 chunklist
->chunk
[i
].img_start_sector
= sector
;
2775 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2781 len
= (int)grub_strlen(file
->name
);
2782 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2783 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2784 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2785 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2787 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2789 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2799 chunklist
->chunk
[i
].img_start_sector
= sector
;
2800 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2808 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2812 grub_disk_addr_t start
;
2817 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2820 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2823 g_conf_replace_node
= NULL
;
2824 g_conf_replace_offset
= 0;
2826 if (g_img_chunk_list
.chunk
)
2828 grub_free(g_img_chunk_list
.chunk
);
2831 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2833 grub_file_close(file
);
2834 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2837 /* get image chunk data */
2838 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2839 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2840 if (NULL
== g_img_chunk_list
.chunk
)
2842 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2845 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2846 g_img_chunk_list
.cur_chunk
= 0;
2848 start
= file
->device
->disk
->partition
->start
;
2850 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2852 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2853 grub_file_close(file
);
2857 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2860 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2861 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2864 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2866 grub_uint64_t offset
= 0;
2867 grub_uint32_t align
= 0;
2868 grub_file_t file
= NULL
;
2869 conf_replace
*node
= NULL
;
2875 debug("select conf replace argc:%d\n", argc
);
2882 node
= ventoy_plugin_find_conf_replace(args
[1]);
2885 debug("Conf replace not found for %s\n", args
[1]);
2889 debug("Find conf replace for %s\n", args
[1]);
2891 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2894 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2898 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2899 grub_file_close(file
);
2901 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2904 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2908 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2910 if (align
> vtoy_max_replace_file_size
)
2912 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2916 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2917 g_conf_replace_new_len
= (int)file
->size
;
2918 g_conf_replace_new_len_align
= align
;
2920 g_conf_replace_node
= node
;
2921 g_conf_replace_offset
= offset
+ 2;
2923 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2928 grub_file_close(file
);
2930 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2933 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2938 char configfile
[128];
2939 install_template
*node
= NULL
;
2945 debug("select auto installation argc:%d\n", argc
);
2952 node
= ventoy_plugin_find_install_template(args
[0]);
2955 debug("Auto install template not found for %s\n", args
[0]);
2959 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2961 node
->cursel
= node
->autosel
- 1;
2962 debug("Auto install template auto select %d\n", node
->autosel
);
2966 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2972 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2973 " echo %s\n}\n", "123");
2975 for (i
= 0; i
< node
->templatenum
; i
++)
2977 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2979 node
->templatepath
[i
].path
);
2982 g_ventoy_menu_esc
= 1;
2983 g_ventoy_suppress_esc
= 1;
2985 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2986 grub_script_execute_sourcecode(configfile
);
2988 g_ventoy_menu_esc
= 0;
2989 g_ventoy_suppress_esc
= 0;
2993 node
->cursel
= g_ventoy_last_entry
- 1;
2995 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2998 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3003 char configfile
[128];
3004 persistence_config
*node
;
3010 debug("select persistence argc:%d\n", argc
);
3017 node
= ventoy_plugin_find_persistent(args
[0]);
3020 debug("Persistence image not found for %s\n", args
[0]);
3024 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3026 node
->cursel
= node
->autosel
- 1;
3027 debug("Persistence image auto select %d\n", node
->autosel
);
3031 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3037 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3038 " echo %s\n}\n", "123");
3040 for (i
= 0; i
< node
->backendnum
; i
++)
3042 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3044 node
->backendpath
[i
].path
);
3048 g_ventoy_menu_esc
= 1;
3049 g_ventoy_suppress_esc
= 1;
3051 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3052 grub_script_execute_sourcecode(configfile
);
3054 g_ventoy_menu_esc
= 0;
3055 g_ventoy_suppress_esc
= 0;
3059 node
->cursel
= g_ventoy_last_entry
- 1;
3061 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3064 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3067 ventoy_img_chunk
*cur
;
3073 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3075 cur
= g_img_chunk_list
.chunk
+ i
;
3076 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3077 cur
->img_start_sector
, cur
->img_end_sector
,
3078 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3082 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3085 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3089 ventoy_img_chunk_list chunklist
;
3094 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3097 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3100 /* get image chunk data */
3101 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3102 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3103 if (NULL
== chunklist
.chunk
)
3105 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3108 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3109 chunklist
.cur_chunk
= 0;
3111 ventoy_get_block_list(file
, &chunklist
, 0);
3113 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3115 grub_printf("########## UNSUPPORTED ###############\n");
3118 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3120 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3122 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3123 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3126 grub_printf("\n==================================\n");
3128 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3130 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3131 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3132 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3133 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3134 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3138 grub_free(chunklist
.chunk
);
3139 grub_file_close(file
);
3141 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3144 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3147 ventoy_grub_param_file_replace
*replace
= NULL
;
3155 replace
= &(g_grub_param
->file_replace
);
3156 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3158 replace
->old_name_cnt
= 0;
3159 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3161 replace
->old_name_cnt
++;
3162 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3165 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3168 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3171 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3174 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3180 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3181 grub_env_set(args
[0], buf
);
3184 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3187 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3195 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3196 grub_printf("%s", g_list_script_buf
);
3200 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3201 grub_printf("%s", g_tree_script_buf
);
3207 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3209 img_info
*cur
= g_ventoy_img_list
;
3217 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3218 grub_printf("name:<%s>\n\n", cur
->name
);
3225 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3231 ventoy_plugin_dump_injection();
3236 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3242 ventoy_plugin_dump_auto_install();
3247 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3253 ventoy_plugin_dump_persistence();
3258 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3269 if (args
[0][0] == '0')
3271 return g_ventoy_memdisk_mode
? 0 : 1;
3273 else if (args
[0][0] == '1')
3275 return g_ventoy_iso_raw
? 0 : 1;
3277 else if (args
[0][0] == '2')
3279 return g_ventoy_iso_uefi_drv
? 0 : 1;
3281 else if (args
[0][0] == '3')
3283 return g_ventoy_grub2_mode
? 0 : 1;
3285 else if (args
[0][0] == '4')
3287 return g_ventoy_wimboot_mode
? 0 : 1;
3293 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3295 static int configfile_mode
= 0;
3296 char memfile
[128] = {0};
3303 * args[0]: 0:normal 1:configfile
3304 * args[1]: 0:list_buf 1:tree_buf
3309 debug("Invalid argc %d\n", argc
);
3315 if (args
[0][0] == '0')
3317 if (args
[1][0] == '0')
3319 grub_script_execute_sourcecode(g_list_script_buf
);
3323 grub_script_execute_sourcecode(g_tree_script_buf
);
3328 if (configfile_mode
)
3330 debug("Now already in F3 mode %d\n", configfile_mode
);
3334 if (args
[1][0] == '0')
3336 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3337 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3341 g_ventoy_last_entry
= -1;
3342 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3343 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3346 configfile_mode
= 1;
3347 grub_script_execute_sourcecode(memfile
);
3348 configfile_mode
= 0;
3354 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3365 g_ventoy_case_insensitive
= 1;
3366 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3367 g_ventoy_case_insensitive
= 0;
3373 grub_file_close(file
);
3379 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3384 const char *isopath
= NULL
;
3386 ventoy_mbr_head mbr
;
3393 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3396 isopath
= grub_env_get("vtoy_iso_part");
3399 debug("isopath is null %p\n", isopath
);
3403 debug("isopath is %s\n", isopath
);
3405 for (id
= 0; id
< 30 && (find
== 0); id
++)
3407 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3408 if (grub_strstr(isopath
, hdname
))
3410 debug("skip %s ...\n", hdname
);
3414 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3416 disk
= grub_disk_open(hdname
);
3419 debug("%s not exist\n", hdname
);
3423 grub_memset(&mbr
, 0, sizeof(mbr
));
3424 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3426 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3428 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3429 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3432 grub_env_set(args
[0], hdname
);
3436 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3440 debug("read %s failed\n", hdname
);
3443 grub_disk_close(disk
);
3449 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3460 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3463 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3466 debug("failed to open file %s\n", args
[0]);
3470 buf
= grub_malloc(len
);
3477 grub_file_read(file
, buf
, len
- 1);
3479 ventoy_get_line(buf
);
3480 ventoy_set_env(args
[1], buf
);
3484 grub_check_free(buf
);
3485 grub_file_close(file
);
3490 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3495 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3496 "0 %llu linear /dev/ventoy %llu\n",
3497 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3502 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3504 char *device_name
= NULL
;
3505 grub_device_t dev
= NULL
;
3510 g_part_list_pos
= 0;
3511 grub_env_unset("vtoy_img_part_file");
3518 device_name
= grub_file_get_device_name(args
[0]);
3521 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3525 dev
= grub_device_open(device_name
);
3528 debug("grub_device_open failed, %s\n", device_name
);
3532 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3534 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3535 grub_env_set("vtoy_img_part_file", buf
);
3539 check_free(device_name
, grub_free
);
3540 check_free(dev
, grub_device_close
);
3546 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3557 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3560 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3563 debug("failed to open file %s\n", args
[0]);
3567 buf
= grub_malloc(file
->size
+ 1);
3573 buf
[file
->size
] = 0;
3574 grub_file_read(file
, buf
, file
->size
);
3576 if (grub_strstr(buf
, args
[1]))
3583 grub_check_free(buf
);
3584 grub_file_close(file
);
3589 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3595 ventoy_iso9660_vd pvd
;
3602 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3605 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3608 debug("failed to open file %s\n", args
[0]);
3612 grub_file_seek(file
, 16 * 2048);
3613 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3614 if (len
!= sizeof(pvd
))
3616 debug("failed to read pvd %d\n", len
);
3620 grub_memset(buf
, 0, sizeof(buf
));
3621 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3622 ventoy_set_env(args
[1], buf
);
3624 grub_memset(buf
, 0, sizeof(buf
));
3625 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3626 ventoy_set_env(args
[2], buf
);
3630 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3631 ventoy_set_env(args
[3], buf
);
3634 grub_file_close(file
);
3639 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3650 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3653 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3656 debug("failed to open file %s\n", args
[0]);
3660 grub_memset(buf
, 0, sizeof(buf
));
3661 grub_file_seek(file
, 16 * 2048 + 813);
3662 len
= (int)grub_file_read(file
, buf
, 17);
3665 debug("failed to read create date %d\n", len
);
3669 ventoy_set_env(args
[1], buf
);
3672 grub_file_close(file
);
3677 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3683 ventoy_env_hook_root(1);
3688 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3694 ventoy_env_hook_root(0);
3699 #ifdef GRUB_MACHINE_EFI
3700 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3705 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3711 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3712 if (var
&& *var
== 1)
3720 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3729 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3734 grub_uint64_t FileSectors
= 0;
3735 ventoy_gpt_info
*gpt
= NULL
;
3736 ventoy_part_table
*pt
= NULL
;
3737 grub_uint8_t zeroguid
[16] = {0};
3742 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3745 debug("failed to open file %s\n", args
[0]);
3749 if (file
->size
% 512)
3751 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3755 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3761 FileSectors
= file
->size
/ 512;
3763 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3764 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3766 debug("This is EFI partition table\n");
3768 for (i
= 0; i
< 128; i
++)
3770 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3772 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3774 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3775 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3783 debug("This is MBR partition table\n");
3785 for (i
= 0; i
< 4; i
++)
3787 pt
= gpt
->MBR
.PartTbl
+ i
;
3788 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3790 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3791 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3792 (ulonglong
)FileSectors
);
3801 grub_file_close(file
);
3802 grub_check_free(gpt
);
3803 grub_errno
= GRUB_ERR_NONE
;
3807 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3816 for (i
= 0; i
< 500; i
++)
3818 ret
= grub_getkey_noblock();
3819 if (ret
== GRUB_TERM_NO_KEY
)
3828 grub_printf("\n\n Still have key input after clear.\n");
3836 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3843 int image_sector_size
;
3845 ventoy_chain_head
*chain
;
3846 ventoy_img_chunk
*chunk
;
3847 ventoy_os_param
*osparam
;
3848 ventoy_image_location
*location
;
3849 ventoy_image_disk_region
*region
;
3850 struct grub_acpi_table_header
*acpi
;
3859 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3861 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3867 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3869 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3871 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3875 img_chunk_num
= chain
->img_chunk_num
;
3877 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3878 datalen
= sizeof(ventoy_os_param
) + loclen
;
3880 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3881 acpi
= grub_zalloc(buflen
);
3887 /* Step1: Fill acpi table header */
3888 grub_memcpy(acpi
->signature
, "VTOY", 4);
3889 acpi
->length
= buflen
;
3891 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3892 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3894 acpi
->creator_id
[0] = 1;
3895 acpi
->creator_rev
= 1;
3897 /* Step2: Fill data */
3898 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3899 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3900 osparam
->vtoy_img_location_addr
= 0;
3901 osparam
->vtoy_img_location_len
= loclen
;
3902 osparam
->chksum
= 0;
3903 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3905 location
= (ventoy_image_location
*)(osparam
+ 1);
3906 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3907 location
->image_sector_size
= image_sector_size
;
3908 location
->disk_sector_size
= chain
->disk_sector_size
;
3909 location
->region_count
= img_chunk_num
;
3911 region
= location
->regions
;
3912 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3913 if (512 == image_sector_size
)
3915 for (i
= 0; i
< img_chunk_num
; i
++)
3917 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3918 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3919 region
->disk_start_sector
= chunk
->disk_start_sector
;
3926 for (i
= 0; i
< img_chunk_num
; i
++)
3928 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3929 region
->image_start_sector
= chunk
->img_start_sector
;
3930 region
->disk_start_sector
= chunk
->disk_start_sector
;
3936 /* Step3: Fill acpi checksum */
3938 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3940 /* load acpi table */
3941 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3942 grub_script_execute_sourcecode(cmd
);
3946 VENTOY_CMD_RETURN(0);
3949 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3955 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3956 g_ventoy_last_entry
= -1;
3961 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3967 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3972 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3974 const char *pos
= filename
+ 1;
3982 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3984 grub_strncpy((char *)data
, filename
, 128);
3995 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3998 char *device_name
= NULL
;
3999 grub_device_t dev
= NULL
;
4000 grub_fs_t fs
= NULL
;
4001 char buf
[128] = {0};
4007 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4011 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4013 device_name
= grub_file_get_device_name(args
[0]);
4016 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4020 dev
= grub_device_open(device_name
);
4023 debug("grub_device_open failed, %s\n", device_name
);
4027 fs
= grub_fs_probe(dev
);
4030 debug("grub_fs_probe failed, %s\n", device_name
);
4034 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4038 ventoy_set_env(args
[2], buf
);
4045 check_free(device_name
, grub_free
);
4046 check_free(dev
, grub_device_close
);
4051 int ventoy_load_part_table(const char *diskname
)
4058 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4059 if (!g_ventoy_part_info
)
4064 disk
= grub_disk_open(diskname
);
4067 debug("Failed to open disk %s\n", diskname
);
4071 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4073 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4074 grub_disk_close(disk
);
4076 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4077 dev
= grub_device_open(name
);
4080 /* Check for official Ventoy device */
4081 ret
= ventoy_check_official_device(dev
);
4082 grub_device_close(dev
);
4090 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4091 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4096 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4103 ret
= ventoy_load_part_table(args
[0]);
4109 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4110 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4115 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4118 const char *vcfg
= NULL
;
4123 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4126 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4127 grub_env_set(args
[1], vcfg
);
4132 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4140 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4143 grub_uint8_t zeroguid
[16] = {0};
4148 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4151 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4153 if (id
>= 1 && id
<= 128)
4155 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4163 if (id
>= 1 && id
<= 4)
4165 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4175 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4178 char *device_name
= NULL
;
4179 grub_device_t dev
= NULL
;
4180 grub_fs_t fs
= NULL
;
4185 debug("get fs label for %s\n", args
[0]);
4189 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4193 device_name
= grub_file_get_device_name(args
[0]);
4196 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4200 dev
= grub_device_open(device_name
);
4203 debug("grub_device_open failed, %s\n", device_name
);
4207 fs
= grub_fs_probe(dev
);
4208 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4210 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4214 fs
->fs_label(dev
, &label
);
4217 debug("label=<%s>\n", label
);
4218 ventoy_set_env(args
[1], label
);
4226 check_free(device_name
, grub_free
);
4227 check_free(dev
, grub_device_close
);
4232 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4236 grub_snprintf((char *)data
, 256, "%s", filename
);
4243 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4245 if (info
->dir
&& filename
&& filename
[0] != '.')
4247 grub_snprintf((char *)data
, 256, "%s", filename
);
4254 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4257 char *device_name
= NULL
;
4258 grub_device_t dev
= NULL
;
4259 grub_fs_t fs
= NULL
;
4260 char name
[256] ={0};
4264 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4268 device_name
= grub_file_get_device_name(args
[0]);
4271 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4275 dev
= grub_device_open(device_name
);
4278 debug("grub_device_open failed, %s\n", device_name
);
4282 fs
= grub_fs_probe(dev
);
4285 debug("grub_fs_probe failed, %s\n", device_name
);
4289 fs
->fs_dir(dev
, args
[1], hook
, name
);
4292 ventoy_set_env(args
[2], name
);
4299 check_free(device_name
, grub_free
);
4300 check_free(dev
, grub_device_close
);
4305 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4308 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4311 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4314 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4317 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4327 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4331 for (pos
= args
[0]; *pos
; pos
++)
4345 grub_env_set(args
[1], args
[0]);
4355 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4365 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4370 len
= (int)grub_strlen(buf
);
4371 for (i
= len
; i
> 0; i
--)
4373 if (buf
[i
- 1] == '/')
4375 grub_env_set(args
[1], buf
+ i
);
4380 grub_env_set(args
[1], buf
);
4385 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4387 struct grub_video_mode_info info
;
4394 if (!g_video_mode_list
)
4396 ventoy_enum_video_mode();
4399 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4401 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4405 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4408 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4410 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4411 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4413 VENTOY_CMD_RETURN(0);
4416 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4418 struct grub_video_mode_info info
;
4425 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4427 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4431 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4434 grub_env_set(args
[0], buf
);
4436 VENTOY_CMD_RETURN(0);
4439 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4447 if (!g_video_mode_list
)
4452 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4453 if (id
< g_video_mode_num
)
4455 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4456 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4459 grub_env_set(args
[1], buf
);
4461 VENTOY_CMD_RETURN(0);
4464 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4467 grub_uint32_t loadsector
= 0;
4470 grub_uint32_t boot_catlog
= 0;
4471 grub_uint8_t buf
[512];
4477 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4481 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4484 debug("failed to open %s\n", args
[0]);
4488 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4489 if (boot_catlog
== 0)
4491 debug("No bootcatlog found\n");
4492 grub_file_close(file
);
4496 grub_memset(buf
, 0, sizeof(buf
));
4497 grub_file_seek(file
, boot_catlog
* 2048);
4498 grub_file_read(file
, buf
, sizeof(buf
));
4499 grub_file_close(file
);
4501 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4503 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4505 if (buf
[i
+ 32] == 0x88)
4507 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4508 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4514 if (loadsector
== 0)
4516 debug("No EFI eltorito info found\n");
4520 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4521 grub_env_set(args
[1], value
);
4522 VENTOY_CMD_RETURN(0);
4525 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4530 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4532 if (pfsdir
->initrd
[0])
4537 curpos
= pfsdir
->curpos
;
4538 len
= grub_strlen(filename
);
4542 if ((len
== 1 && filename
[0] == '.') ||
4543 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4548 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4551 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4552 pfsdir
->curpos
= curpos
+ printlen
;
4553 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4554 pfsdir
->curpos
= curpos
;
4555 pfsdir
->fullpath
[curpos
] = 0;
4559 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4562 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4563 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4565 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4567 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4576 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4580 char *device_name
= NULL
;
4581 grub_device_t dev
= NULL
;
4582 grub_fs_t fs
= NULL
;
4583 replace_fs_dir
*pfsdir
= NULL
;
4589 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4593 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4599 device_name
= grub_file_get_device_name(args
[0]);
4605 dev
= grub_device_open(device_name
);
4611 fs
= grub_fs_probe(dev
);
4620 pfsdir
->fullpath
[0] = '/';
4621 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4623 if (pfsdir
->initrd
[0])
4625 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4627 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4629 if (pfsdir
->initrd
[i
] == '/')
4631 pfsdir
->initrd
[i
] = '\\';
4635 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4636 grub_env_set(args
[1], pos
);
4640 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4645 grub_check_free(pfsdir
);
4646 grub_check_free(device_name
);
4647 check_free(dev
, grub_device_close
);
4649 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4652 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4654 const char *pager
= NULL
;
4660 pager
= grub_env_get("pager");
4664 grub_env_set("pager", "1");
4666 else if (pager
[0] == '1')
4672 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4674 grub_env_set("pager", "1");
4677 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4680 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4686 if (g_pager_flag
== 1)
4688 grub_env_unset("pager");
4690 else if (g_pager_flag
== 2)
4692 grub_env_set("pager", g_old_pager
);
4695 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4698 int ventoy_env_init(void)
4702 grub_env_set("vtdebug_flag", "");
4704 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4705 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4706 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4707 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4709 ventoy_filt_register(0, ventoy_wrapper_open
);
4711 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4714 g_grub_param
->grub_env_get
= grub_env_get
;
4715 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4716 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4717 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4718 grub_env_set("env_param", buf
);
4719 grub_env_set("ventoy_env_param", buf
);
4721 grub_env_export("env_param");
4722 grub_env_export("ventoy_env_param");
4725 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
4726 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
4728 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
4729 grub_env_set("vtoy_winpeshl_ini_size", buf
);
4731 grub_env_export("vtoy_winpeshl_ini_addr");
4732 grub_env_export("vtoy_winpeshl_ini_size");
4734 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
4735 grub_env_set("vtoy_chain_file_size", buf
);
4736 grub_env_export("vtoy_chain_file_size");
4738 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
4739 grub_env_set("vtoy_chain_file_read", buf
);
4740 grub_env_export("vtoy_chain_file_read");
4745 static cmd_para ventoy_cmds
[] =
4747 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4748 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4749 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4750 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4751 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4752 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4753 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4754 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4755 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4756 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4757 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4758 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4759 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4760 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4761 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4762 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4763 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4764 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4765 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4766 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4767 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4768 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4769 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4770 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4772 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4773 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4774 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4775 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4776 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4777 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4778 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4780 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4781 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4782 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4783 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4784 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
4785 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4786 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4787 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4788 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4789 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4792 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4793 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4794 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4795 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4796 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4797 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4798 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4799 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4800 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4801 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4802 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4804 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4805 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
4806 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4807 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4808 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4809 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4810 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4812 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4813 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4814 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4815 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4816 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4817 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4818 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4819 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4820 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4821 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4823 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4824 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4825 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
4826 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4827 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4828 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4829 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4830 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4831 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4833 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4834 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
4835 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4836 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4839 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4840 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4841 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4843 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4844 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4845 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4848 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4849 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4850 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4851 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4852 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
4853 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4854 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4855 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4856 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4857 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4858 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4860 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4861 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4862 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4863 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4864 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
4865 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
4866 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
4867 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
4868 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
4869 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
4871 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
4872 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
4873 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
4874 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
4877 int ventoy_register_all_cmd(void)
4880 cmd_para
*cur
= NULL
;
4882 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4884 cur
= ventoy_cmds
+ i
;
4885 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4886 cur
->summary
, cur
->description
, cur
->parser
);
4892 int ventoy_unregister_all_cmd(void)
4896 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4898 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);