1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 initrd_info
*g_initrd_img_list
= NULL
;
55 initrd_info
*g_initrd_img_tail
= NULL
;
56 int g_initrd_img_count
= 0;
57 int g_valid_initrd_count
= 0;
58 int g_default_menu_mode
= 0;
59 int g_filt_dot_underscore_file
= 0;
60 int g_sort_case_sensitive
= 0;
61 int g_tree_view_menu_style
= 0;
62 static grub_file_t g_old_file
;
63 static int g_ventoy_last_entry_back
;
66 char g_img_swap_tmp_buf
[1024];
67 img_info g_img_swap_tmp
;
68 img_info
*g_ventoy_img_list
= NULL
;
70 int g_ventoy_img_count
= 0;
72 grub_device_t g_enum_dev
= NULL
;
73 grub_fs_t g_enum_fs
= NULL
;
74 int g_img_max_search_level
= -1;
75 img_iterator_node g_img_iterator_head
;
76 img_iterator_node
*g_img_iterator_tail
= NULL
;
78 grub_uint8_t g_ventoy_break_level
= 0;
79 grub_uint8_t g_ventoy_debug_level
= 0;
80 grub_uint8_t g_ventoy_chain_type
= 0;
82 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
83 grub_uint32_t g_ventoy_cpio_size
= 0;
84 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
85 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
87 int g_plugin_image_list
= 0;
89 ventoy_grub_param
*g_grub_param
= NULL
;
91 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
93 ventoy_img_chunk_list g_img_chunk_list
;
95 int g_wimboot_enable
= 0;
96 ventoy_img_chunk_list g_wimiso_chunk_list
;
97 char *g_wimiso_path
= NULL
;
99 int g_vhdboot_enable
= 0;
101 grub_uint64_t g_conf_replace_offset
= 0;
102 grub_uint64_t g_svd_replace_offset
= 0;
103 conf_replace
*g_conf_replace_node
= NULL
;
104 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
105 int g_conf_replace_new_len
= 0;
106 int g_conf_replace_new_len_align
= 0;
108 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
109 grub_uint64_t g_ventoy_disk_size
= 0;
110 grub_uint64_t g_ventoy_disk_part_size
[2];
112 static char *g_tree_script_buf
= NULL
;
113 static int g_tree_script_pos
= 0;
115 static char *g_list_script_buf
= NULL
;
116 static int g_list_script_pos
= 0;
118 static char *g_part_list_buf
= NULL
;
119 static int g_part_list_pos
= 0;
121 static int g_video_mode_max
= 0;
122 static int g_video_mode_num
= 0;
123 static ventoy_video_mode
*g_video_mode_list
= NULL
;
125 static int g_enumerate_time_checked
= 0;
126 static grub_uint64_t g_enumerate_start_time_ms
;
127 static grub_uint64_t g_enumerate_finish_time_ms
;
128 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
130 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
132 static const char *g_menu_class
[] =
134 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
137 const char *g_menu_prefix
[img_type_max
] =
139 "iso", "wim", "efi", "img", "vhd", "vtoy"
142 static int g_vtoy_load_prompt
= 0;
143 static char g_vtoy_prompt_msg
[64];
145 static int ventoy_get_fs_type(const char *fs
)
149 return ventoy_fs_max
;
151 else if (grub_strncmp(fs
, "exfat", 5) == 0)
153 return ventoy_fs_exfat
;
155 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
157 return ventoy_fs_ntfs
;
159 else if (grub_strncmp(fs
, "ext", 3) == 0)
161 return ventoy_fs_ext
;
163 else if (grub_strncmp(fs
, "xfs", 3) == 0)
165 return ventoy_fs_xfs
;
167 else if (grub_strncmp(fs
, "udf", 3) == 0)
169 return ventoy_fs_udf
;
171 else if (grub_strncmp(fs
, "fat", 3) == 0)
173 return ventoy_fs_fat
;
176 return ventoy_fs_max
;
179 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
198 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
200 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
204 static int ventoy_control_get_flag(const char *key
)
206 const char *val
= ventoy_get_env(key
);
208 if (val
&& val
[0] == '1' && val
[1] == 0)
215 static grub_err_t
ventoy_fs_close(grub_file_t file
)
217 grub_file_close(g_old_file
);
218 grub_free(file
->data
);
226 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
232 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
237 for (i
= 0; i
< g_video_mode_num
; i
++)
239 if (g_video_mode_list
[i
].width
== info
->width
&&
240 g_video_mode_list
[i
].height
== info
->height
&&
241 g_video_mode_list
[i
].bpp
== info
->bpp
)
247 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
248 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
249 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
252 if (g_video_mode_num
== g_video_mode_max
)
254 g_video_mode_max
*= 2;
255 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
261 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
263 if (v1
->bpp
== v2
->bpp
)
265 if (v1
->width
== v2
->width
)
267 if (v1
->height
== v2
->height
)
273 return (v1
->height
< v2
->height
) ? -1 : 1;
278 return (v1
->width
< v2
->width
) ? -1 : 1;
283 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
287 static int ventoy_enum_video_mode(void)
290 grub_video_adapter_t adapter
;
291 grub_video_driver_id_t id
;
292 ventoy_video_mode mode
;
294 g_video_mode_num
= 0;
295 g_video_mode_max
= 1024;
296 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
297 if (!g_video_mode_list
)
302 #ifdef GRUB_MACHINE_PCBIOS
303 grub_dl_load ("vbe");
306 id
= grub_video_get_driver_id ();
308 FOR_VIDEO_ADAPTERS (adapter
)
310 if (!adapter
->iterate
||
311 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
312 adapter
->init() != GRUB_ERR_NONE
)))
317 adapter
->iterate(ventoy_video_hook
, NULL
);
319 if (adapter
->id
!= id
)
325 /* sort video mode */
326 for (i
= 0; i
< g_video_mode_num
; i
++)
327 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
329 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
331 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
332 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
333 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
337 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
340 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
344 static struct grub_fs vtoy_fs
=
349 .fs_read
= ventoy_fs_read
,
350 .fs_close
= ventoy_fs_close
,
360 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
366 file
->data
= grub_malloc(rawFile
->size
+ 4096);
372 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
373 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
375 g_old_file
= rawFile
;
377 file
->size
= rawFile
->size
+ len
;
378 file
->device
= rawFile
->device
;
380 file
->not_easily_seekable
= 1;
385 static int ventoy_check_decimal_var(const char *name
, long *value
)
387 const char *value_str
= NULL
;
389 value_str
= grub_env_get(name
);
390 if (NULL
== value_str
)
392 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
395 if (!ventoy_is_decimal(value_str
))
397 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
400 *value
= grub_strtol(value_str
, NULL
, 10);
402 return GRUB_ERR_NONE
;
405 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
407 grub_uint64_t sectors
;
409 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
411 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
415 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
418 return sectors
* 512;
421 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
427 grub_uint32_t offset
;
429 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
432 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
436 len
= (int)file
->size
;
438 data
= (char *)grub_malloc(file
->size
);
444 grub_file_read(file
, data
, file
->size
);
445 grub_file_close(file
);
447 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
448 grub_script_execute_sourcecode(exec
);
450 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
451 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
452 grub_file_close(file
);
454 grub_script_execute_sourcecode("loopback -d efiboot");
458 *direntoff
= offset
+ 2;
463 static int ventoy_set_check_result(int ret
)
467 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
468 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
469 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
473 grub_printf(VTOY_WARNING
"\n");
474 grub_printf(VTOY_WARNING
"\n");
475 grub_printf(VTOY_WARNING
"\n\n\n");
477 grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret
);
478 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
480 grub_printf("\n\nWill exit after 10 seconds ...... ");
488 static int ventoy_check_official_device(grub_device_t dev
)
492 grub_uint64_t offset
;
497 struct grub_partition
*partition
;
499 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
501 return ventoy_set_check_result(1 | 0x1000);
504 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
505 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
506 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
508 #ifndef GRUB_MACHINE_EFI
509 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
510 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
511 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
513 return ventoy_set_check_result(2 | 0x1000);
522 /* We must have partition 2 */
525 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
529 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
533 return ventoy_set_check_result(3 | 0x1000);
536 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
538 grub_file_close(file
);
539 return ventoy_set_check_result(4 | 0x1000);
542 partition
= dev
->disk
->partition
;
543 if (partition
->number
!= 0 || partition
->start
!= 2048)
545 return ventoy_set_check_result(5);
550 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
552 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
553 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
554 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
556 grub_file_close(file
);
557 return ventoy_set_check_result(6);
562 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
563 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
564 PartTbl
[1].SectorCount
!= 65536)
566 grub_file_close(file
);
567 return ventoy_set_check_result(6);
573 offset
= partition
->start
+ partition
->len
;
574 partition
= file
->device
->disk
->partition
;
575 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
577 grub_file_close(file
);
578 return ventoy_set_check_result(7);
582 grub_file_close(file
);
586 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
587 dev2
= grub_device_open(devname
);
590 return ventoy_set_check_result(8);
593 fs
= grub_fs_probe(dev2
);
596 grub_device_close(dev2
);
597 return ventoy_set_check_result(9);
600 fs
->fs_label(dev2
, &label
);
601 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
603 grub_device_close(dev2
);
604 return ventoy_set_check_result(10);
607 grub_device_close(dev2
);
610 return ventoy_set_check_result(0);
613 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
617 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
627 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
629 grub_uint64_t size
= 0;
632 char fullpath
[256] = {0};
635 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
638 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
641 debug("grub_file_open failed <%s>\n", fullpath
);
647 grub_file_close(file
);
651 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
655 char fullpath
[256] = {0};
658 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
661 file
= grub_file_open(fullpath
, type
);
664 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
671 int ventoy_is_file_exist(const char *fmt
, ...)
678 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
682 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
685 grub_strncpy(pos
+ len
, "\" ]", 3);
687 debug("script exec %s\n", buf
);
689 if (0 == grub_script_execute_sourcecode(buf
))
697 int ventoy_is_dir_exist(const char *fmt
, ...)
704 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
708 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
711 grub_strncpy(pos
+ len
, "\" ]", 3);
713 debug("script exec %s\n", buf
);
715 if (0 == grub_script_execute_sourcecode(buf
))
723 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
726 grub_uint8_t
*outbuf
;
727 grub_uint8_t gzHdr
[10] =
729 0x1F, 0x8B, /* magic */
737 grub_memset(&s
, 0, sizeof(mz_stream
));
739 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
741 outbuf
= (grub_uint8_t
*)mem_out
;
743 mem_out_len
-= sizeof(gzHdr
) + 8;
744 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
745 outbuf
+= sizeof(gzHdr
);
747 s
.avail_in
= mem_in_len
;
750 s
.avail_out
= mem_out_len
;
753 mz_deflate(&s
, MZ_FINISH
);
757 outbuf
+= s
.total_out
;
758 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
759 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
761 return s
.total_out
+ sizeof(gzHdr
) + 8;
769 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
773 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
776 if (0 == grub_strcmp(args
[0], "on"))
779 grub_env_set("vtdebug_flag", "debug");
784 grub_env_set("vtdebug_flag", "");
787 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
790 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
794 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
796 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
797 grub_printf(" level:\r\n");
798 grub_printf(" 01/11: busybox / (+cat log)\r\n");
799 grub_printf(" 02/12: initrd / (+cat log)\r\n");
800 grub_printf(" 03/13: hook / (+cat log)\r\n");
802 grub_printf(" debug:\r\n");
803 grub_printf(" 0: debug is off\r\n");
804 grub_printf(" 1: debug is on\r\n");
806 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
809 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
811 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
813 g_ventoy_debug_level
= 1;
816 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
819 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
828 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
831 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
863 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
868 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
870 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
873 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
878 value_long
+= grub_strtol(args
[1], NULL
, 10);
880 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
881 grub_env_set(args
[0], buf
);
883 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
886 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
888 ulonglong value1
= 0;
889 ulonglong value2
= 0;
894 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
897 value1
= grub_strtoull(args
[0], NULL
, 10);
898 value2
= grub_strtoull(args
[1], NULL
, 10);
900 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
901 grub_env_set(args
[2], buf
);
903 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
906 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
921 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
924 debug("failed to open file <%s> for udf check\n", args
[0]);
928 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
930 grub_env_set(args
[1], buf
);
932 grub_file_close(file
);
938 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
946 g_wimboot_enable
= 0;
947 grub_check_free(g_wimiso_path
);
948 grub_check_free(g_wimiso_chunk_list
.chunk
);
950 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
956 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
957 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
958 if (NULL
== g_wimiso_chunk_list
.chunk
)
960 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
963 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
964 g_wimiso_chunk_list
.cur_chunk
= 0;
966 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
968 g_wimboot_enable
= 1;
969 g_wimiso_path
= grub_strdup(args
[0]);
971 grub_file_close(file
);
976 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
986 ventoy_iso9660_override
*dirent
;
995 totlen
= sizeof(ventoy_chain_head
);
997 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
999 debug("failed to load efiboot template %d\n", len
);
1005 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1007 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1010 debug("failed to open file <%s>\n", args
[0]);
1014 totlen
+= ventoy_align_2k(file
->size
);
1016 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1017 dirent
->first_sector
= len
/ 2048;
1018 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1019 dirent
->size
= (grub_uint32_t
)file
->size
;
1020 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1022 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1024 #ifdef GRUB_MACHINE_EFI
1025 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1027 data
= (char *)grub_malloc(totlen
);
1030 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1032 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1033 grub_check_free(buf
);
1035 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1036 grub_file_close(file
);
1038 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1039 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1040 grub_env_set(name
, value
);
1042 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1043 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1044 grub_env_set(name
, value
);
1049 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1055 g_vtoy_load_prompt
= 0;
1056 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1058 if (argc
== 2 && args
[0][0] == '1')
1060 g_vtoy_load_prompt
= 1;
1061 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1064 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1067 int ventoy_need_prompt_load_file(void)
1069 return g_vtoy_load_prompt
;
1072 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1074 grub_uint64_t ro
= 0;
1075 grub_uint64_t div
= 0;
1076 grub_ssize_t left
= size
;
1077 char *cur
= (char *)buf
;
1079 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1082 while (left
>= VTOY_SIZE_2MB
)
1084 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1085 cur
+= VTOY_SIZE_2MB
;
1086 left
-= VTOY_SIZE_2MB
;
1088 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1089 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1095 grub_file_read(file
, cur
, left
);
1098 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1104 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1111 enum grub_file_type type
;
1122 if (grub_strcmp(args
[0], "nodecompress") == 0)
1124 type
= VENTOY_FILE_TYPE
;
1128 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1131 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1134 debug("failed to open file <%s>\n", args
[1]);
1138 #ifdef GRUB_MACHINE_EFI
1139 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1141 buf
= (char *)grub_malloc(file
->size
);
1146 grub_file_close(file
);
1150 if (g_vtoy_load_prompt
)
1152 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1156 grub_file_read(file
, buf
, file
->size
);
1159 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1160 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1161 grub_env_set(name
, value
);
1163 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1164 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1165 grub_env_set(name
, value
);
1167 grub_file_close(file
);
1173 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1191 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1194 debug("failed to open file <%s> for udf check\n", args
[0]);
1198 headlen
= sizeof(ventoy_chain_head
);
1200 #ifdef GRUB_MACHINE_EFI
1201 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1203 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1206 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1208 grub_file_read(file
, buf
+ headlen
, file
->size
);
1210 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1211 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1212 grub_env_set(name
, value
);
1214 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1215 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1216 grub_env_set(name
, value
);
1218 grub_file_close(file
);
1224 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1230 if (grub_iso9660_is_joliet())
1232 debug("This time has joliet process\n");
1241 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1250 if (args
[0][0] == '1')
1252 grub_iso9660_set_nojoliet(1);
1256 grub_iso9660_set_nojoliet(0);
1262 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1267 grub_uint8_t buf
[32];
1278 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1281 debug("failed to open file <%s> for udf check\n", args
[0]);
1285 for (i
= 16; i
< 32; i
++)
1287 grub_file_seek(file
, i
* 2048);
1288 grub_file_read(file
, buf
, sizeof(buf
));
1296 grub_file_seek(file
, i
* 2048);
1297 grub_file_read(file
, buf
, sizeof(buf
));
1299 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1302 grub_file_seek(file
, i
* 2048);
1303 grub_file_read(file
, buf
, sizeof(buf
));
1305 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1306 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1312 grub_file_close(file
);
1314 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1319 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1321 long value_long1
= 0;
1322 long value_long2
= 0;
1324 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1326 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1329 value_long1
= grub_strtol(args
[0], NULL
, 10);
1330 value_long2
= grub_strtol(args
[2], NULL
, 10);
1332 if (0 == grub_strcmp(args
[1], "eq"))
1334 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1336 else if (0 == grub_strcmp(args
[1], "ne"))
1338 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1340 else if (0 == grub_strcmp(args
[1], "gt"))
1342 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1344 else if (0 == grub_strcmp(args
[1], "lt"))
1346 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1348 else if (0 == grub_strcmp(args
[1], "ge"))
1350 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1352 else if (0 == grub_strcmp(args
[1], "le"))
1354 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1358 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1364 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1367 char buf
[128] = {0};
1371 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1374 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1375 pos
= grub_strstr(buf
, ",");
1381 grub_env_set(args
[1], buf
);
1383 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1386 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1392 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1398 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1401 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1403 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1404 if (0 == grub_script_execute_sourcecode(buf
))
1406 debug("file %s exist, ventoy_compatible YES\n", buf
);
1407 grub_env_set("ventoy_compatible", "YES");
1408 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1412 debug("file %s NOT exist\n", buf
);
1416 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1417 pos
= grub_strstr(buf
, ")");
1423 disk
= grub_disk_open(buf
);
1426 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1427 grub_disk_close(disk
);
1429 g_img_swap_tmp_buf
[703] = 0;
1430 for (i
= 318; i
< 703; i
++)
1432 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1433 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1435 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1436 grub_env_set("ventoy_compatible", "YES");
1437 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1443 debug("failed to open disk <%s>\n", buf
);
1446 grub_env_set("ventoy_compatible", "NO");
1447 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1450 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1456 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1458 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1461 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1466 if (0 == g_sort_case_sensitive
)
1468 if (grub_islower(c1
))
1470 c1
= c1
- 'a' + 'A';
1473 if (grub_islower(c2
))
1475 c2
= c2
- 'a' + 'A';
1488 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1494 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1496 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1499 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1504 if (0 == g_sort_case_sensitive
)
1506 if (grub_islower(c1
))
1508 c1
= c1
- 'a' + 'A';
1511 if (grub_islower(c2
))
1513 c2
= c2
- 'a' + 'A';
1526 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1528 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1530 grub_memcpy(img1
, img2
, sizeof(img_info
));
1531 img1
->next
= g_img_swap_tmp
.next
;
1532 img1
->prev
= g_img_swap_tmp
.prev
;
1534 g_img_swap_tmp
.next
= img2
->next
;
1535 g_img_swap_tmp
.prev
= img2
->prev
;
1536 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1539 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1543 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1551 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1560 img_iterator_node
*tmp
;
1561 img_iterator_node
*new_node
;
1562 img_iterator_node
*node
= (img_iterator_node
*)data
;
1564 if (g_enumerate_time_checked
== 0)
1566 g_enumerate_finish_time_ms
= grub_get_time_ms();
1567 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1570 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1572 g_enumerate_time_checked
= 1;
1576 len
= grub_strlen(filename
);
1580 if (node
->level
+ 1 > g_img_max_search_level
)
1585 if ((len
== 1 && filename
[0] == '.') ||
1586 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1591 if (!ventoy_img_name_valid(filename
, len
))
1596 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1601 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1603 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1604 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1607 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1612 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1615 new_node
->level
= node
->level
+ 1;
1616 new_node
->plugin_list_index
= index
;
1617 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1619 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1622 debug("Directory %s ignored...\n", new_node
->dir
);
1623 grub_free(new_node
);
1627 new_node
->tail
= node
->tail
;
1629 new_node
->parent
= node
;
1630 if (!node
->firstchild
)
1632 node
->firstchild
= new_node
;
1635 if (g_img_iterator_tail
)
1637 g_img_iterator_tail
->next
= new_node
;
1638 g_img_iterator_tail
= new_node
;
1642 g_img_iterator_head
.next
= new_node
;
1643 g_img_iterator_tail
= new_node
;
1649 debug("Find a file %s\n", filename
);
1655 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1657 type
= img_type_iso
;
1659 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1661 type
= img_type_wim
;
1663 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1664 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1666 type
= img_type_vhd
;
1668 #ifdef GRUB_MACHINE_EFI
1669 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1671 type
= img_type_efi
;
1674 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1676 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1678 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1679 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1684 type
= img_type_img
;
1686 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1688 type
= img_type_vtoy
;
1690 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1692 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1694 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1695 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1704 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1709 if (g_plugin_image_list
)
1711 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1712 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1713 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1715 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1718 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1720 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1725 img
= grub_zalloc(sizeof(img_info
));
1729 img
->plugin_list_index
= index
;
1730 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1732 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1734 img
->size
= info
->size
;
1737 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1740 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1742 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1747 if (g_ventoy_img_list
)
1749 tail
= *(node
->tail
);
1755 g_ventoy_img_list
= img
;
1758 img
->id
= g_ventoy_img_count
;
1760 if (node
&& NULL
== node
->firstiso
)
1762 node
->firstiso
= img
;
1773 *((img_info
**)(node
->tail
)) = img
;
1774 g_ventoy_img_count
++;
1776 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1777 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1780 img
->class = g_menu_class
[type
];
1782 img
->menu_prefix
= g_menu_prefix
[type
];
1784 if (img_type_iso
== type
)
1786 if (ventoy_plugin_check_memdisk(img
->path
))
1788 img
->menu_prefix
= "miso";
1792 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1799 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1801 int len
= GRUB_UINT_MAX
;
1802 const char *value
= NULL
;
1803 char name
[32] = {0};
1804 char plat
[32] = {0};
1805 char guidstr
[32] = {0};
1806 ventoy_guid guid
= VENTOY_GUID
;
1807 const char *fmt1
= NULL
;
1808 const char *fmt2
= NULL
;
1809 const char *fmt3
= NULL
;
1810 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1811 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1812 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1813 const char fmtcode
[]={
1814 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1815 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1816 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1817 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1818 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1819 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1822 grub_memset(name
, 0, sizeof(name
));
1823 puint
[0] = grub_swap_bytes32(0x56454e54);
1824 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1825 puint
[2] = grub_swap_bytes32(0x45525349);
1826 puint
[1] = grub_swap_bytes32(0x4f595f56);
1827 value
= ventoy_get_env(name
);
1829 grub_memset(name
, 0, sizeof(name
));
1830 puint
[1] = grub_swap_bytes32(0x5f544f50);
1831 puint
[0] = grub_swap_bytes32(0x56544c45);
1832 fmt1
= ventoy_get_env(name
);
1838 grub_memset(name
, 0, sizeof(name
));
1839 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1840 puint
[0] = grub_swap_bytes32(0x56544c45);
1841 fmt2
= ventoy_get_env(name
);
1843 grub_memset(name
, 0, sizeof(name
));
1844 puint
[1] = grub_swap_bytes32(0x5f434c52);
1845 puint
[0] = grub_swap_bytes32(0x56544c45);
1846 fmt3
= ventoy_get_env(name
);
1848 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1850 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1852 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1853 #pragma GCC diagnostic push
1854 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1855 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1856 fmt1
? fmt1
: fmtdata
,
1857 fmt2
? fmt2
: fmtdata
+ 4,
1858 value
? value
: "", plat
, guidstr
,
1859 fmt3
? fmt3
: fmtdata
+ 6);
1860 #pragma GCC diagnostic pop
1862 grub_memset(name
, 0, sizeof(name
));
1863 puint
[0] = grub_swap_bytes32(0x76746f79);
1864 puint
[2] = grub_swap_bytes32(0x656e7365);
1865 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1866 ventoy_set_env(name
, guidstr
);
1871 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1875 grub_uint8_t md5
[16];
1879 grub_memset(input
, 0, sizeof(input
));
1881 grub_printf("Enter password: ");
1884 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1886 grub_password_get(input
, 128);
1887 if (grub_strcmp(pwd
->text
, input
) == 0)
1892 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1894 grub_password_get(input
, 128);
1895 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1896 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1901 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1903 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1904 grub_password_get(input
+ offset
, 128);
1906 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1907 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1913 grub_printf("Invalid password!\n\n");
1920 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1922 img_info
*minimg
= NULL
;
1923 img_info
*img
= (img_info
*)(node
->firstiso
);
1925 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1927 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1942 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1944 img_iterator_node
*Minchild
= NULL
;
1945 img_iterator_node
*child
= node
->firstchild
;
1947 while (child
&& child
->parent
== node
)
1949 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1953 child
= child
->next
;
1958 Minchild
->select
= 1;
1964 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1967 img_info
*img
= NULL
;
1968 const char *dir_class
= NULL
;
1969 const char *dir_alias
= NULL
;
1970 img_iterator_node
*child
= NULL
;
1972 if (node
->isocnt
== 0 || node
->done
== 1)
1977 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1979 offset
= node
->parent
->dirlen
;
1982 if (node
== &g_img_iterator_head
)
1984 if (g_default_menu_mode
== 0)
1986 if (g_tree_view_menu_style
== 0)
1988 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1989 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1990 " echo 'return ...' \n"
1995 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1996 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2004 node
->dir
[node
->dirlen
- 1] = 0;
2005 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2008 dir_class
= "vtoydir";
2011 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2014 if (g_tree_view_menu_style
== 0)
2016 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2017 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2018 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2022 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2023 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2024 dir_alias
, dir_class
, node
->dir
+ offset
);
2029 dir_alias
= node
->dir
+ offset
;
2031 if (g_tree_view_menu_style
== 0)
2033 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2034 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2035 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2039 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2040 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2041 dir_alias
, dir_class
, node
->dir
+ offset
);
2045 if (g_tree_view_menu_style
== 0)
2047 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2048 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2049 " echo 'return ...' \n"
2054 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2055 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2061 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2063 ventoy_dynamic_tree_menu(child
);
2066 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2068 if (g_tree_view_menu_style
== 0)
2070 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2071 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2074 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2075 img
->unsupport
? "[***********] " : "",
2076 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2078 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2082 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2083 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2086 img
->unsupport
? "[***********] " : "",
2087 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2089 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2093 if (node
!= &g_img_iterator_head
)
2095 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2102 static int ventoy_set_default_menu(void)
2108 const char *strdata
= NULL
;
2109 img_info
*cur
= NULL
;
2110 img_info
*default_node
= NULL
;
2111 const char *default_image
= NULL
;
2113 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2114 if (default_image
&& default_image
[0] == '/')
2116 img_len
= grub_strlen(default_image
);
2118 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2120 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2132 if (0 == g_default_menu_mode
)
2134 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
2138 def
= grub_strdup(default_image
);
2144 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2146 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2147 if (strdata
&& strdata
[0] == '/')
2149 pos
= def
+ grub_strlen(strdata
);
2160 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2163 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2167 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
2175 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2177 img_info
*next
= NULL
;
2178 img_info
*cur
= g_ventoy_img_list
;
2191 g_ventoy_img_list
= NULL
;
2192 g_ventoy_img_count
= 0;
2194 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2197 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2200 img_info
*cur
= g_ventoy_img_list
;
2204 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2206 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2209 img_id
= grub_strtol(args
[0], NULL
, 10);
2210 if (img_id
>= g_ventoy_img_count
)
2212 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2215 debug("Find image %ld name \n", img_id
);
2217 while (cur
&& img_id
> 0)
2225 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2228 debug("image name is %s\n", cur
->name
);
2230 grub_env_set(args
[1], cur
->name
);
2232 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2235 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2239 img_info
*cur
= g_ventoy_img_list
;
2245 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2248 len
= (int)grub_strlen(args
[0]);
2252 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2261 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2264 grub_snprintf(id
, sizeof(id
), "VID_%d", cur
->id
);
2265 grub_env_set("chosen", id
);
2266 grub_env_export("chosen");
2268 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2271 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2276 const char *id
= NULL
;
2277 img_info
*cur
= g_ventoy_img_list
;
2281 if (argc
< 1 || argc
> 2)
2283 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2286 id
= grub_env_get("chosen");
2288 pos
= grub_strstr(id
, "VID_");
2291 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2295 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2300 if (img_id
== cur
->id
)
2309 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2312 grub_env_set(args
[0], cur
->path
);
2316 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2317 grub_env_set(args
[1], value
);
2320 g_svd_replace_offset
= 0;
2322 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2326 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2330 grub_device_t dev
= NULL
;
2331 img_info
*cur
= NULL
;
2332 img_info
*tail
= NULL
;
2333 const char *strdata
= NULL
;
2334 char *device_name
= NULL
;
2336 img_iterator_node
*node
= NULL
;
2337 img_iterator_node
*tmp
= NULL
;
2343 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2346 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2348 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2353 g_enumerate_time_checked
= 0;
2354 g_enumerate_start_time_ms
= grub_get_time_ms();
2356 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2357 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2359 g_filt_dot_underscore_file
= 1;
2362 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2363 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2365 g_sort_case_sensitive
= 1;
2368 device_name
= grub_file_get_device_name(args
[0]);
2374 g_enum_dev
= dev
= grub_device_open(device_name
);
2380 g_enum_fs
= fs
= grub_fs_probe(dev
);
2386 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2388 debug("unsupported fs:<%s>\n", fs
->name
);
2389 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2393 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2395 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2396 if (strdata
&& strdata
[0] == '1')
2398 g_default_menu_mode
= 1;
2401 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2403 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2405 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2406 if (strdata
&& strdata
[0] == '/')
2408 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2409 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2411 g_img_iterator_head
.dir
[len
++] = '/';
2413 g_img_iterator_head
.dirlen
= len
;
2417 g_img_iterator_head
.dirlen
= 1;
2418 grub_strcpy(g_img_iterator_head
.dir
, "/");
2421 g_img_iterator_head
.tail
= &tail
;
2423 if (g_img_max_search_level
< 0)
2425 g_img_max_search_level
= GRUB_INT_MAX
;
2426 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2427 if (strdata
&& ventoy_is_decimal(strdata
))
2429 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2433 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2434 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2435 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2436 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2437 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2438 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2440 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2442 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2445 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2446 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2448 g_tree_view_menu_style
= 1;
2451 ventoy_set_default_menu();
2453 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2455 ventoy_dynamic_tree_menu(node
);
2459 node
= g_img_iterator_head
.next
;
2467 /* sort image list by image name */
2468 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2470 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2472 if (ventoy_cmp_img(cur
, tail
) > 0)
2474 ventoy_swap_img(cur
, tail
);
2479 if (g_default_menu_mode
== 1)
2481 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2482 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2483 " echo 'return ...' \n"
2487 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2489 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2490 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2493 cur
->unsupport
? "[***********] " : "",
2494 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2496 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2499 g_tree_script_buf
[g_tree_script_pos
] = 0;
2500 g_list_script_buf
[g_list_script_pos
] = 0;
2502 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2503 grub_env_set(args
[1], buf
);
2507 check_free(device_name
, grub_free
);
2508 check_free(dev
, grub_device_close
);
2510 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2513 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2520 device_name
= grub_file_get_device_name(filename
);
2532 pos2
= grub_strstr(pos
, ",");
2535 pos2
= grub_strstr(pos
, ")");
2543 disk
= grub_disk_open(pos
);
2546 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2547 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2548 grub_disk_close(disk
);
2555 grub_free(device_name
);
2559 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2561 eltorito_descriptor desc
;
2563 grub_memset(&desc
, 0, sizeof(desc
));
2564 grub_file_seek(file
, 17 * 2048);
2565 grub_file_read(file
, &desc
, sizeof(desc
));
2567 if (desc
.type
!= 0 || desc
.version
!= 1)
2572 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2573 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2581 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2585 grub_uint8_t buf
[512];
2586 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2588 grub_file_seek(file
, sector
* 2048);
2589 grub_file_read(file
, buf
, sizeof(buf
));
2591 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2593 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2597 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2602 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2604 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2606 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2610 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2612 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2617 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2619 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2621 if (buf
[36] == parttype
[i
])
2623 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2629 debug("%s does not contain efi eltorito\n", file
->name
);
2633 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2636 const char *fs
= NULL
;
2637 const char *cdprompt
= NULL
;
2639 grub_uint8_t chksum
= 0;
2642 disk
= file
->device
->disk
;
2643 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2645 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2646 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2647 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2649 pos
= grub_strstr(file
->name
, "/");
2655 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2657 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2659 param
->vtoy_img_size
= file
->size
;
2661 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2662 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2664 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2666 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2667 param
->vtoy_reserved
[4] = 0;
2668 if (g_ventoy_chain_type
== 1) /* Windows */
2670 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2671 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2673 param
->vtoy_reserved
[4] = 1;
2677 fs
= ventoy_get_env("ventoy_fs_probe");
2678 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2680 param
->vtoy_reserved
[3] = 1;
2683 /* calculate checksum */
2684 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2686 chksum
+= *((grub_uint8_t
*)param
+ i
);
2688 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2693 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2695 grub_uint32_t i
= 0;
2696 grub_uint64_t total
= 0;
2697 grub_uint64_t fileblk
= 0;
2698 ventoy_img_chunk
*chunk
= NULL
;
2700 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2702 chunk
= chunklist
->chunk
+ i
;
2704 if (chunk
->disk_start_sector
<= start
)
2706 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2710 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2713 fileblk
= (file
->size
+ 511) / 512;
2715 if (total
!= fileblk
)
2717 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2718 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2720 debug("maybe img file to be processed.\n");
2730 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2734 grub_uint32_t i
= 0;
2735 grub_uint32_t sector
= 0;
2736 grub_uint32_t count
= 0;
2737 grub_off_t size
= 0;
2738 grub_off_t read
= 0;
2740 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2741 if (fs_type
== ventoy_fs_exfat
)
2743 grub_fat_get_file_chunk(start
, file
, chunklist
);
2745 else if (fs_type
== ventoy_fs_ext
)
2747 grub_ext_get_file_chunk(start
, file
, chunklist
);
2751 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2752 file
->read_hook_data
= chunklist
;
2754 for (size
= file
->size
; size
> 0; size
-= read
)
2756 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2757 grub_file_read(file
, NULL
, read
);
2760 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2762 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2763 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2766 if (ventoy_fs_udf
== fs_type
)
2768 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2770 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2771 chunklist
->chunk
[i
].img_start_sector
= sector
;
2772 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2778 len
= (int)grub_strlen(file
->name
);
2779 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2780 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2781 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2782 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2784 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2786 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2796 chunklist
->chunk
[i
].img_start_sector
= sector
;
2797 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2805 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2809 grub_disk_addr_t start
;
2814 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2817 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2820 g_conf_replace_node
= NULL
;
2821 g_conf_replace_offset
= 0;
2823 if (g_img_chunk_list
.chunk
)
2825 grub_free(g_img_chunk_list
.chunk
);
2828 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2830 grub_file_close(file
);
2831 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2834 /* get image chunk data */
2835 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2836 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2837 if (NULL
== g_img_chunk_list
.chunk
)
2839 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2842 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2843 g_img_chunk_list
.cur_chunk
= 0;
2845 start
= file
->device
->disk
->partition
->start
;
2847 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2849 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2850 grub_file_close(file
);
2854 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2857 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2858 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2861 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2863 grub_uint64_t offset
= 0;
2864 grub_uint32_t align
= 0;
2865 grub_file_t file
= NULL
;
2866 conf_replace
*node
= NULL
;
2872 debug("select conf replace argc:%d\n", argc
);
2879 node
= ventoy_plugin_find_conf_replace(args
[1]);
2882 debug("Conf replace not found for %s\n", args
[1]);
2886 debug("Find conf replace for %s\n", args
[1]);
2888 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2891 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2895 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2896 grub_file_close(file
);
2898 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2901 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2905 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2907 if (align
> vtoy_max_replace_file_size
)
2909 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2913 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2914 g_conf_replace_new_len
= (int)file
->size
;
2915 g_conf_replace_new_len_align
= align
;
2917 g_conf_replace_node
= node
;
2918 g_conf_replace_offset
= offset
+ 2;
2920 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2925 grub_file_close(file
);
2927 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2930 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2935 char configfile
[128];
2936 install_template
*node
= NULL
;
2942 debug("select auto installation argc:%d\n", argc
);
2949 node
= ventoy_plugin_find_install_template(args
[0]);
2952 debug("Auto install template not found for %s\n", args
[0]);
2956 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2958 node
->cursel
= node
->autosel
- 1;
2959 debug("Auto install template auto select %d\n", node
->autosel
);
2963 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2969 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2970 " echo %s\n}\n", "123");
2972 for (i
= 0; i
< node
->templatenum
; i
++)
2974 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2976 node
->templatepath
[i
].path
);
2979 g_ventoy_menu_esc
= 1;
2980 g_ventoy_suppress_esc
= 1;
2982 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2983 grub_script_execute_sourcecode(configfile
);
2985 g_ventoy_menu_esc
= 0;
2986 g_ventoy_suppress_esc
= 0;
2990 node
->cursel
= g_ventoy_last_entry
- 1;
2992 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2995 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3000 char configfile
[128];
3001 persistence_config
*node
;
3007 debug("select persistence argc:%d\n", argc
);
3014 node
= ventoy_plugin_find_persistent(args
[0]);
3017 debug("Persistence image not found for %s\n", args
[0]);
3021 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3023 node
->cursel
= node
->autosel
- 1;
3024 debug("Persistence image auto select %d\n", node
->autosel
);
3028 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3034 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3035 " echo %s\n}\n", "123");
3037 for (i
= 0; i
< node
->backendnum
; i
++)
3039 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3041 node
->backendpath
[i
].path
);
3045 g_ventoy_menu_esc
= 1;
3046 g_ventoy_suppress_esc
= 1;
3048 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3049 grub_script_execute_sourcecode(configfile
);
3051 g_ventoy_menu_esc
= 0;
3052 g_ventoy_suppress_esc
= 0;
3056 node
->cursel
= g_ventoy_last_entry
- 1;
3058 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3061 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3064 ventoy_img_chunk
*cur
;
3070 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3072 cur
= g_img_chunk_list
.chunk
+ i
;
3073 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3074 cur
->img_start_sector
, cur
->img_end_sector
,
3075 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3079 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3082 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3086 ventoy_img_chunk_list chunklist
;
3091 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3094 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3097 /* get image chunk data */
3098 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3099 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3100 if (NULL
== chunklist
.chunk
)
3102 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3105 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3106 chunklist
.cur_chunk
= 0;
3108 ventoy_get_block_list(file
, &chunklist
, 0);
3110 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3112 grub_printf("########## UNSUPPORTED ###############\n");
3115 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3117 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3119 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3120 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3123 grub_printf("\n==================================\n");
3125 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3127 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3128 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3129 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3130 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3131 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3135 grub_free(chunklist
.chunk
);
3136 grub_file_close(file
);
3138 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3141 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3144 ventoy_grub_param_file_replace
*replace
= NULL
;
3152 replace
= &(g_grub_param
->file_replace
);
3153 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3155 replace
->old_name_cnt
= 0;
3156 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3158 replace
->old_name_cnt
++;
3159 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3162 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3165 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3168 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3171 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3177 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3178 grub_env_set(args
[0], buf
);
3181 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3184 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3192 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3193 grub_printf("%s", g_list_script_buf
);
3197 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3198 grub_printf("%s", g_tree_script_buf
);
3204 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3206 img_info
*cur
= g_ventoy_img_list
;
3214 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3215 grub_printf("name:<%s>\n\n", cur
->name
);
3222 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3228 ventoy_plugin_dump_injection();
3233 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3239 ventoy_plugin_dump_auto_install();
3244 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3250 ventoy_plugin_dump_persistence();
3255 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3266 if (args
[0][0] == '0')
3268 return g_ventoy_memdisk_mode
? 0 : 1;
3270 else if (args
[0][0] == '1')
3272 return g_ventoy_iso_raw
? 0 : 1;
3274 else if (args
[0][0] == '2')
3276 return g_ventoy_iso_uefi_drv
? 0 : 1;
3278 else if (args
[0][0] == '3')
3280 return g_ventoy_grub2_mode
? 0 : 1;
3282 else if (args
[0][0] == '4')
3284 return g_ventoy_wimboot_mode
? 0 : 1;
3290 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3292 static int configfile_mode
= 0;
3293 char memfile
[128] = {0};
3300 * args[0]: 0:normal 1:configfile
3301 * args[1]: 0:list_buf 1:tree_buf
3306 debug("Invalid argc %d\n", argc
);
3312 if (args
[0][0] == '0')
3314 if (args
[1][0] == '0')
3316 grub_script_execute_sourcecode(g_list_script_buf
);
3320 grub_script_execute_sourcecode(g_tree_script_buf
);
3325 if (configfile_mode
)
3327 debug("Now already in F3 mode %d\n", configfile_mode
);
3331 if (args
[1][0] == '0')
3333 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3334 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3338 g_ventoy_last_entry
= -1;
3339 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3340 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3343 configfile_mode
= 1;
3344 grub_script_execute_sourcecode(memfile
);
3345 configfile_mode
= 0;
3351 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3362 g_ventoy_case_insensitive
= 1;
3363 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3364 g_ventoy_case_insensitive
= 0;
3370 grub_file_close(file
);
3376 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3381 const char *isopath
= NULL
;
3383 ventoy_mbr_head mbr
;
3390 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3393 isopath
= grub_env_get("vtoy_iso_part");
3396 debug("isopath is null %p\n", isopath
);
3400 debug("isopath is %s\n", isopath
);
3402 for (id
= 0; id
< 30 && (find
== 0); id
++)
3404 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3405 if (grub_strstr(isopath
, hdname
))
3407 debug("skip %s ...\n", hdname
);
3411 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3413 disk
= grub_disk_open(hdname
);
3416 debug("%s not exist\n", hdname
);
3420 grub_memset(&mbr
, 0, sizeof(mbr
));
3421 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3423 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3425 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3426 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3429 grub_env_set(args
[0], hdname
);
3433 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3437 debug("read %s failed\n", hdname
);
3440 grub_disk_close(disk
);
3446 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3457 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3460 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3463 debug("failed to open file %s\n", args
[0]);
3467 buf
= grub_malloc(len
);
3474 grub_file_read(file
, buf
, len
- 1);
3476 ventoy_get_line(buf
);
3477 ventoy_set_env(args
[1], buf
);
3481 grub_check_free(buf
);
3482 grub_file_close(file
);
3487 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3492 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3493 "0 %llu linear /dev/ventoy %llu\n",
3494 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3499 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3501 char *device_name
= NULL
;
3502 grub_device_t dev
= NULL
;
3507 g_part_list_pos
= 0;
3508 grub_env_unset("vtoy_img_part_file");
3515 device_name
= grub_file_get_device_name(args
[0]);
3518 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3522 dev
= grub_device_open(device_name
);
3525 debug("grub_device_open failed, %s\n", device_name
);
3529 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3531 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3532 grub_env_set("vtoy_img_part_file", buf
);
3536 check_free(device_name
, grub_free
);
3537 check_free(dev
, grub_device_close
);
3543 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3554 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3557 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3560 debug("failed to open file %s\n", args
[0]);
3564 buf
= grub_malloc(file
->size
+ 1);
3570 buf
[file
->size
] = 0;
3571 grub_file_read(file
, buf
, file
->size
);
3573 if (grub_strstr(buf
, args
[1]))
3580 grub_check_free(buf
);
3581 grub_file_close(file
);
3586 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3592 ventoy_iso9660_vd pvd
;
3599 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3602 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3605 debug("failed to open file %s\n", args
[0]);
3609 grub_file_seek(file
, 16 * 2048);
3610 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3611 if (len
!= sizeof(pvd
))
3613 debug("failed to read pvd %d\n", len
);
3617 grub_memset(buf
, 0, sizeof(buf
));
3618 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3619 ventoy_set_env(args
[1], buf
);
3621 grub_memset(buf
, 0, sizeof(buf
));
3622 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3623 ventoy_set_env(args
[2], buf
);
3627 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3628 ventoy_set_env(args
[3], buf
);
3631 grub_file_close(file
);
3636 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3647 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3650 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3653 debug("failed to open file %s\n", args
[0]);
3657 grub_memset(buf
, 0, sizeof(buf
));
3658 grub_file_seek(file
, 16 * 2048 + 813);
3659 len
= (int)grub_file_read(file
, buf
, 17);
3662 debug("failed to read create date %d\n", len
);
3666 ventoy_set_env(args
[1], buf
);
3669 grub_file_close(file
);
3674 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3680 ventoy_env_hook_root(1);
3685 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3691 ventoy_env_hook_root(0);
3696 #ifdef GRUB_MACHINE_EFI
3697 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3702 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3708 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3709 if (var
&& *var
== 1)
3717 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3726 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3731 grub_uint64_t FileSectors
= 0;
3732 ventoy_gpt_info
*gpt
= NULL
;
3733 ventoy_part_table
*pt
= NULL
;
3734 grub_uint8_t zeroguid
[16] = {0};
3739 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3742 debug("failed to open file %s\n", args
[0]);
3746 if (file
->size
% 512)
3748 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3752 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3758 FileSectors
= file
->size
/ 512;
3760 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3761 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3763 debug("This is EFI partition table\n");
3765 for (i
= 0; i
< 128; i
++)
3767 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3769 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3771 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3772 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3780 debug("This is MBR partition table\n");
3782 for (i
= 0; i
< 4; i
++)
3784 pt
= gpt
->MBR
.PartTbl
+ i
;
3785 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3787 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3788 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3789 (ulonglong
)FileSectors
);
3798 grub_file_close(file
);
3799 grub_check_free(gpt
);
3800 grub_errno
= GRUB_ERR_NONE
;
3804 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3813 for (i
= 0; i
< 500; i
++)
3815 ret
= grub_getkey_noblock();
3816 if (ret
== GRUB_TERM_NO_KEY
)
3825 grub_printf("\n\n Still have key input after clear.\n");
3833 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3840 int image_sector_size
;
3842 ventoy_chain_head
*chain
;
3843 ventoy_img_chunk
*chunk
;
3844 ventoy_os_param
*osparam
;
3845 ventoy_image_location
*location
;
3846 ventoy_image_disk_region
*region
;
3847 struct grub_acpi_table_header
*acpi
;
3856 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3858 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3864 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3866 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3868 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3872 img_chunk_num
= chain
->img_chunk_num
;
3874 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3875 datalen
= sizeof(ventoy_os_param
) + loclen
;
3877 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3878 acpi
= grub_zalloc(buflen
);
3884 /* Step1: Fill acpi table header */
3885 grub_memcpy(acpi
->signature
, "VTOY", 4);
3886 acpi
->length
= buflen
;
3888 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3889 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3891 acpi
->creator_id
[0] = 1;
3892 acpi
->creator_rev
= 1;
3894 /* Step2: Fill data */
3895 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3896 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3897 osparam
->vtoy_img_location_addr
= 0;
3898 osparam
->vtoy_img_location_len
= loclen
;
3899 osparam
->chksum
= 0;
3900 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3902 location
= (ventoy_image_location
*)(osparam
+ 1);
3903 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3904 location
->image_sector_size
= image_sector_size
;
3905 location
->disk_sector_size
= chain
->disk_sector_size
;
3906 location
->region_count
= img_chunk_num
;
3908 region
= location
->regions
;
3909 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3910 if (512 == image_sector_size
)
3912 for (i
= 0; i
< img_chunk_num
; i
++)
3914 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3915 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3916 region
->disk_start_sector
= chunk
->disk_start_sector
;
3923 for (i
= 0; i
< img_chunk_num
; i
++)
3925 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3926 region
->image_start_sector
= chunk
->img_start_sector
;
3927 region
->disk_start_sector
= chunk
->disk_start_sector
;
3933 /* Step3: Fill acpi checksum */
3935 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3937 /* load acpi table */
3938 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3939 grub_script_execute_sourcecode(cmd
);
3943 VENTOY_CMD_RETURN(0);
3946 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3952 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3953 g_ventoy_last_entry
= -1;
3958 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3964 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3969 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3971 const char *pos
= filename
+ 1;
3979 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3981 grub_strncpy((char *)data
, filename
, 128);
3992 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3995 char *device_name
= NULL
;
3996 grub_device_t dev
= NULL
;
3997 grub_fs_t fs
= NULL
;
3998 char buf
[128] = {0};
4004 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4008 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4010 device_name
= grub_file_get_device_name(args
[0]);
4013 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4017 dev
= grub_device_open(device_name
);
4020 debug("grub_device_open failed, %s\n", device_name
);
4024 fs
= grub_fs_probe(dev
);
4027 debug("grub_fs_probe failed, %s\n", device_name
);
4031 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4035 ventoy_set_env(args
[2], buf
);
4042 check_free(device_name
, grub_free
);
4043 check_free(dev
, grub_device_close
);
4048 int ventoy_load_part_table(const char *diskname
)
4055 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4056 if (!g_ventoy_part_info
)
4061 disk
= grub_disk_open(diskname
);
4064 debug("Failed to open disk %s\n", diskname
);
4068 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4070 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4071 grub_disk_close(disk
);
4073 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4074 dev
= grub_device_open(name
);
4077 /* Check for official Ventoy device */
4078 ret
= ventoy_check_official_device(dev
);
4079 grub_device_close(dev
);
4087 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4088 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4093 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4100 ret
= ventoy_load_part_table(args
[0]);
4106 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4107 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4112 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4115 const char *vcfg
= NULL
;
4120 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4123 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4124 grub_env_set(args
[1], vcfg
);
4129 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4137 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4140 grub_uint8_t zeroguid
[16] = {0};
4145 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4148 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4150 if (id
>= 1 && id
<= 128)
4152 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4160 if (id
>= 1 && id
<= 4)
4162 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4172 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4175 char *device_name
= NULL
;
4176 grub_device_t dev
= NULL
;
4177 grub_fs_t fs
= NULL
;
4182 debug("get fs label for %s\n", args
[0]);
4186 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4190 device_name
= grub_file_get_device_name(args
[0]);
4193 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4197 dev
= grub_device_open(device_name
);
4200 debug("grub_device_open failed, %s\n", device_name
);
4204 fs
= grub_fs_probe(dev
);
4205 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4207 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4211 fs
->fs_label(dev
, &label
);
4214 debug("label=<%s>\n", label
);
4215 ventoy_set_env(args
[1], label
);
4223 check_free(device_name
, grub_free
);
4224 check_free(dev
, grub_device_close
);
4229 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4233 grub_snprintf((char *)data
, 256, "%s", filename
);
4240 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4242 if (info
->dir
&& filename
&& filename
[0] != '.')
4244 grub_snprintf((char *)data
, 256, "%s", filename
);
4251 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4254 char *device_name
= NULL
;
4255 grub_device_t dev
= NULL
;
4256 grub_fs_t fs
= NULL
;
4257 char name
[256] ={0};
4261 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4265 device_name
= grub_file_get_device_name(args
[0]);
4268 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4272 dev
= grub_device_open(device_name
);
4275 debug("grub_device_open failed, %s\n", device_name
);
4279 fs
= grub_fs_probe(dev
);
4282 debug("grub_fs_probe failed, %s\n", device_name
);
4286 fs
->fs_dir(dev
, args
[1], hook
, name
);
4289 ventoy_set_env(args
[2], name
);
4296 check_free(device_name
, grub_free
);
4297 check_free(dev
, grub_device_close
);
4302 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4305 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4308 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4311 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4314 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4324 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4328 for (pos
= args
[0]; *pos
; pos
++)
4342 grub_env_set(args
[1], args
[0]);
4352 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4362 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4367 len
= (int)grub_strlen(buf
);
4368 for (i
= len
; i
> 0; i
--)
4370 if (buf
[i
- 1] == '/')
4372 grub_env_set(args
[1], buf
+ i
);
4377 grub_env_set(args
[1], buf
);
4382 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4384 struct grub_video_mode_info info
;
4391 if (!g_video_mode_list
)
4393 ventoy_enum_video_mode();
4396 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4398 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4402 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4405 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4407 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4408 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4410 VENTOY_CMD_RETURN(0);
4413 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4415 struct grub_video_mode_info info
;
4422 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4424 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4428 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4431 grub_env_set(args
[0], buf
);
4433 VENTOY_CMD_RETURN(0);
4436 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4444 if (!g_video_mode_list
)
4449 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4450 if (id
< g_video_mode_num
)
4452 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4453 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4456 grub_env_set(args
[1], buf
);
4458 VENTOY_CMD_RETURN(0);
4461 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4464 grub_uint32_t loadsector
= 0;
4467 grub_uint32_t boot_catlog
= 0;
4468 grub_uint8_t buf
[512];
4474 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4478 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4481 debug("failed to open %s\n", args
[0]);
4485 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4486 if (boot_catlog
== 0)
4488 debug("No bootcatlog found\n");
4489 grub_file_close(file
);
4493 grub_memset(buf
, 0, sizeof(buf
));
4494 grub_file_seek(file
, boot_catlog
* 2048);
4495 grub_file_read(file
, buf
, sizeof(buf
));
4496 grub_file_close(file
);
4498 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4500 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4502 if (buf
[i
+ 32] == 0x88)
4504 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4505 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4511 if (loadsector
== 0)
4513 debug("No EFI eltorito info found\n");
4517 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4518 grub_env_set(args
[1], value
);
4519 VENTOY_CMD_RETURN(0);
4522 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4527 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4529 if (pfsdir
->initrd
[0])
4534 curpos
= pfsdir
->curpos
;
4535 len
= grub_strlen(filename
);
4539 if ((len
== 1 && filename
[0] == '.') ||
4540 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4545 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4548 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4549 pfsdir
->curpos
= curpos
+ printlen
;
4550 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4551 pfsdir
->curpos
= curpos
;
4552 pfsdir
->fullpath
[curpos
] = 0;
4556 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4559 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4560 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4562 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4564 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4573 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4577 char *device_name
= NULL
;
4578 grub_device_t dev
= NULL
;
4579 grub_fs_t fs
= NULL
;
4580 replace_fs_dir
*pfsdir
= NULL
;
4586 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4590 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4596 device_name
= grub_file_get_device_name(args
[0]);
4602 dev
= grub_device_open(device_name
);
4608 fs
= grub_fs_probe(dev
);
4617 pfsdir
->fullpath
[0] = '/';
4618 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4620 if (pfsdir
->initrd
[0])
4622 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4624 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4626 if (pfsdir
->initrd
[i
] == '/')
4628 pfsdir
->initrd
[i
] = '\\';
4632 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4633 grub_env_set(args
[1], pos
);
4637 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4642 grub_check_free(pfsdir
);
4643 grub_check_free(device_name
);
4644 check_free(dev
, grub_device_close
);
4646 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4649 int ventoy_env_init(void)
4653 grub_env_set("vtdebug_flag", "");
4655 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4656 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4657 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4658 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4660 ventoy_filt_register(0, ventoy_wrapper_open
);
4662 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4665 g_grub_param
->grub_env_get
= grub_env_get
;
4666 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4667 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4668 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4669 grub_env_set("env_param", buf
);
4670 grub_env_set("ventoy_env_param", buf
);
4672 grub_env_export("env_param");
4673 grub_env_export("ventoy_env_param");
4676 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
4677 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
4679 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
4680 grub_env_set("vtoy_winpeshl_ini_size", buf
);
4682 grub_env_export("vtoy_winpeshl_ini_addr");
4683 grub_env_export("vtoy_winpeshl_ini_size");
4685 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
4686 grub_env_set("vtoy_chain_file_size", buf
);
4687 grub_env_export("vtoy_chain_file_size");
4689 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
4690 grub_env_set("vtoy_chain_file_read", buf
);
4691 grub_env_export("vtoy_chain_file_read");
4696 static cmd_para ventoy_cmds
[] =
4698 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4699 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4700 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4701 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4702 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4703 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4704 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4705 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4706 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4707 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4708 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4709 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4710 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4711 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4712 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4713 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4714 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4715 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4716 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4717 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4718 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4719 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4720 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4721 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4723 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4724 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4725 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4726 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4727 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4728 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4729 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4731 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4732 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4733 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4734 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4735 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
4736 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4737 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4738 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4739 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4740 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4743 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4744 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4745 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4746 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4747 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4748 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4749 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4750 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4751 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4752 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4753 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4755 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4756 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
4757 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4758 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4759 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4760 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4761 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4763 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4764 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4765 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4766 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4767 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4768 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4769 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4770 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4771 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4772 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4774 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4775 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4776 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
4777 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4778 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4779 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4780 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4781 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4782 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4784 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4785 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
4786 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4787 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4790 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4791 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4792 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4794 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4795 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4796 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4799 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4800 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4801 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4802 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4803 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
4804 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4805 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4806 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4807 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4808 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4809 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4811 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4812 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4813 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4814 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4815 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
4816 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
4817 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
4818 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
4819 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
4820 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
4822 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
4823 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
4826 int ventoy_register_all_cmd(void)
4829 cmd_para
*cur
= NULL
;
4831 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4833 cur
= ventoy_cmds
+ i
;
4834 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4835 cur
->summary
, cur
->description
, cur
->parser
);
4841 int ventoy_unregister_all_cmd(void)
4845 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4847 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);