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
;
3766 g_ventoy_secondary_menu_on
= 1;
3768 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3769 grub_script_execute_sourcecode(configfile
);
3771 g_ventoy_menu_esc
= 0;
3772 g_ventoy_suppress_esc
= 0;
3773 g_ventoy_suppress_esc_default
= 1;
3774 g_ventoy_secondary_menu_on
= 0;
3778 node
->cursel
= g_ventoy_last_entry
- 1;
3781 grub_check_free(node
->filebuf
);
3784 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3786 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3787 node
->templatepath
[node
->cursel
].path
);
3790 node
->filebuf
= grub_malloc(file
->size
+ 8);
3793 grub_file_read(file
, node
->filebuf
, file
->size
);
3794 grub_file_close(file
);
3796 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3797 node
->filelen
= (int)file
->size
;
3799 ventoy_auto_install_var_expand(node
);
3804 debug("Failed to open auto install script <%s%s>\n",
3805 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3809 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3812 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3818 char configfile
[128];
3819 persistence_config
*node
;
3825 debug("select persistence argc:%d\n", argc
);
3832 node
= ventoy_plugin_find_persistent(args
[0]);
3835 debug("Persistence image not found for %s\n", args
[0]);
3839 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3841 defidx
= node
->autosel
;
3842 if (node
->timeout
< 0)
3844 node
->cursel
= node
->autosel
- 1;
3845 debug("Persistence image auto select %d\n", node
->autosel
);
3850 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3856 if (node
->timeout
> 0)
3858 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3861 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_PERSISTENCE\" --class=\"sel_persistence\" {\n"
3862 " echo %s\n}\n", "");
3864 for (i
= 0; i
< node
->backendnum
; i
++)
3866 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3868 ventoy_get_vmenu_title("VTLANG_PERSIST_USE"),
3869 node
->backendpath
[i
].path
);
3873 g_ventoy_menu_esc
= 1;
3874 g_ventoy_suppress_esc
= 1;
3875 g_ventoy_suppress_esc_default
= defidx
;
3876 g_ventoy_secondary_menu_on
= 1;
3878 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3879 grub_script_execute_sourcecode(configfile
);
3881 g_ventoy_menu_esc
= 0;
3882 g_ventoy_suppress_esc
= 0;
3883 g_ventoy_suppress_esc_default
= 1;
3884 g_ventoy_secondary_menu_on
= 0;
3888 node
->cursel
= g_ventoy_last_entry
- 1;
3890 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3893 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3896 ventoy_img_chunk
*cur
;
3902 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3904 cur
= g_img_chunk_list
.chunk
+ i
;
3905 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3906 cur
->img_start_sector
, cur
->img_end_sector
,
3907 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3911 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3914 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3918 ventoy_img_chunk_list chunklist
;
3923 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3926 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3929 /* get image chunk data */
3930 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3931 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3932 if (NULL
== chunklist
.chunk
)
3934 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3937 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3938 chunklist
.cur_chunk
= 0;
3940 ventoy_get_block_list(file
, &chunklist
, 0);
3942 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3944 grub_printf("########## UNSUPPORTED ###############\n");
3947 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3949 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3951 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3952 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3955 grub_printf("\n==================================\n");
3957 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3959 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3960 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3961 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3962 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3963 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3967 grub_free(chunklist
.chunk
);
3968 grub_file_close(file
);
3970 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3973 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3976 ventoy_grub_param_file_replace
*replace
= NULL
;
3984 replace
= &(g_grub_param
->file_replace
);
3985 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3987 replace
->old_name_cnt
= 0;
3988 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3990 replace
->old_name_cnt
++;
3991 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3994 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3997 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4000 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4003 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
4009 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
4010 grub_env_set(args
[0], buf
);
4013 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4016 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4024 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4025 grub_printf("%s", g_list_script_buf
);
4029 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4030 grub_printf("%s", g_tree_script_buf
);
4036 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4038 img_info
*cur
= g_ventoy_img_list
;
4046 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4047 grub_printf("name:<%s>\n\n", cur
->name
);
4054 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4060 ventoy_plugin_dump_injection();
4065 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4071 ventoy_plugin_dump_auto_install();
4076 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4082 ventoy_plugin_dump_persistence();
4087 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4093 len1
= (int)grub_strlen(filename
);
4094 len2
= (int)grub_strlen(suffix
);
4101 for (i
= len1
- 1; i
>= 0; i
--)
4103 if (filename
[i
] == '.')
4114 if (filename
[i
- len2
- 1] != '_')
4119 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4127 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4133 if (argc
!= 1 && argc
!= 2)
4138 if (args
[0][0] == '0')
4140 if (g_ventoy_memdisk_mode
)
4145 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4152 else if (args
[0][0] == '1')
4154 return g_ventoy_iso_raw
? 0 : 1;
4156 else if (args
[0][0] == '2')
4158 return g_ventoy_iso_uefi_drv
? 0 : 1;
4160 else if (args
[0][0] == '3')
4162 if (g_ventoy_grub2_mode
)
4167 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4174 else if (args
[0][0] == '4')
4176 if (g_ventoy_wimboot_mode
)
4181 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4192 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4194 static int configfile_mode
= 0;
4195 char memfile
[128] = {0};
4202 * args[0]: 0:normal 1:configfile
4203 * args[1]: 0:list_buf 1:tree_buf
4208 debug("Invalid argc %d\n", argc
);
4214 if (args
[0][0] == '0')
4216 if (args
[1][0] == '0')
4218 grub_script_execute_sourcecode(g_list_script_buf
);
4222 grub_script_execute_sourcecode(g_tree_script_buf
);
4227 if (configfile_mode
)
4229 debug("Now already in F3 mode %d\n", configfile_mode
);
4233 if (args
[1][0] == '0')
4235 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4236 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4240 g_ventoy_last_entry
= -1;
4241 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4242 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4245 configfile_mode
= 1;
4246 grub_script_execute_sourcecode(memfile
);
4247 configfile_mode
= 0;
4253 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4264 g_ventoy_case_insensitive
= 1;
4265 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4266 g_ventoy_case_insensitive
= 0;
4272 grub_file_close(file
);
4278 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4283 const char *isopath
= NULL
;
4285 ventoy_mbr_head mbr
;
4292 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4295 isopath
= grub_env_get("vtoy_iso_part");
4298 debug("isopath is null %p\n", isopath
);
4302 debug("isopath is %s\n", isopath
);
4304 for (id
= 0; id
< 30 && (find
== 0); id
++)
4306 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4307 if (grub_strstr(isopath
, hdname
))
4309 debug("skip %s ...\n", hdname
);
4313 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4315 disk
= grub_disk_open(hdname
);
4318 debug("%s not exist\n", hdname
);
4322 grub_memset(&mbr
, 0, sizeof(mbr
));
4323 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4325 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4327 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4328 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4331 grub_env_set(args
[0], hdname
);
4335 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4339 debug("read %s failed\n", hdname
);
4342 grub_disk_close(disk
);
4348 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4359 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4362 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4365 debug("failed to open file %s\n", args
[0]);
4369 buf
= grub_malloc(len
);
4376 grub_file_read(file
, buf
, len
- 1);
4378 ventoy_get_line(buf
);
4379 ventoy_set_env(args
[1], buf
);
4383 grub_check_free(buf
);
4384 grub_file_close(file
);
4389 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4391 grub_uint64_t end_max
= 0;
4392 int *pCnt
= (int *)data
;
4397 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4398 "0 %llu linear /dev/ventoy %llu\n",
4399 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4401 end_max
= (partition
->len
+ partition
->start
) * 512;
4402 if (end_max
> g_part_end_max
)
4404 g_part_end_max
= end_max
;
4410 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4413 char *device_name
= NULL
;
4414 grub_device_t dev
= NULL
;
4419 g_part_list_pos
= 0;
4421 grub_env_unset("vtoy_img_part_file");
4428 device_name
= grub_file_get_device_name(args
[0]);
4431 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4435 dev
= grub_device_open(device_name
);
4438 debug("grub_device_open failed, %s\n", device_name
);
4442 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4444 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4445 grub_env_set("vtoy_img_part_file", buf
);
4447 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4448 grub_env_set("vtoy_img_part_cnt", buf
);
4450 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4451 grub_env_set("vtoy_img_max_part_end", buf
);
4455 check_free(device_name
, grub_free
);
4456 check_free(dev
, grub_device_close
);
4462 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4473 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4476 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4479 debug("failed to open file %s\n", args
[0]);
4483 buf
= grub_malloc(file
->size
+ 1);
4489 buf
[file
->size
] = 0;
4490 grub_file_read(file
, buf
, file
->size
);
4492 if (grub_strstr(buf
, args
[1]))
4499 grub_check_free(buf
);
4500 grub_file_close(file
);
4505 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4511 ventoy_iso9660_vd pvd
;
4518 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4521 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4524 debug("failed to open file %s\n", args
[0]);
4528 grub_file_seek(file
, 16 * 2048);
4529 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4530 if (len
!= sizeof(pvd
))
4532 debug("failed to read pvd %d\n", len
);
4536 grub_memset(buf
, 0, sizeof(buf
));
4537 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4538 ventoy_set_env(args
[1], buf
);
4540 grub_memset(buf
, 0, sizeof(buf
));
4541 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4542 ventoy_set_env(args
[2], buf
);
4546 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4547 ventoy_set_env(args
[3], buf
);
4550 grub_file_close(file
);
4555 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4566 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4569 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4572 debug("failed to open file %s\n", args
[0]);
4576 grub_memset(buf
, 0, sizeof(buf
));
4577 grub_file_seek(file
, 16 * 2048 + 813);
4578 len
= (int)grub_file_read(file
, buf
, 17);
4581 debug("failed to read create date %d\n", len
);
4585 ventoy_set_env(args
[1], buf
);
4588 grub_file_close(file
);
4593 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4599 ventoy_env_hook_root(1);
4604 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4610 ventoy_env_hook_root(0);
4615 #ifdef GRUB_MACHINE_EFI
4616 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4621 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4627 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4628 if (var
&& *var
== 1)
4636 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4645 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4650 grub_uint64_t FileSectors
= 0;
4651 ventoy_gpt_info
*gpt
= NULL
;
4652 ventoy_part_table
*pt
= NULL
;
4653 grub_uint8_t zeroguid
[16] = {0};
4658 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4661 debug("failed to open file %s\n", args
[0]);
4665 if (file
->size
% 512)
4667 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4671 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4677 FileSectors
= file
->size
/ 512;
4679 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4680 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4682 debug("This is EFI partition table\n");
4684 for (i
= 0; i
< 128; i
++)
4686 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4688 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4690 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4691 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4699 debug("This is MBR partition table\n");
4701 for (i
= 0; i
< 4; i
++)
4703 pt
= gpt
->MBR
.PartTbl
+ i
;
4704 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4706 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4707 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4708 (ulonglong
)FileSectors
);
4717 grub_file_close(file
);
4718 grub_check_free(gpt
);
4719 grub_errno
= GRUB_ERR_NONE
;
4723 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4732 for (i
= 0; i
< 500; i
++)
4734 ret
= grub_getkey_noblock();
4735 if (ret
== GRUB_TERM_NO_KEY
)
4744 grub_printf("\n\n Still have key input after clear.\n");
4752 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4759 int image_sector_size
;
4761 ventoy_chain_head
*chain
;
4762 ventoy_img_chunk
*chunk
;
4763 ventoy_os_param
*osparam
;
4764 ventoy_image_location
*location
;
4765 ventoy_image_disk_region
*region
;
4766 struct grub_acpi_table_header
*acpi
;
4775 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4777 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4783 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4785 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4787 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4791 img_chunk_num
= chain
->img_chunk_num
;
4793 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4794 datalen
= sizeof(ventoy_os_param
) + loclen
;
4796 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4797 acpi
= grub_zalloc(buflen
);
4803 /* Step1: Fill acpi table header */
4804 grub_memcpy(acpi
->signature
, "VTOY", 4);
4805 acpi
->length
= buflen
;
4807 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4808 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4810 acpi
->creator_id
[0] = 1;
4811 acpi
->creator_rev
= 1;
4813 /* Step2: Fill data */
4814 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4815 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4816 osparam
->vtoy_img_location_addr
= 0;
4817 osparam
->vtoy_img_location_len
= loclen
;
4818 osparam
->chksum
= 0;
4819 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4821 location
= (ventoy_image_location
*)(osparam
+ 1);
4822 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4823 location
->image_sector_size
= image_sector_size
;
4824 location
->disk_sector_size
= chain
->disk_sector_size
;
4825 location
->region_count
= img_chunk_num
;
4827 region
= location
->regions
;
4828 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4829 if (512 == image_sector_size
)
4831 for (i
= 0; i
< img_chunk_num
; i
++)
4833 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4834 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4835 region
->disk_start_sector
= chunk
->disk_start_sector
;
4842 for (i
= 0; i
< img_chunk_num
; i
++)
4844 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4845 region
->image_start_sector
= chunk
->img_start_sector
;
4846 region
->disk_start_sector
= chunk
->disk_start_sector
;
4852 /* Step3: Fill acpi checksum */
4854 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4856 /* load acpi table */
4857 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4858 grub_script_execute_sourcecode(cmd
);
4862 VENTOY_CMD_RETURN(0);
4865 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4871 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4872 g_ventoy_last_entry
= -1;
4877 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4883 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4888 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4890 const char *pos
= filename
+ 1;
4898 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4900 grub_strncpy((char *)data
, filename
, 128);
4911 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4914 char *device_name
= NULL
;
4915 grub_device_t dev
= NULL
;
4916 grub_fs_t fs
= NULL
;
4917 char buf
[128] = {0};
4923 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4927 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4929 device_name
= grub_file_get_device_name(args
[0]);
4932 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4936 dev
= grub_device_open(device_name
);
4939 debug("grub_device_open failed, %s\n", device_name
);
4943 fs
= grub_fs_probe(dev
);
4946 debug("grub_fs_probe failed, %s\n", device_name
);
4950 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4954 ventoy_set_env(args
[2], buf
);
4961 check_free(device_name
, grub_free
);
4962 check_free(dev
, grub_device_close
);
4967 int ventoy_load_part_table(const char *diskname
)
4974 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4975 if (!g_ventoy_part_info
)
4980 disk
= grub_disk_open(diskname
);
4983 debug("Failed to open disk %s\n", diskname
);
4987 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4989 g_ventoy_disk_bios_id
= disk
->id
;
4991 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4992 grub_disk_close(disk
);
4994 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4995 dev
= grub_device_open(name
);
4998 /* Check for official Ventoy device */
4999 ret
= ventoy_check_official_device(dev
);
5000 grub_device_close(dev
);
5008 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5009 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5014 static void ventoy_prompt_end(void)
5019 grub_printf("\n\n\n");
5020 grub_printf(" 1 --- Exit grub\n");
5021 grub_printf(" 2 --- Reboot\n");
5022 grub_printf(" 3 --- Shut down\n");
5023 grub_printf("Please enter your choice: ");
5029 if (c
>= '1' && c
<= '3')
5034 grub_printf("%c", c
);
5038 else if (c
== '\r' || c
== '\n')
5052 grub_script_execute_sourcecode("halt");
5061 grub_printf("\rPlease enter your choice: ");
5062 grub_printf("\rPlease enter your choice: ");
5069 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5076 ret
= ventoy_load_part_table(args
[0]);
5079 ventoy_prompt_end();
5082 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5083 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5088 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5091 const char *vcfg
= NULL
;
5096 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5099 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5100 grub_env_set(args
[1], vcfg
);
5105 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5113 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5116 grub_uint8_t zeroguid
[16] = {0};
5121 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5124 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5126 if (id
>= 1 && id
<= 128)
5128 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5136 if (id
>= 1 && id
<= 4)
5138 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5148 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5151 char *device_name
= NULL
;
5152 grub_device_t dev
= NULL
;
5153 grub_fs_t fs
= NULL
;
5158 debug("get fs label for %s\n", args
[0]);
5162 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5166 device_name
= grub_file_get_device_name(args
[0]);
5169 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5173 dev
= grub_device_open(device_name
);
5176 debug("grub_device_open failed, %s\n", device_name
);
5180 fs
= grub_fs_probe(dev
);
5181 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5183 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5187 fs
->fs_label(dev
, &label
);
5190 debug("label=<%s>\n", label
);
5191 ventoy_set_env(args
[1], label
);
5199 check_free(device_name
, grub_free
);
5200 check_free(dev
, grub_device_close
);
5205 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5209 grub_snprintf((char *)data
, 256, "%s", filename
);
5216 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5218 if (info
->dir
&& filename
&& filename
[0] != '.')
5220 grub_snprintf((char *)data
, 256, "%s", filename
);
5227 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5230 char *device_name
= NULL
;
5231 grub_device_t dev
= NULL
;
5232 grub_fs_t fs
= NULL
;
5233 char name
[256] ={0};
5237 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5241 device_name
= grub_file_get_device_name(args
[0]);
5244 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5248 dev
= grub_device_open(device_name
);
5251 debug("grub_device_open failed, %s\n", device_name
);
5255 fs
= grub_fs_probe(dev
);
5258 debug("grub_fs_probe failed, %s\n", device_name
);
5262 fs
->fs_dir(dev
, args
[1], hook
, name
);
5265 ventoy_set_env(args
[2], name
);
5272 check_free(device_name
, grub_free
);
5273 check_free(dev
, grub_device_close
);
5278 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5281 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5284 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5287 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5290 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5300 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5304 for (pos
= args
[0]; *pos
; pos
++)
5318 grub_env_set(args
[1], args
[0]);
5328 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5338 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5343 len
= (int)grub_strlen(buf
);
5344 for (i
= len
; i
> 0; i
--)
5346 if (buf
[i
- 1] == '/')
5348 grub_env_set(args
[1], buf
+ i
);
5353 grub_env_set(args
[1], buf
);
5358 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5360 struct grub_video_mode_info info
;
5367 if (!g_video_mode_list
)
5369 ventoy_enum_video_mode();
5372 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5374 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5378 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5381 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5383 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5384 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5386 VENTOY_CMD_RETURN(0);
5389 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5391 struct grub_video_mode_info info
;
5398 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5400 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5404 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5407 grub_env_set(args
[0], buf
);
5409 VENTOY_CMD_RETURN(0);
5412 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5420 if (!g_video_mode_list
)
5425 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5426 if (id
< g_video_mode_num
)
5428 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5429 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5432 grub_env_set(args
[1], buf
);
5434 VENTOY_CMD_RETURN(0);
5437 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5440 grub_uint32_t loadsector
= 0;
5443 grub_uint32_t boot_catlog
= 0;
5444 grub_uint8_t buf
[512];
5450 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5454 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5457 debug("failed to open %s\n", args
[0]);
5461 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5462 if (boot_catlog
== 0)
5464 debug("No bootcatlog found\n");
5465 grub_file_close(file
);
5469 grub_memset(buf
, 0, sizeof(buf
));
5470 grub_file_seek(file
, boot_catlog
* 2048);
5471 grub_file_read(file
, buf
, sizeof(buf
));
5472 grub_file_close(file
);
5474 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5476 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5478 if (buf
[i
+ 32] == 0x88)
5480 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5481 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5487 if (loadsector
== 0)
5489 debug("No EFI eltorito info found\n");
5493 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5494 grub_env_set(args
[1], value
);
5495 VENTOY_CMD_RETURN(0);
5498 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5503 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5505 if (pfsdir
->initrd
[0])
5510 curpos
= pfsdir
->curpos
;
5511 len
= grub_strlen(filename
);
5515 if ((len
== 1 && filename
[0] == '.') ||
5516 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5521 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5524 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5525 pfsdir
->curpos
= curpos
+ printlen
;
5526 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5527 pfsdir
->curpos
= curpos
;
5528 pfsdir
->fullpath
[curpos
] = 0;
5532 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5535 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5536 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5538 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5540 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5549 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5553 char *device_name
= NULL
;
5554 grub_device_t dev
= NULL
;
5555 grub_fs_t fs
= NULL
;
5556 replace_fs_dir
*pfsdir
= NULL
;
5562 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5566 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5572 device_name
= grub_file_get_device_name(args
[0]);
5578 dev
= grub_device_open(device_name
);
5584 fs
= grub_fs_probe(dev
);
5593 pfsdir
->fullpath
[0] = '/';
5594 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5596 if (pfsdir
->initrd
[0])
5598 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5600 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5602 if (pfsdir
->initrd
[i
] == '/')
5604 pfsdir
->initrd
[i
] = '\\';
5608 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5609 grub_env_set(args
[1], pos
);
5613 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5618 grub_check_free(pfsdir
);
5619 grub_check_free(device_name
);
5620 check_free(dev
, grub_device_close
);
5622 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5625 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5627 const char *pager
= NULL
;
5633 pager
= grub_env_get("pager");
5637 grub_env_set("pager", "1");
5639 else if (pager
[0] == '1')
5645 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5647 grub_env_set("pager", "1");
5650 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5653 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5659 if (g_pager_flag
== 1)
5661 grub_env_unset("pager");
5663 else if (g_pager_flag
== 2)
5665 grub_env_set("pager", g_old_pager
);
5668 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5671 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5673 if (g_json_case_mis_path
[0])
5678 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5680 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5686 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5689 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5691 if (g_json_case_mis_path
[0])
5696 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5698 if (grub_strcasecmp(filename
, "ventoy") == 0)
5700 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5701 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5702 if (g_json_case_mis_path
[0])
5712 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5715 char *device_name
= NULL
;
5716 grub_device_t dev
= NULL
;
5717 grub_fs_t fs
= NULL
;
5718 chk_case_fs_dir fs_dir
;
5724 device_name
= grub_file_get_device_name(args
[0]);
5730 dev
= grub_device_open(device_name
);
5736 fs
= grub_fs_probe(dev
);
5742 fstype
= ventoy_get_fs_type(fs
->name
);
5743 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5748 g_json_case_mis_path
[0] = 0;
5751 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5753 if (g_json_case_mis_path
[0])
5755 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5760 grub_check_free(device_name
);
5761 check_free(dev
, grub_device_close
);
5763 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5766 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5769 grub_partition_t part
;
5770 char priority_str
[3]; /* Maximum value 15 */
5774 if (argc
< 2 || argc
> 3)
5775 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5776 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5778 /* Open the disk if it exists */
5779 disk
= grub_disk_open (args
[0]);
5782 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5786 part
= grub_partition_probe (disk
, args
[1]);
5789 grub_disk_close (disk
);
5790 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5791 "No such partition");
5794 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5796 grub_disk_close (disk
);
5797 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5798 "Not a GPT partition");
5801 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5802 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5806 grub_env_set (args
[2], priority_str
);
5807 grub_env_export (args
[2]);
5811 grub_printf ("Priority is %s\n", priority_str
);
5814 grub_disk_close (disk
);
5815 return GRUB_ERR_NONE
;
5819 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5823 grub_file_t file
= NULL
;
5824 grub_uint32_t loadrba
= 0;
5825 grub_uint32_t boot_catlog
= 0;
5826 grub_uint8_t sector
[512];
5827 boot_info_table
*info
= NULL
;
5832 /* This also trigger a iso9660 fs parse */
5833 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5838 joliet
= grub_iso9660_is_joliet();
5844 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5847 debug("failed to open %s\n", args
[0]);
5851 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5852 if (boot_catlog
== 0)
5854 debug("no bootcatlog found %u\n", boot_catlog
);
5858 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5861 debug("no bios eltorito rba found %u\n", loadrba
);
5865 grub_file_seek(file
, loadrba
* 2048);
5866 grub_file_read(file
, sector
, 512);
5868 info
= (boot_info_table
*)sector
;
5869 if (info
->bi_data0
== 0x7c6ceafa &&
5870 info
->bi_data1
== 0x90900000 &&
5871 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5872 info
->bi_BootFileLocation
== loadrba
)
5874 debug("bootloader is syslinux, %u.\n", loadrba
);
5880 grub_file_close(file
);
5881 grub_errno
= GRUB_ERR_NONE
;
5885 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5888 ventoy_vlnk_part
*node
;
5894 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5896 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5897 ++n
, node
->device
, node
->disksig
,
5898 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5904 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5912 len
= (int)grub_strlen(args
[0]);
5913 if (grub_file_is_vlnk_suffix(args
[0], len
))
5922 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5925 const char *name
= NULL
;
5931 grub_env_unset(args
[1]);
5932 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5935 debug("VLNK SRC: <%s>\n", args
[0]);
5936 debug("VLNK DST: <%s>\n", name
);
5937 grub_env_set(args
[1], name
);
5945 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5949 grub_file_t file
= NULL
;
5960 len
= (int)grub_strlen(args
[0]);
5961 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5963 grub_printf("Invalid vlnk suffix\n");
5967 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5970 grub_printf("Failed to open %s\n", args
[0]);
5974 if (file
->size
!= 32768)
5976 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5980 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5981 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5983 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5988 check_free(file
, grub_file_close
);
5989 grub_errno
= GRUB_ERR_NONE
;
5993 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5999 g_iso_vd_id_publisher
[0] = 0;
6000 g_iso_vd_id_prepare
[0] = 0;
6001 g_iso_vd_id_application
[0] = 0;
6006 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6010 grub_file_t file
= NULL
;
6015 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
6018 grub_printf("Failed to open %s\n", args
[0]);
6022 grub_file_seek(file
, 16 * 2048 + offset
);
6023 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
6026 grub_file_seek(file
, 16 * 2048 + offset
);
6027 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
6030 grub_file_seek(file
, 16 * 2048 + offset
);
6031 grub_file_read(file
, g_iso_vd_id_application
, 128);
6035 check_free(file
, grub_file_close
);
6036 grub_errno
= GRUB_ERR_NONE
;
6040 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6043 char *id
= g_iso_vd_id_publisher
;
6048 if (args
[0][0] == '1')
6050 id
= g_iso_vd_id_prepare
;
6052 else if (args
[0][0] == '2')
6054 id
= g_iso_vd_id_application
;
6057 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6062 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6067 grub_errno
= GRUB_ERR_NONE
;
6071 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6076 g_ventoy_fn_mutex
= 0;
6077 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
6079 g_ventoy_fn_mutex
= 1;
6082 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6085 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6087 grub_uint64_t total
;
6088 grub_uint64_t org_required
;
6089 grub_uint64_t new_required
;
6095 #ifdef GRUB_MACHINE_EFI
6096 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6097 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6098 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6099 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6104 grub_printf("Non EFI mode!\n");
6109 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6112 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6114 const char *env
= NULL
;
6119 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6124 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6125 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6126 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6127 ventoy_check_mode_by_name(args
[0], "vtnormal")
6133 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6134 if (env
&& env
[0] == '0' && env
[1] == 0)
6142 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6150 const char *env
= NULL
;
6151 ulonglong fsize
= 0;
6153 int seldata
[16] = {0};
6158 len
= 8 * VTOY_SIZE_1KB
;
6159 cmd
= (char *)grub_malloc(len
);
6165 g_vtoy_secondary_need_recover
= 0;
6166 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6168 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6171 timeout
= (int)grub_strtol(env
, NULL
, 10);
6176 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6179 fsize
= grub_strtoull(args
[2], NULL
, 10);
6181 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6183 if (grub_strcmp(args
[1], "Unix") != 0)
6185 if (grub_strcmp(args
[1], "Windows") == 0)
6187 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6191 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6194 if (fsize
<= VTOY_SIZE_1GB
)
6196 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6200 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6203 g_ventoy_menu_esc
= 1;
6204 g_ventoy_suppress_esc
= 1;
6205 g_ventoy_suppress_esc_default
= 0;
6206 g_ventoy_secondary_menu_on
= 1;
6207 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6208 grub_script_execute_sourcecode(cfgfile
);
6209 g_ventoy_menu_esc
= 0;
6210 g_ventoy_suppress_esc
= 0;
6211 g_ventoy_suppress_esc_default
= 1;
6212 g_ventoy_secondary_menu_on
= 0;
6214 select
= seldata
[g_ventoy_last_entry
];
6218 g_ventoy_wimboot_mode
= 1;
6219 g_vtoy_secondary_need_recover
= 1;
6221 else if (select
== 3)
6223 g_ventoy_grub2_mode
= 1;
6224 g_vtoy_secondary_need_recover
= 2;
6226 else if (select
== 4)
6228 g_ventoy_memdisk_mode
= 1;
6229 g_vtoy_secondary_need_recover
= 3;
6231 else if (select
== 5)
6233 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6234 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6236 }while (select
== 5);
6242 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6248 if (g_vtoy_secondary_need_recover
== 1)
6250 g_ventoy_wimboot_mode
= 0;
6252 else if (g_vtoy_secondary_need_recover
== 2)
6254 g_ventoy_grub2_mode
= 0;
6256 else if (g_vtoy_secondary_need_recover
== 3)
6258 g_ventoy_memdisk_mode
= 0;
6261 g_vtoy_secondary_need_recover
= 0;
6263 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6266 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6271 if (args
[0][0] == '0')
6273 g_ventoy_case_insensitive
= 0;
6277 g_ventoy_case_insensitive
= 1;
6283 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6288 ventoy_plugin_load_menu_lang(1, args
[0]);
6289 VENTOY_CMD_RETURN(0);
6292 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6297 ventoy_plugin_load_menu_lang(0, args
[0]);
6298 VENTOY_CMD_RETURN(0);
6301 static grub_err_t
ventoy_cmd_vtoychksum_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6310 cnt
= ventoy_str_chrcnt(args
[1], '/');
6313 pos
= grub_strrchr(args
[1], '/');
6316 if (ventoy_check_file_exist("%s%s/VENTOY_CHECKSUM", args
[0], args
[1]))
6318 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6323 if (ventoy_check_file_exist("%s/VENTOY_CHECKSUM", args
[0]))
6325 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6331 static int ventoy_chksum_pathcmp(int chktype
, char *rlpath
, char *rdpath
)
6338 pos1
= ventoy_str_basename(rlpath
);
6339 pos2
= ventoy_str_basename(rdpath
);
6340 return grub_strcmp(pos1
, pos2
);
6342 else if (chktype
== 3 || chktype
== 4)
6344 if (grub_strcmp(rlpath
, rdpath
) == 0 || grub_strcmp(rlpath
+ 1, rdpath
) == 0)
6353 static int ventoy_find_checksum
6368 char *currline
= NULL
;
6369 char *nextline
= NULL
;
6371 ulen
= (int)grub_strlen(uname
);
6373 /* read file to buffer */
6374 buf
= grub_malloc(file
->size
+ 4);
6379 grub_file_read(file
, buf
, file
->size
);
6380 buf
[file
->size
] = 0;
6382 /* parse each line */
6383 for (currline
= buf
; currline
; currline
= nextline
)
6385 nextline
= ventoy_get_line(currline
);
6386 VTOY_SKIP_SPACE(currline
);
6388 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6390 pos
= grub_strchr(currline
, '=');
6391 pos1
= grub_strchr(currline
, '(');
6392 pos2
= grub_strchr(currline
, ')');
6394 if (pos
&& pos1
&& pos2
)
6397 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6399 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6400 grub_memcpy(chksum
, pos
, retlen
);
6405 else if (ventoy_str_len_alnum(currline
, retlen
))
6407 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, retlen
);
6408 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6410 grub_memcpy(chksum
, currline
, retlen
);
6421 static int ventoy_check_chkfile(const char *isopart
, char *path
, const char *lchkname
, grub_file_t
*pfile
)
6427 grub_file_t file
= NULL
;
6429 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s.%s", isopart
, path
, lchkname
);
6435 cnt
= ventoy_str_chrcnt(path
, '/');
6438 pos
= grub_strrchr(path
, '/');
6442 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, path
);
6451 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6454 ret
= (cnt
> 1) ? 3 : 4;
6465 check_free(file
, grub_file_close
);
6470 static grub_err_t
ventoy_cmd_cmp_checksum(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6475 grub_file_t file
= NULL
;
6476 const char *calc_value
= NULL
;
6477 const char *isopart
= NULL
;
6479 char readchk
[256] = {0};
6480 char filebuf
[512] = {0};
6481 int retlen
[] = { 32, 40, 64, 128 };
6486 index
= (int)grub_strtol(args
[0], NULL
, 10);
6487 if (argc
!= 2 || index
< 0 || index
>= (int)ARRAY_SIZE(retlen
))
6492 grub_strncpy(uchkname
, g_lower_chksum_name
[index
], sizeof(uchkname
));
6493 ventoy_str_toupper(uchkname
);
6495 isopart
= grub_env_get("vtoy_iso_part");
6496 calc_value
= grub_env_get("VT_LAST_CHECK_SUM");
6498 chktype
= ventoy_check_chkfile(isopart
, args
[1], g_lower_chksum_name
[index
], &file
);
6501 grub_printf("\n\nNo checksum file found.\n");
6507 grub_snprintf(fchksum
, sizeof(fchksum
), ".%s", g_lower_chksum_name
[index
]);
6508 grub_memset(filebuf
, 0, sizeof(filebuf
));
6509 grub_file_read(file
, filebuf
, 511);
6511 pos
= grub_strchr(filebuf
, '=');
6514 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6515 grub_memcpy(readchk
, pos
, retlen
[index
]);
6519 grub_memcpy(readchk
, filebuf
, retlen
[index
]);
6522 else if (chktype
== 3 || chktype
== 4)
6524 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6525 ventoy_find_checksum(file
, uchkname
, retlen
[index
], args
[1], chktype
, readchk
);
6526 if (readchk
[0] == 0)
6528 grub_printf("\n\n%s value not found in %s.\n", uchkname
, fchksum
);
6534 grub_snprintf(fchksum
, sizeof(fchksum
), "local VENTOY_CHECKSUM");
6535 ventoy_find_checksum(file
, uchkname
, retlen
[index
], args
[1], chktype
, readchk
);
6536 if (readchk
[0] == 0)
6538 grub_file_close(file
);
6539 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6542 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6543 ventoy_find_checksum(file
, uchkname
, retlen
[index
], args
[1], 3, readchk
);
6544 if (readchk
[0] == 0)
6546 grub_printf("\n\n%s value not found in both local and global VENTOY_CHECKSUM.\n", uchkname
);
6553 if (grub_strcasecmp(calc_value
, readchk
) == 0)
6555 grub_printf("\n\nCheck %s value with %s file. [ SUCCESS ]\n", uchkname
, fchksum
);
6559 grub_printf("\n\nCheck %s value with %s file. [ ERROR ]\n", uchkname
, fchksum
);
6560 grub_printf("The %s value in %s file is:\n%s\n", uchkname
, fchksum
, readchk
);
6565 check_free(file
, grub_file_close
);
6566 VENTOY_CMD_RETURN(0);
6570 static const char * ventoy_menu_lang_read_hook(struct grub_env_var
*var
, const char *val
)
6573 return ventoy_get_vmenu_title(val
);
6576 int ventoy_env_init(void)
6581 grub_env_set("vtdebug_flag", "");
6583 grub_register_vtoy_menu_lang_hook(ventoy_menu_lang_read_hook
);
6584 ventoy_ctrl_var_init();
6585 ventoy_global_var_init();
6587 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6588 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6589 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6590 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6592 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6595 ventoy_filt_register(0, ventoy_wrapper_open
);
6597 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6600 g_grub_param
->grub_env_get
= grub_env_get
;
6601 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6602 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6603 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6604 grub_env_set("env_param", buf
);
6605 grub_env_set("ventoy_env_param", buf
);
6607 grub_env_export("env_param");
6608 grub_env_export("ventoy_env_param");
6611 grub_env_export("vtoy_winpeshl_ini_addr");
6612 grub_env_export("vtoy_winpeshl_ini_size");
6614 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6615 grub_env_set("vtoy_chain_file_size", buf
);
6616 grub_env_export("vtoy_chain_file_size");
6618 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6619 grub_env_set("vtoy_chain_file_read", buf
);
6620 grub_env_export("vtoy_chain_file_read");
6622 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6623 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6624 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6626 grub_snprintf(buf
, sizeof(buf
), "%s-%s", GRUB_TARGET_CPU
, GRUB_PLATFORM
);
6627 grub_env_set("grub_cpu_platform", buf
);
6628 grub_env_export("grub_cpu_platform");
6635 static cmd_para ventoy_cmds
[] =
6637 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6638 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6639 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6640 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6641 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6642 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6643 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6644 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6645 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6646 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6647 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6648 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6649 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6650 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6651 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6652 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6653 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6654 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6655 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6656 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6657 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6658 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6659 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6660 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6661 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6662 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6663 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6665 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6666 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6667 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6668 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6669 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6670 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6671 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6673 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6674 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6675 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6676 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6677 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6678 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6679 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6680 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6681 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6682 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6685 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6686 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6687 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6688 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6689 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6690 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6691 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6692 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6693 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6694 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6695 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6697 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6698 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6699 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6700 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6701 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6702 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6703 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6705 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6706 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6707 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6708 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6709 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6710 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6711 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6712 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6713 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6714 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6716 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6717 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6718 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6719 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6720 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6721 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6722 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6723 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6724 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6726 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6727 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6728 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6729 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6732 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6733 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6734 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6736 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6737 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6738 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6741 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6742 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6743 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6744 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6745 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6746 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6747 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6748 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6749 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6750 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6751 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6752 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6753 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6754 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6756 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6757 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6758 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6759 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6760 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6761 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6762 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6763 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6764 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6765 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6766 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6767 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6769 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6770 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6771 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6772 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6773 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6774 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6775 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6776 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6777 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6778 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6779 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6780 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6781 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6782 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6783 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6784 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6785 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6786 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6787 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6788 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6789 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6790 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6791 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6792 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6793 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6794 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6795 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6796 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6797 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6798 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6799 { "vt_vtoychksum_exist", ventoy_cmd_vtoychksum_exist
, 0, NULL
, "", "", NULL
},
6800 { "vt_cmp_checksum", ventoy_cmd_cmp_checksum
, 0, NULL
, "", "", NULL
},
6804 int ventoy_register_all_cmd(void)
6807 cmd_para
*cur
= NULL
;
6809 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6811 cur
= ventoy_cmds
+ i
;
6812 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6813 cur
->summary
, cur
->description
, cur
->parser
);
6819 int ventoy_unregister_all_cmd(void)
6823 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6825 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);