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
[VTOY_CHKSUM_NUM
] = { "md5", "sha1", "sha256", "sha512" };
162 static int g_lower_chksum_namelen
[VTOY_CHKSUM_NUM
] = { 3, 4, 6, 6 };
163 static int g_chksum_retlen
[VTOY_CHKSUM_NUM
] = { 32, 40, 64, 128 };
165 static int g_vtoy_secondary_need_recover
= 0;
167 static int g_vtoy_load_prompt
= 0;
168 static char g_vtoy_prompt_msg
[64];
170 static char g_json_case_mis_path
[32];
172 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
174 int ventoy_get_fs_type(const char *fs
)
178 return ventoy_fs_max
;
180 else if (grub_strncmp(fs
, "exfat", 5) == 0)
182 return ventoy_fs_exfat
;
184 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
186 return ventoy_fs_ntfs
;
188 else if (grub_strncmp(fs
, "ext", 3) == 0)
190 return ventoy_fs_ext
;
192 else if (grub_strncmp(fs
, "xfs", 3) == 0)
194 return ventoy_fs_xfs
;
196 else if (grub_strncmp(fs
, "udf", 3) == 0)
198 return ventoy_fs_udf
;
200 else if (grub_strncmp(fs
, "fat", 3) == 0)
202 return ventoy_fs_fat
;
205 return ventoy_fs_max
;
208 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
227 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
229 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
233 static int ventoy_control_get_flag(const char *key
)
235 const char *val
= ventoy_get_env(key
);
237 if (val
&& val
[0] == '1' && val
[1] == 0)
244 static grub_err_t
ventoy_fs_close(grub_file_t file
)
246 grub_file_close(g_old_file
);
247 grub_free(file
->data
);
255 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
261 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
266 for (i
= 0; i
< g_video_mode_num
; i
++)
268 if (g_video_mode_list
[i
].width
== info
->width
&&
269 g_video_mode_list
[i
].height
== info
->height
&&
270 g_video_mode_list
[i
].bpp
== info
->bpp
)
276 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
277 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
278 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
281 if (g_video_mode_num
== g_video_mode_max
)
283 g_video_mode_max
*= 2;
284 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
290 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
292 if (v1
->bpp
== v2
->bpp
)
294 if (v1
->width
== v2
->width
)
296 if (v1
->height
== v2
->height
)
302 return (v1
->height
< v2
->height
) ? -1 : 1;
307 return (v1
->width
< v2
->width
) ? -1 : 1;
312 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
316 static int ventoy_enum_video_mode(void)
319 grub_video_adapter_t adapter
;
320 grub_video_driver_id_t id
;
321 ventoy_video_mode mode
;
323 g_video_mode_num
= 0;
324 g_video_mode_max
= 1024;
325 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
326 if (!g_video_mode_list
)
331 #ifdef GRUB_MACHINE_PCBIOS
332 grub_dl_load ("vbe");
335 id
= grub_video_get_driver_id ();
337 FOR_VIDEO_ADAPTERS (adapter
)
339 if (!adapter
->iterate
||
340 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
341 adapter
->init() != GRUB_ERR_NONE
)))
346 adapter
->iterate(ventoy_video_hook
, NULL
);
348 if (adapter
->id
!= id
)
354 /* sort video mode */
355 for (i
= 0; i
< g_video_mode_num
; i
++)
356 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
358 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
360 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
361 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
362 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
366 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
369 static int ventoy_pre_parse_data(char *src
, int size
)
375 if (size
< 20 || grub_strncmp(src
, "ventoy_left_top_color", 21))
381 while (*pos
&& *pos
!= '\r' && *pos
!= '\n')
389 if (grub_strlen(src
) > 200)
394 grub_snprintf(buf
, sizeof(buf
),
395 "regexp -s 1:%s -s 2:%s -s 3:%s \"@([^@]*)@([^@]*)@([^@]*)@\" \"%s\"",
396 ventoy_left_key
, ventoy_top_key
, ventoy_color_key
, src
);
398 grub_script_execute_sourcecode(buf
);
405 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
409 static struct grub_fs vtoy_fs
=
414 .fs_read
= ventoy_fs_read
,
415 .fs_close
= ventoy_fs_close
,
425 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
431 file
->data
= grub_malloc(rawFile
->size
+ 4096);
437 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
438 ventoy_pre_parse_data((char *)file
->data
, (int)rawFile
->size
);
439 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
441 g_old_file
= rawFile
;
443 file
->size
= rawFile
->size
+ len
;
444 file
->device
= rawFile
->device
;
446 file
->not_easily_seekable
= 1;
451 static int ventoy_check_decimal_var(const char *name
, long *value
)
453 const char *value_str
= NULL
;
455 value_str
= grub_env_get(name
);
456 if (NULL
== value_str
)
458 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
461 if (!ventoy_is_decimal(value_str
))
463 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
466 *value
= grub_strtol(value_str
, NULL
, 10);
468 return GRUB_ERR_NONE
;
471 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
473 grub_uint64_t sectors
;
475 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
477 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
481 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
484 return sectors
* 512;
487 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
493 grub_uint32_t offset
;
495 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
498 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
502 len
= (int)file
->size
;
504 data
= (char *)grub_malloc(file
->size
);
510 grub_file_read(file
, data
, file
->size
);
511 grub_file_close(file
);
513 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
514 grub_script_execute_sourcecode(exec
);
516 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
517 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
518 grub_file_close(file
);
520 grub_script_execute_sourcecode("loopback -d efiboot");
524 *direntoff
= offset
+ 2;
529 static int ventoy_set_check_result(int ret
, const char *msg
)
533 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
534 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
535 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
540 grub_printf(VTOY_WARNING
"\n");
541 grub_printf(VTOY_WARNING
"\n");
542 grub_printf(VTOY_WARNING
"\n\n\n");
544 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
545 grub_printf("Error message: <%s>\n\n", msg
);
546 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
553 static int ventoy_check_official_device(grub_device_t dev
)
557 grub_uint64_t offset
;
560 grub_uint8_t mbr
[512];
564 struct grub_partition
*partition
;
566 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
568 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
571 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
572 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
573 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
575 #ifndef GRUB_MACHINE_EFI
576 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
578 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
580 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
582 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
584 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
586 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
595 /* We must have partition 2 */
598 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
602 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
606 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
609 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
611 grub_file_close(file
);
612 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
615 partition
= dev
->disk
->partition
;
616 if (partition
->number
!= 0 || partition
->start
!= 2048)
618 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
623 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
625 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
626 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
627 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
629 grub_file_close(file
);
630 return ventoy_set_check_result(6, "Disk partition layout check failed.");
635 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
636 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
637 PartTbl
[1].SectorCount
!= 65536)
639 grub_file_close(file
);
640 return ventoy_set_check_result(6, "Disk partition layout check failed.");
646 offset
= partition
->start
+ partition
->len
;
647 partition
= file
->device
->disk
->partition
;
648 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
650 grub_file_close(file
);
651 return ventoy_set_check_result(7, "Disk partition layout check failed.");
655 grub_file_close(file
);
659 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
660 dev2
= grub_device_open(devname
);
663 return ventoy_set_check_result(8, "Disk open failed");
666 fs
= grub_fs_probe(dev2
);
669 grub_device_close(dev2
);
670 return ventoy_set_check_result(9, "FS probe failed");
673 fs
->fs_label(dev2
, &label
);
674 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
676 grub_device_close(dev2
);
677 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
680 grub_device_close(dev2
);
684 disk
= grub_disk_open(dev
->disk
->name
);
687 return ventoy_set_check_result(11, "Disk open failed");
690 grub_memset(mbr
, 0, 512);
691 grub_disk_read(disk
, 0, 0, 512, mbr
);
692 grub_disk_close(disk
);
694 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
696 return ventoy_set_check_result(12, "MBR check failed");
699 return ventoy_set_check_result(0, NULL
);
702 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
706 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
716 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
718 grub_uint64_t size
= 0;
721 char fullpath
[256] = {0};
724 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
727 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
730 debug("grub_file_open failed <%s>\n", fullpath
);
736 grub_file_close(file
);
740 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
744 char fullpath
[512] = {0};
747 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
750 file
= grub_file_open(fullpath
, type
);
753 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
760 int ventoy_is_dir_exist(const char *fmt
, ...)
767 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
771 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
774 grub_strncpy(pos
+ len
, "\" ]", 3);
776 debug("script exec %s\n", buf
);
778 if (0 == grub_script_execute_sourcecode(buf
))
786 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
789 grub_uint8_t
*outbuf
;
790 grub_uint8_t gzHdr
[10] =
792 0x1F, 0x8B, /* magic */
800 grub_memset(&s
, 0, sizeof(mz_stream
));
802 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
804 outbuf
= (grub_uint8_t
*)mem_out
;
806 mem_out_len
-= sizeof(gzHdr
) + 8;
807 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
808 outbuf
+= sizeof(gzHdr
);
810 s
.avail_in
= mem_in_len
;
813 s
.avail_out
= mem_out_len
;
816 mz_deflate(&s
, MZ_FINISH
);
820 outbuf
+= s
.total_out
;
821 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
822 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
824 return s
.total_out
+ sizeof(gzHdr
) + 8;
832 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
836 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
839 if (0 == grub_strcmp(args
[0], "on"))
842 grub_env_set("vtdebug_flag", "debug");
847 grub_env_set("vtdebug_flag", "");
850 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
853 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
857 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
859 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
860 grub_printf(" level:\r\n");
861 grub_printf(" 01/11: busybox / (+cat log)\r\n");
862 grub_printf(" 02/12: initrd / (+cat log)\r\n");
863 grub_printf(" 03/13: hook / (+cat log)\r\n");
865 grub_printf(" debug:\r\n");
866 grub_printf(" 0: debug is off\r\n");
867 grub_printf(" 1: debug is on\r\n");
869 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
872 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
874 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
876 g_ventoy_debug_level
= 1;
879 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
882 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
891 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
894 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
926 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
942 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
958 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
963 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
965 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
968 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
973 value_long
+= grub_strtol(args
[1], NULL
, 10);
975 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
976 grub_env_set(args
[0], buf
);
978 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
981 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
983 ulonglong value1
= 0;
984 ulonglong value2
= 0;
989 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
992 value1
= grub_strtoull(args
[0], NULL
, 10);
993 value2
= grub_strtoull(args
[1], NULL
, 10);
995 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
996 grub_env_set(args
[2], buf
);
998 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1001 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1016 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1019 debug("failed to open file <%s> for udf check\n", args
[0]);
1023 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
1025 grub_env_set(args
[1], buf
);
1027 grub_file_close(file
);
1033 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1041 g_wimboot_enable
= 0;
1043 grub_check_free(g_wimiso_path
);
1044 grub_check_free(g_wimiso_chunk_list
.chunk
);
1046 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1052 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1053 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1054 if (NULL
== g_wimiso_chunk_list
.chunk
)
1056 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1059 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1060 g_wimiso_chunk_list
.cur_chunk
= 0;
1062 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1064 g_wimboot_enable
= 1;
1065 g_wimiso_path
= grub_strdup(args
[0]);
1066 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1067 grub_file_close(file
);
1072 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1080 ventoy_iso9660_override
*dirent
;
1089 totlen
= sizeof(ventoy_chain_head
);
1091 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1093 debug("failed to load efiboot template %d\n", len
);
1099 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1101 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1104 debug("failed to open file <%s>\n", args
[0]);
1108 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1113 totlen
+= ventoy_align_2k(file
->size
);
1115 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1116 dirent
->first_sector
= len
/ 2048;
1117 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1118 dirent
->size
= (grub_uint32_t
)file
->size
;
1119 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1121 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1123 #ifdef GRUB_MACHINE_EFI
1124 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1126 data
= (char *)grub_malloc(totlen
);
1129 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1131 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1132 grub_check_free(buf
);
1134 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1135 grub_file_close(file
);
1137 ventoy_memfile_env_set(args
[1], data
, (ulonglong
)totlen
);
1142 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1148 g_vtoy_load_prompt
= 0;
1149 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1151 if (argc
== 2 && args
[0][0] == '1')
1153 g_vtoy_load_prompt
= 1;
1154 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1157 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1160 int ventoy_need_prompt_load_file(void)
1162 return g_vtoy_load_prompt
;
1165 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1167 grub_uint64_t ro
= 0;
1168 grub_uint64_t div
= 0;
1169 grub_ssize_t left
= size
;
1170 char *cur
= (char *)buf
;
1172 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1175 while (left
>= VTOY_SIZE_2MB
)
1177 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1178 cur
+= VTOY_SIZE_2MB
;
1179 left
-= VTOY_SIZE_2MB
;
1181 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1186 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1192 grub_file_read(file
, cur
, left
);
1195 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1201 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1206 enum grub_file_type type
;
1217 if (grub_strcmp(args
[0], "nodecompress") == 0)
1219 type
= VENTOY_FILE_TYPE
;
1223 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1226 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1229 debug("failed to open file <%s>\n", args
[1]);
1233 #ifdef GRUB_MACHINE_EFI
1234 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1236 buf
= (char *)grub_malloc(file
->size
);
1241 grub_file_close(file
);
1245 if (g_vtoy_load_prompt
)
1247 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1251 grub_file_read(file
, buf
, file
->size
);
1254 ventoy_memfile_env_set(args
[2], buf
, (ulonglong
)(file
->size
));
1256 grub_file_close(file
);
1262 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1278 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1281 debug("failed to open file <%s> for udf check\n", args
[0]);
1285 headlen
= sizeof(ventoy_chain_head
);
1287 #ifdef GRUB_MACHINE_EFI
1288 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1290 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1293 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1295 grub_file_read(file
, buf
+ headlen
, file
->size
);
1297 ventoy_memfile_env_set(args
[1], buf
, (ulonglong
)(file
->size
));
1299 grub_file_close(file
);
1305 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1311 if (grub_iso9660_is_joliet())
1313 debug("This time has joliet process\n");
1322 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1331 if (args
[0][0] == '1')
1333 grub_iso9660_set_nojoliet(1);
1337 grub_iso9660_set_nojoliet(0);
1343 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1348 grub_uint8_t buf
[32];
1359 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1362 debug("failed to open file <%s> for udf check\n", args
[0]);
1366 for (i
= 16; i
< 32; i
++)
1368 grub_file_seek(file
, i
* 2048);
1369 grub_file_read(file
, buf
, sizeof(buf
));
1377 grub_file_seek(file
, i
* 2048);
1378 grub_file_read(file
, buf
, sizeof(buf
));
1380 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1383 grub_file_seek(file
, i
* 2048);
1384 grub_file_read(file
, buf
, sizeof(buf
));
1386 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1387 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1393 grub_file_close(file
);
1395 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1400 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1402 long value_long1
= 0;
1403 long value_long2
= 0;
1405 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1407 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1410 value_long1
= grub_strtol(args
[0], NULL
, 10);
1411 value_long2
= grub_strtol(args
[2], NULL
, 10);
1413 if (0 == grub_strcmp(args
[1], "eq"))
1415 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1417 else if (0 == grub_strcmp(args
[1], "ne"))
1419 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1421 else if (0 == grub_strcmp(args
[1], "gt"))
1423 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1425 else if (0 == grub_strcmp(args
[1], "lt"))
1427 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1429 else if (0 == grub_strcmp(args
[1], "ge"))
1431 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1433 else if (0 == grub_strcmp(args
[1], "le"))
1435 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1439 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1445 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1448 char buf
[128] = {0};
1452 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1455 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1456 pos
= grub_strstr(buf
, ",");
1462 grub_env_set(args
[1], buf
);
1464 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1467 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1473 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1479 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1482 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1484 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1485 if (0 == grub_script_execute_sourcecode(buf
))
1487 debug("file %s exist, ventoy_compatible YES\n", buf
);
1488 grub_env_set("ventoy_compatible", "YES");
1489 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1493 debug("file %s NOT exist\n", buf
);
1497 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1498 pos
= grub_strstr(buf
, ")");
1504 disk
= grub_disk_open(buf
);
1507 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1508 grub_disk_close(disk
);
1510 g_img_swap_tmp_buf
[703] = 0;
1511 for (i
= 318; i
< 703; i
++)
1513 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1514 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1516 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1517 grub_env_set("ventoy_compatible", "YES");
1518 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1524 debug("failed to open disk <%s>\n", buf
);
1527 grub_env_set("ventoy_compatible", "NO");
1528 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1531 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1537 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1539 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1542 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1547 if (0 == g_sort_case_sensitive
)
1549 if (grub_islower(c1
))
1551 c1
= c1
- 'a' + 'A';
1554 if (grub_islower(c2
))
1556 c2
= c2
- 'a' + 'A';
1569 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1575 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1577 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1580 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1585 if (0 == g_sort_case_sensitive
)
1587 if (grub_islower(c1
))
1589 c1
= c1
- 'a' + 'A';
1592 if (grub_islower(c2
))
1594 c2
= c2
- 'a' + 'A';
1607 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1609 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1611 grub_memcpy(img1
, img2
, sizeof(img_info
));
1612 img1
->next
= g_img_swap_tmp
.next
;
1613 img1
->prev
= g_img_swap_tmp
.prev
;
1615 g_img_swap_tmp
.next
= img2
->next
;
1616 g_img_swap_tmp
.prev
= img2
->prev
;
1617 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1620 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1624 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1632 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1634 ventoy_vlnk_part
*node
= NULL
;
1635 grub_uint32_t SelfSig
;
1636 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1638 /* skip Ventoy partition 1/2 */
1639 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1640 if (partition
->number
< 2 && SelfSig
== *pSig
)
1645 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1648 node
->disksig
= *pSig
;
1649 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1650 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1651 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1653 node
->next
= g_vlnk_part_list
;
1654 g_vlnk_part_list
= node
;
1660 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1667 disk
= grub_disk_open(name
);
1670 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1671 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1672 grub_disk_close(disk
);
1678 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1680 const char *fs
[ventoy_fs_max
+ 1] =
1682 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1687 cur
->dev
= grub_device_open(cur
->device
);
1692 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1698 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1703 char *disk
, *device
;
1704 grub_uint32_t readcrc
, calccrc
;
1705 ventoy_vlnk_part
*cur
;
1706 grub_fs_t fs
= NULL
;
1708 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1712 grub_printf("VLNK invalid guid\n");
1718 readcrc
= vlnk
->crc32
;
1720 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1721 if (readcrc
!= calccrc
)
1725 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1731 if (!g_vlnk_part_list
)
1733 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1736 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1738 if (cur
->disksig
== vlnk
->disk_signature
)
1742 if (cur
->partoffset
== vlnk
->part_offset
)
1745 device
= cur
->device
;
1747 if (cur
->probe
== 0)
1750 ventoy_vlnk_probe_fs(cur
);
1760 struct grub_file file
;
1762 grub_memset(&file
, 0, sizeof(file
));
1763 file
.device
= cur
->dev
;
1764 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1767 cur
->fs
->fs_close(&file
);
1768 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1781 grub_printf("\n==== VLNK Information ====\n"
1782 "Disk Signature: %08x\n"
1783 "Partition Offset: %llu\n"
1784 "File Path: <%s>\n\n",
1785 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1789 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1793 grub_printf("Disk Find: [ NO ]\n");
1798 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1802 grub_printf("Part Find: [ NO ]\n");
1804 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1807 grub_printf("VLNK File: <%s>\n", dst
);
1814 return (1 - filefind
);
1817 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1822 grub_file_t file
= NULL
;
1827 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1829 else if (dir
[0] == '/')
1831 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1835 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1838 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1844 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1845 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1846 grub_file_close(file
);
1848 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1850 rc
= grub_file_add_vlnk(src
, dst
);
1856 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1866 const menu_tip
*tip
;
1867 img_iterator_node
*tmp
;
1868 img_iterator_node
*new_node
;
1869 img_iterator_node
*node
= (img_iterator_node
*)data
;
1871 if (g_enumerate_time_checked
== 0)
1873 g_enumerate_finish_time_ms
= grub_get_time_ms();
1874 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1877 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1879 g_enumerate_time_checked
= 1;
1883 len
= grub_strlen(filename
);
1887 if (node
->level
+ 1 > g_img_max_search_level
)
1892 if ((len
== 1 && filename
[0] == '.') ||
1893 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1898 if (!ventoy_img_name_valid(filename
, len
))
1903 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1908 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1910 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1911 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1914 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1919 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1922 new_node
->level
= node
->level
+ 1;
1923 new_node
->plugin_list_index
= index
;
1924 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1926 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1929 debug("Directory %s ignored...\n", new_node
->dir
);
1930 grub_free(new_node
);
1934 new_node
->tail
= node
->tail
;
1936 new_node
->parent
= node
;
1937 if (!node
->firstchild
)
1939 node
->firstchild
= new_node
;
1942 if (g_img_iterator_tail
)
1944 g_img_iterator_tail
->next
= new_node
;
1945 g_img_iterator_tail
= new_node
;
1949 g_img_iterator_head
.next
= new_node
;
1950 g_img_iterator_tail
= new_node
;
1956 debug("Find a file %s\n", filename
);
1962 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1964 type
= img_type_iso
;
1966 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1968 type
= img_type_wim
;
1970 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1971 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1973 type
= img_type_vhd
;
1975 #ifdef GRUB_MACHINE_EFI
1976 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1978 type
= img_type_efi
;
1981 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1983 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1985 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1986 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1991 type
= img_type_img
;
1993 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1995 type
= img_type_vtoy
;
1997 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1999 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
2001 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2002 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
2011 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
2016 if (g_plugin_image_list
)
2018 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2019 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
2020 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
2022 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2025 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2027 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2032 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2034 if (grub_file_is_vlnk_suffix(filename
, len
))
2037 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2044 img
= grub_zalloc(sizeof(img_info
));
2048 img
->plugin_list_index
= index
;
2049 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2051 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2053 img
->size
= info
->size
;
2054 if (vlnk
|| 0 == img
->size
)
2056 if (node
->dir
[0] == '/')
2058 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2062 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2066 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2068 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2073 if (g_ventoy_img_list
)
2075 tail
= *(node
->tail
);
2081 g_ventoy_img_list
= img
;
2084 img
->id
= g_ventoy_img_count
;
2086 if (node
&& NULL
== node
->firstiso
)
2088 node
->firstiso
= img
;
2099 *((img_info
**)(node
->tail
)) = img
;
2100 g_ventoy_img_count
++;
2102 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2104 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2107 img
->tip1
= tip
->tip1
;
2108 img
->tip2
= tip
->tip2
;
2111 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2114 img
->class = g_menu_class
[type
];
2116 img
->menu_prefix
= g_menu_prefix
[type
];
2118 if (img_type_iso
== type
)
2120 if (ventoy_plugin_check_memdisk(img
->path
))
2122 img
->menu_prefix
= "miso";
2125 else if (img_type_img
== type
)
2127 if (ventoy_plugin_check_memdisk(img
->path
))
2129 img
->menu_prefix
= "mimg";
2133 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2140 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2142 int len
= GRUB_UINT_MAX
;
2143 const char *value
= NULL
;
2144 char name
[32] = {0};
2145 char plat
[32] = {0};
2146 char guidstr
[32] = {0};
2147 ventoy_guid guid
= VENTOY_GUID
;
2148 const char *fmt1
= NULL
;
2149 const char *fmt2
= NULL
;
2150 const char *fmt3
= NULL
;
2151 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2152 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2153 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2154 const char fmtcode
[]={
2155 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2156 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2157 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2158 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2159 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2160 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2163 grub_memset(name
, 0, sizeof(name
));
2164 puint
[0] = grub_swap_bytes32(0x56454e54);
2165 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2166 puint
[2] = grub_swap_bytes32(0x45525349);
2167 puint
[1] = grub_swap_bytes32(0x4f595f56);
2168 value
= ventoy_get_env(name
);
2170 grub_memset(name
, 0, sizeof(name
));
2171 puint
[1] = grub_swap_bytes32(0x5f544f50);
2172 puint
[0] = grub_swap_bytes32(0x56544c45);
2173 fmt1
= ventoy_get_env(name
);
2179 grub_memset(name
, 0, sizeof(name
));
2180 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2181 puint
[0] = grub_swap_bytes32(0x56544c45);
2182 fmt2
= ventoy_get_env(name
);
2184 grub_memset(name
, 0, sizeof(name
));
2185 puint
[1] = grub_swap_bytes32(0x5f434c52);
2186 puint
[0] = grub_swap_bytes32(0x56544c45);
2187 fmt3
= ventoy_get_env(name
);
2189 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2191 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2193 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2194 #pragma GCC diagnostic push
2195 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2196 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2197 fmt1
? fmt1
: fmtdata
,
2198 fmt2
? fmt2
: fmtdata
+ 4,
2199 value
? value
: "", plat
, guidstr
,
2200 fmt3
? fmt3
: fmtdata
+ 6);
2201 #pragma GCC diagnostic pop
2203 grub_memset(name
, 0, sizeof(name
));
2204 puint
[0] = grub_swap_bytes32(0x76746f79);
2205 puint
[2] = grub_swap_bytes32(0x656e7365);
2206 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2207 ventoy_set_env(name
, guidstr
);
2213 ventoy_password_get (char buf
[], unsigned buf_size
)
2215 unsigned i
, cur_len
= 0;
2217 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2221 key
= grub_getkey ();
2222 if (key
== '\n' || key
== '\r')
2225 if (key
== GRUB_TERM_ESC
)
2235 grub_term_restore_pos (pos
);
2236 for (i
= 0; i
< cur_len
; i
++)
2238 grub_term_restore_pos (pos
);
2240 for (i
= 0; i
< cur_len
; i
++)
2247 if (!grub_isprint (key
))
2250 if (cur_len
+ 2 < buf_size
)
2251 buf
[cur_len
++] = key
;
2256 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2262 return (key
!= GRUB_TERM_ESC
);
2265 static int ventoy_get_password(char buf
[], unsigned buf_size
)
2267 const char *env
= NULL
;
2269 env
= grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2270 if (env
&& env
[0] == '0' && env
[1] == 0)
2272 return grub_password_get(buf
, buf_size
);
2276 return ventoy_password_get(buf
, buf_size
);
2280 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2284 grub_uint8_t md5
[16];
2288 grub_memset(input
, 0, sizeof(input
));
2290 grub_printf("Enter password: ");
2293 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2295 ventoy_get_password(input
, 128);
2296 if (grub_strcmp(pwd
->text
, input
) == 0)
2301 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2303 ventoy_get_password(input
, 128);
2304 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2305 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2310 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2312 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2313 ventoy_get_password(input
+ offset
, 128);
2315 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2316 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2322 grub_printf("Invalid password!\n\n");
2329 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2331 img_info
*minimg
= NULL
;
2332 img_info
*img
= (img_info
*)(node
->firstiso
);
2334 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2336 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2351 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2353 img_iterator_node
*Minchild
= NULL
;
2354 img_iterator_node
*child
= node
->firstchild
;
2356 while (child
&& child
->parent
== node
)
2358 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2362 child
= child
->next
;
2367 Minchild
->select
= 1;
2373 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2376 img_info
*img
= NULL
;
2377 const char *dir_class
= NULL
;
2378 const char *dir_alias
= NULL
;
2379 img_iterator_node
*child
= NULL
;
2380 const menu_tip
*tip
= NULL
;
2382 if (node
->isocnt
== 0 || node
->done
== 1)
2387 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2389 offset
= node
->parent
->dirlen
;
2392 if (node
== &g_img_iterator_head
)
2394 if (g_default_menu_mode
== 0)
2396 if (g_tree_view_menu_style
== 0)
2398 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2399 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2400 " echo 'return ...' \n"
2401 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2405 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2406 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2407 " echo 'return ...' \n"
2408 "}\n", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2412 g_tree_script_pre
= g_tree_script_pos
;
2416 node
->dir
[node
->dirlen
- 1] = 0;
2417 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2420 dir_class
= "vtoydir";
2423 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2425 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2428 if (g_tree_view_menu_style
== 0)
2430 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2431 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2432 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2436 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2437 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2438 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2443 dir_alias
= node
->dir
+ offset
;
2445 if (g_tree_view_menu_style
== 0)
2447 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2448 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2449 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2453 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2454 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2455 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2459 if (g_tree_view_menu_style
== 0)
2461 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2462 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2463 " echo 'return ...' \n"
2464 "}\n", "<--", node
->dir
);
2468 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2469 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2470 " echo 'return ...' \n"
2475 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2477 ventoy_dynamic_tree_menu(child
);
2480 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2482 if (g_tree_view_menu_style
== 0)
2484 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2485 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2488 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2489 img
->unsupport
? "[***********] " : "",
2490 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2492 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2496 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2497 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2500 img
->unsupport
? "[***********] " : "",
2501 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2503 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2507 if (node
!= &g_img_iterator_head
)
2509 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2516 static int ventoy_set_default_menu(void)
2522 const char *strdata
= NULL
;
2523 img_info
*cur
= NULL
;
2524 img_info
*default_node
= NULL
;
2525 const char *default_image
= NULL
;
2527 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2528 if (default_image
&& default_image
[0] == '/')
2530 img_len
= grub_strlen(default_image
);
2532 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2534 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2546 if (0 == g_default_menu_mode
)
2548 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2552 def
= grub_strdup(default_image
);
2558 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2560 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2561 if (strdata
&& strdata
[0] == '/')
2563 pos
= def
+ grub_strlen(strdata
);
2574 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2577 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2581 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2589 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2591 img_info
*next
= NULL
;
2592 img_info
*cur
= g_ventoy_img_list
;
2605 g_ventoy_img_list
= NULL
;
2606 g_ventoy_img_count
= 0;
2608 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2611 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2614 img_info
*cur
= g_ventoy_img_list
;
2618 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2620 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2623 img_id
= grub_strtol(args
[0], NULL
, 10);
2624 if (img_id
>= g_ventoy_img_count
)
2626 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2629 debug("Find image %ld name \n", img_id
);
2631 while (cur
&& img_id
> 0)
2639 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2642 debug("image name is %s\n", cur
->name
);
2644 grub_env_set(args
[1], cur
->name
);
2646 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2649 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2653 img_info
*cur
= g_ventoy_img_list
;
2659 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2662 len
= (int)grub_strlen(args
[0]);
2666 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2675 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2678 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2679 grub_env_set("chosen", id
);
2680 grub_env_export("chosen");
2682 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2685 static char g_fake_vlnk_src
[512];
2686 static char g_fake_vlnk_dst
[512];
2687 static grub_uint64_t g_fake_vlnk_size
;
2688 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2694 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2696 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2697 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2699 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2701 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2704 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2710 g_fake_vlnk_src
[0] = 0;
2711 g_fake_vlnk_dst
[0] = 0;
2712 g_fake_vlnk_size
= 0;
2713 grub_file_vtoy_vlnk(NULL
, NULL
);
2715 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2719 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2724 const char *id
= NULL
;
2725 img_info
*cur
= NULL
;
2729 if (argc
< 1 || argc
> 3)
2731 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2734 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2736 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2737 grub_env_set(args
[0], pos
);
2740 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2741 grub_env_set(args
[1], value
);
2746 for (last
= pos
; *pos
; pos
++)
2753 grub_env_set(args
[2], last
+ 1);
2759 id
= grub_env_get("chosen");
2761 pos
= grub_strstr(id
, "VID_");
2764 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2768 cur
= g_ventoy_img_list
;
2773 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2776 grub_env_set(args
[0], cur
->path
);
2780 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2781 grub_env_set(args
[1], value
);
2786 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2787 grub_env_set(args
[2], cur
->name
);
2791 g_svd_replace_offset
= 0;
2793 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2797 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2801 grub_device_t dev
= NULL
;
2802 img_info
*cur
= NULL
;
2803 img_info
*tail
= NULL
;
2804 img_info
*min
= NULL
;
2805 img_info
*head
= NULL
;
2806 const char *strdata
= NULL
;
2807 char *device_name
= NULL
;
2809 img_iterator_node
*node
= NULL
;
2810 img_iterator_node
*tmp
= NULL
;
2816 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2819 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2821 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2826 g_enumerate_time_checked
= 0;
2827 g_enumerate_start_time_ms
= grub_get_time_ms();
2829 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2830 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2832 g_filt_dot_underscore_file
= 1;
2835 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2836 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2838 g_sort_case_sensitive
= 1;
2841 device_name
= grub_file_get_device_name(args
[0]);
2847 g_enum_dev
= dev
= grub_device_open(device_name
);
2853 g_enum_fs
= fs
= grub_fs_probe(dev
);
2859 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2861 debug("unsupported fs:<%s>\n", fs
->name
);
2862 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2866 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2868 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2869 if (strdata
&& strdata
[0] == '1')
2871 g_default_menu_mode
= 1;
2874 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2876 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2878 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2879 if (strdata
&& strdata
[0] == '/')
2881 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2882 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2884 g_img_iterator_head
.dir
[len
++] = '/';
2886 g_img_iterator_head
.dirlen
= len
;
2890 g_img_iterator_head
.dirlen
= 1;
2891 grub_strcpy(g_img_iterator_head
.dir
, "/");
2894 g_img_iterator_head
.tail
= &tail
;
2896 if (g_img_max_search_level
< 0)
2898 g_img_max_search_level
= GRUB_INT_MAX
;
2899 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2900 if (strdata
&& ventoy_is_decimal(strdata
))
2902 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2906 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2907 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2908 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2909 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2910 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2911 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2913 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2915 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2918 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2919 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2921 g_tree_view_menu_style
= 1;
2924 ventoy_set_default_menu();
2926 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2928 ventoy_dynamic_tree_menu(node
);
2932 node
= g_img_iterator_head
.next
;
2940 /* sort image list by image name */
2941 while (g_ventoy_img_list
)
2943 min
= g_ventoy_img_list
;
2944 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2946 if (ventoy_cmp_img(min
, cur
) > 0)
2954 min
->prev
->next
= min
->next
;
2959 min
->next
->prev
= min
->prev
;
2962 if (min
== g_ventoy_img_list
)
2964 g_ventoy_img_list
= min
->next
;
2982 g_ventoy_img_list
= head
;
2984 if (g_default_menu_mode
== 1)
2986 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2987 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2988 " echo 'return ...' \n"
2989 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_TREEVIEW"));
2992 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2994 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2995 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2998 cur
->unsupport
? "[***********] " : "",
2999 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
3001 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
3004 g_tree_script_buf
[g_tree_script_pos
] = 0;
3005 g_list_script_buf
[g_list_script_pos
] = 0;
3007 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
3008 grub_env_set(args
[1], buf
);
3012 check_free(device_name
, grub_free
);
3013 check_free(dev
, grub_device_close
);
3015 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3018 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
3025 device_name
= grub_file_get_device_name(filename
);
3037 pos2
= grub_strstr(pos
, ",");
3040 pos2
= grub_strstr(pos
, ")");
3048 disk
= grub_disk_open(pos
);
3051 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3052 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3053 grub_disk_close(disk
);
3060 grub_free(device_name
);
3064 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3066 eltorito_descriptor desc
;
3068 grub_memset(&desc
, 0, sizeof(desc
));
3069 grub_file_seek(file
, 17 * 2048);
3070 grub_file_read(file
, &desc
, sizeof(desc
));
3072 if (desc
.type
!= 0 || desc
.version
!= 1)
3077 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3078 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3086 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3088 grub_uint8_t buf
[512];
3090 grub_file_seek(file
, sector
* 2048);
3091 grub_file_read(file
, buf
, sizeof(buf
));
3093 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3094 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3096 return *((grub_uint32_t
*)(buf
+ 40));
3102 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3106 grub_uint8_t buf
[512];
3107 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3109 grub_file_seek(file
, sector
* 2048);
3110 grub_file_read(file
, buf
, sizeof(buf
));
3112 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3114 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3118 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3123 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3125 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3127 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3131 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3133 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3138 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3140 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3142 if (buf
[36] == parttype
[i
])
3144 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3150 debug("%s does not contain efi eltorito\n", file
->name
);
3154 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3157 const char *fs
= NULL
;
3158 const char *val
= NULL
;
3159 const char *cdprompt
= NULL
;
3161 grub_uint8_t chksum
= 0;
3164 disk
= file
->device
->disk
;
3165 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3167 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3168 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3169 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3171 pos
= grub_strstr(file
->name
, "/");
3177 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3179 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3181 param
->vtoy_img_size
= file
->size
;
3183 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3184 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3186 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3188 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3189 param
->vtoy_reserved
[4] = 0;
3190 if (g_ventoy_chain_type
== 1) /* Windows */
3192 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3193 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3195 param
->vtoy_reserved
[4] = 1;
3199 fs
= ventoy_get_env("ventoy_fs_probe");
3200 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3202 param
->vtoy_reserved
[3] = 1;
3205 param
->vtoy_reserved
[5] = 0;
3206 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3207 if (val
&& val
[0] == '1' && val
[1] == 0)
3209 param
->vtoy_reserved
[5] = 1;
3212 /* ventoy_disk_signature used for vlnk */
3213 param
->vtoy_reserved
[6] = file
->vlnk
;
3214 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3216 /* calculate checksum */
3217 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3219 chksum
+= *((grub_uint8_t
*)param
+ i
);
3221 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3226 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3228 grub_uint32_t i
= 0;
3229 grub_uint64_t total
= 0;
3230 grub_uint64_t fileblk
= 0;
3231 ventoy_img_chunk
*chunk
= NULL
;
3233 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3235 chunk
= chunklist
->chunk
+ i
;
3237 if (chunk
->disk_start_sector
<= start
)
3239 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3243 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3246 fileblk
= (file
->size
+ 511) / 512;
3248 if (total
!= fileblk
)
3250 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3251 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3253 debug("maybe img file to be processed.\n");
3263 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3267 grub_uint32_t i
= 0;
3268 grub_uint32_t sector
= 0;
3269 grub_uint32_t count
= 0;
3270 grub_off_t size
= 0;
3271 grub_off_t read
= 0;
3273 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3274 if (fs_type
== ventoy_fs_exfat
)
3276 grub_fat_get_file_chunk(start
, file
, chunklist
);
3278 else if (fs_type
== ventoy_fs_ext
)
3280 grub_ext_get_file_chunk(start
, file
, chunklist
);
3284 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3285 file
->read_hook_data
= chunklist
;
3287 for (size
= file
->size
; size
> 0; size
-= read
)
3289 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3290 grub_file_read(file
, NULL
, read
);
3293 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3295 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3296 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3299 if (ventoy_fs_udf
== fs_type
)
3301 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3303 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3304 chunklist
->chunk
[i
].img_start_sector
= sector
;
3305 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3311 len
= (int)grub_strlen(file
->name
);
3312 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3313 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3314 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3315 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3317 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3319 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3329 chunklist
->chunk
[i
].img_start_sector
= sector
;
3330 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3338 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3342 grub_disk_addr_t start
;
3347 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3350 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3353 g_conf_replace_count
= 0;
3354 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3355 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3357 if (g_img_chunk_list
.chunk
)
3359 grub_free(g_img_chunk_list
.chunk
);
3362 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3364 grub_file_close(file
);
3365 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3368 /* get image chunk data */
3369 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3370 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3371 if (NULL
== g_img_chunk_list
.chunk
)
3373 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3376 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3377 g_img_chunk_list
.cur_chunk
= 0;
3379 start
= file
->device
->disk
->partition
->start
;
3381 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3383 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3384 grub_file_close(file
);
3388 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3391 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3392 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3393 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3396 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3400 grub_uint64_t offset
= 0;
3401 grub_uint32_t align
= 0;
3402 grub_file_t file
= NULL
;
3403 conf_replace
*node
= NULL
;
3404 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3405 ventoy_grub_param_file_replace
*replace
= NULL
;
3411 debug("select conf replace argc:%d\n", argc
);
3418 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3421 debug("Conf replace not found for %s\n", args
[1]);
3425 debug("Find %d conf replace for %s\n", n
, args
[1]);
3427 g_conf_replace_count
= n
;
3428 for (i
= 0; i
< n
; i
++)
3432 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3435 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3436 grub_file_close(file
);
3438 else if (node
->img
> 0)
3444 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3448 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3451 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3455 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3457 if (align
> vtoy_max_replace_file_size
)
3459 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3460 grub_file_close(file
);
3464 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3465 grub_file_close(file
);
3466 g_conf_replace_new_len
[i
] = (int)file
->size
;
3467 g_conf_replace_new_len_align
[i
] = align
;
3469 g_conf_replace_node
[i
] = node
;
3470 g_conf_replace_offset
[i
] = offset
+ 2;
3474 replace
= &(g_grub_param
->img_replace
[i
]);
3475 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3476 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3477 replace
->old_name_cnt
++;
3480 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3484 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3487 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3492 const char *ch
= var
;
3499 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3506 debug("Invalid variable letter <%c>\n", *ch
);
3513 debug("Invalid variable length:%d <%s>\n", n
, var
);
3517 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3526 grub_printf("\n=================== Variables Expansion ===================\n\n");
3529 grub_printf("<%s>: ", var
);
3532 while (i
< (len
- 1))
3535 if ((c
== '\n') || (c
== '\r'))
3545 else if (grub_isprint(c
))
3547 if (i
+ 1 < (len
- 1))
3549 grub_printf("%c", c
);
3559 expand
[i
- 1] = ' ';
3560 grub_printf("\r<%s>: %s", var
, expand
);
3563 grub_printf("\r<%s>: %s", var
, expand
);
3575 grub_snprintf(expand
, len
, "$$%s$$", var
);
3581 static int ventoy_auto_install_var_expand(install_template
*node
)
3589 char *newbuf
= NULL
;
3590 char *curline
= NULL
;
3591 char *nextline
= NULL
;
3592 grub_uint8_t
*code
= NULL
;
3594 var_node
*CurNode
= NULL
;
3595 var_node
*pVarList
= NULL
;
3597 code
= (grub_uint8_t
*)node
->filebuf
;
3599 if (node
->filelen
>= VTOY_SIZE_1MB
)
3601 debug("auto install script too long %d\n", node
->filelen
);
3605 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3607 debug("UCS-2 encoding NOT supported\n");
3611 start
= grub_strstr(node
->filebuf
, "$$");
3614 debug("no need to expand variable, no start.\n");
3618 end
= grub_strstr(start
+ 2, "$$");
3621 debug("no need to expand variable, no end.\n");
3625 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3626 newbuf
= grub_malloc(newlen
);
3629 debug("Failed to alloc newbuf %d\n", newlen
);
3633 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3635 nextline
= ventoy_get_line(curline
);
3637 start
= grub_strstr(curline
, "$$");
3640 end
= grub_strstr(start
+ 2, "$$");
3646 VTOY_APPEND_NEWBUF(curline
);
3648 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3650 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3652 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3659 value
[sizeof(value
) - 1] = 0;
3660 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3664 CurNode
= grub_zalloc(sizeof(var_node
));
3667 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3668 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3669 CurNode
->next
= pVarList
;
3675 VTOY_APPEND_NEWBUF(value
);
3677 VTOY_APPEND_NEWBUF(end
+ 2);
3681 VTOY_APPEND_NEWBUF(curline
);
3684 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3686 newbuf
[pos
- 1] = '\n';
3690 newbuf
[pos
++] = '\n';
3694 grub_free(node
->filebuf
);
3695 node
->filebuf
= newbuf
;
3696 node
->filelen
= pos
;
3700 CurNode
= pVarList
->next
;
3701 grub_free(pVarList
);
3708 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3714 grub_file_t file
= NULL
;
3715 char configfile
[128];
3716 install_template
*node
= NULL
;
3722 debug("select auto installation argc:%d\n", argc
);
3729 node
= ventoy_plugin_find_install_template(args
[0]);
3732 debug("Auto install template not found for %s\n", args
[0]);
3736 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3738 defidx
= node
->autosel
;
3739 if (node
->timeout
< 0)
3741 node
->cursel
= node
->autosel
- 1;
3742 debug("Auto install template auto select %d\n", node
->autosel
);
3747 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3753 if (node
->timeout
> 0)
3755 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3758 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3759 " echo %s\n}\n", "");
3761 for (i
= 0; i
< node
->templatenum
; i
++)
3763 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3765 ventoy_get_vmenu_title("VTLANG_AUTOINS_USE"),
3766 node
->templatepath
[i
].path
);
3769 g_ventoy_menu_esc
= 1;
3770 g_ventoy_suppress_esc
= 1;
3771 g_ventoy_suppress_esc_default
= defidx
;
3772 g_ventoy_secondary_menu_on
= 1;
3774 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3775 grub_script_execute_sourcecode(configfile
);
3777 g_ventoy_menu_esc
= 0;
3778 g_ventoy_suppress_esc
= 0;
3779 g_ventoy_suppress_esc_default
= 1;
3780 g_ventoy_secondary_menu_on
= 0;
3784 node
->cursel
= g_ventoy_last_entry
- 1;
3787 grub_check_free(node
->filebuf
);
3790 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3792 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3793 node
->templatepath
[node
->cursel
].path
);
3796 node
->filebuf
= grub_malloc(file
->size
+ 8);
3799 grub_file_read(file
, node
->filebuf
, file
->size
);
3800 grub_file_close(file
);
3802 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3803 node
->filelen
= (int)file
->size
;
3805 ventoy_auto_install_var_expand(node
);
3810 debug("Failed to open auto install script <%s%s>\n",
3811 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3815 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3818 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3824 char configfile
[128];
3825 persistence_config
*node
;
3831 debug("select persistence argc:%d\n", argc
);
3838 node
= ventoy_plugin_find_persistent(args
[0]);
3841 debug("Persistence image not found for %s\n", args
[0]);
3845 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3847 defidx
= node
->autosel
;
3848 if (node
->timeout
< 0)
3850 node
->cursel
= node
->autosel
- 1;
3851 debug("Persistence image auto select %d\n", node
->autosel
);
3856 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3862 if (node
->timeout
> 0)
3864 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3867 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_PERSIST\" --class=\"sel_persistence\" {\n"
3868 " echo %s\n}\n", "");
3870 for (i
= 0; i
< node
->backendnum
; i
++)
3872 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3874 ventoy_get_vmenu_title("VTLANG_PERSIST_USE"),
3875 node
->backendpath
[i
].path
);
3879 g_ventoy_menu_esc
= 1;
3880 g_ventoy_suppress_esc
= 1;
3881 g_ventoy_suppress_esc_default
= defidx
;
3882 g_ventoy_secondary_menu_on
= 1;
3884 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3885 grub_script_execute_sourcecode(configfile
);
3887 g_ventoy_menu_esc
= 0;
3888 g_ventoy_suppress_esc
= 0;
3889 g_ventoy_suppress_esc_default
= 1;
3890 g_ventoy_secondary_menu_on
= 0;
3894 node
->cursel
= g_ventoy_last_entry
- 1;
3896 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3899 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3902 ventoy_img_chunk
*cur
;
3908 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3910 cur
= g_img_chunk_list
.chunk
+ i
;
3911 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3912 cur
->img_start_sector
, cur
->img_end_sector
,
3913 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3917 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3920 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3924 ventoy_img_chunk_list chunklist
;
3929 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3932 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3935 /* get image chunk data */
3936 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3937 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3938 if (NULL
== chunklist
.chunk
)
3940 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3943 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3944 chunklist
.cur_chunk
= 0;
3946 ventoy_get_block_list(file
, &chunklist
, 0);
3948 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3950 grub_printf("########## UNSUPPORTED ###############\n");
3953 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3955 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3957 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3958 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3961 grub_printf("\n==================================\n");
3963 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3965 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3966 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3967 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3968 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3969 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3973 grub_free(chunklist
.chunk
);
3974 grub_file_close(file
);
3976 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3979 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3982 ventoy_grub_param_file_replace
*replace
= NULL
;
3990 replace
= &(g_grub_param
->file_replace
);
3991 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3993 replace
->old_name_cnt
= 0;
3994 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3996 replace
->old_name_cnt
++;
3997 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
4000 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
4003 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4006 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4009 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
4015 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
4016 grub_env_set(args
[0], buf
);
4019 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4022 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4030 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4031 grub_printf("%s", g_list_script_buf
);
4035 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4036 grub_printf("%s", g_tree_script_buf
);
4042 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4044 img_info
*cur
= g_ventoy_img_list
;
4052 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4053 grub_printf("name:<%s>\n\n", cur
->name
);
4060 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4066 ventoy_plugin_dump_injection();
4071 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4077 ventoy_plugin_dump_auto_install();
4082 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4088 ventoy_plugin_dump_persistence();
4093 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4099 len1
= (int)grub_strlen(filename
);
4100 len2
= (int)grub_strlen(suffix
);
4107 for (i
= len1
- 1; i
>= 0; i
--)
4109 if (filename
[i
] == '.')
4120 if (filename
[i
- len2
- 1] != '_')
4125 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4133 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4139 if (argc
!= 1 && argc
!= 2)
4144 if (args
[0][0] == '0')
4146 if (g_ventoy_memdisk_mode
)
4151 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4158 else if (args
[0][0] == '1')
4160 return g_ventoy_iso_raw
? 0 : 1;
4162 else if (args
[0][0] == '2')
4164 return g_ventoy_iso_uefi_drv
? 0 : 1;
4166 else if (args
[0][0] == '3')
4168 if (g_ventoy_grub2_mode
)
4173 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4180 else if (args
[0][0] == '4')
4182 if (g_ventoy_wimboot_mode
)
4187 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4198 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4200 static int configfile_mode
= 0;
4201 char memfile
[128] = {0};
4208 * args[0]: 0:normal 1:configfile
4209 * args[1]: 0:list_buf 1:tree_buf
4214 debug("Invalid argc %d\n", argc
);
4220 if (args
[0][0] == '0')
4222 if (args
[1][0] == '0')
4224 grub_script_execute_sourcecode(g_list_script_buf
);
4228 grub_script_execute_sourcecode(g_tree_script_buf
);
4233 if (configfile_mode
)
4235 debug("Now already in F3 mode %d\n", configfile_mode
);
4239 if (args
[1][0] == '0')
4241 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4242 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4246 g_ventoy_last_entry
= -1;
4247 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4248 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4251 configfile_mode
= 1;
4252 grub_script_execute_sourcecode(memfile
);
4253 configfile_mode
= 0;
4259 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4270 g_ventoy_case_insensitive
= 1;
4271 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4272 g_ventoy_case_insensitive
= 0;
4278 grub_file_close(file
);
4284 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4289 const char *isopath
= NULL
;
4291 ventoy_mbr_head mbr
;
4298 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4301 isopath
= grub_env_get("vtoy_iso_part");
4304 debug("isopath is null %p\n", isopath
);
4308 debug("isopath is %s\n", isopath
);
4310 for (id
= 0; id
< 30 && (find
== 0); id
++)
4312 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4313 if (grub_strstr(isopath
, hdname
))
4315 debug("skip %s ...\n", hdname
);
4319 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4321 disk
= grub_disk_open(hdname
);
4324 debug("%s not exist\n", hdname
);
4328 grub_memset(&mbr
, 0, sizeof(mbr
));
4329 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4331 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4333 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4334 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4337 grub_env_set(args
[0], hdname
);
4341 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4345 debug("read %s failed\n", hdname
);
4348 grub_disk_close(disk
);
4354 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4365 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4368 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4371 debug("failed to open file %s\n", args
[0]);
4375 buf
= grub_malloc(len
);
4382 grub_file_read(file
, buf
, len
- 1);
4384 ventoy_get_line(buf
);
4385 ventoy_set_env(args
[1], buf
);
4389 grub_check_free(buf
);
4390 grub_file_close(file
);
4395 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4397 grub_uint64_t end_max
= 0;
4398 int *pCnt
= (int *)data
;
4403 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4404 "0 %llu linear /dev/ventoy %llu\n",
4405 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4407 end_max
= (partition
->len
+ partition
->start
) * 512;
4408 if (end_max
> g_part_end_max
)
4410 g_part_end_max
= end_max
;
4416 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4419 char *device_name
= NULL
;
4420 grub_device_t dev
= NULL
;
4425 g_part_list_pos
= 0;
4427 grub_env_unset("vtoy_img_part_file");
4434 device_name
= grub_file_get_device_name(args
[0]);
4437 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4441 dev
= grub_device_open(device_name
);
4444 debug("grub_device_open failed, %s\n", device_name
);
4448 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4450 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4451 grub_env_set("vtoy_img_part_file", buf
);
4453 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4454 grub_env_set("vtoy_img_part_cnt", buf
);
4456 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4457 grub_env_set("vtoy_img_max_part_end", buf
);
4461 check_free(device_name
, grub_free
);
4462 check_free(dev
, grub_device_close
);
4468 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4479 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4482 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4485 debug("failed to open file %s\n", args
[0]);
4489 buf
= grub_malloc(file
->size
+ 1);
4495 buf
[file
->size
] = 0;
4496 grub_file_read(file
, buf
, file
->size
);
4498 if (grub_strstr(buf
, args
[1]))
4505 grub_check_free(buf
);
4506 grub_file_close(file
);
4511 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4517 ventoy_iso9660_vd pvd
;
4524 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4527 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4530 debug("failed to open file %s\n", args
[0]);
4534 grub_file_seek(file
, 16 * 2048);
4535 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4536 if (len
!= sizeof(pvd
))
4538 debug("failed to read pvd %d\n", len
);
4542 grub_memset(buf
, 0, sizeof(buf
));
4543 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4544 ventoy_set_env(args
[1], buf
);
4546 grub_memset(buf
, 0, sizeof(buf
));
4547 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4548 ventoy_set_env(args
[2], buf
);
4552 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4553 ventoy_set_env(args
[3], buf
);
4556 grub_file_close(file
);
4561 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4572 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4575 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4578 debug("failed to open file %s\n", args
[0]);
4582 grub_memset(buf
, 0, sizeof(buf
));
4583 grub_file_seek(file
, 16 * 2048 + 813);
4584 len
= (int)grub_file_read(file
, buf
, 17);
4587 debug("failed to read create date %d\n", len
);
4591 ventoy_set_env(args
[1], buf
);
4594 grub_file_close(file
);
4599 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4605 ventoy_env_hook_root(1);
4610 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4616 ventoy_env_hook_root(0);
4621 #ifdef GRUB_MACHINE_EFI
4622 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4627 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4633 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4634 if (var
&& *var
== 1)
4642 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4651 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4656 grub_uint64_t FileSectors
= 0;
4657 ventoy_gpt_info
*gpt
= NULL
;
4658 ventoy_part_table
*pt
= NULL
;
4659 grub_uint8_t zeroguid
[16] = {0};
4664 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4667 debug("failed to open file %s\n", args
[0]);
4671 if (file
->size
% 512)
4673 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4677 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4683 FileSectors
= file
->size
/ 512;
4685 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4686 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4688 debug("This is EFI partition table\n");
4690 for (i
= 0; i
< 128; i
++)
4692 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4694 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4696 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4697 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4705 debug("This is MBR partition table\n");
4707 for (i
= 0; i
< 4; i
++)
4709 pt
= gpt
->MBR
.PartTbl
+ i
;
4710 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4712 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4713 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4714 (ulonglong
)FileSectors
);
4723 grub_file_close(file
);
4724 grub_check_free(gpt
);
4725 grub_errno
= GRUB_ERR_NONE
;
4729 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4738 for (i
= 0; i
< 500; i
++)
4740 ret
= grub_getkey_noblock();
4741 if (ret
== GRUB_TERM_NO_KEY
)
4750 grub_printf("\n\n Still have key input after clear.\n");
4758 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4765 int image_sector_size
;
4767 ventoy_chain_head
*chain
;
4768 ventoy_img_chunk
*chunk
;
4769 ventoy_os_param
*osparam
;
4770 ventoy_image_location
*location
;
4771 ventoy_image_disk_region
*region
;
4772 struct grub_acpi_table_header
*acpi
;
4781 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4783 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4789 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4791 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4793 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4797 img_chunk_num
= chain
->img_chunk_num
;
4799 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4800 datalen
= sizeof(ventoy_os_param
) + loclen
;
4802 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4803 acpi
= grub_zalloc(buflen
);
4809 /* Step1: Fill acpi table header */
4810 grub_memcpy(acpi
->signature
, "VTOY", 4);
4811 acpi
->length
= buflen
;
4813 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4814 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4816 acpi
->creator_id
[0] = 1;
4817 acpi
->creator_rev
= 1;
4819 /* Step2: Fill data */
4820 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4821 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4822 osparam
->vtoy_img_location_addr
= 0;
4823 osparam
->vtoy_img_location_len
= loclen
;
4824 osparam
->chksum
= 0;
4825 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4827 location
= (ventoy_image_location
*)(osparam
+ 1);
4828 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4829 location
->image_sector_size
= image_sector_size
;
4830 location
->disk_sector_size
= chain
->disk_sector_size
;
4831 location
->region_count
= img_chunk_num
;
4833 region
= location
->regions
;
4834 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4835 if (512 == image_sector_size
)
4837 for (i
= 0; i
< img_chunk_num
; i
++)
4839 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4840 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4841 region
->disk_start_sector
= chunk
->disk_start_sector
;
4848 for (i
= 0; i
< img_chunk_num
; i
++)
4850 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4851 region
->image_start_sector
= chunk
->img_start_sector
;
4852 region
->disk_start_sector
= chunk
->disk_start_sector
;
4858 /* Step3: Fill acpi checksum */
4860 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4862 /* load acpi table */
4863 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4864 grub_script_execute_sourcecode(cmd
);
4868 VENTOY_CMD_RETURN(0);
4871 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4877 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4878 g_ventoy_last_entry
= -1;
4883 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4889 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4894 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4896 const char *pos
= filename
+ 1;
4904 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4906 grub_strncpy((char *)data
, filename
, 128);
4917 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4920 char *device_name
= NULL
;
4921 grub_device_t dev
= NULL
;
4922 grub_fs_t fs
= NULL
;
4923 char buf
[128] = {0};
4929 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4933 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4935 device_name
= grub_file_get_device_name(args
[0]);
4938 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4942 dev
= grub_device_open(device_name
);
4945 debug("grub_device_open failed, %s\n", device_name
);
4949 fs
= grub_fs_probe(dev
);
4952 debug("grub_fs_probe failed, %s\n", device_name
);
4956 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4960 ventoy_set_env(args
[2], buf
);
4967 check_free(device_name
, grub_free
);
4968 check_free(dev
, grub_device_close
);
4973 int ventoy_load_part_table(const char *diskname
)
4980 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4981 if (!g_ventoy_part_info
)
4986 disk
= grub_disk_open(diskname
);
4989 debug("Failed to open disk %s\n", diskname
);
4993 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4995 g_ventoy_disk_bios_id
= disk
->id
;
4997 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4998 grub_disk_close(disk
);
5000 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
5001 dev
= grub_device_open(name
);
5004 /* Check for official Ventoy device */
5005 ret
= ventoy_check_official_device(dev
);
5006 grub_device_close(dev
);
5014 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5015 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5020 static void ventoy_prompt_end(void)
5025 grub_printf("\n\n\n");
5026 grub_printf(" 1 --- Exit grub\n");
5027 grub_printf(" 2 --- Reboot\n");
5028 grub_printf(" 3 --- Shut down\n");
5029 grub_printf("Please enter your choice: ");
5035 if (c
>= '1' && c
<= '3')
5040 grub_printf("%c", c
);
5044 else if (c
== '\r' || c
== '\n')
5058 grub_script_execute_sourcecode("halt");
5067 grub_printf("\rPlease enter your choice: ");
5068 grub_printf("\rPlease enter your choice: ");
5075 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5082 ret
= ventoy_load_part_table(args
[0]);
5085 ventoy_prompt_end();
5088 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5089 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5094 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5097 const char *vcfg
= NULL
;
5102 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5105 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5106 grub_env_set(args
[1], vcfg
);
5111 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5119 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5122 grub_uint8_t zeroguid
[16] = {0};
5127 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5130 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5132 if (id
>= 1 && id
<= 128)
5134 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5142 if (id
>= 1 && id
<= 4)
5144 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5154 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5157 char *device_name
= NULL
;
5158 grub_device_t dev
= NULL
;
5159 grub_fs_t fs
= NULL
;
5164 debug("get fs label for %s\n", args
[0]);
5168 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5172 device_name
= grub_file_get_device_name(args
[0]);
5175 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5179 dev
= grub_device_open(device_name
);
5182 debug("grub_device_open failed, %s\n", device_name
);
5186 fs
= grub_fs_probe(dev
);
5187 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5189 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5193 fs
->fs_label(dev
, &label
);
5196 debug("label=<%s>\n", label
);
5197 ventoy_set_env(args
[1], label
);
5205 check_free(device_name
, grub_free
);
5206 check_free(dev
, grub_device_close
);
5211 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5215 grub_snprintf((char *)data
, 256, "%s", filename
);
5222 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5224 if (info
->dir
&& filename
&& filename
[0] != '.')
5226 grub_snprintf((char *)data
, 256, "%s", filename
);
5233 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5236 char *device_name
= NULL
;
5237 grub_device_t dev
= NULL
;
5238 grub_fs_t fs
= NULL
;
5239 char name
[256] ={0};
5243 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5247 device_name
= grub_file_get_device_name(args
[0]);
5250 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5254 dev
= grub_device_open(device_name
);
5257 debug("grub_device_open failed, %s\n", device_name
);
5261 fs
= grub_fs_probe(dev
);
5264 debug("grub_fs_probe failed, %s\n", device_name
);
5268 fs
->fs_dir(dev
, args
[1], hook
, name
);
5271 ventoy_set_env(args
[2], name
);
5278 check_free(device_name
, grub_free
);
5279 check_free(dev
, grub_device_close
);
5284 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5287 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5290 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5293 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5296 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5306 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5310 for (pos
= args
[0]; *pos
; pos
++)
5324 grub_env_set(args
[1], args
[0]);
5334 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5344 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5349 len
= (int)grub_strlen(buf
);
5350 for (i
= len
; i
> 0; i
--)
5352 if (buf
[i
- 1] == '/')
5354 grub_env_set(args
[1], buf
+ i
);
5359 grub_env_set(args
[1], buf
);
5364 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5366 struct grub_video_mode_info info
;
5373 if (!g_video_mode_list
)
5375 ventoy_enum_video_mode();
5378 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5380 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5384 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5387 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5389 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5390 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5392 VENTOY_CMD_RETURN(0);
5395 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5397 struct grub_video_mode_info info
;
5404 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5406 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5410 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5413 grub_env_set(args
[0], buf
);
5415 VENTOY_CMD_RETURN(0);
5418 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5426 if (!g_video_mode_list
)
5431 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5432 if (id
< g_video_mode_num
)
5434 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5435 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5438 grub_env_set(args
[1], buf
);
5440 VENTOY_CMD_RETURN(0);
5443 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5446 grub_uint32_t loadsector
= 0;
5449 grub_uint32_t boot_catlog
= 0;
5450 grub_uint8_t buf
[512];
5456 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5460 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5463 debug("failed to open %s\n", args
[0]);
5467 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5468 if (boot_catlog
== 0)
5470 debug("No bootcatlog found\n");
5471 grub_file_close(file
);
5475 grub_memset(buf
, 0, sizeof(buf
));
5476 grub_file_seek(file
, boot_catlog
* 2048);
5477 grub_file_read(file
, buf
, sizeof(buf
));
5478 grub_file_close(file
);
5480 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5482 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5484 if (buf
[i
+ 32] == 0x88)
5486 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5487 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5493 if (loadsector
== 0)
5495 debug("No EFI eltorito info found\n");
5499 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5500 grub_env_set(args
[1], value
);
5501 VENTOY_CMD_RETURN(0);
5504 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5509 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5511 if (pfsdir
->initrd
[0])
5516 curpos
= pfsdir
->curpos
;
5517 len
= grub_strlen(filename
);
5521 if ((len
== 1 && filename
[0] == '.') ||
5522 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5527 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5530 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5531 pfsdir
->curpos
= curpos
+ printlen
;
5532 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5533 pfsdir
->curpos
= curpos
;
5534 pfsdir
->fullpath
[curpos
] = 0;
5538 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5541 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5542 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5544 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5546 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5555 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5559 char *device_name
= NULL
;
5560 grub_device_t dev
= NULL
;
5561 grub_fs_t fs
= NULL
;
5562 replace_fs_dir
*pfsdir
= NULL
;
5568 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5572 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5578 device_name
= grub_file_get_device_name(args
[0]);
5584 dev
= grub_device_open(device_name
);
5590 fs
= grub_fs_probe(dev
);
5599 pfsdir
->fullpath
[0] = '/';
5600 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5602 if (pfsdir
->initrd
[0])
5604 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5606 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5608 if (pfsdir
->initrd
[i
] == '/')
5610 pfsdir
->initrd
[i
] = '\\';
5614 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5615 grub_env_set(args
[1], pos
);
5619 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5624 grub_check_free(pfsdir
);
5625 grub_check_free(device_name
);
5626 check_free(dev
, grub_device_close
);
5628 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5631 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5633 const char *pager
= NULL
;
5639 pager
= grub_env_get("pager");
5643 grub_env_set("pager", "1");
5645 else if (pager
[0] == '1')
5651 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5653 grub_env_set("pager", "1");
5656 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5659 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5665 if (g_pager_flag
== 1)
5667 grub_env_unset("pager");
5669 else if (g_pager_flag
== 2)
5671 grub_env_set("pager", g_old_pager
);
5674 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5677 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5679 if (g_json_case_mis_path
[0])
5684 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5686 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5692 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5695 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5697 if (g_json_case_mis_path
[0])
5702 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5704 if (grub_strcasecmp(filename
, "ventoy") == 0)
5706 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5707 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5708 if (g_json_case_mis_path
[0])
5718 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5721 char *device_name
= NULL
;
5722 grub_device_t dev
= NULL
;
5723 grub_fs_t fs
= NULL
;
5724 chk_case_fs_dir fs_dir
;
5730 device_name
= grub_file_get_device_name(args
[0]);
5736 dev
= grub_device_open(device_name
);
5742 fs
= grub_fs_probe(dev
);
5748 fstype
= ventoy_get_fs_type(fs
->name
);
5749 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5754 g_json_case_mis_path
[0] = 0;
5757 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5759 if (g_json_case_mis_path
[0])
5761 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5766 grub_check_free(device_name
);
5767 check_free(dev
, grub_device_close
);
5769 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5772 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5775 grub_partition_t part
;
5776 char priority_str
[3]; /* Maximum value 15 */
5780 if (argc
< 2 || argc
> 3)
5781 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5782 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5784 /* Open the disk if it exists */
5785 disk
= grub_disk_open (args
[0]);
5788 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5792 part
= grub_partition_probe (disk
, args
[1]);
5795 grub_disk_close (disk
);
5796 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5797 "No such partition");
5800 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5802 grub_disk_close (disk
);
5803 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5804 "Not a GPT partition");
5807 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5808 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5812 grub_env_set (args
[2], priority_str
);
5813 grub_env_export (args
[2]);
5817 grub_printf ("Priority is %s\n", priority_str
);
5820 grub_disk_close (disk
);
5821 return GRUB_ERR_NONE
;
5825 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5829 grub_file_t file
= NULL
;
5830 grub_uint32_t loadrba
= 0;
5831 grub_uint32_t boot_catlog
= 0;
5832 grub_uint8_t sector
[512];
5833 boot_info_table
*info
= NULL
;
5838 /* This also trigger a iso9660 fs parse */
5839 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5844 joliet
= grub_iso9660_is_joliet();
5850 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5853 debug("failed to open %s\n", args
[0]);
5857 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5858 if (boot_catlog
== 0)
5860 debug("no bootcatlog found %u\n", boot_catlog
);
5864 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5867 debug("no bios eltorito rba found %u\n", loadrba
);
5871 grub_file_seek(file
, loadrba
* 2048);
5872 grub_file_read(file
, sector
, 512);
5874 info
= (boot_info_table
*)sector
;
5875 if (info
->bi_data0
== 0x7c6ceafa &&
5876 info
->bi_data1
== 0x90900000 &&
5877 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5878 info
->bi_BootFileLocation
== loadrba
)
5880 debug("bootloader is syslinux, %u.\n", loadrba
);
5886 grub_file_close(file
);
5887 grub_errno
= GRUB_ERR_NONE
;
5891 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5894 ventoy_vlnk_part
*node
;
5900 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5902 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5903 ++n
, node
->device
, node
->disksig
,
5904 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5910 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5918 len
= (int)grub_strlen(args
[0]);
5919 if (grub_file_is_vlnk_suffix(args
[0], len
))
5928 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5931 const char *name
= NULL
;
5937 grub_env_unset(args
[1]);
5938 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5941 debug("VLNK SRC: <%s>\n", args
[0]);
5942 debug("VLNK DST: <%s>\n", name
);
5943 grub_env_set(args
[1], name
);
5951 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5955 grub_file_t file
= NULL
;
5966 len
= (int)grub_strlen(args
[0]);
5967 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5969 grub_printf("Invalid vlnk suffix\n");
5973 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5976 grub_printf("Failed to open %s\n", args
[0]);
5980 if (file
->size
!= 32768)
5982 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5986 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5987 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5989 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5994 check_free(file
, grub_file_close
);
5995 grub_errno
= GRUB_ERR_NONE
;
5999 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6005 g_iso_vd_id_publisher
[0] = 0;
6006 g_iso_vd_id_prepare
[0] = 0;
6007 g_iso_vd_id_application
[0] = 0;
6012 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6016 grub_file_t file
= NULL
;
6021 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
6024 grub_printf("Failed to open %s\n", args
[0]);
6028 grub_file_seek(file
, 16 * 2048 + offset
);
6029 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
6032 grub_file_seek(file
, 16 * 2048 + offset
);
6033 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
6036 grub_file_seek(file
, 16 * 2048 + offset
);
6037 grub_file_read(file
, g_iso_vd_id_application
, 128);
6041 check_free(file
, grub_file_close
);
6042 grub_errno
= GRUB_ERR_NONE
;
6046 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6049 char *id
= g_iso_vd_id_publisher
;
6054 if (args
[0][0] == '1')
6056 id
= g_iso_vd_id_prepare
;
6058 else if (args
[0][0] == '2')
6060 id
= g_iso_vd_id_application
;
6063 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6068 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6073 grub_errno
= GRUB_ERR_NONE
;
6077 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6082 g_ventoy_fn_mutex
= 0;
6083 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
6085 g_ventoy_fn_mutex
= 1;
6088 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6091 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6093 grub_uint64_t total
;
6094 grub_uint64_t org_required
;
6095 grub_uint64_t new_required
;
6101 #ifdef GRUB_MACHINE_EFI
6102 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6103 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6104 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6105 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6110 grub_printf("Non EFI mode!\n");
6115 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6118 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6120 const char *env
= NULL
;
6125 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6130 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6131 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6132 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6133 ventoy_check_mode_by_name(args
[0], "vtnormal")
6139 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6140 if (env
&& env
[0] == '0' && env
[1] == 0)
6148 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6156 const char *env
= NULL
;
6157 ulonglong fsize
= 0;
6159 int seldata
[16] = {0};
6164 len
= 8 * VTOY_SIZE_1KB
;
6165 cmd
= (char *)grub_malloc(len
);
6171 g_vtoy_secondary_need_recover
= 0;
6172 grub_env_unset("VTOY_SECOND_EXIT");
6173 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6175 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6178 timeout
= (int)grub_strtol(env
, NULL
, 10);
6183 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6186 fsize
= grub_strtoull(args
[2], NULL
, 10);
6188 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6190 if (grub_strcmp(args
[1], "Unix") != 0)
6192 if (grub_strcmp(args
[1], "Windows") == 0)
6194 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6198 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6201 if (fsize
<= VTOY_SIZE_1GB
)
6203 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6207 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6208 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_RETURN_PRV_NOESC", "second_return"); seldata
[n
++] = 6;
6211 grub_errno
= GRUB_ERR_NONE
;
6212 g_ventoy_menu_esc
= 1;
6213 g_ventoy_suppress_esc
= 1;
6214 g_ventoy_suppress_esc_default
= 0;
6215 g_ventoy_secondary_menu_on
= 1;
6216 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6217 grub_script_execute_sourcecode(cfgfile
);
6218 g_ventoy_menu_esc
= 0;
6219 g_ventoy_suppress_esc
= 0;
6220 g_ventoy_suppress_esc_default
= 1;
6221 g_ventoy_secondary_menu_on
= 0;
6223 select
= seldata
[g_ventoy_last_entry
];
6227 g_ventoy_wimboot_mode
= 1;
6228 g_vtoy_secondary_need_recover
= 1;
6230 else if (select
== 3)
6232 g_ventoy_grub2_mode
= 1;
6233 g_vtoy_secondary_need_recover
= 2;
6235 else if (select
== 4)
6237 g_ventoy_memdisk_mode
= 1;
6238 g_vtoy_secondary_need_recover
= 3;
6240 else if (select
== 5)
6242 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6243 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6245 else if (select
== 6)
6247 grub_env_set("VTOY_SECOND_EXIT", "1");
6249 }while (select
== 5);
6252 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6255 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6261 if (g_vtoy_secondary_need_recover
== 1)
6263 g_ventoy_wimboot_mode
= 0;
6265 else if (g_vtoy_secondary_need_recover
== 2)
6267 g_ventoy_grub2_mode
= 0;
6269 else if (g_vtoy_secondary_need_recover
== 3)
6271 g_ventoy_memdisk_mode
= 0;
6274 g_vtoy_secondary_need_recover
= 0;
6276 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6279 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6284 if (args
[0][0] == '0')
6286 g_ventoy_case_insensitive
= 0;
6290 g_ventoy_case_insensitive
= 1;
6296 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6301 ventoy_plugin_load_menu_lang(1, args
[0]);
6302 VENTOY_CMD_RETURN(0);
6305 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6310 ventoy_plugin_load_menu_lang(0, args
[0]);
6311 VENTOY_CMD_RETURN(0);
6314 static int ventoy_chksum_pathcmp(int chktype
, char *rlpath
, char *rdpath
)
6321 pos1
= ventoy_str_basename(rlpath
);
6322 pos2
= ventoy_str_basename(rdpath
);
6323 return grub_strcmp(pos1
, pos2
);
6325 else if (chktype
== 3 || chktype
== 4)
6327 if (grub_strcmp(rlpath
, rdpath
) == 0 || grub_strcmp(rlpath
+ 1, rdpath
) == 0)
6336 static int ventoy_find_checksum
6351 char *currline
= NULL
;
6352 char *nextline
= NULL
;
6354 ulen
= (int)grub_strlen(uname
);
6356 /* read file to buffer */
6357 buf
= grub_malloc(file
->size
+ 4);
6362 grub_file_read(file
, buf
, file
->size
);
6363 buf
[file
->size
] = 0;
6365 /* parse each line */
6366 for (currline
= buf
; currline
; currline
= nextline
)
6368 nextline
= ventoy_get_line(currline
);
6369 VTOY_SKIP_SPACE(currline
);
6371 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6373 pos
= grub_strchr(currline
, '=');
6374 pos1
= grub_strchr(currline
, '(');
6375 pos2
= grub_strchr(currline
, ')');
6377 if (pos
&& pos1
&& pos2
)
6380 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6382 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6383 grub_memcpy(chksum
, pos
, retlen
);
6388 else if (ventoy_str_len_alnum(currline
, retlen
))
6390 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, retlen
);
6391 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6393 grub_memcpy(chksum
, currline
, retlen
);
6404 static int ventoy_check_chkfile(const char *isopart
, char *path
, const char *lchkname
, grub_file_t
*pfile
)
6410 grub_file_t file
= NULL
;
6412 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s.%s", isopart
, path
, lchkname
);
6418 cnt
= ventoy_str_chrcnt(path
, '/');
6421 pos
= grub_strrchr(path
, '/');
6425 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, path
);
6434 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6437 ret
= (cnt
> 1) ? 3 : 4;
6448 check_free(file
, grub_file_close
);
6453 static grub_err_t
ventoy_cmd_cmp_checksum(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6458 grub_file_t file
= NULL
;
6459 const char *calc_value
= NULL
;
6460 const char *isopart
= NULL
;
6462 char readchk
[256] = {0};
6463 char filebuf
[512] = {0};
6468 index
= (int)grub_strtol(args
[0], NULL
, 10);
6469 if (argc
!= 2 || index
< 0 || index
>= VTOY_CHKSUM_NUM
)
6474 grub_strncpy(uchkname
, g_lower_chksum_name
[index
], sizeof(uchkname
));
6475 ventoy_str_toupper(uchkname
);
6477 isopart
= grub_env_get("vtoy_iso_part");
6478 calc_value
= grub_env_get("VT_LAST_CHECK_SUM");
6480 chktype
= ventoy_check_chkfile(isopart
, args
[1], g_lower_chksum_name
[index
], &file
);
6483 grub_printf("\n\nNo checksum file found.\n");
6489 grub_snprintf(fchksum
, sizeof(fchksum
), ".%s", g_lower_chksum_name
[index
]);
6490 grub_memset(filebuf
, 0, sizeof(filebuf
));
6491 grub_file_read(file
, filebuf
, 511);
6493 pos
= grub_strchr(filebuf
, '=');
6496 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6497 grub_memcpy(readchk
, pos
, g_chksum_retlen
[index
]);
6501 grub_memcpy(readchk
, filebuf
, g_chksum_retlen
[index
]);
6504 else if (chktype
== 3 || chktype
== 4)
6506 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6507 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], chktype
, readchk
);
6508 if (readchk
[0] == 0)
6510 grub_printf("\n\n%s value not found in %s.\n", uchkname
, fchksum
);
6516 grub_snprintf(fchksum
, sizeof(fchksum
), "local VENTOY_CHECKSUM");
6517 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], chktype
, readchk
);
6518 if (readchk
[0] == 0)
6520 grub_file_close(file
);
6521 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6524 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6525 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], 3, readchk
);
6526 if (readchk
[0] == 0)
6528 grub_printf("\n\n%s value not found in both local and global VENTOY_CHECKSUM.\n", uchkname
);
6535 if (grub_strcasecmp(calc_value
, readchk
) == 0)
6537 grub_printf("\n\nCheck %s value with %s file. [ SUCCESS ]\n", uchkname
, fchksum
);
6541 grub_printf("\n\nCheck %s value with %s file. [ ERROR ]\n", uchkname
, fchksum
);
6542 grub_printf("The %s value in %s file is:\n%s\n", uchkname
, fchksum
, readchk
);
6547 check_free(file
, grub_file_close
);
6548 VENTOY_CMD_RETURN(0);
6551 static int ventoy_find_all_checksum
6556 int exists
[VTOY_CHKSUM_NUM
],
6568 char *currline
= NULL
;
6569 char *nextline
= NULL
;
6570 const char *uname
= NULL
;
6574 /* read file to buffer */
6575 buf
= grub_malloc(file
->size
+ 4);
6580 grub_file_read(file
, buf
, file
->size
);
6581 buf
[file
->size
] = 0;
6583 /* parse each line */
6584 for (currline
= buf
; currline
; currline
= nextline
)
6586 nextline
= ventoy_get_line(currline
);
6587 VTOY_SKIP_SPACE(currline
);
6589 for (i
= 0; i
< VTOY_CHKSUM_NUM
; i
++)
6596 uname
= g_lower_chksum_name
[i
];
6597 ulen
= g_lower_chksum_namelen
[i
];
6599 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6601 pos
= grub_strchr(currline
, '=');
6602 pos1
= grub_strchr(currline
, '(');
6603 pos2
= grub_strchr(currline
, ')');
6605 if (pos
&& pos1
&& pos2
)
6609 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6617 else if (ventoy_str_len_alnum(currline
, g_chksum_retlen
[i
]))
6619 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, g_chksum_retlen
[i
]);
6620 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6627 if (tot
>= VTOY_CHKSUM_NUM
)
6641 static grub_err_t
ventoy_cmd_vtoychksum_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6648 grub_file_t file
= NULL
;
6649 const char *isopart
= NULL
;
6650 int exists
[VTOY_CHKSUM_NUM
] = { 0, 0, 0, 0 };
6656 isopart
= grub_env_get("vtoy_iso_part");
6658 for (i
= 0; i
< VTOY_CHKSUM_NUM
; i
++)
6660 if (ventoy_check_file_exist("%s%s.%s", isopart
, args
[0], g_lower_chksum_name
[i
]))
6667 if (totexist
== VTOY_CHKSUM_NUM
)
6672 cnt
= ventoy_str_chrcnt(args
[0], '/');
6675 pos
= grub_strrchr(args
[0], '/');
6678 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, args
[0]);
6683 if (tip
== 0 && file
->size
> (32 * VTOY_SIZE_1KB
))
6686 grub_printf("Reading checksum file...\n");
6690 debug("parse local VENTOY_CHECKSUM\n");
6691 ventoy_find_all_checksum(file
, args
[0], 2, exists
, &totexist
);
6692 grub_file_close(file
);
6696 if (totexist
== VTOY_CHKSUM_NUM
)
6701 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6704 if (tip
== 0 && file
->size
> (32 * VTOY_SIZE_1KB
))
6707 grub_printf("Reading checksum file...\n");
6711 debug("parse global VENTOY_CHECKSUM\n");
6712 ventoy_find_all_checksum(file
, args
[0], (cnt
> 1) ? 3 : 4, exists
, &totexist
);
6713 grub_file_close(file
);
6718 ventoy_env_int_set("VT_EXIST_MD5", exists
[0]);
6719 ventoy_env_int_set("VT_EXIST_SHA1", exists
[1]);
6720 ventoy_env_int_set("VT_EXIST_SHA256", exists
[2]);
6721 ventoy_env_int_set("VT_EXIST_SHA512", exists
[3]);
6723 VENTOY_CMD_RETURN(0);
6727 static const char * ventoy_menu_lang_read_hook(struct grub_env_var
*var
, const char *val
)
6730 return ventoy_get_vmenu_title(val
);
6733 int ventoy_env_init(void)
6738 grub_env_set("vtdebug_flag", "");
6740 grub_register_vtoy_menu_lang_hook(ventoy_menu_lang_read_hook
);
6741 ventoy_ctrl_var_init();
6742 ventoy_global_var_init();
6744 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6745 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6746 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6747 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6749 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6752 ventoy_filt_register(0, ventoy_wrapper_open
);
6754 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6757 g_grub_param
->grub_env_get
= grub_env_get
;
6758 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6759 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6760 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6761 grub_env_set("env_param", buf
);
6762 grub_env_set("ventoy_env_param", buf
);
6764 grub_env_export("env_param");
6765 grub_env_export("ventoy_env_param");
6768 grub_env_export("vtoy_winpeshl_ini_addr");
6769 grub_env_export("vtoy_winpeshl_ini_size");
6771 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6772 grub_env_set("vtoy_chain_file_size", buf
);
6773 grub_env_export("vtoy_chain_file_size");
6775 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6776 grub_env_set("vtoy_chain_file_read", buf
);
6777 grub_env_export("vtoy_chain_file_read");
6779 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6780 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6781 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6783 grub_snprintf(buf
, sizeof(buf
), "%s-%s", GRUB_TARGET_CPU
, GRUB_PLATFORM
);
6784 grub_env_set("grub_cpu_platform", buf
);
6785 grub_env_export("grub_cpu_platform");
6792 static cmd_para ventoy_cmds
[] =
6794 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6795 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6796 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6797 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6798 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6799 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6800 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6801 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6802 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6803 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6804 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6805 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6806 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6807 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6808 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6809 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6810 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6811 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6812 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6813 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6814 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6815 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6816 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6817 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6818 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6819 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6820 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6822 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6823 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6824 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6825 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6826 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6827 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6828 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6830 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6831 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6832 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6833 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6834 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6835 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6836 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6837 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6838 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6839 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6842 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6843 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6844 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6845 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6846 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6847 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6848 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6849 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6850 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6851 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6852 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6854 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6855 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6856 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6857 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6858 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6859 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6860 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6862 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6863 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6864 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6865 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6866 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6867 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6868 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6869 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6870 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6871 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6873 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6874 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6875 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6876 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6877 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6878 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6879 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6880 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6881 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6883 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6884 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6885 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6886 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6889 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6890 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6891 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6893 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6894 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6895 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6898 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6899 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6900 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6901 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6902 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6903 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6904 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6905 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6906 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6907 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6908 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6909 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6910 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6911 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6913 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6914 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6915 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6916 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6917 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6918 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6919 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6920 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6921 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6922 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6923 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6924 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6926 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6927 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6928 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6929 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6930 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6931 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6932 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6933 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6934 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6935 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6936 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6937 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6938 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6939 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6940 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6941 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6942 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6943 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6944 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6945 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6946 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6947 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6948 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6949 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6950 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6951 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6952 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6953 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6954 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6955 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6956 { "vt_vtoychksum_exist", ventoy_cmd_vtoychksum_exist
, 0, NULL
, "", "", NULL
},
6957 { "vt_cmp_checksum", ventoy_cmd_cmp_checksum
, 0, NULL
, "", "", NULL
},
6958 { "vt_push_menu_lang", ventoy_cmd_push_menulang
, 0, NULL
, "", "", NULL
},
6959 { "vt_pop_menu_lang", ventoy_cmd_pop_menulang
, 0, NULL
, "", "", NULL
},
6963 int ventoy_register_all_cmd(void)
6966 cmd_para
*cur
= NULL
;
6968 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6970 cur
= ventoy_cmds
+ i
;
6971 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6972 cur
->summary
, cur
->description
, cur
->parser
);
6978 int ventoy_unregister_all_cmd(void)
6982 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6984 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);