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/random.h>
49 #include <grub/ventoy.h>
50 #include "ventoy_def.h"
53 GRUB_MOD_LICENSE ("GPLv3+");
55 static grub_uint8_t g_check_mbr_data
[] = {
56 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
62 initrd_info
*g_initrd_img_list
= NULL
;
63 initrd_info
*g_initrd_img_tail
= NULL
;
64 int g_initrd_img_count
= 0;
65 int g_valid_initrd_count
= 0;
66 int g_default_menu_mode
= 0;
67 int g_filt_dot_underscore_file
= 0;
68 int g_sort_case_sensitive
= 0;
69 int g_tree_view_menu_style
= 0;
70 static grub_file_t g_old_file
;
71 static int g_ventoy_last_entry_back
;
74 char g_img_swap_tmp_buf
[1024];
75 img_info g_img_swap_tmp
;
76 img_info
*g_ventoy_img_list
= NULL
;
78 int g_ventoy_img_count
= 0;
80 grub_device_t g_enum_dev
= NULL
;
81 grub_fs_t g_enum_fs
= NULL
;
82 int g_img_max_search_level
= -1;
83 img_iterator_node g_img_iterator_head
;
84 img_iterator_node
*g_img_iterator_tail
= NULL
;
86 grub_uint8_t g_ventoy_break_level
= 0;
87 grub_uint8_t g_ventoy_debug_level
= 0;
88 grub_uint8_t g_ventoy_chain_type
= 0;
90 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
91 grub_uint32_t g_ventoy_cpio_size
= 0;
92 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
93 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
95 int g_plugin_image_list
= 0;
97 ventoy_grub_param
*g_grub_param
= NULL
;
99 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
101 ventoy_img_chunk_list g_img_chunk_list
;
103 int g_wimboot_enable
= 0;
104 ventoy_img_chunk_list g_wimiso_chunk_list
;
105 char *g_wimiso_path
= NULL
;
106 grub_uint32_t g_wimiso_size
= 0;
108 int g_vhdboot_enable
= 0;
110 grub_uint64_t g_svd_replace_offset
= 0;
112 int g_conf_replace_count
= 0;
113 grub_uint64_t g_conf_replace_offset
[VTOY_MAX_CONF_REPLACE
] = { 0 };
114 conf_replace
*g_conf_replace_node
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
115 grub_uint8_t
*g_conf_replace_new_buf
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
116 int g_conf_replace_new_len
[VTOY_MAX_CONF_REPLACE
] = { 0 };
117 int g_conf_replace_new_len_align
[VTOY_MAX_CONF_REPLACE
] = { 0 };
119 int g_ventoy_disk_bios_id
= 0;
120 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
121 grub_uint64_t g_ventoy_disk_size
= 0;
122 grub_uint64_t g_ventoy_disk_part_size
[2];
124 char *g_tree_script_buf
= NULL
;
125 int g_tree_script_pos
= 0;
126 int g_tree_script_pre
= 0;
128 static char *g_list_script_buf
= NULL
;
129 static int g_list_script_pos
= 0;
131 static char *g_part_list_buf
= NULL
;
132 static int g_part_list_pos
= 0;
133 static grub_uint64_t g_part_end_max
= 0;
135 static int g_video_mode_max
= 0;
136 static int g_video_mode_num
= 0;
137 static ventoy_video_mode
*g_video_mode_list
= NULL
;
139 static int g_enumerate_time_checked
= 0;
140 static grub_uint64_t g_enumerate_start_time_ms
;
141 static grub_uint64_t g_enumerate_finish_time_ms
;
142 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
144 static char g_iso_vd_id_publisher
[130];
145 static char g_iso_vd_id_prepare
[130];
146 static char g_iso_vd_id_application
[130];
148 static int g_pager_flag
= 0;
149 static char g_old_pager
[32];
151 const char *g_menu_class
[img_type_max
] =
153 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
156 const char *g_menu_prefix
[img_type_max
] =
158 "iso", "wim", "efi", "img", "vhd", "vtoy"
161 static const char *g_lower_chksum_name
[] = { "md5", "sha1", "sha256", "sha512" };
163 static int g_vtoy_secondary_need_recover
= 0;
165 static int g_vtoy_load_prompt
= 0;
166 static char g_vtoy_prompt_msg
[64];
168 static char g_json_case_mis_path
[32];
170 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
172 int ventoy_get_fs_type(const char *fs
)
176 return ventoy_fs_max
;
178 else if (grub_strncmp(fs
, "exfat", 5) == 0)
180 return ventoy_fs_exfat
;
182 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
184 return ventoy_fs_ntfs
;
186 else if (grub_strncmp(fs
, "ext", 3) == 0)
188 return ventoy_fs_ext
;
190 else if (grub_strncmp(fs
, "xfs", 3) == 0)
192 return ventoy_fs_xfs
;
194 else if (grub_strncmp(fs
, "udf", 3) == 0)
196 return ventoy_fs_udf
;
198 else if (grub_strncmp(fs
, "fat", 3) == 0)
200 return ventoy_fs_fat
;
203 return ventoy_fs_max
;
206 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
225 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
227 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
231 static int ventoy_control_get_flag(const char *key
)
233 const char *val
= ventoy_get_env(key
);
235 if (val
&& val
[0] == '1' && val
[1] == 0)
242 static grub_err_t
ventoy_fs_close(grub_file_t file
)
244 grub_file_close(g_old_file
);
245 grub_free(file
->data
);
253 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
259 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
264 for (i
= 0; i
< g_video_mode_num
; i
++)
266 if (g_video_mode_list
[i
].width
== info
->width
&&
267 g_video_mode_list
[i
].height
== info
->height
&&
268 g_video_mode_list
[i
].bpp
== info
->bpp
)
274 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
275 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
276 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
279 if (g_video_mode_num
== g_video_mode_max
)
281 g_video_mode_max
*= 2;
282 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
288 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
290 if (v1
->bpp
== v2
->bpp
)
292 if (v1
->width
== v2
->width
)
294 if (v1
->height
== v2
->height
)
300 return (v1
->height
< v2
->height
) ? -1 : 1;
305 return (v1
->width
< v2
->width
) ? -1 : 1;
310 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
314 static int ventoy_enum_video_mode(void)
317 grub_video_adapter_t adapter
;
318 grub_video_driver_id_t id
;
319 ventoy_video_mode mode
;
321 g_video_mode_num
= 0;
322 g_video_mode_max
= 1024;
323 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
324 if (!g_video_mode_list
)
329 #ifdef GRUB_MACHINE_PCBIOS
330 grub_dl_load ("vbe");
333 id
= grub_video_get_driver_id ();
335 FOR_VIDEO_ADAPTERS (adapter
)
337 if (!adapter
->iterate
||
338 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
339 adapter
->init() != GRUB_ERR_NONE
)))
344 adapter
->iterate(ventoy_video_hook
, NULL
);
346 if (adapter
->id
!= id
)
352 /* sort video mode */
353 for (i
= 0; i
< g_video_mode_num
; i
++)
354 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
356 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
358 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
359 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
360 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
364 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
367 static int ventoy_pre_parse_data(char *src
, int size
)
373 if (size
< 20 || grub_strncmp(src
, "ventoy_left_top_color", 21))
379 while (*pos
&& *pos
!= '\r' && *pos
!= '\n')
387 if (grub_strlen(src
) > 200)
392 grub_snprintf(buf
, sizeof(buf
),
393 "regexp -s 1:%s -s 2:%s -s 3:%s \"@([^@]*)@([^@]*)@([^@]*)@\" \"%s\"",
394 ventoy_left_key
, ventoy_top_key
, ventoy_color_key
, src
);
396 grub_script_execute_sourcecode(buf
);
403 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
407 static struct grub_fs vtoy_fs
=
412 .fs_read
= ventoy_fs_read
,
413 .fs_close
= ventoy_fs_close
,
423 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
429 file
->data
= grub_malloc(rawFile
->size
+ 4096);
435 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
436 ventoy_pre_parse_data((char *)file
->data
, (int)rawFile
->size
);
437 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
439 g_old_file
= rawFile
;
441 file
->size
= rawFile
->size
+ len
;
442 file
->device
= rawFile
->device
;
444 file
->not_easily_seekable
= 1;
449 static int ventoy_check_decimal_var(const char *name
, long *value
)
451 const char *value_str
= NULL
;
453 value_str
= grub_env_get(name
);
454 if (NULL
== value_str
)
456 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
459 if (!ventoy_is_decimal(value_str
))
461 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
464 *value
= grub_strtol(value_str
, NULL
, 10);
466 return GRUB_ERR_NONE
;
469 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
471 grub_uint64_t sectors
;
473 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
475 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
479 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
482 return sectors
* 512;
485 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
491 grub_uint32_t offset
;
493 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
496 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
500 len
= (int)file
->size
;
502 data
= (char *)grub_malloc(file
->size
);
508 grub_file_read(file
, data
, file
->size
);
509 grub_file_close(file
);
511 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
512 grub_script_execute_sourcecode(exec
);
514 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
515 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
516 grub_file_close(file
);
518 grub_script_execute_sourcecode("loopback -d efiboot");
522 *direntoff
= offset
+ 2;
527 static int ventoy_set_check_result(int ret
, const char *msg
)
531 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
532 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
533 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
538 grub_printf(VTOY_WARNING
"\n");
539 grub_printf(VTOY_WARNING
"\n");
540 grub_printf(VTOY_WARNING
"\n\n\n");
542 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
543 grub_printf("Error message: <%s>\n\n", msg
);
544 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
551 static int ventoy_check_official_device(grub_device_t dev
)
555 grub_uint64_t offset
;
558 grub_uint8_t mbr
[512];
562 struct grub_partition
*partition
;
564 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
566 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
569 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
570 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
571 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
573 #ifndef GRUB_MACHINE_EFI
574 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
576 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
578 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
580 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
582 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
584 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
593 /* We must have partition 2 */
596 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
600 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
604 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
607 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
609 grub_file_close(file
);
610 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
613 partition
= dev
->disk
->partition
;
614 if (partition
->number
!= 0 || partition
->start
!= 2048)
616 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
621 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
623 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
624 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
625 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
627 grub_file_close(file
);
628 return ventoy_set_check_result(6, "Disk partition layout check failed.");
633 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
634 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
635 PartTbl
[1].SectorCount
!= 65536)
637 grub_file_close(file
);
638 return ventoy_set_check_result(6, "Disk partition layout check failed.");
644 offset
= partition
->start
+ partition
->len
;
645 partition
= file
->device
->disk
->partition
;
646 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
648 grub_file_close(file
);
649 return ventoy_set_check_result(7, "Disk partition layout check failed.");
653 grub_file_close(file
);
657 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
658 dev2
= grub_device_open(devname
);
661 return ventoy_set_check_result(8, "Disk open failed");
664 fs
= grub_fs_probe(dev2
);
667 grub_device_close(dev2
);
668 return ventoy_set_check_result(9, "FS probe failed");
671 fs
->fs_label(dev2
, &label
);
672 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
674 grub_device_close(dev2
);
675 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
678 grub_device_close(dev2
);
682 disk
= grub_disk_open(dev
->disk
->name
);
685 return ventoy_set_check_result(11, "Disk open failed");
688 grub_memset(mbr
, 0, 512);
689 grub_disk_read(disk
, 0, 0, 512, mbr
);
690 grub_disk_close(disk
);
692 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
694 return ventoy_set_check_result(12, "MBR check failed");
697 return ventoy_set_check_result(0, NULL
);
700 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
704 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
714 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
716 grub_uint64_t size
= 0;
719 char fullpath
[256] = {0};
722 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
725 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
728 debug("grub_file_open failed <%s>\n", fullpath
);
734 grub_file_close(file
);
738 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
742 char fullpath
[512] = {0};
745 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
748 file
= grub_file_open(fullpath
, type
);
751 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
758 int ventoy_is_dir_exist(const char *fmt
, ...)
765 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
769 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
772 grub_strncpy(pos
+ len
, "\" ]", 3);
774 debug("script exec %s\n", buf
);
776 if (0 == grub_script_execute_sourcecode(buf
))
784 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
787 grub_uint8_t
*outbuf
;
788 grub_uint8_t gzHdr
[10] =
790 0x1F, 0x8B, /* magic */
798 grub_memset(&s
, 0, sizeof(mz_stream
));
800 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
802 outbuf
= (grub_uint8_t
*)mem_out
;
804 mem_out_len
-= sizeof(gzHdr
) + 8;
805 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
806 outbuf
+= sizeof(gzHdr
);
808 s
.avail_in
= mem_in_len
;
811 s
.avail_out
= mem_out_len
;
814 mz_deflate(&s
, MZ_FINISH
);
818 outbuf
+= s
.total_out
;
819 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
820 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
822 return s
.total_out
+ sizeof(gzHdr
) + 8;
830 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
834 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
837 if (0 == grub_strcmp(args
[0], "on"))
840 grub_env_set("vtdebug_flag", "debug");
845 grub_env_set("vtdebug_flag", "");
848 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
851 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
855 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
857 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
858 grub_printf(" level:\r\n");
859 grub_printf(" 01/11: busybox / (+cat log)\r\n");
860 grub_printf(" 02/12: initrd / (+cat log)\r\n");
861 grub_printf(" 03/13: hook / (+cat log)\r\n");
863 grub_printf(" debug:\r\n");
864 grub_printf(" 0: debug is off\r\n");
865 grub_printf(" 1: debug is on\r\n");
867 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
870 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
872 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
874 g_ventoy_debug_level
= 1;
877 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
880 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
889 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
892 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
924 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
940 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
956 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
961 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
963 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
966 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
971 value_long
+= grub_strtol(args
[1], NULL
, 10);
973 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
974 grub_env_set(args
[0], buf
);
976 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
979 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
981 ulonglong value1
= 0;
982 ulonglong value2
= 0;
987 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
990 value1
= grub_strtoull(args
[0], NULL
, 10);
991 value2
= grub_strtoull(args
[1], NULL
, 10);
993 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
994 grub_env_set(args
[2], buf
);
996 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
999 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1014 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1017 debug("failed to open file <%s> for udf check\n", args
[0]);
1021 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
1023 grub_env_set(args
[1], buf
);
1025 grub_file_close(file
);
1031 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1039 g_wimboot_enable
= 0;
1041 grub_check_free(g_wimiso_path
);
1042 grub_check_free(g_wimiso_chunk_list
.chunk
);
1044 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1050 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1051 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1052 if (NULL
== g_wimiso_chunk_list
.chunk
)
1054 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1057 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1058 g_wimiso_chunk_list
.cur_chunk
= 0;
1060 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1062 g_wimboot_enable
= 1;
1063 g_wimiso_path
= grub_strdup(args
[0]);
1064 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1065 grub_file_close(file
);
1070 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1078 ventoy_iso9660_override
*dirent
;
1087 totlen
= sizeof(ventoy_chain_head
);
1089 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1091 debug("failed to load efiboot template %d\n", len
);
1097 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1099 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1102 debug("failed to open file <%s>\n", args
[0]);
1106 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1111 totlen
+= ventoy_align_2k(file
->size
);
1113 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1114 dirent
->first_sector
= len
/ 2048;
1115 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1116 dirent
->size
= (grub_uint32_t
)file
->size
;
1117 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1119 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1121 #ifdef GRUB_MACHINE_EFI
1122 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1124 data
= (char *)grub_malloc(totlen
);
1127 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1129 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1130 grub_check_free(buf
);
1132 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1133 grub_file_close(file
);
1135 ventoy_memfile_env_set(args
[1], data
, (ulonglong
)totlen
);
1140 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1146 g_vtoy_load_prompt
= 0;
1147 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1149 if (argc
== 2 && args
[0][0] == '1')
1151 g_vtoy_load_prompt
= 1;
1152 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1155 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1158 int ventoy_need_prompt_load_file(void)
1160 return g_vtoy_load_prompt
;
1163 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1165 grub_uint64_t ro
= 0;
1166 grub_uint64_t div
= 0;
1167 grub_ssize_t left
= size
;
1168 char *cur
= (char *)buf
;
1170 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1173 while (left
>= VTOY_SIZE_2MB
)
1175 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1176 cur
+= VTOY_SIZE_2MB
;
1177 left
-= VTOY_SIZE_2MB
;
1179 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1184 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1190 grub_file_read(file
, cur
, left
);
1193 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1199 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1204 enum grub_file_type type
;
1215 if (grub_strcmp(args
[0], "nodecompress") == 0)
1217 type
= VENTOY_FILE_TYPE
;
1221 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1224 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1227 debug("failed to open file <%s>\n", args
[1]);
1231 #ifdef GRUB_MACHINE_EFI
1232 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1234 buf
= (char *)grub_malloc(file
->size
);
1239 grub_file_close(file
);
1243 if (g_vtoy_load_prompt
)
1245 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1249 grub_file_read(file
, buf
, file
->size
);
1252 ventoy_memfile_env_set(args
[2], buf
, (ulonglong
)(file
->size
));
1254 grub_file_close(file
);
1260 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1276 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1279 debug("failed to open file <%s> for udf check\n", args
[0]);
1283 headlen
= sizeof(ventoy_chain_head
);
1285 #ifdef GRUB_MACHINE_EFI
1286 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1288 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1291 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1293 grub_file_read(file
, buf
+ headlen
, file
->size
);
1295 ventoy_memfile_env_set(args
[1], buf
, (ulonglong
)(file
->size
));
1297 grub_file_close(file
);
1303 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1309 if (grub_iso9660_is_joliet())
1311 debug("This time has joliet process\n");
1320 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1329 if (args
[0][0] == '1')
1331 grub_iso9660_set_nojoliet(1);
1335 grub_iso9660_set_nojoliet(0);
1341 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1346 grub_uint8_t buf
[32];
1357 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1360 debug("failed to open file <%s> for udf check\n", args
[0]);
1364 for (i
= 16; i
< 32; i
++)
1366 grub_file_seek(file
, i
* 2048);
1367 grub_file_read(file
, buf
, sizeof(buf
));
1375 grub_file_seek(file
, i
* 2048);
1376 grub_file_read(file
, buf
, sizeof(buf
));
1378 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1381 grub_file_seek(file
, i
* 2048);
1382 grub_file_read(file
, buf
, sizeof(buf
));
1384 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1385 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1391 grub_file_close(file
);
1393 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1398 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1400 long value_long1
= 0;
1401 long value_long2
= 0;
1403 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1405 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1408 value_long1
= grub_strtol(args
[0], NULL
, 10);
1409 value_long2
= grub_strtol(args
[2], NULL
, 10);
1411 if (0 == grub_strcmp(args
[1], "eq"))
1413 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1415 else if (0 == grub_strcmp(args
[1], "ne"))
1417 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1419 else if (0 == grub_strcmp(args
[1], "gt"))
1421 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1423 else if (0 == grub_strcmp(args
[1], "lt"))
1425 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1427 else if (0 == grub_strcmp(args
[1], "ge"))
1429 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1431 else if (0 == grub_strcmp(args
[1], "le"))
1433 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1437 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1443 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1446 char buf
[128] = {0};
1450 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1453 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1454 pos
= grub_strstr(buf
, ",");
1460 grub_env_set(args
[1], buf
);
1462 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1465 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1471 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1477 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1480 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1482 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1483 if (0 == grub_script_execute_sourcecode(buf
))
1485 debug("file %s exist, ventoy_compatible YES\n", buf
);
1486 grub_env_set("ventoy_compatible", "YES");
1487 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1491 debug("file %s NOT exist\n", buf
);
1495 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1496 pos
= grub_strstr(buf
, ")");
1502 disk
= grub_disk_open(buf
);
1505 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1506 grub_disk_close(disk
);
1508 g_img_swap_tmp_buf
[703] = 0;
1509 for (i
= 318; i
< 703; i
++)
1511 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1512 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1514 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1515 grub_env_set("ventoy_compatible", "YES");
1516 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1522 debug("failed to open disk <%s>\n", buf
);
1525 grub_env_set("ventoy_compatible", "NO");
1526 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1529 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1535 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1537 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1540 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1545 if (0 == g_sort_case_sensitive
)
1547 if (grub_islower(c1
))
1549 c1
= c1
- 'a' + 'A';
1552 if (grub_islower(c2
))
1554 c2
= c2
- 'a' + 'A';
1567 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1573 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1575 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1578 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1583 if (0 == g_sort_case_sensitive
)
1585 if (grub_islower(c1
))
1587 c1
= c1
- 'a' + 'A';
1590 if (grub_islower(c2
))
1592 c2
= c2
- 'a' + 'A';
1605 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1607 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1609 grub_memcpy(img1
, img2
, sizeof(img_info
));
1610 img1
->next
= g_img_swap_tmp
.next
;
1611 img1
->prev
= g_img_swap_tmp
.prev
;
1613 g_img_swap_tmp
.next
= img2
->next
;
1614 g_img_swap_tmp
.prev
= img2
->prev
;
1615 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1618 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1622 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1630 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1632 ventoy_vlnk_part
*node
= NULL
;
1633 grub_uint32_t SelfSig
;
1634 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1636 /* skip Ventoy partition 1/2 */
1637 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1638 if (partition
->number
< 2 && SelfSig
== *pSig
)
1643 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1646 node
->disksig
= *pSig
;
1647 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1648 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1649 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1651 node
->next
= g_vlnk_part_list
;
1652 g_vlnk_part_list
= node
;
1658 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1665 disk
= grub_disk_open(name
);
1668 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1669 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1670 grub_disk_close(disk
);
1676 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1678 const char *fs
[ventoy_fs_max
+ 1] =
1680 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1685 cur
->dev
= grub_device_open(cur
->device
);
1690 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1696 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1701 char *disk
, *device
;
1702 grub_uint32_t readcrc
, calccrc
;
1703 ventoy_vlnk_part
*cur
;
1704 grub_fs_t fs
= NULL
;
1706 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1710 grub_printf("VLNK invalid guid\n");
1716 readcrc
= vlnk
->crc32
;
1718 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1719 if (readcrc
!= calccrc
)
1723 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1729 if (!g_vlnk_part_list
)
1731 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1734 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1736 if (cur
->disksig
== vlnk
->disk_signature
)
1740 if (cur
->partoffset
== vlnk
->part_offset
)
1743 device
= cur
->device
;
1745 if (cur
->probe
== 0)
1748 ventoy_vlnk_probe_fs(cur
);
1758 struct grub_file file
;
1760 grub_memset(&file
, 0, sizeof(file
));
1761 file
.device
= cur
->dev
;
1762 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1765 cur
->fs
->fs_close(&file
);
1766 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1775 grub_printf("\n==== VLNK Information ====\n"
1776 "Disk Signature: %08x\n"
1777 "Partition Offset: %llu\n"
1778 "File Path: <%s>\n\n",
1779 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1783 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1787 grub_printf("Disk Find: [ NO ]\n");
1792 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1796 grub_printf("Part Find: [ NO ]\n");
1798 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1801 grub_printf("VLNK File: <%s>\n", dst
);
1808 return (1 - filefind
);
1811 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1816 grub_file_t file
= NULL
;
1821 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1823 else if (dir
[0] == '/')
1825 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1829 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1832 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1838 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1839 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1840 grub_file_close(file
);
1842 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1844 rc
= grub_file_add_vlnk(src
, dst
);
1850 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1860 const menu_tip
*tip
;
1861 img_iterator_node
*tmp
;
1862 img_iterator_node
*new_node
;
1863 img_iterator_node
*node
= (img_iterator_node
*)data
;
1865 if (g_enumerate_time_checked
== 0)
1867 g_enumerate_finish_time_ms
= grub_get_time_ms();
1868 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1871 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1873 g_enumerate_time_checked
= 1;
1877 len
= grub_strlen(filename
);
1881 if (node
->level
+ 1 > g_img_max_search_level
)
1886 if ((len
== 1 && filename
[0] == '.') ||
1887 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1892 if (!ventoy_img_name_valid(filename
, len
))
1897 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1902 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1904 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1905 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1908 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1913 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1916 new_node
->level
= node
->level
+ 1;
1917 new_node
->plugin_list_index
= index
;
1918 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1920 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1923 debug("Directory %s ignored...\n", new_node
->dir
);
1924 grub_free(new_node
);
1928 new_node
->tail
= node
->tail
;
1930 new_node
->parent
= node
;
1931 if (!node
->firstchild
)
1933 node
->firstchild
= new_node
;
1936 if (g_img_iterator_tail
)
1938 g_img_iterator_tail
->next
= new_node
;
1939 g_img_iterator_tail
= new_node
;
1943 g_img_iterator_head
.next
= new_node
;
1944 g_img_iterator_tail
= new_node
;
1950 debug("Find a file %s\n", filename
);
1956 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1958 type
= img_type_iso
;
1960 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1962 type
= img_type_wim
;
1964 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1965 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1967 type
= img_type_vhd
;
1969 #ifdef GRUB_MACHINE_EFI
1970 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1972 type
= img_type_efi
;
1975 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1977 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1979 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1980 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1985 type
= img_type_img
;
1987 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1989 type
= img_type_vtoy
;
1991 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1993 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1995 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1996 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
2005 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
2010 if (g_plugin_image_list
)
2012 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2013 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
2014 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
2016 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2019 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2021 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2026 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2028 if (grub_file_is_vlnk_suffix(filename
, len
))
2031 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2038 img
= grub_zalloc(sizeof(img_info
));
2042 img
->plugin_list_index
= index
;
2043 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2045 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2047 img
->size
= info
->size
;
2048 if (vlnk
|| 0 == img
->size
)
2050 if (node
->dir
[0] == '/')
2052 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2056 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2060 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2062 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2067 if (g_ventoy_img_list
)
2069 tail
= *(node
->tail
);
2075 g_ventoy_img_list
= img
;
2078 img
->id
= g_ventoy_img_count
;
2080 if (node
&& NULL
== node
->firstiso
)
2082 node
->firstiso
= img
;
2093 *((img_info
**)(node
->tail
)) = img
;
2094 g_ventoy_img_count
++;
2096 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2098 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2101 img
->tip1
= tip
->tip1
;
2102 img
->tip2
= tip
->tip2
;
2105 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2108 img
->class = g_menu_class
[type
];
2110 img
->menu_prefix
= g_menu_prefix
[type
];
2112 if (img_type_iso
== type
)
2114 if (ventoy_plugin_check_memdisk(img
->path
))
2116 img
->menu_prefix
= "miso";
2119 else if (img_type_img
== type
)
2121 if (ventoy_plugin_check_memdisk(img
->path
))
2123 img
->menu_prefix
= "mimg";
2127 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2134 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2136 int len
= GRUB_UINT_MAX
;
2137 const char *value
= NULL
;
2138 char name
[32] = {0};
2139 char plat
[32] = {0};
2140 char guidstr
[32] = {0};
2141 ventoy_guid guid
= VENTOY_GUID
;
2142 const char *fmt1
= NULL
;
2143 const char *fmt2
= NULL
;
2144 const char *fmt3
= NULL
;
2145 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2146 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2147 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2148 const char fmtcode
[]={
2149 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2150 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2151 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2152 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2153 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2154 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2157 grub_memset(name
, 0, sizeof(name
));
2158 puint
[0] = grub_swap_bytes32(0x56454e54);
2159 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2160 puint
[2] = grub_swap_bytes32(0x45525349);
2161 puint
[1] = grub_swap_bytes32(0x4f595f56);
2162 value
= ventoy_get_env(name
);
2164 grub_memset(name
, 0, sizeof(name
));
2165 puint
[1] = grub_swap_bytes32(0x5f544f50);
2166 puint
[0] = grub_swap_bytes32(0x56544c45);
2167 fmt1
= ventoy_get_env(name
);
2173 grub_memset(name
, 0, sizeof(name
));
2174 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2175 puint
[0] = grub_swap_bytes32(0x56544c45);
2176 fmt2
= ventoy_get_env(name
);
2178 grub_memset(name
, 0, sizeof(name
));
2179 puint
[1] = grub_swap_bytes32(0x5f434c52);
2180 puint
[0] = grub_swap_bytes32(0x56544c45);
2181 fmt3
= ventoy_get_env(name
);
2183 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2185 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2187 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2188 #pragma GCC diagnostic push
2189 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2190 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2191 fmt1
? fmt1
: fmtdata
,
2192 fmt2
? fmt2
: fmtdata
+ 4,
2193 value
? value
: "", plat
, guidstr
,
2194 fmt3
? fmt3
: fmtdata
+ 6);
2195 #pragma GCC diagnostic pop
2197 grub_memset(name
, 0, sizeof(name
));
2198 puint
[0] = grub_swap_bytes32(0x76746f79);
2199 puint
[2] = grub_swap_bytes32(0x656e7365);
2200 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2201 ventoy_set_env(name
, guidstr
);
2207 ventoy_password_get (char buf
[], unsigned buf_size
)
2209 unsigned i
, cur_len
= 0;
2211 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2215 key
= grub_getkey ();
2216 if (key
== '\n' || key
== '\r')
2219 if (key
== GRUB_TERM_ESC
)
2229 grub_term_restore_pos (pos
);
2230 for (i
= 0; i
< cur_len
; i
++)
2232 grub_term_restore_pos (pos
);
2234 for (i
= 0; i
< cur_len
; i
++)
2241 if (!grub_isprint (key
))
2244 if (cur_len
+ 2 < buf_size
)
2245 buf
[cur_len
++] = key
;
2250 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2256 return (key
!= GRUB_TERM_ESC
);
2259 static int ventoy_get_password(char buf
[], unsigned buf_size
)
2261 const char *env
= NULL
;
2263 env
= grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2264 if (env
&& env
[0] == '0' && env
[1] == 0)
2266 return grub_password_get(buf
, buf_size
);
2270 return ventoy_password_get(buf
, buf_size
);
2274 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2278 grub_uint8_t md5
[16];
2282 grub_memset(input
, 0, sizeof(input
));
2284 grub_printf("Enter password: ");
2287 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2289 ventoy_get_password(input
, 128);
2290 if (grub_strcmp(pwd
->text
, input
) == 0)
2295 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2297 ventoy_get_password(input
, 128);
2298 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2299 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2304 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2306 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2307 ventoy_get_password(input
+ offset
, 128);
2309 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2310 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2316 grub_printf("Invalid password!\n\n");
2323 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2325 img_info
*minimg
= NULL
;
2326 img_info
*img
= (img_info
*)(node
->firstiso
);
2328 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2330 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2345 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2347 img_iterator_node
*Minchild
= NULL
;
2348 img_iterator_node
*child
= node
->firstchild
;
2350 while (child
&& child
->parent
== node
)
2352 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2356 child
= child
->next
;
2361 Minchild
->select
= 1;
2367 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2370 img_info
*img
= NULL
;
2371 const char *dir_class
= NULL
;
2372 const char *dir_alias
= NULL
;
2373 img_iterator_node
*child
= NULL
;
2374 const menu_tip
*tip
= NULL
;
2376 if (node
->isocnt
== 0 || node
->done
== 1)
2381 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2383 offset
= node
->parent
->dirlen
;
2386 if (node
== &g_img_iterator_head
)
2388 if (g_default_menu_mode
== 0)
2390 if (g_tree_view_menu_style
== 0)
2392 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2393 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2394 " echo 'return ...' \n"
2395 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2399 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2400 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2401 " echo 'return ...' \n"
2402 "}\n", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2406 g_tree_script_pre
= g_tree_script_pos
;
2410 node
->dir
[node
->dirlen
- 1] = 0;
2411 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2414 dir_class
= "vtoydir";
2417 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2419 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2422 if (g_tree_view_menu_style
== 0)
2424 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2425 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2426 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2430 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2431 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2432 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2437 dir_alias
= node
->dir
+ offset
;
2439 if (g_tree_view_menu_style
== 0)
2441 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2442 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2443 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2447 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2448 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2449 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2453 if (g_tree_view_menu_style
== 0)
2455 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2456 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2457 " echo 'return ...' \n"
2458 "}\n", "<--", node
->dir
);
2462 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2463 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2464 " echo 'return ...' \n"
2469 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2471 ventoy_dynamic_tree_menu(child
);
2474 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2476 if (g_tree_view_menu_style
== 0)
2478 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2479 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2482 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2483 img
->unsupport
? "[***********] " : "",
2484 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2486 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2490 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2491 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2494 img
->unsupport
? "[***********] " : "",
2495 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2497 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2501 if (node
!= &g_img_iterator_head
)
2503 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2510 static int ventoy_set_default_menu(void)
2516 const char *strdata
= NULL
;
2517 img_info
*cur
= NULL
;
2518 img_info
*default_node
= NULL
;
2519 const char *default_image
= NULL
;
2521 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2522 if (default_image
&& default_image
[0] == '/')
2524 img_len
= grub_strlen(default_image
);
2526 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2528 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2540 if (0 == g_default_menu_mode
)
2542 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2546 def
= grub_strdup(default_image
);
2552 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2554 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2555 if (strdata
&& strdata
[0] == '/')
2557 pos
= def
+ grub_strlen(strdata
);
2568 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2571 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2575 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2583 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2585 img_info
*next
= NULL
;
2586 img_info
*cur
= g_ventoy_img_list
;
2599 g_ventoy_img_list
= NULL
;
2600 g_ventoy_img_count
= 0;
2602 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2605 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2608 img_info
*cur
= g_ventoy_img_list
;
2612 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2614 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2617 img_id
= grub_strtol(args
[0], NULL
, 10);
2618 if (img_id
>= g_ventoy_img_count
)
2620 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2623 debug("Find image %ld name \n", img_id
);
2625 while (cur
&& img_id
> 0)
2633 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2636 debug("image name is %s\n", cur
->name
);
2638 grub_env_set(args
[1], cur
->name
);
2640 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2643 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2647 img_info
*cur
= g_ventoy_img_list
;
2653 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2656 len
= (int)grub_strlen(args
[0]);
2660 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2669 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2672 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2673 grub_env_set("chosen", id
);
2674 grub_env_export("chosen");
2676 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2679 static char g_fake_vlnk_src
[512];
2680 static char g_fake_vlnk_dst
[512];
2681 static grub_uint64_t g_fake_vlnk_size
;
2682 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2688 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2690 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2691 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2693 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2695 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2698 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2704 g_fake_vlnk_src
[0] = 0;
2705 g_fake_vlnk_dst
[0] = 0;
2706 g_fake_vlnk_size
= 0;
2707 grub_file_vtoy_vlnk(NULL
, NULL
);
2709 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2713 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2718 const char *id
= NULL
;
2719 img_info
*cur
= NULL
;
2723 if (argc
< 1 || argc
> 3)
2725 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2728 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2730 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2731 grub_env_set(args
[0], pos
);
2734 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2735 grub_env_set(args
[1], value
);
2740 for (last
= pos
; *pos
; pos
++)
2747 grub_env_set(args
[2], last
+ 1);
2753 id
= grub_env_get("chosen");
2755 pos
= grub_strstr(id
, "VID_");
2758 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2762 cur
= g_ventoy_img_list
;
2767 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2770 grub_env_set(args
[0], cur
->path
);
2774 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2775 grub_env_set(args
[1], value
);
2780 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2781 grub_env_set(args
[2], cur
->name
);
2785 g_svd_replace_offset
= 0;
2787 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2791 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2795 grub_device_t dev
= NULL
;
2796 img_info
*cur
= NULL
;
2797 img_info
*tail
= NULL
;
2798 img_info
*min
= NULL
;
2799 img_info
*head
= NULL
;
2800 const char *strdata
= NULL
;
2801 char *device_name
= NULL
;
2803 img_iterator_node
*node
= NULL
;
2804 img_iterator_node
*tmp
= NULL
;
2810 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2813 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2815 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2820 g_enumerate_time_checked
= 0;
2821 g_enumerate_start_time_ms
= grub_get_time_ms();
2823 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2824 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2826 g_filt_dot_underscore_file
= 1;
2829 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2830 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2832 g_sort_case_sensitive
= 1;
2835 device_name
= grub_file_get_device_name(args
[0]);
2841 g_enum_dev
= dev
= grub_device_open(device_name
);
2847 g_enum_fs
= fs
= grub_fs_probe(dev
);
2853 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2855 debug("unsupported fs:<%s>\n", fs
->name
);
2856 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2860 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2862 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2863 if (strdata
&& strdata
[0] == '1')
2865 g_default_menu_mode
= 1;
2868 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2870 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2872 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2873 if (strdata
&& strdata
[0] == '/')
2875 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2876 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2878 g_img_iterator_head
.dir
[len
++] = '/';
2880 g_img_iterator_head
.dirlen
= len
;
2884 g_img_iterator_head
.dirlen
= 1;
2885 grub_strcpy(g_img_iterator_head
.dir
, "/");
2888 g_img_iterator_head
.tail
= &tail
;
2890 if (g_img_max_search_level
< 0)
2892 g_img_max_search_level
= GRUB_INT_MAX
;
2893 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2894 if (strdata
&& ventoy_is_decimal(strdata
))
2896 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2900 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2901 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2902 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2903 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2904 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2905 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2907 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2909 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2912 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2913 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2915 g_tree_view_menu_style
= 1;
2918 ventoy_set_default_menu();
2920 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2922 ventoy_dynamic_tree_menu(node
);
2926 node
= g_img_iterator_head
.next
;
2934 /* sort image list by image name */
2935 while (g_ventoy_img_list
)
2937 min
= g_ventoy_img_list
;
2938 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2940 if (ventoy_cmp_img(min
, cur
) > 0)
2948 min
->prev
->next
= min
->next
;
2953 min
->next
->prev
= min
->prev
;
2956 if (min
== g_ventoy_img_list
)
2958 g_ventoy_img_list
= min
->next
;
2976 g_ventoy_img_list
= head
;
2978 if (g_default_menu_mode
== 1)
2980 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2981 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2982 " echo 'return ...' \n"
2983 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_TREEVIEW"));
2986 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2988 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2989 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2992 cur
->unsupport
? "[***********] " : "",
2993 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2995 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2998 g_tree_script_buf
[g_tree_script_pos
] = 0;
2999 g_list_script_buf
[g_list_script_pos
] = 0;
3001 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
3002 grub_env_set(args
[1], buf
);
3006 check_free(device_name
, grub_free
);
3007 check_free(dev
, grub_device_close
);
3009 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3012 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
3019 device_name
= grub_file_get_device_name(filename
);
3031 pos2
= grub_strstr(pos
, ",");
3034 pos2
= grub_strstr(pos
, ")");
3042 disk
= grub_disk_open(pos
);
3045 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3046 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3047 grub_disk_close(disk
);
3054 grub_free(device_name
);
3058 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3060 eltorito_descriptor desc
;
3062 grub_memset(&desc
, 0, sizeof(desc
));
3063 grub_file_seek(file
, 17 * 2048);
3064 grub_file_read(file
, &desc
, sizeof(desc
));
3066 if (desc
.type
!= 0 || desc
.version
!= 1)
3071 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3072 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3080 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3082 grub_uint8_t buf
[512];
3084 grub_file_seek(file
, sector
* 2048);
3085 grub_file_read(file
, buf
, sizeof(buf
));
3087 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3088 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3090 return *((grub_uint32_t
*)(buf
+ 40));
3096 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3100 grub_uint8_t buf
[512];
3101 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3103 grub_file_seek(file
, sector
* 2048);
3104 grub_file_read(file
, buf
, sizeof(buf
));
3106 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3108 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3112 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3117 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3119 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3121 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3125 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3127 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3132 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3134 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3136 if (buf
[36] == parttype
[i
])
3138 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3144 debug("%s does not contain efi eltorito\n", file
->name
);
3148 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3151 const char *fs
= NULL
;
3152 const char *val
= NULL
;
3153 const char *cdprompt
= NULL
;
3155 grub_uint8_t chksum
= 0;
3158 disk
= file
->device
->disk
;
3159 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3161 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3162 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3163 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3165 pos
= grub_strstr(file
->name
, "/");
3171 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3173 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3175 param
->vtoy_img_size
= file
->size
;
3177 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3178 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3180 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3182 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3183 param
->vtoy_reserved
[4] = 0;
3184 if (g_ventoy_chain_type
== 1) /* Windows */
3186 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3187 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3189 param
->vtoy_reserved
[4] = 1;
3193 fs
= ventoy_get_env("ventoy_fs_probe");
3194 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3196 param
->vtoy_reserved
[3] = 1;
3199 param
->vtoy_reserved
[5] = 0;
3200 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3201 if (val
&& val
[0] == '1' && val
[1] == 0)
3203 param
->vtoy_reserved
[5] = 1;
3206 /* ventoy_disk_signature used for vlnk */
3207 param
->vtoy_reserved
[6] = file
->vlnk
;
3208 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3210 /* calculate checksum */
3211 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3213 chksum
+= *((grub_uint8_t
*)param
+ i
);
3215 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3220 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3222 grub_uint32_t i
= 0;
3223 grub_uint64_t total
= 0;
3224 grub_uint64_t fileblk
= 0;
3225 ventoy_img_chunk
*chunk
= NULL
;
3227 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3229 chunk
= chunklist
->chunk
+ i
;
3231 if (chunk
->disk_start_sector
<= start
)
3233 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3237 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3240 fileblk
= (file
->size
+ 511) / 512;
3242 if (total
!= fileblk
)
3244 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3245 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3247 debug("maybe img file to be processed.\n");
3257 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3261 grub_uint32_t i
= 0;
3262 grub_uint32_t sector
= 0;
3263 grub_uint32_t count
= 0;
3264 grub_off_t size
= 0;
3265 grub_off_t read
= 0;
3267 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3268 if (fs_type
== ventoy_fs_exfat
)
3270 grub_fat_get_file_chunk(start
, file
, chunklist
);
3272 else if (fs_type
== ventoy_fs_ext
)
3274 grub_ext_get_file_chunk(start
, file
, chunklist
);
3278 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3279 file
->read_hook_data
= chunklist
;
3281 for (size
= file
->size
; size
> 0; size
-= read
)
3283 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3284 grub_file_read(file
, NULL
, read
);
3287 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3289 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3290 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3293 if (ventoy_fs_udf
== fs_type
)
3295 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3297 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3298 chunklist
->chunk
[i
].img_start_sector
= sector
;
3299 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3305 len
= (int)grub_strlen(file
->name
);
3306 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3307 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3308 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3309 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3311 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3313 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3323 chunklist
->chunk
[i
].img_start_sector
= sector
;
3324 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3332 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3336 grub_disk_addr_t start
;
3341 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3344 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3347 g_conf_replace_count
= 0;
3348 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3349 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3351 if (g_img_chunk_list
.chunk
)
3353 grub_free(g_img_chunk_list
.chunk
);
3356 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3358 grub_file_close(file
);
3359 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3362 /* get image chunk data */
3363 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3364 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3365 if (NULL
== g_img_chunk_list
.chunk
)
3367 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3370 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3371 g_img_chunk_list
.cur_chunk
= 0;
3373 start
= file
->device
->disk
->partition
->start
;
3375 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3377 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3378 grub_file_close(file
);
3382 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3385 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3386 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3387 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3390 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3394 grub_uint64_t offset
= 0;
3395 grub_uint32_t align
= 0;
3396 grub_file_t file
= NULL
;
3397 conf_replace
*node
= NULL
;
3398 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3399 ventoy_grub_param_file_replace
*replace
= NULL
;
3405 debug("select conf replace argc:%d\n", argc
);
3412 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3415 debug("Conf replace not found for %s\n", args
[1]);
3419 debug("Find %d conf replace for %s\n", n
, args
[1]);
3421 g_conf_replace_count
= n
;
3422 for (i
= 0; i
< n
; i
++)
3426 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3429 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3430 grub_file_close(file
);
3432 else if (node
->img
> 0)
3438 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3442 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3445 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3449 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3451 if (align
> vtoy_max_replace_file_size
)
3453 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3454 grub_file_close(file
);
3458 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3459 grub_file_close(file
);
3460 g_conf_replace_new_len
[i
] = (int)file
->size
;
3461 g_conf_replace_new_len_align
[i
] = align
;
3463 g_conf_replace_node
[i
] = node
;
3464 g_conf_replace_offset
[i
] = offset
+ 2;
3468 replace
= &(g_grub_param
->img_replace
[i
]);
3469 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3470 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3471 replace
->old_name_cnt
++;
3474 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3478 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3481 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3486 const char *ch
= var
;
3493 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3500 debug("Invalid variable letter <%c>\n", *ch
);
3507 debug("Invalid variable length:%d <%s>\n", n
, var
);
3511 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3520 grub_printf("\n=================== Variables Expansion ===================\n\n");
3523 grub_printf("<%s>: ", var
);
3526 while (i
< (len
- 1))
3529 if ((c
== '\n') || (c
== '\r'))
3539 else if (grub_isprint(c
))
3541 if (i
+ 1 < (len
- 1))
3543 grub_printf("%c", c
);
3553 expand
[i
- 1] = ' ';
3554 grub_printf("\r<%s>: %s", var
, expand
);
3557 grub_printf("\r<%s>: %s", var
, expand
);
3569 grub_snprintf(expand
, len
, "$$%s$$", var
);
3575 static int ventoy_auto_install_var_expand(install_template
*node
)
3583 char *newbuf
= NULL
;
3584 char *curline
= NULL
;
3585 char *nextline
= NULL
;
3586 grub_uint8_t
*code
= NULL
;
3588 var_node
*CurNode
= NULL
;
3589 var_node
*pVarList
= NULL
;
3591 code
= (grub_uint8_t
*)node
->filebuf
;
3593 if (node
->filelen
>= VTOY_SIZE_1MB
)
3595 debug("auto install script too long %d\n", node
->filelen
);
3599 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3601 debug("UCS-2 encoding NOT supported\n");
3605 start
= grub_strstr(node
->filebuf
, "$$");
3608 debug("no need to expand variable, no start.\n");
3612 end
= grub_strstr(start
+ 2, "$$");
3615 debug("no need to expand variable, no end.\n");
3619 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3620 newbuf
= grub_malloc(newlen
);
3623 debug("Failed to alloc newbuf %d\n", newlen
);
3627 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3629 nextline
= ventoy_get_line(curline
);
3631 start
= grub_strstr(curline
, "$$");
3634 end
= grub_strstr(start
+ 2, "$$");
3640 VTOY_APPEND_NEWBUF(curline
);
3642 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3644 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3646 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3653 value
[sizeof(value
) - 1] = 0;
3654 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3658 CurNode
= grub_zalloc(sizeof(var_node
));
3661 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3662 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3663 CurNode
->next
= pVarList
;
3669 VTOY_APPEND_NEWBUF(value
);
3671 VTOY_APPEND_NEWBUF(end
+ 2);
3675 VTOY_APPEND_NEWBUF(curline
);
3678 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3680 newbuf
[pos
- 1] = '\n';
3684 newbuf
[pos
++] = '\n';
3688 grub_free(node
->filebuf
);
3689 node
->filebuf
= newbuf
;
3690 node
->filelen
= pos
;
3694 CurNode
= pVarList
->next
;
3695 grub_free(pVarList
);
3702 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3708 grub_file_t file
= NULL
;
3709 char configfile
[128];
3710 install_template
*node
= NULL
;
3716 debug("select auto installation argc:%d\n", argc
);
3723 node
= ventoy_plugin_find_install_template(args
[0]);
3726 debug("Auto install template not found for %s\n", args
[0]);
3730 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3732 defidx
= node
->autosel
;
3733 if (node
->timeout
< 0)
3735 node
->cursel
= node
->autosel
- 1;
3736 debug("Auto install template auto select %d\n", node
->autosel
);
3741 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3747 if (node
->timeout
> 0)
3749 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3752 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3753 " echo %s\n}\n", "");
3755 for (i
= 0; i
< node
->templatenum
; i
++)
3757 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3759 ventoy_get_vmenu_title("VTLANG_AUTOINS_USE"),
3760 node
->templatepath
[i
].path
);
3763 g_ventoy_menu_esc
= 1;
3764 g_ventoy_suppress_esc
= 1;
3765 g_ventoy_suppress_esc_default
= defidx
;
3767 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3768 grub_script_execute_sourcecode(configfile
);
3770 g_ventoy_menu_esc
= 0;
3771 g_ventoy_suppress_esc
= 0;
3772 g_ventoy_suppress_esc_default
= 1;
3776 node
->cursel
= g_ventoy_last_entry
- 1;
3779 grub_check_free(node
->filebuf
);
3782 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3784 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3785 node
->templatepath
[node
->cursel
].path
);
3788 node
->filebuf
= grub_malloc(file
->size
+ 8);
3791 grub_file_read(file
, node
->filebuf
, file
->size
);
3792 grub_file_close(file
);
3794 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3795 node
->filelen
= (int)file
->size
;
3797 ventoy_auto_install_var_expand(node
);
3802 debug("Failed to open auto install script <%s%s>\n",
3803 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3807 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3810 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3816 char configfile
[128];
3817 persistence_config
*node
;
3823 debug("select persistence argc:%d\n", argc
);
3830 node
= ventoy_plugin_find_persistent(args
[0]);
3833 debug("Persistence image not found for %s\n", args
[0]);
3837 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3839 defidx
= node
->autosel
;
3840 if (node
->timeout
< 0)
3842 node
->cursel
= node
->autosel
- 1;
3843 debug("Persistence image auto select %d\n", node
->autosel
);
3848 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3854 if (node
->timeout
> 0)
3856 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3859 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_PERSISTENCE\" --class=\"sel_persistence\" {\n"
3860 " echo %s\n}\n", "");
3862 for (i
= 0; i
< node
->backendnum
; i
++)
3864 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3866 ventoy_get_vmenu_title("VTLANG_PERSIST_USE"),
3867 node
->backendpath
[i
].path
);
3871 g_ventoy_menu_esc
= 1;
3872 g_ventoy_suppress_esc
= 1;
3873 g_ventoy_suppress_esc_default
= defidx
;
3875 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3876 grub_script_execute_sourcecode(configfile
);
3878 g_ventoy_menu_esc
= 0;
3879 g_ventoy_suppress_esc
= 0;
3880 g_ventoy_suppress_esc_default
= 1;
3884 node
->cursel
= g_ventoy_last_entry
- 1;
3886 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3889 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3892 ventoy_img_chunk
*cur
;
3898 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3900 cur
= g_img_chunk_list
.chunk
+ i
;
3901 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3902 cur
->img_start_sector
, cur
->img_end_sector
,
3903 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3907 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3910 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3914 ventoy_img_chunk_list chunklist
;
3919 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3922 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3925 /* get image chunk data */
3926 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3927 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3928 if (NULL
== chunklist
.chunk
)
3930 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3933 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3934 chunklist
.cur_chunk
= 0;
3936 ventoy_get_block_list(file
, &chunklist
, 0);
3938 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3940 grub_printf("########## UNSUPPORTED ###############\n");
3943 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3945 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3947 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3948 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3951 grub_printf("\n==================================\n");
3953 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3955 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3956 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3957 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3958 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3959 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3963 grub_free(chunklist
.chunk
);
3964 grub_file_close(file
);
3966 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3969 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3972 ventoy_grub_param_file_replace
*replace
= NULL
;
3980 replace
= &(g_grub_param
->file_replace
);
3981 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3983 replace
->old_name_cnt
= 0;
3984 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3986 replace
->old_name_cnt
++;
3987 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3990 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3993 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3996 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3999 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
4005 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
4006 grub_env_set(args
[0], buf
);
4009 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4012 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4020 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4021 grub_printf("%s", g_list_script_buf
);
4025 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4026 grub_printf("%s", g_tree_script_buf
);
4032 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4034 img_info
*cur
= g_ventoy_img_list
;
4042 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4043 grub_printf("name:<%s>\n\n", cur
->name
);
4050 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4056 ventoy_plugin_dump_injection();
4061 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4067 ventoy_plugin_dump_auto_install();
4072 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4078 ventoy_plugin_dump_persistence();
4083 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4089 len1
= (int)grub_strlen(filename
);
4090 len2
= (int)grub_strlen(suffix
);
4097 for (i
= len1
- 1; i
>= 0; i
--)
4099 if (filename
[i
] == '.')
4110 if (filename
[i
- len2
- 1] != '_')
4115 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4123 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4129 if (argc
!= 1 && argc
!= 2)
4134 if (args
[0][0] == '0')
4136 if (g_ventoy_memdisk_mode
)
4141 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4148 else if (args
[0][0] == '1')
4150 return g_ventoy_iso_raw
? 0 : 1;
4152 else if (args
[0][0] == '2')
4154 return g_ventoy_iso_uefi_drv
? 0 : 1;
4156 else if (args
[0][0] == '3')
4158 if (g_ventoy_grub2_mode
)
4163 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4170 else if (args
[0][0] == '4')
4172 if (g_ventoy_wimboot_mode
)
4177 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4188 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4190 static int configfile_mode
= 0;
4191 char memfile
[128] = {0};
4198 * args[0]: 0:normal 1:configfile
4199 * args[1]: 0:list_buf 1:tree_buf
4204 debug("Invalid argc %d\n", argc
);
4210 if (args
[0][0] == '0')
4212 if (args
[1][0] == '0')
4214 grub_script_execute_sourcecode(g_list_script_buf
);
4218 grub_script_execute_sourcecode(g_tree_script_buf
);
4223 if (configfile_mode
)
4225 debug("Now already in F3 mode %d\n", configfile_mode
);
4229 if (args
[1][0] == '0')
4231 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4232 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4236 g_ventoy_last_entry
= -1;
4237 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4238 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4241 configfile_mode
= 1;
4242 grub_script_execute_sourcecode(memfile
);
4243 configfile_mode
= 0;
4249 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4260 g_ventoy_case_insensitive
= 1;
4261 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4262 g_ventoy_case_insensitive
= 0;
4268 grub_file_close(file
);
4274 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4279 const char *isopath
= NULL
;
4281 ventoy_mbr_head mbr
;
4288 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4291 isopath
= grub_env_get("vtoy_iso_part");
4294 debug("isopath is null %p\n", isopath
);
4298 debug("isopath is %s\n", isopath
);
4300 for (id
= 0; id
< 30 && (find
== 0); id
++)
4302 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4303 if (grub_strstr(isopath
, hdname
))
4305 debug("skip %s ...\n", hdname
);
4309 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4311 disk
= grub_disk_open(hdname
);
4314 debug("%s not exist\n", hdname
);
4318 grub_memset(&mbr
, 0, sizeof(mbr
));
4319 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4321 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4323 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4324 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4327 grub_env_set(args
[0], hdname
);
4331 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4335 debug("read %s failed\n", hdname
);
4338 grub_disk_close(disk
);
4344 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4355 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4358 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4361 debug("failed to open file %s\n", args
[0]);
4365 buf
= grub_malloc(len
);
4372 grub_file_read(file
, buf
, len
- 1);
4374 ventoy_get_line(buf
);
4375 ventoy_set_env(args
[1], buf
);
4379 grub_check_free(buf
);
4380 grub_file_close(file
);
4385 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4387 grub_uint64_t end_max
= 0;
4388 int *pCnt
= (int *)data
;
4393 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4394 "0 %llu linear /dev/ventoy %llu\n",
4395 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4397 end_max
= (partition
->len
+ partition
->start
) * 512;
4398 if (end_max
> g_part_end_max
)
4400 g_part_end_max
= end_max
;
4406 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4409 char *device_name
= NULL
;
4410 grub_device_t dev
= NULL
;
4415 g_part_list_pos
= 0;
4417 grub_env_unset("vtoy_img_part_file");
4424 device_name
= grub_file_get_device_name(args
[0]);
4427 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4431 dev
= grub_device_open(device_name
);
4434 debug("grub_device_open failed, %s\n", device_name
);
4438 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4440 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4441 grub_env_set("vtoy_img_part_file", buf
);
4443 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4444 grub_env_set("vtoy_img_part_cnt", buf
);
4446 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4447 grub_env_set("vtoy_img_max_part_end", buf
);
4451 check_free(device_name
, grub_free
);
4452 check_free(dev
, grub_device_close
);
4458 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4469 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4472 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4475 debug("failed to open file %s\n", args
[0]);
4479 buf
= grub_malloc(file
->size
+ 1);
4485 buf
[file
->size
] = 0;
4486 grub_file_read(file
, buf
, file
->size
);
4488 if (grub_strstr(buf
, args
[1]))
4495 grub_check_free(buf
);
4496 grub_file_close(file
);
4501 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4507 ventoy_iso9660_vd pvd
;
4514 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4517 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4520 debug("failed to open file %s\n", args
[0]);
4524 grub_file_seek(file
, 16 * 2048);
4525 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4526 if (len
!= sizeof(pvd
))
4528 debug("failed to read pvd %d\n", len
);
4532 grub_memset(buf
, 0, sizeof(buf
));
4533 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4534 ventoy_set_env(args
[1], buf
);
4536 grub_memset(buf
, 0, sizeof(buf
));
4537 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4538 ventoy_set_env(args
[2], buf
);
4542 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4543 ventoy_set_env(args
[3], buf
);
4546 grub_file_close(file
);
4551 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4562 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4565 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4568 debug("failed to open file %s\n", args
[0]);
4572 grub_memset(buf
, 0, sizeof(buf
));
4573 grub_file_seek(file
, 16 * 2048 + 813);
4574 len
= (int)grub_file_read(file
, buf
, 17);
4577 debug("failed to read create date %d\n", len
);
4581 ventoy_set_env(args
[1], buf
);
4584 grub_file_close(file
);
4589 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4595 ventoy_env_hook_root(1);
4600 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4606 ventoy_env_hook_root(0);
4611 #ifdef GRUB_MACHINE_EFI
4612 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4617 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4623 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4624 if (var
&& *var
== 1)
4632 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4641 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4646 grub_uint64_t FileSectors
= 0;
4647 ventoy_gpt_info
*gpt
= NULL
;
4648 ventoy_part_table
*pt
= NULL
;
4649 grub_uint8_t zeroguid
[16] = {0};
4654 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4657 debug("failed to open file %s\n", args
[0]);
4661 if (file
->size
% 512)
4663 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4667 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4673 FileSectors
= file
->size
/ 512;
4675 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4676 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4678 debug("This is EFI partition table\n");
4680 for (i
= 0; i
< 128; i
++)
4682 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4684 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4686 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4687 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4695 debug("This is MBR partition table\n");
4697 for (i
= 0; i
< 4; i
++)
4699 pt
= gpt
->MBR
.PartTbl
+ i
;
4700 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4702 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4703 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4704 (ulonglong
)FileSectors
);
4713 grub_file_close(file
);
4714 grub_check_free(gpt
);
4715 grub_errno
= GRUB_ERR_NONE
;
4719 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4728 for (i
= 0; i
< 500; i
++)
4730 ret
= grub_getkey_noblock();
4731 if (ret
== GRUB_TERM_NO_KEY
)
4740 grub_printf("\n\n Still have key input after clear.\n");
4748 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4755 int image_sector_size
;
4757 ventoy_chain_head
*chain
;
4758 ventoy_img_chunk
*chunk
;
4759 ventoy_os_param
*osparam
;
4760 ventoy_image_location
*location
;
4761 ventoy_image_disk_region
*region
;
4762 struct grub_acpi_table_header
*acpi
;
4771 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4773 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4779 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4781 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4783 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4787 img_chunk_num
= chain
->img_chunk_num
;
4789 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4790 datalen
= sizeof(ventoy_os_param
) + loclen
;
4792 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4793 acpi
= grub_zalloc(buflen
);
4799 /* Step1: Fill acpi table header */
4800 grub_memcpy(acpi
->signature
, "VTOY", 4);
4801 acpi
->length
= buflen
;
4803 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4804 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4806 acpi
->creator_id
[0] = 1;
4807 acpi
->creator_rev
= 1;
4809 /* Step2: Fill data */
4810 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4811 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4812 osparam
->vtoy_img_location_addr
= 0;
4813 osparam
->vtoy_img_location_len
= loclen
;
4814 osparam
->chksum
= 0;
4815 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4817 location
= (ventoy_image_location
*)(osparam
+ 1);
4818 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4819 location
->image_sector_size
= image_sector_size
;
4820 location
->disk_sector_size
= chain
->disk_sector_size
;
4821 location
->region_count
= img_chunk_num
;
4823 region
= location
->regions
;
4824 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4825 if (512 == image_sector_size
)
4827 for (i
= 0; i
< img_chunk_num
; i
++)
4829 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4830 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4831 region
->disk_start_sector
= chunk
->disk_start_sector
;
4838 for (i
= 0; i
< img_chunk_num
; i
++)
4840 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4841 region
->image_start_sector
= chunk
->img_start_sector
;
4842 region
->disk_start_sector
= chunk
->disk_start_sector
;
4848 /* Step3: Fill acpi checksum */
4850 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4852 /* load acpi table */
4853 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4854 grub_script_execute_sourcecode(cmd
);
4858 VENTOY_CMD_RETURN(0);
4861 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4867 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4868 g_ventoy_last_entry
= -1;
4873 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4879 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4884 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4886 const char *pos
= filename
+ 1;
4894 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4896 grub_strncpy((char *)data
, filename
, 128);
4907 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4910 char *device_name
= NULL
;
4911 grub_device_t dev
= NULL
;
4912 grub_fs_t fs
= NULL
;
4913 char buf
[128] = {0};
4919 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4923 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4925 device_name
= grub_file_get_device_name(args
[0]);
4928 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4932 dev
= grub_device_open(device_name
);
4935 debug("grub_device_open failed, %s\n", device_name
);
4939 fs
= grub_fs_probe(dev
);
4942 debug("grub_fs_probe failed, %s\n", device_name
);
4946 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4950 ventoy_set_env(args
[2], buf
);
4957 check_free(device_name
, grub_free
);
4958 check_free(dev
, grub_device_close
);
4963 int ventoy_load_part_table(const char *diskname
)
4970 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4971 if (!g_ventoy_part_info
)
4976 disk
= grub_disk_open(diskname
);
4979 debug("Failed to open disk %s\n", diskname
);
4983 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4985 g_ventoy_disk_bios_id
= disk
->id
;
4987 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4988 grub_disk_close(disk
);
4990 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4991 dev
= grub_device_open(name
);
4994 /* Check for official Ventoy device */
4995 ret
= ventoy_check_official_device(dev
);
4996 grub_device_close(dev
);
5004 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5005 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5010 static void ventoy_prompt_end(void)
5015 grub_printf("\n\n\n");
5016 grub_printf(" 1 --- Exit grub\n");
5017 grub_printf(" 2 --- Reboot\n");
5018 grub_printf(" 3 --- Shut down\n");
5019 grub_printf("Please enter your choice: ");
5025 if (c
>= '1' && c
<= '3')
5030 grub_printf("%c", c
);
5034 else if (c
== '\r' || c
== '\n')
5048 grub_script_execute_sourcecode("halt");
5057 grub_printf("\rPlease enter your choice: ");
5058 grub_printf("\rPlease enter your choice: ");
5065 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5072 ret
= ventoy_load_part_table(args
[0]);
5075 ventoy_prompt_end();
5078 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5079 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5084 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5087 const char *vcfg
= NULL
;
5092 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5095 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5096 grub_env_set(args
[1], vcfg
);
5101 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5109 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5112 grub_uint8_t zeroguid
[16] = {0};
5117 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5120 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5122 if (id
>= 1 && id
<= 128)
5124 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5132 if (id
>= 1 && id
<= 4)
5134 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5144 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5147 char *device_name
= NULL
;
5148 grub_device_t dev
= NULL
;
5149 grub_fs_t fs
= NULL
;
5154 debug("get fs label for %s\n", args
[0]);
5158 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5162 device_name
= grub_file_get_device_name(args
[0]);
5165 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5169 dev
= grub_device_open(device_name
);
5172 debug("grub_device_open failed, %s\n", device_name
);
5176 fs
= grub_fs_probe(dev
);
5177 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5179 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5183 fs
->fs_label(dev
, &label
);
5186 debug("label=<%s>\n", label
);
5187 ventoy_set_env(args
[1], label
);
5195 check_free(device_name
, grub_free
);
5196 check_free(dev
, grub_device_close
);
5201 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5205 grub_snprintf((char *)data
, 256, "%s", filename
);
5212 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5214 if (info
->dir
&& filename
&& filename
[0] != '.')
5216 grub_snprintf((char *)data
, 256, "%s", filename
);
5223 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5226 char *device_name
= NULL
;
5227 grub_device_t dev
= NULL
;
5228 grub_fs_t fs
= NULL
;
5229 char name
[256] ={0};
5233 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5237 device_name
= grub_file_get_device_name(args
[0]);
5240 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5244 dev
= grub_device_open(device_name
);
5247 debug("grub_device_open failed, %s\n", device_name
);
5251 fs
= grub_fs_probe(dev
);
5254 debug("grub_fs_probe failed, %s\n", device_name
);
5258 fs
->fs_dir(dev
, args
[1], hook
, name
);
5261 ventoy_set_env(args
[2], name
);
5268 check_free(device_name
, grub_free
);
5269 check_free(dev
, grub_device_close
);
5274 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5277 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5280 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5283 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5286 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5296 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5300 for (pos
= args
[0]; *pos
; pos
++)
5314 grub_env_set(args
[1], args
[0]);
5324 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5334 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5339 len
= (int)grub_strlen(buf
);
5340 for (i
= len
; i
> 0; i
--)
5342 if (buf
[i
- 1] == '/')
5344 grub_env_set(args
[1], buf
+ i
);
5349 grub_env_set(args
[1], buf
);
5354 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5356 struct grub_video_mode_info info
;
5363 if (!g_video_mode_list
)
5365 ventoy_enum_video_mode();
5368 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5370 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5374 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5377 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5379 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5380 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5382 VENTOY_CMD_RETURN(0);
5385 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5387 struct grub_video_mode_info info
;
5394 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5396 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5400 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5403 grub_env_set(args
[0], buf
);
5405 VENTOY_CMD_RETURN(0);
5408 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5416 if (!g_video_mode_list
)
5421 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5422 if (id
< g_video_mode_num
)
5424 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5425 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5428 grub_env_set(args
[1], buf
);
5430 VENTOY_CMD_RETURN(0);
5433 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5436 grub_uint32_t loadsector
= 0;
5439 grub_uint32_t boot_catlog
= 0;
5440 grub_uint8_t buf
[512];
5446 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5450 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5453 debug("failed to open %s\n", args
[0]);
5457 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5458 if (boot_catlog
== 0)
5460 debug("No bootcatlog found\n");
5461 grub_file_close(file
);
5465 grub_memset(buf
, 0, sizeof(buf
));
5466 grub_file_seek(file
, boot_catlog
* 2048);
5467 grub_file_read(file
, buf
, sizeof(buf
));
5468 grub_file_close(file
);
5470 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5472 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5474 if (buf
[i
+ 32] == 0x88)
5476 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5477 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5483 if (loadsector
== 0)
5485 debug("No EFI eltorito info found\n");
5489 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5490 grub_env_set(args
[1], value
);
5491 VENTOY_CMD_RETURN(0);
5494 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5499 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5501 if (pfsdir
->initrd
[0])
5506 curpos
= pfsdir
->curpos
;
5507 len
= grub_strlen(filename
);
5511 if ((len
== 1 && filename
[0] == '.') ||
5512 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5517 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5520 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5521 pfsdir
->curpos
= curpos
+ printlen
;
5522 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5523 pfsdir
->curpos
= curpos
;
5524 pfsdir
->fullpath
[curpos
] = 0;
5528 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5531 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5532 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5534 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5536 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5545 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5549 char *device_name
= NULL
;
5550 grub_device_t dev
= NULL
;
5551 grub_fs_t fs
= NULL
;
5552 replace_fs_dir
*pfsdir
= NULL
;
5558 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5562 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5568 device_name
= grub_file_get_device_name(args
[0]);
5574 dev
= grub_device_open(device_name
);
5580 fs
= grub_fs_probe(dev
);
5589 pfsdir
->fullpath
[0] = '/';
5590 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5592 if (pfsdir
->initrd
[0])
5594 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5596 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5598 if (pfsdir
->initrd
[i
] == '/')
5600 pfsdir
->initrd
[i
] = '\\';
5604 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5605 grub_env_set(args
[1], pos
);
5609 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5614 grub_check_free(pfsdir
);
5615 grub_check_free(device_name
);
5616 check_free(dev
, grub_device_close
);
5618 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5621 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5623 const char *pager
= NULL
;
5629 pager
= grub_env_get("pager");
5633 grub_env_set("pager", "1");
5635 else if (pager
[0] == '1')
5641 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5643 grub_env_set("pager", "1");
5646 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5649 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5655 if (g_pager_flag
== 1)
5657 grub_env_unset("pager");
5659 else if (g_pager_flag
== 2)
5661 grub_env_set("pager", g_old_pager
);
5664 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5667 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5669 if (g_json_case_mis_path
[0])
5674 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5676 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5682 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5685 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5687 if (g_json_case_mis_path
[0])
5692 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5694 if (grub_strcasecmp(filename
, "ventoy") == 0)
5696 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5697 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5698 if (g_json_case_mis_path
[0])
5708 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5711 char *device_name
= NULL
;
5712 grub_device_t dev
= NULL
;
5713 grub_fs_t fs
= NULL
;
5714 chk_case_fs_dir fs_dir
;
5720 device_name
= grub_file_get_device_name(args
[0]);
5726 dev
= grub_device_open(device_name
);
5732 fs
= grub_fs_probe(dev
);
5738 fstype
= ventoy_get_fs_type(fs
->name
);
5739 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5744 g_json_case_mis_path
[0] = 0;
5747 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5749 if (g_json_case_mis_path
[0])
5751 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5756 grub_check_free(device_name
);
5757 check_free(dev
, grub_device_close
);
5759 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5762 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5765 grub_partition_t part
;
5766 char priority_str
[3]; /* Maximum value 15 */
5770 if (argc
< 2 || argc
> 3)
5771 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5772 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5774 /* Open the disk if it exists */
5775 disk
= grub_disk_open (args
[0]);
5778 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5782 part
= grub_partition_probe (disk
, args
[1]);
5785 grub_disk_close (disk
);
5786 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5787 "No such partition");
5790 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5792 grub_disk_close (disk
);
5793 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5794 "Not a GPT partition");
5797 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5798 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5802 grub_env_set (args
[2], priority_str
);
5803 grub_env_export (args
[2]);
5807 grub_printf ("Priority is %s\n", priority_str
);
5810 grub_disk_close (disk
);
5811 return GRUB_ERR_NONE
;
5815 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5819 grub_file_t file
= NULL
;
5820 grub_uint32_t loadrba
= 0;
5821 grub_uint32_t boot_catlog
= 0;
5822 grub_uint8_t sector
[512];
5823 boot_info_table
*info
= NULL
;
5828 /* This also trigger a iso9660 fs parse */
5829 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5834 joliet
= grub_iso9660_is_joliet();
5840 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5843 debug("failed to open %s\n", args
[0]);
5847 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5848 if (boot_catlog
== 0)
5850 debug("no bootcatlog found %u\n", boot_catlog
);
5854 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5857 debug("no bios eltorito rba found %u\n", loadrba
);
5861 grub_file_seek(file
, loadrba
* 2048);
5862 grub_file_read(file
, sector
, 512);
5864 info
= (boot_info_table
*)sector
;
5865 if (info
->bi_data0
== 0x7c6ceafa &&
5866 info
->bi_data1
== 0x90900000 &&
5867 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5868 info
->bi_BootFileLocation
== loadrba
)
5870 debug("bootloader is syslinux, %u.\n", loadrba
);
5876 grub_file_close(file
);
5877 grub_errno
= GRUB_ERR_NONE
;
5881 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5884 ventoy_vlnk_part
*node
;
5890 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5892 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5893 ++n
, node
->device
, node
->disksig
,
5894 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5900 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5908 len
= (int)grub_strlen(args
[0]);
5909 if (grub_file_is_vlnk_suffix(args
[0], len
))
5918 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5921 const char *name
= NULL
;
5927 grub_env_unset(args
[1]);
5928 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5931 debug("VLNK SRC: <%s>\n", args
[0]);
5932 debug("VLNK DST: <%s>\n", name
);
5933 grub_env_set(args
[1], name
);
5941 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5945 grub_file_t file
= NULL
;
5956 len
= (int)grub_strlen(args
[0]);
5957 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5959 grub_printf("Invalid vlnk suffix\n");
5963 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5966 grub_printf("Failed to open %s\n", args
[0]);
5970 if (file
->size
!= 32768)
5972 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5976 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5977 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5979 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5984 check_free(file
, grub_file_close
);
5985 grub_errno
= GRUB_ERR_NONE
;
5989 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5995 g_iso_vd_id_publisher
[0] = 0;
5996 g_iso_vd_id_prepare
[0] = 0;
5997 g_iso_vd_id_application
[0] = 0;
6002 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6006 grub_file_t file
= NULL
;
6011 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
6014 grub_printf("Failed to open %s\n", args
[0]);
6018 grub_file_seek(file
, 16 * 2048 + offset
);
6019 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
6022 grub_file_seek(file
, 16 * 2048 + offset
);
6023 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
6026 grub_file_seek(file
, 16 * 2048 + offset
);
6027 grub_file_read(file
, g_iso_vd_id_application
, 128);
6031 check_free(file
, grub_file_close
);
6032 grub_errno
= GRUB_ERR_NONE
;
6036 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6039 char *id
= g_iso_vd_id_publisher
;
6044 if (args
[0][0] == '1')
6046 id
= g_iso_vd_id_prepare
;
6048 else if (args
[0][0] == '2')
6050 id
= g_iso_vd_id_application
;
6053 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6058 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6063 grub_errno
= GRUB_ERR_NONE
;
6067 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6072 g_ventoy_fn_mutex
= 0;
6073 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
6075 g_ventoy_fn_mutex
= 1;
6078 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6081 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6083 grub_uint64_t total
;
6084 grub_uint64_t org_required
;
6085 grub_uint64_t new_required
;
6091 #ifdef GRUB_MACHINE_EFI
6092 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6093 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6094 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6095 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6100 grub_printf("Non EFI mode!\n");
6105 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6108 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6110 const char *env
= NULL
;
6115 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6120 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6121 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6122 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6123 ventoy_check_mode_by_name(args
[0], "vtnormal")
6129 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6130 if (env
&& env
[0] == '0' && env
[1] == 0)
6138 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6146 const char *env
= NULL
;
6147 ulonglong fsize
= 0;
6149 int seldata
[16] = {0};
6154 len
= 8 * VTOY_SIZE_1KB
;
6155 cmd
= (char *)grub_malloc(len
);
6161 g_vtoy_secondary_need_recover
= 0;
6162 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6164 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6167 timeout
= (int)grub_strtol(env
, NULL
, 10);
6172 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6175 fsize
= grub_strtoull(args
[2], NULL
, 10);
6177 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6179 if (grub_strcmp(args
[1], "Unix") != 0)
6181 if (grub_strcmp(args
[1], "Windows") == 0)
6183 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6187 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6190 if (fsize
<= VTOY_SIZE_1GB
)
6192 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6196 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6199 g_ventoy_menu_esc
= 1;
6200 g_ventoy_suppress_esc
= 1;
6201 g_ventoy_suppress_esc_default
= 0;
6202 g_ventoy_secondary_menu_on
= 1;
6203 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6204 grub_script_execute_sourcecode(cfgfile
);
6205 g_ventoy_menu_esc
= 0;
6206 g_ventoy_suppress_esc
= 0;
6207 g_ventoy_suppress_esc_default
= 1;
6208 g_ventoy_secondary_menu_on
= 0;
6210 select
= seldata
[g_ventoy_last_entry
];
6214 g_ventoy_wimboot_mode
= 1;
6215 g_vtoy_secondary_need_recover
= 1;
6217 else if (select
== 3)
6219 g_ventoy_grub2_mode
= 1;
6220 g_vtoy_secondary_need_recover
= 2;
6222 else if (select
== 4)
6224 g_ventoy_memdisk_mode
= 1;
6225 g_vtoy_secondary_need_recover
= 3;
6227 else if (select
== 5)
6229 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6230 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6232 }while (select
== 5);
6238 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6244 if (g_vtoy_secondary_need_recover
== 1)
6246 g_ventoy_wimboot_mode
= 0;
6248 else if (g_vtoy_secondary_need_recover
== 2)
6250 g_ventoy_grub2_mode
= 0;
6252 else if (g_vtoy_secondary_need_recover
== 3)
6254 g_ventoy_memdisk_mode
= 0;
6257 g_vtoy_secondary_need_recover
= 0;
6259 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6262 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6267 if (args
[0][0] == '0')
6269 g_ventoy_case_insensitive
= 0;
6273 g_ventoy_case_insensitive
= 1;
6279 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6284 ventoy_plugin_load_menu_lang(1, args
[0]);
6285 VENTOY_CMD_RETURN(0);
6288 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6293 ventoy_plugin_load_menu_lang(0, args
[0]);
6294 VENTOY_CMD_RETURN(0);
6297 static grub_err_t
ventoy_cmd_vtoychksum_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6306 cnt
= ventoy_str_chrcnt(args
[1], '/');
6309 pos
= grub_strrchr(args
[1], '/');
6312 if (ventoy_check_file_exist("%s%s/VENTOY_CHECKSUM", args
[0], args
[1]))
6314 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6319 if (ventoy_check_file_exist("%s/VENTOY_CHECKSUM", args
[0]))
6321 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6327 static int ventoy_chksum_pathcmp(int chktype
, char *rlpath
, char *rdpath
)
6334 pos1
= ventoy_str_basename(rlpath
);
6335 pos2
= ventoy_str_basename(rdpath
);
6336 return grub_strcmp(pos1
, pos2
);
6338 else if (chktype
== 3 || chktype
== 4)
6340 if (grub_strcmp(rlpath
, rdpath
) == 0 || grub_strcmp(rlpath
+ 1, rdpath
) == 0)
6349 static int ventoy_find_checksum
6364 char *currline
= NULL
;
6365 char *nextline
= NULL
;
6367 ulen
= (int)grub_strlen(uname
);
6369 /* read file to buffer */
6370 buf
= grub_malloc(file
->size
+ 4);
6375 grub_file_read(file
, buf
, file
->size
);
6376 buf
[file
->size
] = 0;
6378 /* parse each line */
6379 for (currline
= buf
; currline
; currline
= nextline
)
6381 nextline
= ventoy_get_line(currline
);
6382 VTOY_SKIP_SPACE(currline
);
6384 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6386 pos
= grub_strchr(currline
, '=');
6387 pos1
= grub_strchr(currline
, '(');
6388 pos2
= grub_strchr(currline
, ')');
6390 if (pos
&& pos1
&& pos2
)
6393 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6395 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6396 grub_memcpy(chksum
, pos
, retlen
);
6401 else if (ventoy_str_len_alnum(currline
, retlen
))
6403 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, retlen
);
6404 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6406 grub_memcpy(chksum
, currline
, retlen
);
6417 static int ventoy_check_chkfile(const char *isopart
, char *path
, const char *lchkname
, grub_file_t
*pfile
)
6423 grub_file_t file
= NULL
;
6425 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s.%s", isopart
, path
, lchkname
);
6431 cnt
= ventoy_str_chrcnt(path
, '/');
6434 pos
= grub_strrchr(path
, '/');
6438 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, path
);
6447 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6450 ret
= (cnt
> 1) ? 3 : 4;
6461 check_free(file
, grub_file_close
);
6466 static grub_err_t
ventoy_cmd_cmp_checksum(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6471 grub_file_t file
= NULL
;
6472 const char *calc_value
= NULL
;
6473 const char *isopart
= NULL
;
6475 char readchk
[256] = {0};
6476 char filebuf
[512] = {0};
6477 int retlen
[] = { 32, 40, 64, 128 };
6482 index
= (int)grub_strtol(args
[0], NULL
, 10);
6483 if (argc
!= 2 || index
< 0 || index
>= (int)ARRAY_SIZE(retlen
))
6488 grub_strncpy(uchkname
, g_lower_chksum_name
[index
], sizeof(uchkname
));
6489 ventoy_str_toupper(uchkname
);
6491 isopart
= grub_env_get("vtoy_iso_part");
6492 calc_value
= grub_env_get("VT_LAST_CHECK_SUM");
6494 chktype
= ventoy_check_chkfile(isopart
, args
[1], g_lower_chksum_name
[index
], &file
);
6497 grub_printf("\n\nNo checksum file found.\n");
6503 grub_snprintf(fchksum
, sizeof(fchksum
), ".%s", g_lower_chksum_name
[index
]);
6504 grub_memset(filebuf
, 0, sizeof(filebuf
));
6505 grub_file_read(file
, filebuf
, 511);
6507 pos
= grub_strchr(filebuf
, '=');
6510 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6511 grub_memcpy(readchk
, pos
, retlen
[index
]);
6515 grub_memcpy(readchk
, filebuf
, retlen
[index
]);
6518 else if (chktype
== 3 || chktype
== 4)
6520 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6521 ventoy_find_checksum(file
, uchkname
, retlen
[index
], args
[1], chktype
, readchk
);
6522 if (readchk
[0] == 0)
6524 grub_printf("\n\n%s value not found in %s.\n", uchkname
, fchksum
);
6530 grub_snprintf(fchksum
, sizeof(fchksum
), "local VENTOY_CHECKSUM");
6531 ventoy_find_checksum(file
, uchkname
, retlen
[index
], args
[1], chktype
, readchk
);
6532 if (readchk
[0] == 0)
6534 grub_file_close(file
);
6535 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6538 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6539 ventoy_find_checksum(file
, uchkname
, retlen
[index
], args
[1], 3, readchk
);
6540 if (readchk
[0] == 0)
6542 grub_printf("\n\n%s value not found in both local and global VENTOY_CHECKSUM.\n", uchkname
);
6549 if (grub_strcasecmp(calc_value
, readchk
) == 0)
6551 grub_printf("\n\nCheck %s value with %s file. [ SUCCESS ]\n", uchkname
, fchksum
);
6555 grub_printf("\n\nCheck %s value with %s file. [ ERROR ]\n", uchkname
, fchksum
);
6556 grub_printf("The %s value in %s file is:\n%s\n", uchkname
, fchksum
, readchk
);
6561 check_free(file
, grub_file_close
);
6562 VENTOY_CMD_RETURN(0);
6566 static const char * ventoy_menu_lang_read_hook(struct grub_env_var
*var
, const char *val
)
6569 return ventoy_get_vmenu_title(val
);
6572 int ventoy_env_init(void)
6577 grub_env_set("vtdebug_flag", "");
6579 grub_register_vtoy_menu_lang_hook(ventoy_menu_lang_read_hook
);
6580 ventoy_ctrl_var_init();
6581 ventoy_global_var_init();
6583 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6584 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6585 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6586 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6588 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6591 ventoy_filt_register(0, ventoy_wrapper_open
);
6593 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6596 g_grub_param
->grub_env_get
= grub_env_get
;
6597 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6598 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6599 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6600 grub_env_set("env_param", buf
);
6601 grub_env_set("ventoy_env_param", buf
);
6603 grub_env_export("env_param");
6604 grub_env_export("ventoy_env_param");
6607 grub_env_export("vtoy_winpeshl_ini_addr");
6608 grub_env_export("vtoy_winpeshl_ini_size");
6610 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6611 grub_env_set("vtoy_chain_file_size", buf
);
6612 grub_env_export("vtoy_chain_file_size");
6614 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6615 grub_env_set("vtoy_chain_file_read", buf
);
6616 grub_env_export("vtoy_chain_file_read");
6618 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6619 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6620 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6622 grub_snprintf(buf
, sizeof(buf
), "%s-%s", GRUB_TARGET_CPU
, GRUB_PLATFORM
);
6623 grub_env_set("grub_cpu_platform", buf
);
6624 grub_env_export("grub_cpu_platform");
6631 static cmd_para ventoy_cmds
[] =
6633 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6634 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6635 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6636 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6637 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6638 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6639 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6640 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6641 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6642 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6643 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6644 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6645 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6646 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6647 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6648 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6649 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6650 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6651 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6652 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6653 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6654 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6655 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6656 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6657 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6658 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6659 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6661 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6662 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6663 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6664 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6665 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6666 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6667 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6669 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6670 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6671 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6672 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6673 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6674 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6675 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6676 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6677 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6678 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6681 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6682 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6683 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6684 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6685 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6686 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6687 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6688 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6689 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6690 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6691 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6693 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6694 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6695 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6696 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6697 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6698 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6699 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6701 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6702 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6703 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6704 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6705 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6706 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6707 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6708 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6709 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6710 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6712 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6713 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6714 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6715 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6716 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6717 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6718 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6719 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6720 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6722 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6723 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6724 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6725 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6728 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6729 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6730 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6732 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6733 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6734 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6737 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6738 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6739 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6740 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6741 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6742 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6743 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6744 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6745 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6746 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6747 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6748 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6749 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6750 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6752 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6753 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6754 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6755 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6756 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6757 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6758 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6759 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6760 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6761 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6762 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6763 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6765 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6766 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6767 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6768 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6769 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6770 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6771 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6772 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6773 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6774 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6775 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6776 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6777 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6778 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6779 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6780 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6781 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6782 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6783 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6784 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6785 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6786 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6787 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6788 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6789 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6790 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6791 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6792 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6793 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6794 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6795 { "vt_vtoychksum_exist", ventoy_cmd_vtoychksum_exist
, 0, NULL
, "", "", NULL
},
6796 { "vt_cmp_checksum", ventoy_cmd_cmp_checksum
, 0, NULL
, "", "", NULL
},
6800 int ventoy_register_all_cmd(void)
6803 cmd_para
*cur
= NULL
;
6805 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6807 cur
= ventoy_cmds
+ i
;
6808 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6809 cur
->summary
, cur
->description
, cur
->parser
);
6815 int ventoy_unregister_all_cmd(void)
6819 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6821 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);