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_filt_trash_dir
= 1;
69 int g_sort_case_sensitive
= 0;
70 int g_tree_view_menu_style
= 0;
71 static grub_file_t g_old_file
;
72 static int g_ventoy_last_entry_back
;
75 char g_img_swap_tmp_buf
[1024];
76 img_info g_img_swap_tmp
;
77 img_info
*g_ventoy_img_list
= NULL
;
79 int g_ventoy_img_count
= 0;
81 grub_device_t g_enum_dev
= NULL
;
82 grub_fs_t g_enum_fs
= NULL
;
83 int g_img_max_search_level
= -1;
84 img_iterator_node g_img_iterator_head
;
85 img_iterator_node
*g_img_iterator_tail
= NULL
;
87 grub_uint8_t g_ventoy_break_level
= 0;
88 grub_uint8_t g_ventoy_debug_level
= 0;
89 grub_uint8_t g_ventoy_chain_type
= 0;
91 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
92 grub_uint32_t g_ventoy_cpio_size
= 0;
93 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
94 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
96 int g_plugin_image_list
= 0;
98 ventoy_grub_param
*g_grub_param
= NULL
;
100 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
102 ventoy_img_chunk_list g_img_chunk_list
;
104 int g_wimboot_enable
= 0;
105 ventoy_img_chunk_list g_wimiso_chunk_list
;
106 char *g_wimiso_path
= NULL
;
107 grub_uint32_t g_wimiso_size
= 0;
109 int g_vhdboot_enable
= 0;
111 grub_uint64_t g_svd_replace_offset
= 0;
113 int g_conf_replace_count
= 0;
114 grub_uint64_t g_conf_replace_offset
[VTOY_MAX_CONF_REPLACE
] = { 0 };
115 conf_replace
*g_conf_replace_node
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
116 grub_uint8_t
*g_conf_replace_new_buf
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
117 int g_conf_replace_new_len
[VTOY_MAX_CONF_REPLACE
] = { 0 };
118 int g_conf_replace_new_len_align
[VTOY_MAX_CONF_REPLACE
] = { 0 };
120 int g_ventoy_disk_bios_id
= 0;
121 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
122 grub_uint64_t g_ventoy_disk_size
= 0;
123 grub_uint64_t g_ventoy_disk_part_size
[2];
125 char *g_tree_script_buf
= NULL
;
126 int g_tree_script_pos
= 0;
127 int g_tree_script_pre
= 0;
129 static char *g_list_script_buf
= NULL
;
130 static int g_list_script_pos
= 0;
132 static char *g_part_list_buf
= NULL
;
133 static int g_part_list_pos
= 0;
134 static grub_uint64_t g_part_end_max
= 0;
136 static int g_video_mode_max
= 0;
137 static int g_video_mode_num
= 0;
138 static ventoy_video_mode
*g_video_mode_list
= NULL
;
140 static int g_enumerate_time_checked
= 0;
141 static grub_uint64_t g_enumerate_start_time_ms
;
142 static grub_uint64_t g_enumerate_finish_time_ms
;
143 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
145 static char g_iso_vd_id_publisher
[130];
146 static char g_iso_vd_id_prepare
[130];
147 static char g_iso_vd_id_application
[130];
149 static int g_pager_flag
= 0;
150 static char g_old_pager
[32];
152 const char *g_menu_class
[img_type_max
] =
154 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
157 const char *g_menu_prefix
[img_type_max
] =
159 "iso", "wim", "efi", "img", "vhd", "vtoy"
162 static const char *g_lower_chksum_name
[VTOY_CHKSUM_NUM
] = { "md5", "sha1", "sha256", "sha512" };
163 static int g_lower_chksum_namelen
[VTOY_CHKSUM_NUM
] = { 3, 4, 6, 6 };
164 static int g_chksum_retlen
[VTOY_CHKSUM_NUM
] = { 32, 40, 64, 128 };
166 static int g_vtoy_secondary_need_recover
= 0;
168 static int g_vtoy_load_prompt
= 0;
169 static char g_vtoy_prompt_msg
[64];
171 static char g_json_case_mis_path
[32];
173 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
175 int ventoy_get_fs_type(const char *fs
)
179 return ventoy_fs_max
;
181 else if (grub_strncmp(fs
, "exfat", 5) == 0)
183 return ventoy_fs_exfat
;
185 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
187 return ventoy_fs_ntfs
;
189 else if (grub_strncmp(fs
, "ext", 3) == 0)
191 return ventoy_fs_ext
;
193 else if (grub_strncmp(fs
, "xfs", 3) == 0)
195 return ventoy_fs_xfs
;
197 else if (grub_strncmp(fs
, "udf", 3) == 0)
199 return ventoy_fs_udf
;
201 else if (grub_strncmp(fs
, "fat", 3) == 0)
203 return ventoy_fs_fat
;
206 return ventoy_fs_max
;
209 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
228 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
230 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
234 static int ventoy_control_get_flag(const char *key
)
236 const char *val
= ventoy_get_env(key
);
238 if (val
&& val
[0] == '1' && val
[1] == 0)
245 static grub_err_t
ventoy_fs_close(grub_file_t file
)
247 grub_file_close(g_old_file
);
248 grub_free(file
->data
);
256 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
262 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
267 for (i
= 0; i
< g_video_mode_num
; i
++)
269 if (g_video_mode_list
[i
].width
== info
->width
&&
270 g_video_mode_list
[i
].height
== info
->height
&&
271 g_video_mode_list
[i
].bpp
== info
->bpp
)
277 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
278 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
279 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
282 if (g_video_mode_num
== g_video_mode_max
)
284 g_video_mode_max
*= 2;
285 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
291 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
293 if (v1
->bpp
== v2
->bpp
)
295 if (v1
->width
== v2
->width
)
297 if (v1
->height
== v2
->height
)
303 return (v1
->height
< v2
->height
) ? -1 : 1;
308 return (v1
->width
< v2
->width
) ? -1 : 1;
313 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
317 static int ventoy_enum_video_mode(void)
320 grub_video_adapter_t adapter
;
321 grub_video_driver_id_t id
;
322 ventoy_video_mode mode
;
324 g_video_mode_num
= 0;
325 g_video_mode_max
= 1024;
326 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
327 if (!g_video_mode_list
)
332 #ifdef GRUB_MACHINE_PCBIOS
333 grub_dl_load ("vbe");
336 id
= grub_video_get_driver_id ();
338 FOR_VIDEO_ADAPTERS (adapter
)
340 if (!adapter
->iterate
||
341 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
342 adapter
->init() != GRUB_ERR_NONE
)))
347 adapter
->iterate(ventoy_video_hook
, NULL
);
349 if (adapter
->id
!= id
)
355 /* sort video mode */
356 for (i
= 0; i
< g_video_mode_num
; i
++)
357 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
359 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
361 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
362 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
363 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
367 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
370 static int ventoy_pre_parse_data(char *src
, int size
)
376 if (size
< 20 || grub_strncmp(src
, "ventoy_left_top_color", 21))
382 while (*pos
&& *pos
!= '\r' && *pos
!= '\n')
390 if (grub_strlen(src
) > 200)
395 grub_snprintf(buf
, sizeof(buf
),
396 "regexp -s 1:%s -s 2:%s -s 3:%s \"@([^@]*)@([^@]*)@([^@]*)@\" \"%s\"",
397 ventoy_left_key
, ventoy_top_key
, ventoy_color_key
, src
);
399 grub_script_execute_sourcecode(buf
);
406 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
410 static struct grub_fs vtoy_fs
=
415 .fs_read
= ventoy_fs_read
,
416 .fs_close
= ventoy_fs_close
,
426 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
432 file
->data
= grub_malloc(rawFile
->size
+ 4096);
438 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
439 ventoy_pre_parse_data((char *)file
->data
, (int)rawFile
->size
);
440 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
442 g_old_file
= rawFile
;
444 file
->size
= rawFile
->size
+ len
;
445 file
->device
= rawFile
->device
;
447 file
->not_easily_seekable
= 1;
452 static int ventoy_check_decimal_var(const char *name
, long *value
)
454 const char *value_str
= NULL
;
456 value_str
= grub_env_get(name
);
457 if (NULL
== value_str
)
459 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
462 if (!ventoy_is_decimal(value_str
))
464 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
467 *value
= grub_strtol(value_str
, NULL
, 10);
469 return GRUB_ERR_NONE
;
472 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
474 grub_uint64_t sectors
;
476 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
478 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
482 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
485 return sectors
* 512;
488 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
494 grub_uint32_t offset
;
496 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
499 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
503 len
= (int)file
->size
;
505 data
= (char *)grub_malloc(file
->size
);
511 grub_file_read(file
, data
, file
->size
);
512 grub_file_close(file
);
514 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
515 grub_script_execute_sourcecode(exec
);
517 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
518 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
519 grub_file_close(file
);
521 grub_script_execute_sourcecode("loopback -d efiboot");
525 *direntoff
= offset
+ 2;
530 static int ventoy_set_check_result(int ret
, const char *msg
)
534 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
535 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
536 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
541 grub_printf(VTOY_WARNING
"\n");
542 grub_printf(VTOY_WARNING
"\n");
543 grub_printf(VTOY_WARNING
"\n\n\n");
545 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
546 grub_printf("Error message: <%s>\n\n", msg
);
547 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
554 static int ventoy_check_official_device(grub_device_t dev
)
558 grub_uint64_t offset
;
561 grub_uint8_t mbr
[512];
565 struct grub_partition
*partition
;
567 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
569 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
572 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
573 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
574 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
576 #ifndef GRUB_MACHINE_EFI
577 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
579 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
581 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
583 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
585 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
587 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
596 /* We must have partition 2 */
599 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
603 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
607 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
610 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
612 grub_file_close(file
);
613 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
616 partition
= dev
->disk
->partition
;
617 if (partition
->number
!= 0 || partition
->start
!= 2048)
619 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
624 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
626 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
627 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
628 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
630 grub_file_close(file
);
631 return ventoy_set_check_result(6, "Disk partition layout check failed.");
636 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
637 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
638 PartTbl
[1].SectorCount
!= 65536)
640 grub_file_close(file
);
641 return ventoy_set_check_result(6, "Disk partition layout check failed.");
647 offset
= partition
->start
+ partition
->len
;
648 partition
= file
->device
->disk
->partition
;
649 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
651 grub_file_close(file
);
652 return ventoy_set_check_result(7, "Disk partition layout check failed.");
656 grub_file_close(file
);
660 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
661 dev2
= grub_device_open(devname
);
664 return ventoy_set_check_result(8, "Disk open failed");
667 fs
= grub_fs_probe(dev2
);
670 grub_device_close(dev2
);
671 return ventoy_set_check_result(9, "FS probe failed");
674 fs
->fs_label(dev2
, &label
);
675 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
677 grub_device_close(dev2
);
678 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
681 grub_device_close(dev2
);
685 disk
= grub_disk_open(dev
->disk
->name
);
688 return ventoy_set_check_result(11, "Disk open failed");
691 grub_memset(mbr
, 0, 512);
692 grub_disk_read(disk
, 0, 0, 512, mbr
);
693 grub_disk_close(disk
);
695 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
697 return ventoy_set_check_result(12, "MBR check failed");
700 return ventoy_set_check_result(0, NULL
);
703 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
707 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
717 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
719 grub_uint64_t size
= 0;
722 char fullpath
[256] = {0};
725 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
728 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
731 debug("grub_file_open failed <%s>\n", fullpath
);
737 grub_file_close(file
);
741 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
745 char fullpath
[512] = {0};
748 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
751 file
= grub_file_open(fullpath
, type
);
754 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
761 int ventoy_is_dir_exist(const char *fmt
, ...)
768 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
772 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
775 grub_strncpy(pos
+ len
, "\" ]", 3);
777 debug("script exec %s\n", buf
);
779 if (0 == grub_script_execute_sourcecode(buf
))
787 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
790 grub_uint8_t
*outbuf
;
791 grub_uint8_t gzHdr
[10] =
793 0x1F, 0x8B, /* magic */
801 grub_memset(&s
, 0, sizeof(mz_stream
));
803 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
805 outbuf
= (grub_uint8_t
*)mem_out
;
807 mem_out_len
-= sizeof(gzHdr
) + 8;
808 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
809 outbuf
+= sizeof(gzHdr
);
811 s
.avail_in
= mem_in_len
;
814 s
.avail_out
= mem_out_len
;
817 mz_deflate(&s
, MZ_FINISH
);
821 outbuf
+= s
.total_out
;
822 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
823 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
825 return s
.total_out
+ sizeof(gzHdr
) + 8;
833 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
837 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
840 if (0 == grub_strcmp(args
[0], "on"))
843 grub_env_set("vtdebug_flag", "debug");
848 grub_env_set("vtdebug_flag", "");
851 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
854 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
858 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
860 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
861 grub_printf(" level:\r\n");
862 grub_printf(" 01/11: busybox / (+cat log)\r\n");
863 grub_printf(" 02/12: initrd / (+cat log)\r\n");
864 grub_printf(" 03/13: hook / (+cat log)\r\n");
866 grub_printf(" debug:\r\n");
867 grub_printf(" 0: debug is off\r\n");
868 grub_printf(" 1: debug is on\r\n");
870 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
873 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
875 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
877 g_ventoy_debug_level
= 1;
880 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
883 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
892 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
895 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
927 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
943 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
959 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
964 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
966 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
969 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
974 value_long
+= grub_strtol(args
[1], NULL
, 10);
976 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
977 grub_env_set(args
[0], buf
);
979 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
982 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
984 ulonglong value1
= 0;
985 ulonglong value2
= 0;
990 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
993 value1
= grub_strtoull(args
[0], NULL
, 10);
994 value2
= grub_strtoull(args
[1], NULL
, 10);
996 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
997 grub_env_set(args
[2], buf
);
999 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1002 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1017 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1020 debug("failed to open file <%s> for udf check\n", args
[0]);
1024 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
1026 grub_env_set(args
[1], buf
);
1028 grub_file_close(file
);
1034 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1042 g_wimboot_enable
= 0;
1044 grub_check_free(g_wimiso_path
);
1045 grub_check_free(g_wimiso_chunk_list
.chunk
);
1047 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1053 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1054 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1055 if (NULL
== g_wimiso_chunk_list
.chunk
)
1057 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1060 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1061 g_wimiso_chunk_list
.cur_chunk
= 0;
1063 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1065 g_wimboot_enable
= 1;
1066 g_wimiso_path
= grub_strdup(args
[0]);
1067 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1068 grub_file_close(file
);
1073 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1081 ventoy_iso9660_override
*dirent
;
1090 totlen
= sizeof(ventoy_chain_head
);
1092 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1094 debug("failed to load efiboot template %d\n", len
);
1100 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1102 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1105 debug("failed to open file <%s>\n", args
[0]);
1109 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1114 totlen
+= ventoy_align_2k(file
->size
);
1116 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1117 dirent
->first_sector
= len
/ 2048;
1118 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1119 dirent
->size
= (grub_uint32_t
)file
->size
;
1120 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1122 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1124 #ifdef GRUB_MACHINE_EFI
1125 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1127 data
= (char *)grub_malloc(totlen
);
1130 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1132 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1133 grub_check_free(buf
);
1135 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1136 grub_file_close(file
);
1138 ventoy_memfile_env_set(args
[1], data
, (ulonglong
)totlen
);
1143 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1149 g_vtoy_load_prompt
= 0;
1150 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1152 if (argc
== 2 && args
[0][0] == '1')
1154 g_vtoy_load_prompt
= 1;
1155 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1158 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1161 int ventoy_need_prompt_load_file(void)
1163 return g_vtoy_load_prompt
;
1166 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1168 grub_uint64_t ro
= 0;
1169 grub_uint64_t div
= 0;
1170 grub_ssize_t left
= size
;
1171 char *cur
= (char *)buf
;
1173 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1176 while (left
>= VTOY_SIZE_2MB
)
1178 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1179 cur
+= VTOY_SIZE_2MB
;
1180 left
-= VTOY_SIZE_2MB
;
1182 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1187 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1193 grub_file_read(file
, cur
, left
);
1196 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1202 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1207 enum grub_file_type type
;
1218 if (grub_strcmp(args
[0], "nodecompress") == 0)
1220 type
= VENTOY_FILE_TYPE
;
1224 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1227 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1230 debug("failed to open file <%s>\n", args
[1]);
1234 #ifdef GRUB_MACHINE_EFI
1235 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1237 buf
= (char *)grub_malloc(file
->size
);
1242 grub_file_close(file
);
1246 if (g_vtoy_load_prompt
)
1248 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1252 grub_file_read(file
, buf
, file
->size
);
1255 ventoy_memfile_env_set(args
[2], buf
, (ulonglong
)(file
->size
));
1257 grub_file_close(file
);
1263 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1279 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1282 debug("failed to open file <%s> for udf check\n", args
[0]);
1286 headlen
= sizeof(ventoy_chain_head
);
1288 #ifdef GRUB_MACHINE_EFI
1289 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1291 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1294 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1296 grub_file_read(file
, buf
+ headlen
, file
->size
);
1298 ventoy_memfile_env_set(args
[1], buf
, (ulonglong
)(file
->size
));
1300 grub_file_close(file
);
1306 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1312 if (grub_iso9660_is_joliet())
1314 debug("This time has joliet process\n");
1323 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1332 if (args
[0][0] == '1')
1334 grub_iso9660_set_nojoliet(1);
1338 grub_iso9660_set_nojoliet(0);
1344 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1349 grub_uint8_t buf
[32];
1360 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1363 debug("failed to open file <%s> for udf check\n", args
[0]);
1367 for (i
= 16; i
< 32; i
++)
1369 grub_file_seek(file
, i
* 2048);
1370 grub_file_read(file
, buf
, sizeof(buf
));
1378 grub_file_seek(file
, i
* 2048);
1379 grub_file_read(file
, buf
, sizeof(buf
));
1381 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1384 grub_file_seek(file
, i
* 2048);
1385 grub_file_read(file
, buf
, sizeof(buf
));
1387 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1388 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1394 grub_file_close(file
);
1396 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1401 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1403 long value_long1
= 0;
1404 long value_long2
= 0;
1406 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1408 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1411 value_long1
= grub_strtol(args
[0], NULL
, 10);
1412 value_long2
= grub_strtol(args
[2], NULL
, 10);
1414 if (0 == grub_strcmp(args
[1], "eq"))
1416 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1418 else if (0 == grub_strcmp(args
[1], "ne"))
1420 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1422 else if (0 == grub_strcmp(args
[1], "gt"))
1424 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1426 else if (0 == grub_strcmp(args
[1], "lt"))
1428 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1430 else if (0 == grub_strcmp(args
[1], "ge"))
1432 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1434 else if (0 == grub_strcmp(args
[1], "le"))
1436 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1440 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1446 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1449 char buf
[128] = {0};
1453 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1456 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1457 pos
= grub_strstr(buf
, ",");
1463 grub_env_set(args
[1], buf
);
1465 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1468 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1474 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1480 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1483 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1485 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1486 if (0 == grub_script_execute_sourcecode(buf
))
1488 debug("file %s exist, ventoy_compatible YES\n", buf
);
1489 grub_env_set("ventoy_compatible", "YES");
1490 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1494 debug("file %s NOT exist\n", buf
);
1498 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1499 pos
= grub_strstr(buf
, ")");
1505 disk
= grub_disk_open(buf
);
1508 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1509 grub_disk_close(disk
);
1511 g_img_swap_tmp_buf
[703] = 0;
1512 for (i
= 318; i
< 703; i
++)
1514 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1515 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1517 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1518 grub_env_set("ventoy_compatible", "YES");
1519 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1525 debug("failed to open disk <%s>\n", buf
);
1528 grub_env_set("ventoy_compatible", "NO");
1529 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1532 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1538 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1540 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1543 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1548 if (0 == g_sort_case_sensitive
)
1550 if (grub_islower(c1
))
1552 c1
= c1
- 'a' + 'A';
1555 if (grub_islower(c2
))
1557 c2
= c2
- 'a' + 'A';
1570 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1576 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1578 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1581 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1586 if (0 == g_sort_case_sensitive
)
1588 if (grub_islower(c1
))
1590 c1
= c1
- 'a' + 'A';
1593 if (grub_islower(c2
))
1595 c2
= c2
- 'a' + 'A';
1608 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1610 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1612 grub_memcpy(img1
, img2
, sizeof(img_info
));
1613 img1
->next
= g_img_swap_tmp
.next
;
1614 img1
->prev
= g_img_swap_tmp
.prev
;
1616 g_img_swap_tmp
.next
= img2
->next
;
1617 g_img_swap_tmp
.prev
= img2
->prev
;
1618 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1621 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1625 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1633 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1635 ventoy_vlnk_part
*node
= NULL
;
1636 grub_uint32_t SelfSig
;
1637 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1639 /* skip Ventoy partition 1/2 */
1640 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1641 if (partition
->number
< 2 && SelfSig
== *pSig
)
1646 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1649 node
->disksig
= *pSig
;
1650 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1651 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1652 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1654 node
->next
= g_vlnk_part_list
;
1655 g_vlnk_part_list
= node
;
1661 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1668 disk
= grub_disk_open(name
);
1671 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1672 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1673 grub_disk_close(disk
);
1679 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1681 const char *fs
[ventoy_fs_max
+ 1] =
1683 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1688 cur
->dev
= grub_device_open(cur
->device
);
1693 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1699 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1704 char *disk
, *device
;
1705 grub_uint32_t readcrc
, calccrc
;
1706 ventoy_vlnk_part
*cur
;
1707 grub_fs_t fs
= NULL
;
1709 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1713 grub_printf("VLNK invalid guid\n");
1719 readcrc
= vlnk
->crc32
;
1721 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1722 if (readcrc
!= calccrc
)
1726 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1732 if (!g_vlnk_part_list
)
1734 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1737 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1739 if (cur
->disksig
== vlnk
->disk_signature
)
1743 if (cur
->partoffset
== vlnk
->part_offset
)
1746 device
= cur
->device
;
1748 if (cur
->probe
== 0)
1751 ventoy_vlnk_probe_fs(cur
);
1761 struct grub_file file
;
1763 grub_memset(&file
, 0, sizeof(file
));
1764 file
.device
= cur
->dev
;
1765 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1768 cur
->fs
->fs_close(&file
);
1769 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1782 grub_printf("\n==== VLNK Information ====\n"
1783 "Disk Signature: %08x\n"
1784 "Partition Offset: %llu\n"
1785 "File Path: <%s>\n\n",
1786 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1790 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1794 grub_printf("Disk Find: [ NO ]\n");
1799 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1803 grub_printf("Part Find: [ NO ]\n");
1805 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1808 grub_printf("VLNK File: <%s>\n", dst
);
1815 return (1 - filefind
);
1818 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1823 grub_file_t file
= NULL
;
1828 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1830 else if (dir
[0] == '/')
1832 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1836 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1839 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1845 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1846 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1847 grub_file_close(file
);
1849 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1851 rc
= grub_file_add_vlnk(src
, dst
);
1857 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1867 const menu_tip
*tip
;
1868 img_iterator_node
*tmp
;
1869 img_iterator_node
*new_node
;
1870 img_iterator_node
*node
= (img_iterator_node
*)data
;
1872 if (g_enumerate_time_checked
== 0)
1874 g_enumerate_finish_time_ms
= grub_get_time_ms();
1875 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1878 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1880 g_enumerate_time_checked
= 1;
1884 len
= grub_strlen(filename
);
1888 if (node
->level
+ 1 > g_img_max_search_level
)
1893 if ((len
== 1 && filename
[0] == '.') ||
1894 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1899 if (!ventoy_img_name_valid(filename
, len
))
1904 if (g_filt_trash_dir
)
1906 if (0 == grub_strncmp(filename
, ".trash-", 7) ||
1907 0 == grub_strcmp(filename
, ".Trashes") ||
1908 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1914 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1916 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1917 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1920 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1925 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1928 new_node
->level
= node
->level
+ 1;
1929 new_node
->plugin_list_index
= index
;
1930 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1932 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1935 debug("Directory %s ignored...\n", new_node
->dir
);
1936 grub_free(new_node
);
1940 new_node
->tail
= node
->tail
;
1942 new_node
->parent
= node
;
1943 if (!node
->firstchild
)
1945 node
->firstchild
= new_node
;
1948 if (g_img_iterator_tail
)
1950 g_img_iterator_tail
->next
= new_node
;
1951 g_img_iterator_tail
= new_node
;
1955 g_img_iterator_head
.next
= new_node
;
1956 g_img_iterator_tail
= new_node
;
1962 debug("Find a file %s\n", filename
);
1968 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1970 type
= img_type_iso
;
1972 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1974 type
= img_type_wim
;
1976 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1977 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1979 type
= img_type_vhd
;
1981 #ifdef GRUB_MACHINE_EFI
1982 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1984 type
= img_type_efi
;
1987 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1989 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1991 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1992 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1997 type
= img_type_img
;
1999 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
2001 type
= img_type_vtoy
;
2003 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
2005 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
2007 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2008 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
2017 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
2022 if (g_plugin_image_list
)
2024 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2025 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
2026 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
2028 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2031 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2033 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2038 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2040 if (grub_file_is_vlnk_suffix(filename
, len
))
2043 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2050 img
= grub_zalloc(sizeof(img_info
));
2054 img
->plugin_list_index
= index
;
2055 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2057 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2059 img
->size
= info
->size
;
2060 if (vlnk
|| 0 == img
->size
)
2062 if (node
->dir
[0] == '/')
2064 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2068 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2072 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2074 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2079 if (g_ventoy_img_list
)
2081 tail
= *(node
->tail
);
2087 g_ventoy_img_list
= img
;
2090 img
->id
= g_ventoy_img_count
;
2092 if (node
&& NULL
== node
->firstiso
)
2094 node
->firstiso
= img
;
2105 *((img_info
**)(node
->tail
)) = img
;
2106 g_ventoy_img_count
++;
2108 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2110 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2113 img
->tip1
= tip
->tip1
;
2114 img
->tip2
= tip
->tip2
;
2117 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2120 img
->class = g_menu_class
[type
];
2122 img
->menu_prefix
= g_menu_prefix
[type
];
2124 if (img_type_iso
== type
)
2126 if (ventoy_plugin_check_memdisk(img
->path
))
2128 img
->menu_prefix
= "miso";
2131 else if (img_type_img
== type
)
2133 if (ventoy_plugin_check_memdisk(img
->path
))
2135 img
->menu_prefix
= "mimg";
2139 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2146 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2148 int len
= GRUB_UINT_MAX
;
2149 const char *value
= NULL
;
2150 char name
[32] = {0};
2151 char plat
[32] = {0};
2152 char guidstr
[32] = {0};
2153 ventoy_guid guid
= VENTOY_GUID
;
2154 const char *fmt1
= NULL
;
2155 const char *fmt2
= NULL
;
2156 const char *fmt3
= NULL
;
2157 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2158 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2159 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2160 const char fmtcode
[]={
2161 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2162 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2163 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2164 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2165 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2166 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2169 grub_memset(name
, 0, sizeof(name
));
2170 puint
[0] = grub_swap_bytes32(0x56454e54);
2171 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2172 puint
[2] = grub_swap_bytes32(0x45525349);
2173 puint
[1] = grub_swap_bytes32(0x4f595f56);
2174 value
= ventoy_get_env(name
);
2176 grub_memset(name
, 0, sizeof(name
));
2177 puint
[1] = grub_swap_bytes32(0x5f544f50);
2178 puint
[0] = grub_swap_bytes32(0x56544c45);
2179 fmt1
= ventoy_get_env(name
);
2185 grub_memset(name
, 0, sizeof(name
));
2186 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2187 puint
[0] = grub_swap_bytes32(0x56544c45);
2188 fmt2
= ventoy_get_env(name
);
2190 grub_memset(name
, 0, sizeof(name
));
2191 puint
[1] = grub_swap_bytes32(0x5f434c52);
2192 puint
[0] = grub_swap_bytes32(0x56544c45);
2193 fmt3
= ventoy_get_env(name
);
2195 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2197 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2199 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2200 #pragma GCC diagnostic push
2201 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2202 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2203 fmt1
? fmt1
: fmtdata
,
2204 fmt2
? fmt2
: fmtdata
+ 4,
2205 value
? value
: "", plat
, guidstr
,
2206 fmt3
? fmt3
: fmtdata
+ 6);
2207 #pragma GCC diagnostic pop
2209 grub_memset(name
, 0, sizeof(name
));
2210 puint
[0] = grub_swap_bytes32(0x76746f79);
2211 puint
[2] = grub_swap_bytes32(0x656e7365);
2212 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2213 ventoy_set_env(name
, guidstr
);
2219 ventoy_password_get (char buf
[], unsigned buf_size
)
2221 unsigned i
, cur_len
= 0;
2223 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2227 key
= grub_getkey ();
2228 if (key
== '\n' || key
== '\r')
2231 if (key
== GRUB_TERM_ESC
)
2241 grub_term_restore_pos (pos
);
2242 for (i
= 0; i
< cur_len
; i
++)
2244 grub_term_restore_pos (pos
);
2246 for (i
= 0; i
< cur_len
; i
++)
2253 if (!grub_isprint (key
))
2256 if (cur_len
+ 2 < buf_size
)
2257 buf
[cur_len
++] = key
;
2262 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2268 return (key
!= GRUB_TERM_ESC
);
2271 static int ventoy_get_password(char buf
[], unsigned buf_size
)
2273 const char *env
= NULL
;
2275 env
= grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2276 if (env
&& env
[0] == '0' && env
[1] == 0)
2278 return grub_password_get(buf
, buf_size
);
2282 return ventoy_password_get(buf
, buf_size
);
2286 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2290 grub_uint8_t md5
[16];
2294 grub_memset(input
, 0, sizeof(input
));
2296 grub_printf("Enter password: ");
2299 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2301 ventoy_get_password(input
, 128);
2302 if (grub_strcmp(pwd
->text
, input
) == 0)
2307 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2309 ventoy_get_password(input
, 128);
2310 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2311 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2316 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2318 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2319 ventoy_get_password(input
+ offset
, 128);
2321 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2322 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2328 grub_printf("Invalid password!\n\n");
2335 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2337 img_info
*minimg
= NULL
;
2338 img_info
*img
= (img_info
*)(node
->firstiso
);
2340 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2342 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2357 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2359 img_iterator_node
*Minchild
= NULL
;
2360 img_iterator_node
*child
= node
->firstchild
;
2362 while (child
&& child
->parent
== node
)
2364 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2368 child
= child
->next
;
2373 Minchild
->select
= 1;
2379 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2382 img_info
*img
= NULL
;
2383 const char *dir_class
= NULL
;
2384 const char *dir_alias
= NULL
;
2385 img_iterator_node
*child
= NULL
;
2386 const menu_tip
*tip
= NULL
;
2388 if (node
->isocnt
== 0 || node
->done
== 1)
2393 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2395 offset
= node
->parent
->dirlen
;
2398 if (node
== &g_img_iterator_head
)
2400 if (g_default_menu_mode
== 0)
2402 if (g_tree_view_menu_style
== 0)
2404 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2405 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2406 " echo 'return ...' \n"
2407 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2411 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2412 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2413 " echo 'return ...' \n"
2414 "}\n", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2418 g_tree_script_pre
= g_tree_script_pos
;
2422 node
->dir
[node
->dirlen
- 1] = 0;
2423 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2426 dir_class
= "vtoydir";
2429 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2431 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2434 if (g_tree_view_menu_style
== 0)
2436 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2437 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2438 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2442 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2443 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2444 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2449 dir_alias
= node
->dir
+ offset
;
2451 if (g_tree_view_menu_style
== 0)
2453 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2454 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2455 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2459 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2460 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2461 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2465 if (g_tree_view_menu_style
== 0)
2467 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2468 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2469 " echo 'return ...' \n"
2470 "}\n", "<--", node
->dir
);
2474 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2475 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2476 " echo 'return ...' \n"
2481 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2483 ventoy_dynamic_tree_menu(child
);
2486 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2488 if (g_tree_view_menu_style
== 0)
2490 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2491 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2494 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2495 img
->unsupport
? "[***********] " : "",
2496 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2498 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2502 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2503 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2506 img
->unsupport
? "[***********] " : "",
2507 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2509 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2513 if (node
!= &g_img_iterator_head
)
2515 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2522 static int ventoy_set_default_menu(void)
2528 const char *strdata
= NULL
;
2529 img_info
*cur
= NULL
;
2530 img_info
*default_node
= NULL
;
2531 const char *default_image
= NULL
;
2533 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2534 if (default_image
&& default_image
[0] == '/')
2536 img_len
= grub_strlen(default_image
);
2538 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2540 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2552 if (0 == g_default_menu_mode
)
2554 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2558 def
= grub_strdup(default_image
);
2564 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2566 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2567 if (strdata
&& strdata
[0] == '/')
2569 pos
= def
+ grub_strlen(strdata
);
2580 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2583 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2587 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2595 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2597 img_info
*next
= NULL
;
2598 img_info
*cur
= g_ventoy_img_list
;
2611 g_ventoy_img_list
= NULL
;
2612 g_ventoy_img_count
= 0;
2614 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2617 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2620 img_info
*cur
= g_ventoy_img_list
;
2624 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2626 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2629 img_id
= grub_strtol(args
[0], NULL
, 10);
2630 if (img_id
>= g_ventoy_img_count
)
2632 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2635 debug("Find image %ld name \n", img_id
);
2637 while (cur
&& img_id
> 0)
2645 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2648 debug("image name is %s\n", cur
->name
);
2650 grub_env_set(args
[1], cur
->name
);
2652 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2655 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2659 img_info
*cur
= g_ventoy_img_list
;
2665 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2668 len
= (int)grub_strlen(args
[0]);
2672 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2681 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2684 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2685 grub_env_set("chosen", id
);
2686 grub_env_export("chosen");
2688 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2691 static char g_fake_vlnk_src
[512];
2692 static char g_fake_vlnk_dst
[512];
2693 static grub_uint64_t g_fake_vlnk_size
;
2694 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2700 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2702 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2703 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2705 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2707 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2710 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2716 g_fake_vlnk_src
[0] = 0;
2717 g_fake_vlnk_dst
[0] = 0;
2718 g_fake_vlnk_size
= 0;
2719 grub_file_vtoy_vlnk(NULL
, NULL
);
2721 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2725 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2730 const char *id
= NULL
;
2731 img_info
*cur
= NULL
;
2735 if (argc
< 1 || argc
> 3)
2737 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2740 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2742 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2743 grub_env_set(args
[0], pos
);
2746 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2747 grub_env_set(args
[1], value
);
2752 for (last
= pos
; *pos
; pos
++)
2759 grub_env_set(args
[2], last
+ 1);
2765 id
= grub_env_get("chosen");
2767 pos
= grub_strstr(id
, "VID_");
2770 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2774 cur
= g_ventoy_img_list
;
2779 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2782 grub_env_set(args
[0], cur
->path
);
2786 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2787 grub_env_set(args
[1], value
);
2792 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2793 grub_env_set(args
[2], cur
->name
);
2797 g_svd_replace_offset
= 0;
2799 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2803 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2807 grub_device_t dev
= NULL
;
2808 img_info
*cur
= NULL
;
2809 img_info
*tail
= NULL
;
2810 img_info
*min
= NULL
;
2811 img_info
*head
= NULL
;
2812 const char *strdata
= NULL
;
2813 char *device_name
= NULL
;
2815 img_iterator_node
*node
= NULL
;
2816 img_iterator_node
*tmp
= NULL
;
2822 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2825 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2827 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2832 g_enumerate_time_checked
= 0;
2833 g_enumerate_start_time_ms
= grub_get_time_ms();
2835 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2836 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2838 g_filt_dot_underscore_file
= 1;
2841 strdata
= ventoy_get_env("VTOY_FILT_TRASH_DIR");
2842 if (strdata
&& strdata
[0] == '0' && strdata
[1] == 0)
2844 g_filt_trash_dir
= 0;
2847 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2848 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2850 g_sort_case_sensitive
= 1;
2853 device_name
= grub_file_get_device_name(args
[0]);
2859 g_enum_dev
= dev
= grub_device_open(device_name
);
2865 g_enum_fs
= fs
= grub_fs_probe(dev
);
2871 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2873 debug("unsupported fs:<%s>\n", fs
->name
);
2874 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2878 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2880 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2881 if (strdata
&& strdata
[0] == '1')
2883 g_default_menu_mode
= 1;
2886 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2888 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2890 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2891 if (strdata
&& strdata
[0] == '/')
2893 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2894 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2896 g_img_iterator_head
.dir
[len
++] = '/';
2898 g_img_iterator_head
.dirlen
= len
;
2902 g_img_iterator_head
.dirlen
= 1;
2903 grub_strcpy(g_img_iterator_head
.dir
, "/");
2906 g_img_iterator_head
.tail
= &tail
;
2908 if (g_img_max_search_level
< 0)
2910 g_img_max_search_level
= GRUB_INT_MAX
;
2911 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2912 if (strdata
&& ventoy_is_decimal(strdata
))
2914 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2918 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2919 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2920 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2921 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2922 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2923 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2925 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2927 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2930 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2931 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2933 g_tree_view_menu_style
= 1;
2936 ventoy_set_default_menu();
2938 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2940 ventoy_dynamic_tree_menu(node
);
2944 node
= g_img_iterator_head
.next
;
2952 /* sort image list by image name */
2953 while (g_ventoy_img_list
)
2955 min
= g_ventoy_img_list
;
2956 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2958 if (ventoy_cmp_img(min
, cur
) > 0)
2966 min
->prev
->next
= min
->next
;
2971 min
->next
->prev
= min
->prev
;
2974 if (min
== g_ventoy_img_list
)
2976 g_ventoy_img_list
= min
->next
;
2994 g_ventoy_img_list
= head
;
2996 if (g_default_menu_mode
== 1)
2998 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2999 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
3000 " echo 'return ...' \n"
3001 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_TREEVIEW"));
3004 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
3006 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
3007 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
3010 cur
->unsupport
? "[***********] " : "",
3011 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
3013 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
3016 g_tree_script_buf
[g_tree_script_pos
] = 0;
3017 g_list_script_buf
[g_list_script_pos
] = 0;
3019 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
3020 grub_env_set(args
[1], buf
);
3024 check_free(device_name
, grub_free
);
3025 check_free(dev
, grub_device_close
);
3027 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3030 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
3037 device_name
= grub_file_get_device_name(filename
);
3049 pos2
= grub_strstr(pos
, ",");
3052 pos2
= grub_strstr(pos
, ")");
3060 disk
= grub_disk_open(pos
);
3063 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3064 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3065 grub_disk_close(disk
);
3072 grub_free(device_name
);
3076 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3078 eltorito_descriptor desc
;
3080 grub_memset(&desc
, 0, sizeof(desc
));
3081 grub_file_seek(file
, 17 * 2048);
3082 grub_file_read(file
, &desc
, sizeof(desc
));
3084 if (desc
.type
!= 0 || desc
.version
!= 1)
3089 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3090 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3098 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3100 grub_uint8_t buf
[512];
3102 grub_file_seek(file
, sector
* 2048);
3103 grub_file_read(file
, buf
, sizeof(buf
));
3105 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3106 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3108 return *((grub_uint32_t
*)(buf
+ 40));
3114 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3118 grub_uint8_t buf
[512];
3119 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3121 grub_file_seek(file
, sector
* 2048);
3122 grub_file_read(file
, buf
, sizeof(buf
));
3124 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3126 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3130 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3135 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3137 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3139 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3143 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3145 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3150 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3152 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3154 if (buf
[36] == parttype
[i
])
3156 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3162 debug("%s does not contain efi eltorito\n", file
->name
);
3166 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3169 const char *fs
= NULL
;
3170 const char *val
= NULL
;
3171 const char *cdprompt
= NULL
;
3173 grub_uint8_t chksum
= 0;
3176 disk
= file
->device
->disk
;
3177 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3179 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3180 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3181 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3183 pos
= grub_strstr(file
->name
, "/");
3189 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3191 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3193 param
->vtoy_img_size
= file
->size
;
3195 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3196 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3198 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3200 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3201 param
->vtoy_reserved
[4] = 0;
3202 if (g_ventoy_chain_type
== 1) /* Windows */
3204 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3205 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3207 param
->vtoy_reserved
[4] = 1;
3211 fs
= ventoy_get_env("ventoy_fs_probe");
3212 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3214 param
->vtoy_reserved
[3] = 1;
3217 param
->vtoy_reserved
[5] = 0;
3218 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3219 if (val
&& val
[0] == '1' && val
[1] == 0)
3221 param
->vtoy_reserved
[5] = 1;
3224 /* ventoy_disk_signature used for vlnk */
3225 param
->vtoy_reserved
[6] = file
->vlnk
;
3226 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3228 /* calculate checksum */
3229 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3231 chksum
+= *((grub_uint8_t
*)param
+ i
);
3233 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3238 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3240 grub_uint32_t i
= 0;
3241 grub_uint64_t total
= 0;
3242 grub_uint64_t fileblk
= 0;
3243 ventoy_img_chunk
*chunk
= NULL
;
3245 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3247 chunk
= chunklist
->chunk
+ i
;
3249 if (chunk
->disk_start_sector
<= start
)
3251 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3255 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3258 fileblk
= (file
->size
+ 511) / 512;
3260 if (total
!= fileblk
)
3262 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3263 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3265 debug("maybe img file to be processed.\n");
3275 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3279 grub_uint32_t i
= 0;
3280 grub_uint32_t sector
= 0;
3281 grub_uint32_t count
= 0;
3282 grub_off_t size
= 0;
3283 grub_off_t read
= 0;
3285 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3286 if (fs_type
== ventoy_fs_exfat
)
3288 grub_fat_get_file_chunk(start
, file
, chunklist
);
3290 else if (fs_type
== ventoy_fs_ext
)
3292 grub_ext_get_file_chunk(start
, file
, chunklist
);
3296 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3297 file
->read_hook_data
= chunklist
;
3299 for (size
= file
->size
; size
> 0; size
-= read
)
3301 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3302 grub_file_read(file
, NULL
, read
);
3305 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3307 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3308 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3311 if (ventoy_fs_udf
== fs_type
)
3313 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3315 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3316 chunklist
->chunk
[i
].img_start_sector
= sector
;
3317 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3323 len
= (int)grub_strlen(file
->name
);
3324 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3325 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3326 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3327 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3329 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3331 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3341 chunklist
->chunk
[i
].img_start_sector
= sector
;
3342 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3350 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3354 grub_disk_addr_t start
;
3359 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3362 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3365 g_conf_replace_count
= 0;
3366 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3367 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3369 if (g_img_chunk_list
.chunk
)
3371 grub_free(g_img_chunk_list
.chunk
);
3374 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3376 grub_file_close(file
);
3377 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3380 /* get image chunk data */
3381 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3382 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3383 if (NULL
== g_img_chunk_list
.chunk
)
3385 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3388 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3389 g_img_chunk_list
.cur_chunk
= 0;
3391 start
= file
->device
->disk
->partition
->start
;
3393 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3395 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3396 grub_file_close(file
);
3400 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3403 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3404 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3405 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3408 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3412 grub_uint64_t offset
= 0;
3413 grub_uint32_t align
= 0;
3414 grub_file_t file
= NULL
;
3415 conf_replace
*node
= NULL
;
3416 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3417 ventoy_grub_param_file_replace
*replace
= NULL
;
3423 debug("select conf replace argc:%d\n", argc
);
3430 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3433 debug("Conf replace not found for %s\n", args
[1]);
3437 debug("Find %d conf replace for %s\n", n
, args
[1]);
3439 g_conf_replace_count
= n
;
3440 for (i
= 0; i
< n
; i
++)
3444 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3447 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3448 grub_file_close(file
);
3450 else if (node
->img
> 0)
3456 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3460 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3463 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3467 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3469 if (align
> vtoy_max_replace_file_size
)
3471 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3472 grub_file_close(file
);
3476 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3477 grub_file_close(file
);
3478 g_conf_replace_new_len
[i
] = (int)file
->size
;
3479 g_conf_replace_new_len_align
[i
] = align
;
3481 g_conf_replace_node
[i
] = node
;
3482 g_conf_replace_offset
[i
] = offset
+ 2;
3486 replace
= &(g_grub_param
->img_replace
[i
]);
3487 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3488 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3489 replace
->old_name_cnt
++;
3492 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3496 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3499 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3504 const char *ch
= var
;
3511 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3518 debug("Invalid variable letter <%c>\n", *ch
);
3525 debug("Invalid variable length:%d <%s>\n", n
, var
);
3529 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3538 grub_printf("\n=================== Variables Expansion ===================\n\n");
3541 grub_printf("<%s>: ", var
);
3544 while (i
< (len
- 1))
3547 if ((c
== '\n') || (c
== '\r'))
3557 else if (grub_isprint(c
))
3559 if (i
+ 1 < (len
- 1))
3561 grub_printf("%c", c
);
3571 expand
[i
- 1] = ' ';
3572 grub_printf("\r<%s>: %s", var
, expand
);
3575 grub_printf("\r<%s>: %s", var
, expand
);
3587 grub_snprintf(expand
, len
, "$$%s$$", var
);
3593 static int ventoy_auto_install_var_expand(install_template
*node
)
3601 char *newbuf
= NULL
;
3602 char *curline
= NULL
;
3603 char *nextline
= NULL
;
3604 grub_uint8_t
*code
= NULL
;
3606 var_node
*CurNode
= NULL
;
3607 var_node
*pVarList
= NULL
;
3609 code
= (grub_uint8_t
*)node
->filebuf
;
3611 if (node
->filelen
>= VTOY_SIZE_1MB
)
3613 debug("auto install script too long %d\n", node
->filelen
);
3617 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3619 debug("UCS-2 encoding NOT supported\n");
3623 start
= grub_strstr(node
->filebuf
, "$$");
3626 debug("no need to expand variable, no start.\n");
3630 end
= grub_strstr(start
+ 2, "$$");
3633 debug("no need to expand variable, no end.\n");
3637 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3638 newbuf
= grub_malloc(newlen
);
3641 debug("Failed to alloc newbuf %d\n", newlen
);
3645 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3647 nextline
= ventoy_get_line(curline
);
3649 start
= grub_strstr(curline
, "$$");
3652 end
= grub_strstr(start
+ 2, "$$");
3658 VTOY_APPEND_NEWBUF(curline
);
3660 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3662 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3664 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3671 value
[sizeof(value
) - 1] = 0;
3672 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3676 CurNode
= grub_zalloc(sizeof(var_node
));
3679 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3680 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3681 CurNode
->next
= pVarList
;
3687 VTOY_APPEND_NEWBUF(value
);
3689 VTOY_APPEND_NEWBUF(end
+ 2);
3693 VTOY_APPEND_NEWBUF(curline
);
3696 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3698 newbuf
[pos
- 1] = '\n';
3702 newbuf
[pos
++] = '\n';
3706 grub_free(node
->filebuf
);
3707 node
->filebuf
= newbuf
;
3708 node
->filelen
= pos
;
3712 CurNode
= pVarList
->next
;
3713 grub_free(pVarList
);
3720 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3726 grub_file_t file
= NULL
;
3727 char configfile
[128];
3728 install_template
*node
= NULL
;
3734 debug("select auto installation argc:%d\n", argc
);
3741 node
= ventoy_plugin_find_install_template(args
[0]);
3744 debug("Auto install template not found for %s\n", args
[0]);
3748 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3750 defidx
= node
->autosel
;
3751 if (node
->timeout
< 0)
3753 node
->cursel
= node
->autosel
- 1;
3754 debug("Auto install template auto select %d\n", node
->autosel
);
3759 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3765 if (node
->timeout
> 0)
3767 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3770 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3771 " echo %s\n}\n", "");
3773 for (i
= 0; i
< node
->templatenum
; i
++)
3775 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3777 ventoy_get_vmenu_title("VTLANG_AUTOINS_USE"),
3778 node
->templatepath
[i
].path
);
3781 g_ventoy_menu_esc
= 1;
3782 g_ventoy_suppress_esc
= 1;
3783 g_ventoy_suppress_esc_default
= defidx
;
3784 g_ventoy_secondary_menu_on
= 1;
3786 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3787 grub_script_execute_sourcecode(configfile
);
3789 g_ventoy_menu_esc
= 0;
3790 g_ventoy_suppress_esc
= 0;
3791 g_ventoy_suppress_esc_default
= 1;
3792 g_ventoy_secondary_menu_on
= 0;
3796 node
->cursel
= g_ventoy_last_entry
- 1;
3799 grub_check_free(node
->filebuf
);
3802 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3804 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3805 node
->templatepath
[node
->cursel
].path
);
3808 node
->filebuf
= grub_malloc(file
->size
+ 8);
3811 grub_file_read(file
, node
->filebuf
, file
->size
);
3812 grub_file_close(file
);
3814 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3815 node
->filelen
= (int)file
->size
;
3817 ventoy_auto_install_var_expand(node
);
3822 debug("Failed to open auto install script <%s%s>\n",
3823 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3827 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3830 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3836 char configfile
[128];
3837 persistence_config
*node
;
3843 debug("select persistence argc:%d\n", argc
);
3850 node
= ventoy_plugin_find_persistent(args
[0]);
3853 debug("Persistence image not found for %s\n", args
[0]);
3857 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3859 defidx
= node
->autosel
;
3860 if (node
->timeout
< 0)
3862 node
->cursel
= node
->autosel
- 1;
3863 debug("Persistence image auto select %d\n", node
->autosel
);
3868 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3874 if (node
->timeout
> 0)
3876 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3879 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_PERSIST\" --class=\"sel_persistence\" {\n"
3880 " echo %s\n}\n", "");
3882 for (i
= 0; i
< node
->backendnum
; i
++)
3884 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3886 ventoy_get_vmenu_title("VTLANG_PERSIST_USE"),
3887 node
->backendpath
[i
].path
);
3891 g_ventoy_menu_esc
= 1;
3892 g_ventoy_suppress_esc
= 1;
3893 g_ventoy_suppress_esc_default
= defidx
;
3894 g_ventoy_secondary_menu_on
= 1;
3896 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3897 grub_script_execute_sourcecode(configfile
);
3899 g_ventoy_menu_esc
= 0;
3900 g_ventoy_suppress_esc
= 0;
3901 g_ventoy_suppress_esc_default
= 1;
3902 g_ventoy_secondary_menu_on
= 0;
3906 node
->cursel
= g_ventoy_last_entry
- 1;
3908 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3911 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3914 ventoy_img_chunk
*cur
;
3920 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3922 cur
= g_img_chunk_list
.chunk
+ i
;
3923 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3924 cur
->img_start_sector
, cur
->img_end_sector
,
3925 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3929 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3932 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3936 ventoy_img_chunk_list chunklist
;
3941 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3944 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3947 /* get image chunk data */
3948 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3949 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3950 if (NULL
== chunklist
.chunk
)
3952 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3955 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3956 chunklist
.cur_chunk
= 0;
3958 ventoy_get_block_list(file
, &chunklist
, 0);
3960 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3962 grub_printf("########## UNSUPPORTED ###############\n");
3965 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3967 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3969 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3970 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3973 grub_printf("\n==================================\n");
3975 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3977 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3978 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3979 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3980 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3981 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3985 grub_free(chunklist
.chunk
);
3986 grub_file_close(file
);
3988 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3991 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3994 ventoy_grub_param_file_replace
*replace
= NULL
;
4002 replace
= &(g_grub_param
->file_replace
);
4003 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
4005 replace
->old_name_cnt
= 0;
4006 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
4008 replace
->old_name_cnt
++;
4009 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
4012 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
4015 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4018 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4021 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
4027 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
4028 grub_env_set(args
[0], buf
);
4031 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4034 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4042 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4043 grub_printf("%s", g_list_script_buf
);
4047 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4048 grub_printf("%s", g_tree_script_buf
);
4054 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4056 img_info
*cur
= g_ventoy_img_list
;
4064 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4065 grub_printf("name:<%s>\n\n", cur
->name
);
4072 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4078 ventoy_plugin_dump_injection();
4083 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4089 ventoy_plugin_dump_auto_install();
4094 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4100 ventoy_plugin_dump_persistence();
4105 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4111 len1
= (int)grub_strlen(filename
);
4112 len2
= (int)grub_strlen(suffix
);
4119 for (i
= len1
- 1; i
>= 0; i
--)
4121 if (filename
[i
] == '.')
4132 if (filename
[i
- len2
- 1] != '_')
4137 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4145 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4151 if (argc
!= 1 && argc
!= 2)
4156 if (args
[0][0] == '0')
4158 if (g_ventoy_memdisk_mode
)
4163 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4170 else if (args
[0][0] == '1')
4172 return g_ventoy_iso_raw
? 0 : 1;
4174 else if (args
[0][0] == '2')
4176 return g_ventoy_iso_uefi_drv
? 0 : 1;
4178 else if (args
[0][0] == '3')
4180 if (g_ventoy_grub2_mode
)
4185 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4192 else if (args
[0][0] == '4')
4194 if (g_ventoy_wimboot_mode
)
4199 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4210 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4212 static int configfile_mode
= 0;
4213 char memfile
[128] = {0};
4220 * args[0]: 0:normal 1:configfile
4221 * args[1]: 0:list_buf 1:tree_buf
4226 debug("Invalid argc %d\n", argc
);
4232 if (args
[0][0] == '0')
4234 if (args
[1][0] == '0')
4236 grub_script_execute_sourcecode(g_list_script_buf
);
4240 grub_script_execute_sourcecode(g_tree_script_buf
);
4245 if (configfile_mode
)
4247 debug("Now already in F3 mode %d\n", configfile_mode
);
4251 if (args
[1][0] == '0')
4253 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4254 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4258 g_ventoy_last_entry
= -1;
4259 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4260 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4263 configfile_mode
= 1;
4264 grub_script_execute_sourcecode(memfile
);
4265 configfile_mode
= 0;
4271 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4282 g_ventoy_case_insensitive
= 1;
4283 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4284 g_ventoy_case_insensitive
= 0;
4290 grub_file_close(file
);
4296 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4301 const char *isopath
= NULL
;
4303 ventoy_mbr_head mbr
;
4310 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4313 isopath
= grub_env_get("vtoy_iso_part");
4316 debug("isopath is null %p\n", isopath
);
4320 debug("isopath is %s\n", isopath
);
4322 for (id
= 0; id
< 30 && (find
== 0); id
++)
4324 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4325 if (grub_strstr(isopath
, hdname
))
4327 debug("skip %s ...\n", hdname
);
4331 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4333 disk
= grub_disk_open(hdname
);
4336 debug("%s not exist\n", hdname
);
4340 grub_memset(&mbr
, 0, sizeof(mbr
));
4341 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4343 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4345 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4346 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4349 grub_env_set(args
[0], hdname
);
4353 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4357 debug("read %s failed\n", hdname
);
4360 grub_disk_close(disk
);
4366 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4377 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4380 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4383 debug("failed to open file %s\n", args
[0]);
4387 buf
= grub_malloc(len
);
4394 grub_file_read(file
, buf
, len
- 1);
4396 ventoy_get_line(buf
);
4397 ventoy_set_env(args
[1], buf
);
4401 grub_check_free(buf
);
4402 grub_file_close(file
);
4407 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4409 grub_uint64_t end_max
= 0;
4410 int *pCnt
= (int *)data
;
4415 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4416 "0 %llu linear /dev/ventoy %llu\n",
4417 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4419 end_max
= (partition
->len
+ partition
->start
) * 512;
4420 if (end_max
> g_part_end_max
)
4422 g_part_end_max
= end_max
;
4428 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4431 char *device_name
= NULL
;
4432 grub_device_t dev
= NULL
;
4437 g_part_list_pos
= 0;
4439 grub_env_unset("vtoy_img_part_file");
4446 device_name
= grub_file_get_device_name(args
[0]);
4449 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4453 dev
= grub_device_open(device_name
);
4456 debug("grub_device_open failed, %s\n", device_name
);
4460 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4462 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4463 grub_env_set("vtoy_img_part_file", buf
);
4465 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4466 grub_env_set("vtoy_img_part_cnt", buf
);
4468 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4469 grub_env_set("vtoy_img_max_part_end", buf
);
4473 check_free(device_name
, grub_free
);
4474 check_free(dev
, grub_device_close
);
4480 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4491 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4494 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4497 debug("failed to open file %s\n", args
[0]);
4501 buf
= grub_malloc(file
->size
+ 1);
4507 buf
[file
->size
] = 0;
4508 grub_file_read(file
, buf
, file
->size
);
4510 if (grub_strstr(buf
, args
[1]))
4517 grub_check_free(buf
);
4518 grub_file_close(file
);
4523 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4529 ventoy_iso9660_vd pvd
;
4536 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4539 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4542 debug("failed to open file %s\n", args
[0]);
4546 grub_file_seek(file
, 16 * 2048);
4547 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4548 if (len
!= sizeof(pvd
))
4550 debug("failed to read pvd %d\n", len
);
4554 grub_memset(buf
, 0, sizeof(buf
));
4555 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4556 ventoy_set_env(args
[1], buf
);
4558 grub_memset(buf
, 0, sizeof(buf
));
4559 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4560 ventoy_set_env(args
[2], buf
);
4564 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4565 ventoy_set_env(args
[3], buf
);
4568 grub_file_close(file
);
4573 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4584 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4587 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4590 debug("failed to open file %s\n", args
[0]);
4594 grub_memset(buf
, 0, sizeof(buf
));
4595 grub_file_seek(file
, 16 * 2048 + 813);
4596 len
= (int)grub_file_read(file
, buf
, 17);
4599 debug("failed to read create date %d\n", len
);
4603 ventoy_set_env(args
[1], buf
);
4606 grub_file_close(file
);
4611 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4617 ventoy_env_hook_root(1);
4622 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4628 ventoy_env_hook_root(0);
4633 #ifdef GRUB_MACHINE_EFI
4634 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4639 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4645 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4646 if (var
&& *var
== 1)
4654 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4663 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4668 grub_uint64_t FileSectors
= 0;
4669 ventoy_gpt_info
*gpt
= NULL
;
4670 ventoy_part_table
*pt
= NULL
;
4671 grub_uint8_t zeroguid
[16] = {0};
4676 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4679 debug("failed to open file %s\n", args
[0]);
4683 if (file
->size
% 512)
4685 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4689 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4695 FileSectors
= file
->size
/ 512;
4697 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4698 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4700 debug("This is EFI partition table\n");
4702 for (i
= 0; i
< 128; i
++)
4704 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4706 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4708 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4709 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4717 debug("This is MBR partition table\n");
4719 for (i
= 0; i
< 4; i
++)
4721 pt
= gpt
->MBR
.PartTbl
+ i
;
4722 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4724 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4725 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4726 (ulonglong
)FileSectors
);
4735 grub_file_close(file
);
4736 grub_check_free(gpt
);
4737 grub_errno
= GRUB_ERR_NONE
;
4741 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4750 for (i
= 0; i
< 500; i
++)
4752 ret
= grub_getkey_noblock();
4753 if (ret
== GRUB_TERM_NO_KEY
)
4762 grub_printf("\n\n Still have key input after clear.\n");
4770 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4777 int image_sector_size
;
4779 ventoy_chain_head
*chain
;
4780 ventoy_img_chunk
*chunk
;
4781 ventoy_os_param
*osparam
;
4782 ventoy_image_location
*location
;
4783 ventoy_image_disk_region
*region
;
4784 struct grub_acpi_table_header
*acpi
;
4793 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4795 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4801 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4803 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4805 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4809 img_chunk_num
= chain
->img_chunk_num
;
4811 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4812 datalen
= sizeof(ventoy_os_param
) + loclen
;
4814 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4815 acpi
= grub_zalloc(buflen
);
4821 /* Step1: Fill acpi table header */
4822 grub_memcpy(acpi
->signature
, "VTOY", 4);
4823 acpi
->length
= buflen
;
4825 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4826 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4828 acpi
->creator_id
[0] = 1;
4829 acpi
->creator_rev
= 1;
4831 /* Step2: Fill data */
4832 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4833 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4834 osparam
->vtoy_img_location_addr
= 0;
4835 osparam
->vtoy_img_location_len
= loclen
;
4836 osparam
->chksum
= 0;
4837 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4839 location
= (ventoy_image_location
*)(osparam
+ 1);
4840 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4841 location
->image_sector_size
= image_sector_size
;
4842 location
->disk_sector_size
= chain
->disk_sector_size
;
4843 location
->region_count
= img_chunk_num
;
4845 region
= location
->regions
;
4846 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4847 if (512 == image_sector_size
)
4849 for (i
= 0; i
< img_chunk_num
; i
++)
4851 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4852 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4853 region
->disk_start_sector
= chunk
->disk_start_sector
;
4860 for (i
= 0; i
< img_chunk_num
; i
++)
4862 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4863 region
->image_start_sector
= chunk
->img_start_sector
;
4864 region
->disk_start_sector
= chunk
->disk_start_sector
;
4870 /* Step3: Fill acpi checksum */
4872 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4874 /* load acpi table */
4875 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4876 grub_script_execute_sourcecode(cmd
);
4880 VENTOY_CMD_RETURN(0);
4883 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4889 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4890 g_ventoy_last_entry
= -1;
4895 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4901 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4906 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4908 const char *pos
= filename
+ 1;
4916 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4918 grub_strncpy((char *)data
, filename
, 128);
4929 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4932 char *device_name
= NULL
;
4933 grub_device_t dev
= NULL
;
4934 grub_fs_t fs
= NULL
;
4935 char buf
[128] = {0};
4941 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4945 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4947 device_name
= grub_file_get_device_name(args
[0]);
4950 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4954 dev
= grub_device_open(device_name
);
4957 debug("grub_device_open failed, %s\n", device_name
);
4961 fs
= grub_fs_probe(dev
);
4964 debug("grub_fs_probe failed, %s\n", device_name
);
4968 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4972 ventoy_set_env(args
[2], buf
);
4979 check_free(device_name
, grub_free
);
4980 check_free(dev
, grub_device_close
);
4985 int ventoy_load_part_table(const char *diskname
)
4992 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4993 if (!g_ventoy_part_info
)
4998 disk
= grub_disk_open(diskname
);
5001 debug("Failed to open disk %s\n", diskname
);
5005 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
5007 g_ventoy_disk_bios_id
= disk
->id
;
5009 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
5010 grub_disk_close(disk
);
5012 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
5013 dev
= grub_device_open(name
);
5016 /* Check for official Ventoy device */
5017 ret
= ventoy_check_official_device(dev
);
5018 grub_device_close(dev
);
5026 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5027 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5032 static void ventoy_prompt_end(void)
5037 grub_printf("\n\n\n");
5038 grub_printf(" 1 --- Exit grub\n");
5039 grub_printf(" 2 --- Reboot\n");
5040 grub_printf(" 3 --- Shut down\n");
5041 grub_printf("Please enter your choice: ");
5047 if (c
>= '1' && c
<= '3')
5052 grub_printf("%c", c
);
5056 else if (c
== '\r' || c
== '\n')
5070 grub_script_execute_sourcecode("halt");
5079 grub_printf("\rPlease enter your choice: ");
5080 grub_printf("\rPlease enter your choice: ");
5087 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5094 ret
= ventoy_load_part_table(args
[0]);
5097 ventoy_prompt_end();
5100 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5101 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5106 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5109 const char *vcfg
= NULL
;
5114 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5117 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5118 grub_env_set(args
[1], vcfg
);
5123 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5131 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5134 grub_uint8_t zeroguid
[16] = {0};
5139 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5142 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5144 if (id
>= 1 && id
<= 128)
5146 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5154 if (id
>= 1 && id
<= 4)
5156 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5166 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5169 char *device_name
= NULL
;
5170 grub_device_t dev
= NULL
;
5171 grub_fs_t fs
= NULL
;
5176 debug("get fs label for %s\n", args
[0]);
5180 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5184 device_name
= grub_file_get_device_name(args
[0]);
5187 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5191 dev
= grub_device_open(device_name
);
5194 debug("grub_device_open failed, %s\n", device_name
);
5198 fs
= grub_fs_probe(dev
);
5199 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5201 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5205 fs
->fs_label(dev
, &label
);
5208 debug("label=<%s>\n", label
);
5209 ventoy_set_env(args
[1], label
);
5217 check_free(device_name
, grub_free
);
5218 check_free(dev
, grub_device_close
);
5223 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5227 grub_snprintf((char *)data
, 256, "%s", filename
);
5234 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5236 if (info
->dir
&& filename
&& filename
[0] != '.')
5238 grub_snprintf((char *)data
, 256, "%s", filename
);
5245 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5248 char *device_name
= NULL
;
5249 grub_device_t dev
= NULL
;
5250 grub_fs_t fs
= NULL
;
5251 char name
[256] ={0};
5255 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5259 device_name
= grub_file_get_device_name(args
[0]);
5262 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5266 dev
= grub_device_open(device_name
);
5269 debug("grub_device_open failed, %s\n", device_name
);
5273 fs
= grub_fs_probe(dev
);
5276 debug("grub_fs_probe failed, %s\n", device_name
);
5280 fs
->fs_dir(dev
, args
[1], hook
, name
);
5283 ventoy_set_env(args
[2], name
);
5290 check_free(device_name
, grub_free
);
5291 check_free(dev
, grub_device_close
);
5296 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5299 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5302 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5305 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5308 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5318 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5322 for (pos
= args
[0]; *pos
; pos
++)
5336 grub_env_set(args
[1], args
[0]);
5346 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5356 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5361 len
= (int)grub_strlen(buf
);
5362 for (i
= len
; i
> 0; i
--)
5364 if (buf
[i
- 1] == '/')
5366 grub_env_set(args
[1], buf
+ i
);
5371 grub_env_set(args
[1], buf
);
5376 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5378 struct grub_video_mode_info info
;
5385 if (!g_video_mode_list
)
5387 ventoy_enum_video_mode();
5390 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5392 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5396 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5399 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5401 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5402 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5404 VENTOY_CMD_RETURN(0);
5407 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5409 struct grub_video_mode_info info
;
5416 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5418 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5422 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5425 grub_env_set(args
[0], buf
);
5427 VENTOY_CMD_RETURN(0);
5430 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5438 if (!g_video_mode_list
)
5443 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5444 if (id
< g_video_mode_num
)
5446 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5447 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5450 grub_env_set(args
[1], buf
);
5452 VENTOY_CMD_RETURN(0);
5455 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5458 grub_uint32_t loadsector
= 0;
5461 grub_uint32_t boot_catlog
= 0;
5462 grub_uint8_t buf
[512];
5468 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5472 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5475 debug("failed to open %s\n", args
[0]);
5479 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5480 if (boot_catlog
== 0)
5482 debug("No bootcatlog found\n");
5483 grub_file_close(file
);
5487 grub_memset(buf
, 0, sizeof(buf
));
5488 grub_file_seek(file
, boot_catlog
* 2048);
5489 grub_file_read(file
, buf
, sizeof(buf
));
5490 grub_file_close(file
);
5492 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5494 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5496 if (buf
[i
+ 32] == 0x88)
5498 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5499 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5505 if (loadsector
== 0)
5507 debug("No EFI eltorito info found\n");
5511 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5512 grub_env_set(args
[1], value
);
5513 VENTOY_CMD_RETURN(0);
5516 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5521 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5523 if (pfsdir
->initrd
[0])
5528 curpos
= pfsdir
->curpos
;
5529 len
= grub_strlen(filename
);
5533 if ((len
== 1 && filename
[0] == '.') ||
5534 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5539 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5542 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5543 pfsdir
->curpos
= curpos
+ printlen
;
5544 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5545 pfsdir
->curpos
= curpos
;
5546 pfsdir
->fullpath
[curpos
] = 0;
5550 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5553 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5554 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5556 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5558 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5567 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5571 char *device_name
= NULL
;
5572 grub_device_t dev
= NULL
;
5573 grub_fs_t fs
= NULL
;
5574 replace_fs_dir
*pfsdir
= NULL
;
5580 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5584 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5590 device_name
= grub_file_get_device_name(args
[0]);
5596 dev
= grub_device_open(device_name
);
5602 fs
= grub_fs_probe(dev
);
5611 pfsdir
->fullpath
[0] = '/';
5612 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5614 if (pfsdir
->initrd
[0])
5616 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5618 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5620 if (pfsdir
->initrd
[i
] == '/')
5622 pfsdir
->initrd
[i
] = '\\';
5626 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5627 grub_env_set(args
[1], pos
);
5631 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5636 grub_check_free(pfsdir
);
5637 grub_check_free(device_name
);
5638 check_free(dev
, grub_device_close
);
5640 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5643 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5645 const char *pager
= NULL
;
5651 pager
= grub_env_get("pager");
5655 grub_env_set("pager", "1");
5657 else if (pager
[0] == '1')
5663 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5665 grub_env_set("pager", "1");
5668 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5671 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5677 if (g_pager_flag
== 1)
5679 grub_env_unset("pager");
5681 else if (g_pager_flag
== 2)
5683 grub_env_set("pager", g_old_pager
);
5686 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5689 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5691 if (g_json_case_mis_path
[0])
5696 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5698 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5704 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5707 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5709 if (g_json_case_mis_path
[0])
5714 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5716 if (grub_strcasecmp(filename
, "ventoy") == 0)
5718 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5719 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5720 if (g_json_case_mis_path
[0])
5730 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5733 char *device_name
= NULL
;
5734 grub_device_t dev
= NULL
;
5735 grub_fs_t fs
= NULL
;
5736 chk_case_fs_dir fs_dir
;
5742 device_name
= grub_file_get_device_name(args
[0]);
5748 dev
= grub_device_open(device_name
);
5754 fs
= grub_fs_probe(dev
);
5760 fstype
= ventoy_get_fs_type(fs
->name
);
5761 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5766 g_json_case_mis_path
[0] = 0;
5769 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5771 if (g_json_case_mis_path
[0])
5773 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5778 grub_check_free(device_name
);
5779 check_free(dev
, grub_device_close
);
5781 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5784 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5787 grub_partition_t part
;
5788 char priority_str
[3]; /* Maximum value 15 */
5792 if (argc
< 2 || argc
> 3)
5793 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5794 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5796 /* Open the disk if it exists */
5797 disk
= grub_disk_open (args
[0]);
5800 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5804 part
= grub_partition_probe (disk
, args
[1]);
5807 grub_disk_close (disk
);
5808 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5809 "No such partition");
5812 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5814 grub_disk_close (disk
);
5815 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5816 "Not a GPT partition");
5819 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5820 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5824 grub_env_set (args
[2], priority_str
);
5825 grub_env_export (args
[2]);
5829 grub_printf ("Priority is %s\n", priority_str
);
5832 grub_disk_close (disk
);
5833 return GRUB_ERR_NONE
;
5837 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5841 grub_file_t file
= NULL
;
5842 grub_uint32_t loadrba
= 0;
5843 grub_uint32_t boot_catlog
= 0;
5844 grub_uint8_t sector
[512];
5845 boot_info_table
*info
= NULL
;
5850 /* This also trigger a iso9660 fs parse */
5851 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5856 joliet
= grub_iso9660_is_joliet();
5862 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5865 debug("failed to open %s\n", args
[0]);
5869 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5870 if (boot_catlog
== 0)
5872 debug("no bootcatlog found %u\n", boot_catlog
);
5876 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5879 debug("no bios eltorito rba found %u\n", loadrba
);
5883 grub_file_seek(file
, loadrba
* 2048);
5884 grub_file_read(file
, sector
, 512);
5886 info
= (boot_info_table
*)sector
;
5887 if (info
->bi_data0
== 0x7c6ceafa &&
5888 info
->bi_data1
== 0x90900000 &&
5889 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5890 info
->bi_BootFileLocation
== loadrba
)
5892 debug("bootloader is syslinux, %u.\n", loadrba
);
5898 grub_file_close(file
);
5899 grub_errno
= GRUB_ERR_NONE
;
5903 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5906 ventoy_vlnk_part
*node
;
5912 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5914 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5915 ++n
, node
->device
, node
->disksig
,
5916 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5922 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5930 len
= (int)grub_strlen(args
[0]);
5931 if (grub_file_is_vlnk_suffix(args
[0], len
))
5940 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5943 const char *name
= NULL
;
5949 grub_env_unset(args
[1]);
5950 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5953 debug("VLNK SRC: <%s>\n", args
[0]);
5954 debug("VLNK DST: <%s>\n", name
);
5955 grub_env_set(args
[1], name
);
5963 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5967 grub_file_t file
= NULL
;
5978 len
= (int)grub_strlen(args
[0]);
5979 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5981 grub_printf("Invalid vlnk suffix\n");
5985 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5988 grub_printf("Failed to open %s\n", args
[0]);
5992 if (file
->size
!= 32768)
5994 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5998 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5999 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
6001 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
6006 check_free(file
, grub_file_close
);
6007 grub_errno
= GRUB_ERR_NONE
;
6011 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6017 g_iso_vd_id_publisher
[0] = 0;
6018 g_iso_vd_id_prepare
[0] = 0;
6019 g_iso_vd_id_application
[0] = 0;
6024 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6028 grub_file_t file
= NULL
;
6033 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
6036 grub_printf("Failed to open %s\n", args
[0]);
6040 grub_file_seek(file
, 16 * 2048 + offset
);
6041 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
6044 grub_file_seek(file
, 16 * 2048 + offset
);
6045 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
6048 grub_file_seek(file
, 16 * 2048 + offset
);
6049 grub_file_read(file
, g_iso_vd_id_application
, 128);
6053 check_free(file
, grub_file_close
);
6054 grub_errno
= GRUB_ERR_NONE
;
6058 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6061 char *id
= g_iso_vd_id_publisher
;
6066 if (args
[0][0] == '1')
6068 id
= g_iso_vd_id_prepare
;
6070 else if (args
[0][0] == '2')
6072 id
= g_iso_vd_id_application
;
6075 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6080 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6085 grub_errno
= GRUB_ERR_NONE
;
6089 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6094 g_ventoy_fn_mutex
= 0;
6095 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
6097 g_ventoy_fn_mutex
= 1;
6100 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6103 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6105 grub_uint64_t total
;
6106 grub_uint64_t org_required
;
6107 grub_uint64_t new_required
;
6113 #ifdef GRUB_MACHINE_EFI
6114 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6115 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6116 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6117 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6122 grub_printf("Non EFI mode!\n");
6127 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6130 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6132 const char *env
= NULL
;
6137 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6142 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6143 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6144 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6145 ventoy_check_mode_by_name(args
[0], "vtnormal")
6151 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6152 if (env
&& env
[0] == '0' && env
[1] == 0)
6160 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6168 const char *env
= NULL
;
6169 ulonglong fsize
= 0;
6171 int seldata
[16] = {0};
6176 len
= 8 * VTOY_SIZE_1KB
;
6177 cmd
= (char *)grub_malloc(len
);
6183 g_vtoy_secondary_need_recover
= 0;
6184 grub_env_unset("VTOY_SECOND_EXIT");
6185 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6187 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6190 timeout
= (int)grub_strtol(env
, NULL
, 10);
6195 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6198 fsize
= grub_strtoull(args
[2], NULL
, 10);
6200 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6202 if (grub_strcmp(args
[1], "Unix") != 0)
6204 if (grub_strcmp(args
[1], "Windows") == 0)
6206 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6210 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6213 if (fsize
<= VTOY_SIZE_1GB
)
6215 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6219 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6220 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_RETURN_PRV_NOESC", "second_return"); seldata
[n
++] = 6;
6223 grub_errno
= GRUB_ERR_NONE
;
6224 g_ventoy_menu_esc
= 1;
6225 g_ventoy_suppress_esc
= 1;
6226 g_ventoy_suppress_esc_default
= 0;
6227 g_ventoy_secondary_menu_on
= 1;
6228 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6229 grub_script_execute_sourcecode(cfgfile
);
6230 g_ventoy_menu_esc
= 0;
6231 g_ventoy_suppress_esc
= 0;
6232 g_ventoy_suppress_esc_default
= 1;
6233 g_ventoy_secondary_menu_on
= 0;
6235 select
= seldata
[g_ventoy_last_entry
];
6239 g_ventoy_wimboot_mode
= 1;
6240 g_vtoy_secondary_need_recover
= 1;
6242 else if (select
== 3)
6244 g_ventoy_grub2_mode
= 1;
6245 g_vtoy_secondary_need_recover
= 2;
6247 else if (select
== 4)
6249 g_ventoy_memdisk_mode
= 1;
6250 g_vtoy_secondary_need_recover
= 3;
6252 else if (select
== 5)
6254 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6255 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6257 else if (select
== 6)
6259 grub_env_set("VTOY_SECOND_EXIT", "1");
6261 }while (select
== 5);
6264 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6267 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6273 if (g_vtoy_secondary_need_recover
== 1)
6275 g_ventoy_wimboot_mode
= 0;
6277 else if (g_vtoy_secondary_need_recover
== 2)
6279 g_ventoy_grub2_mode
= 0;
6281 else if (g_vtoy_secondary_need_recover
== 3)
6283 g_ventoy_memdisk_mode
= 0;
6286 g_vtoy_secondary_need_recover
= 0;
6288 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6291 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6296 if (args
[0][0] == '0')
6298 g_ventoy_case_insensitive
= 0;
6302 g_ventoy_case_insensitive
= 1;
6308 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6313 ventoy_plugin_load_menu_lang(1, args
[0]);
6314 VENTOY_CMD_RETURN(0);
6317 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6322 ventoy_plugin_load_menu_lang(0, args
[0]);
6323 VENTOY_CMD_RETURN(0);
6326 static int ventoy_chksum_pathcmp(int chktype
, char *rlpath
, char *rdpath
)
6333 pos1
= ventoy_str_basename(rlpath
);
6334 pos2
= ventoy_str_basename(rdpath
);
6335 return grub_strcmp(pos1
, pos2
);
6337 else if (chktype
== 3 || chktype
== 4)
6339 if (grub_strcmp(rlpath
, rdpath
) == 0 || grub_strcmp(rlpath
+ 1, rdpath
) == 0)
6348 static int ventoy_find_checksum
6363 char *currline
= NULL
;
6364 char *nextline
= NULL
;
6366 ulen
= (int)grub_strlen(uname
);
6368 /* read file to buffer */
6369 buf
= grub_malloc(file
->size
+ 4);
6374 grub_file_read(file
, buf
, file
->size
);
6375 buf
[file
->size
] = 0;
6377 /* parse each line */
6378 for (currline
= buf
; currline
; currline
= nextline
)
6380 nextline
= ventoy_get_line(currline
);
6381 VTOY_SKIP_SPACE(currline
);
6383 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6385 pos
= grub_strchr(currline
, '=');
6386 pos1
= grub_strchr(currline
, '(');
6387 pos2
= grub_strchr(currline
, ')');
6389 if (pos
&& pos1
&& pos2
)
6392 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6394 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6395 grub_memcpy(chksum
, pos
, retlen
);
6400 else if (ventoy_str_len_alnum(currline
, retlen
))
6402 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, retlen
);
6403 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6405 grub_memcpy(chksum
, currline
, retlen
);
6416 static int ventoy_check_chkfile(const char *isopart
, char *path
, const char *lchkname
, grub_file_t
*pfile
)
6422 grub_file_t file
= NULL
;
6424 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s.%s", isopart
, path
, lchkname
);
6430 cnt
= ventoy_str_chrcnt(path
, '/');
6433 pos
= grub_strrchr(path
, '/');
6437 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, path
);
6446 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6449 ret
= (cnt
> 1) ? 3 : 4;
6460 check_free(file
, grub_file_close
);
6465 static grub_err_t
ventoy_cmd_cmp_checksum(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6470 grub_file_t file
= NULL
;
6471 const char *calc_value
= NULL
;
6472 const char *isopart
= NULL
;
6474 char readchk
[256] = {0};
6475 char filebuf
[512] = {0};
6480 index
= (int)grub_strtol(args
[0], NULL
, 10);
6481 if (argc
!= 2 || index
< 0 || index
>= VTOY_CHKSUM_NUM
)
6486 grub_strncpy(uchkname
, g_lower_chksum_name
[index
], sizeof(uchkname
));
6487 ventoy_str_toupper(uchkname
);
6489 isopart
= grub_env_get("vtoy_iso_part");
6490 calc_value
= grub_env_get("VT_LAST_CHECK_SUM");
6492 chktype
= ventoy_check_chkfile(isopart
, args
[1], g_lower_chksum_name
[index
], &file
);
6495 grub_printf("\n\nNo checksum file found.\n");
6501 grub_snprintf(fchksum
, sizeof(fchksum
), ".%s", g_lower_chksum_name
[index
]);
6502 grub_memset(filebuf
, 0, sizeof(filebuf
));
6503 grub_file_read(file
, filebuf
, 511);
6505 pos
= grub_strchr(filebuf
, '=');
6508 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6509 grub_memcpy(readchk
, pos
, g_chksum_retlen
[index
]);
6513 grub_memcpy(readchk
, filebuf
, g_chksum_retlen
[index
]);
6516 else if (chktype
== 3 || chktype
== 4)
6518 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6519 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], chktype
, readchk
);
6520 if (readchk
[0] == 0)
6522 grub_printf("\n\n%s value not found in %s.\n", uchkname
, fchksum
);
6528 grub_snprintf(fchksum
, sizeof(fchksum
), "local VENTOY_CHECKSUM");
6529 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], chktype
, readchk
);
6530 if (readchk
[0] == 0)
6532 grub_file_close(file
);
6533 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6536 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6537 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], 3, readchk
);
6538 if (readchk
[0] == 0)
6540 grub_printf("\n\n%s value not found in both local and global VENTOY_CHECKSUM.\n", uchkname
);
6547 if (grub_strcasecmp(calc_value
, readchk
) == 0)
6549 grub_printf("\n\nCheck %s value with %s file. [ SUCCESS ]\n", uchkname
, fchksum
);
6553 grub_printf("\n\nCheck %s value with %s file. [ ERROR ]\n", uchkname
, fchksum
);
6554 grub_printf("The %s value in %s file is:\n%s\n", uchkname
, fchksum
, readchk
);
6559 check_free(file
, grub_file_close
);
6560 VENTOY_CMD_RETURN(0);
6563 static int ventoy_find_all_checksum
6568 int exists
[VTOY_CHKSUM_NUM
],
6580 char *currline
= NULL
;
6581 char *nextline
= NULL
;
6582 const char *uname
= NULL
;
6586 /* read file to buffer */
6587 buf
= grub_malloc(file
->size
+ 4);
6592 grub_file_read(file
, buf
, file
->size
);
6593 buf
[file
->size
] = 0;
6595 /* parse each line */
6596 for (currline
= buf
; currline
; currline
= nextline
)
6598 nextline
= ventoy_get_line(currline
);
6599 VTOY_SKIP_SPACE(currline
);
6601 for (i
= 0; i
< VTOY_CHKSUM_NUM
; i
++)
6608 uname
= g_lower_chksum_name
[i
];
6609 ulen
= g_lower_chksum_namelen
[i
];
6611 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6613 pos
= grub_strchr(currline
, '=');
6614 pos1
= grub_strchr(currline
, '(');
6615 pos2
= grub_strchr(currline
, ')');
6617 if (pos
&& pos1
&& pos2
)
6621 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6629 else if (ventoy_str_len_alnum(currline
, g_chksum_retlen
[i
]))
6631 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, g_chksum_retlen
[i
]);
6632 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6639 if (tot
>= VTOY_CHKSUM_NUM
)
6653 static grub_err_t
ventoy_cmd_vtoychksum_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6660 grub_file_t file
= NULL
;
6661 const char *isopart
= NULL
;
6662 int exists
[VTOY_CHKSUM_NUM
] = { 0, 0, 0, 0 };
6668 isopart
= grub_env_get("vtoy_iso_part");
6670 for (i
= 0; i
< VTOY_CHKSUM_NUM
; i
++)
6672 if (ventoy_check_file_exist("%s%s.%s", isopart
, args
[0], g_lower_chksum_name
[i
]))
6679 if (totexist
== VTOY_CHKSUM_NUM
)
6684 cnt
= ventoy_str_chrcnt(args
[0], '/');
6687 pos
= grub_strrchr(args
[0], '/');
6690 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, args
[0]);
6695 if (tip
== 0 && file
->size
> (32 * VTOY_SIZE_1KB
))
6698 grub_printf("Reading checksum file...\n");
6702 debug("parse local VENTOY_CHECKSUM\n");
6703 ventoy_find_all_checksum(file
, args
[0], 2, exists
, &totexist
);
6704 grub_file_close(file
);
6708 if (totexist
== VTOY_CHKSUM_NUM
)
6713 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6716 if (tip
== 0 && file
->size
> (32 * VTOY_SIZE_1KB
))
6719 grub_printf("Reading checksum file...\n");
6723 debug("parse global VENTOY_CHECKSUM\n");
6724 ventoy_find_all_checksum(file
, args
[0], (cnt
> 1) ? 3 : 4, exists
, &totexist
);
6725 grub_file_close(file
);
6730 ventoy_env_int_set("VT_EXIST_MD5", exists
[0]);
6731 ventoy_env_int_set("VT_EXIST_SHA1", exists
[1]);
6732 ventoy_env_int_set("VT_EXIST_SHA256", exists
[2]);
6733 ventoy_env_int_set("VT_EXIST_SHA512", exists
[3]);
6735 VENTOY_CMD_RETURN(0);
6739 static const char * ventoy_menu_lang_read_hook(struct grub_env_var
*var
, const char *val
)
6742 return ventoy_get_vmenu_title(val
);
6745 int ventoy_env_init(void)
6750 grub_env_set("vtdebug_flag", "");
6752 grub_register_vtoy_menu_lang_hook(ventoy_menu_lang_read_hook
);
6753 ventoy_ctrl_var_init();
6754 ventoy_global_var_init();
6756 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6757 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6758 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6759 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6761 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6764 ventoy_filt_register(0, ventoy_wrapper_open
);
6766 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6769 g_grub_param
->grub_env_get
= grub_env_get
;
6770 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6771 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6772 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6773 grub_env_set("env_param", buf
);
6774 grub_env_set("ventoy_env_param", buf
);
6776 grub_env_export("env_param");
6777 grub_env_export("ventoy_env_param");
6780 grub_env_export("vtoy_winpeshl_ini_addr");
6781 grub_env_export("vtoy_winpeshl_ini_size");
6783 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6784 grub_env_set("vtoy_chain_file_size", buf
);
6785 grub_env_export("vtoy_chain_file_size");
6787 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6788 grub_env_set("vtoy_chain_file_read", buf
);
6789 grub_env_export("vtoy_chain_file_read");
6791 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6792 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6793 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6795 grub_snprintf(buf
, sizeof(buf
), "%s-%s", GRUB_TARGET_CPU
, GRUB_PLATFORM
);
6796 grub_env_set("grub_cpu_platform", buf
);
6797 grub_env_export("grub_cpu_platform");
6804 static cmd_para ventoy_cmds
[] =
6806 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6807 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6808 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6809 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6810 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6811 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6812 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6813 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6814 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6815 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6816 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6817 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6818 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6819 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6820 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6821 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6822 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6823 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6824 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6825 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6826 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6827 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6828 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6829 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6830 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6831 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6832 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6834 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6835 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6836 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6837 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6838 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6839 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6840 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6842 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6843 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6844 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6845 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6846 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6847 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6848 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6849 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6850 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6851 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6854 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6855 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6856 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6857 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6858 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6859 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6860 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6861 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6862 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6863 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6864 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6866 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6867 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6868 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6869 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6870 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6871 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6872 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6874 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6875 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6876 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6877 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6878 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6879 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6880 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6881 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6882 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6883 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6885 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6886 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6887 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6888 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6889 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6890 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6891 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6892 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6893 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6895 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6896 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6897 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6898 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6901 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6902 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6903 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6905 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6906 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6907 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6910 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6911 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6912 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6913 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6914 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6915 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6916 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6917 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6918 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6919 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6920 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6921 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6922 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6923 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6925 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6926 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6927 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6928 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6929 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6930 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6931 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6932 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6933 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6934 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6935 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6936 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6938 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6939 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6940 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6941 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6942 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6943 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6944 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6945 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6946 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6947 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6948 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6949 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6950 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6951 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6952 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6953 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6954 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6955 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6956 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6957 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6958 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6959 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6960 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6961 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6962 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6963 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6964 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6965 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6966 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6967 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6968 { "vt_vtoychksum_exist", ventoy_cmd_vtoychksum_exist
, 0, NULL
, "", "", NULL
},
6969 { "vt_cmp_checksum", ventoy_cmd_cmp_checksum
, 0, NULL
, "", "", NULL
},
6970 { "vt_push_menu_lang", ventoy_cmd_push_menulang
, 0, NULL
, "", "", NULL
},
6971 { "vt_pop_menu_lang", ventoy_cmd_pop_menulang
, 0, NULL
, "", "", NULL
},
6975 int ventoy_register_all_cmd(void)
6978 cmd_para
*cur
= NULL
;
6980 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6982 cur
= ventoy_cmds
+ i
;
6983 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6984 cur
->summary
, cur
->description
, cur
->parser
);
6990 int ventoy_unregister_all_cmd(void)
6994 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6996 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);