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
)
1578 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1580 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1585 len
= grub_min(node1
->dirlen
, node2
->dirlen
);
1587 for (i
= 0; i
< len
; i
++)
1592 if (0 == g_sort_case_sensitive
)
1594 if (grub_islower(c1
))
1596 c1
= c1
- 'a' + 'A';
1599 if (grub_islower(c2
))
1601 c2
= c2
- 'a' + 'A';
1611 if (len
== node1
->dirlen
)
1616 if (len
== node2
->dirlen
)
1624 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1626 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1628 grub_memcpy(img1
, img2
, sizeof(img_info
));
1629 img1
->next
= g_img_swap_tmp
.next
;
1630 img1
->prev
= g_img_swap_tmp
.prev
;
1632 g_img_swap_tmp
.next
= img2
->next
;
1633 g_img_swap_tmp
.prev
= img2
->prev
;
1634 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1637 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1641 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1649 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1651 ventoy_vlnk_part
*node
= NULL
;
1652 grub_uint32_t SelfSig
;
1653 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1655 /* skip Ventoy partition 1/2 */
1656 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1657 if (partition
->number
< 2 && SelfSig
== *pSig
)
1662 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1665 node
->disksig
= *pSig
;
1666 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1667 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1668 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1670 node
->next
= g_vlnk_part_list
;
1671 g_vlnk_part_list
= node
;
1677 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1684 disk
= grub_disk_open(name
);
1687 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1688 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1689 grub_disk_close(disk
);
1695 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1697 const char *fs
[ventoy_fs_max
+ 1] =
1699 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1704 cur
->dev
= grub_device_open(cur
->device
);
1709 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1715 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1720 char *disk
, *device
;
1721 grub_uint32_t readcrc
, calccrc
;
1722 ventoy_vlnk_part
*cur
;
1723 grub_fs_t fs
= NULL
;
1725 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1729 grub_printf("VLNK invalid guid\n");
1735 readcrc
= vlnk
->crc32
;
1737 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1738 if (readcrc
!= calccrc
)
1742 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1748 if (!g_vlnk_part_list
)
1750 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1753 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1755 if (cur
->disksig
== vlnk
->disk_signature
)
1759 if (cur
->partoffset
== vlnk
->part_offset
)
1762 device
= cur
->device
;
1764 if (cur
->probe
== 0)
1767 ventoy_vlnk_probe_fs(cur
);
1777 struct grub_file file
;
1779 grub_memset(&file
, 0, sizeof(file
));
1780 file
.device
= cur
->dev
;
1781 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1784 cur
->fs
->fs_close(&file
);
1785 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1798 grub_printf("\n==== VLNK Information ====\n"
1799 "Disk Signature: %08x\n"
1800 "Partition Offset: %llu\n"
1801 "File Path: <%s>\n\n",
1802 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1806 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1810 grub_printf("Disk Find: [ NO ]\n");
1815 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1819 grub_printf("Part Find: [ NO ]\n");
1821 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1824 grub_printf("VLNK File: <%s>\n", dst
);
1831 return (1 - filefind
);
1834 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1839 grub_file_t file
= NULL
;
1844 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1846 else if (dir
[0] == '/')
1848 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1852 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1855 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1861 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1862 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1863 grub_file_close(file
);
1865 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1867 rc
= grub_file_add_vlnk(src
, dst
);
1873 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1883 const menu_tip
*tip
;
1884 img_iterator_node
*tmp
;
1885 img_iterator_node
*new_node
;
1886 img_iterator_node
*node
= (img_iterator_node
*)data
;
1888 if (g_enumerate_time_checked
== 0)
1890 g_enumerate_finish_time_ms
= grub_get_time_ms();
1891 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1894 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1896 g_enumerate_time_checked
= 1;
1900 len
= grub_strlen(filename
);
1904 if (node
->level
+ 1 > g_img_max_search_level
)
1909 if ((len
== 1 && filename
[0] == '.') ||
1910 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1915 if (!ventoy_img_name_valid(filename
, len
))
1920 if (g_filt_trash_dir
)
1922 if (0 == grub_strncmp(filename
, ".trash-", 7) ||
1923 0 == grub_strcmp(filename
, ".Trashes") ||
1924 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1930 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1932 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1933 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1936 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1941 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1944 new_node
->level
= node
->level
+ 1;
1945 new_node
->plugin_list_index
= index
;
1946 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1948 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1951 debug("Directory %s ignored...\n", new_node
->dir
);
1952 grub_free(new_node
);
1956 new_node
->tail
= node
->tail
;
1958 new_node
->parent
= node
;
1959 if (!node
->firstchild
)
1961 node
->firstchild
= new_node
;
1964 if (g_img_iterator_tail
)
1966 g_img_iterator_tail
->next
= new_node
;
1967 g_img_iterator_tail
= new_node
;
1971 g_img_iterator_head
.next
= new_node
;
1972 g_img_iterator_tail
= new_node
;
1978 debug("Find a file %s\n", filename
);
1984 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1986 type
= img_type_iso
;
1988 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1990 type
= img_type_wim
;
1992 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1993 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1995 type
= img_type_vhd
;
1997 #ifdef GRUB_MACHINE_EFI
1998 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
2000 type
= img_type_efi
;
2003 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
2005 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
2007 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
2008 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
2013 type
= img_type_img
;
2015 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
2017 type
= img_type_vtoy
;
2019 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
2021 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
2023 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2024 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
2033 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
2038 if (g_plugin_image_list
)
2040 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2041 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
2042 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
2044 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2047 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2049 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2054 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2056 if (grub_file_is_vlnk_suffix(filename
, len
))
2059 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2066 img
= grub_zalloc(sizeof(img_info
));
2070 img
->plugin_list_index
= index
;
2071 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2073 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2075 img
->size
= info
->size
;
2076 if (vlnk
|| 0 == img
->size
)
2078 if (node
->dir
[0] == '/')
2080 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2084 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2088 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2090 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2095 if (g_ventoy_img_list
)
2097 tail
= *(node
->tail
);
2103 g_ventoy_img_list
= img
;
2106 img
->id
= g_ventoy_img_count
;
2108 if (node
&& NULL
== node
->firstiso
)
2110 node
->firstiso
= img
;
2121 *((img_info
**)(node
->tail
)) = img
;
2122 g_ventoy_img_count
++;
2124 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2126 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2129 img
->tip1
= tip
->tip1
;
2130 img
->tip2
= tip
->tip2
;
2133 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2136 img
->class = g_menu_class
[type
];
2138 img
->menu_prefix
= g_menu_prefix
[type
];
2140 if (img_type_iso
== type
)
2142 if (ventoy_plugin_check_memdisk(img
->path
))
2144 img
->menu_prefix
= "miso";
2147 else if (img_type_img
== type
)
2149 if (ventoy_plugin_check_memdisk(img
->path
))
2151 img
->menu_prefix
= "mimg";
2155 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2162 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2164 int len
= GRUB_UINT_MAX
;
2165 const char *value
= NULL
;
2166 char name
[32] = {0};
2167 char plat
[32] = {0};
2168 char guidstr
[32] = {0};
2169 ventoy_guid guid
= VENTOY_GUID
;
2170 const char *fmt1
= NULL
;
2171 const char *fmt2
= NULL
;
2172 const char *fmt3
= NULL
;
2173 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2174 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2175 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2176 const char fmtcode
[]={
2177 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2178 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2179 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2180 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2181 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2182 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2185 grub_memset(name
, 0, sizeof(name
));
2186 puint
[0] = grub_swap_bytes32(0x56454e54);
2187 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2188 puint
[2] = grub_swap_bytes32(0x45525349);
2189 puint
[1] = grub_swap_bytes32(0x4f595f56);
2190 value
= ventoy_get_env(name
);
2192 grub_memset(name
, 0, sizeof(name
));
2193 puint
[1] = grub_swap_bytes32(0x5f544f50);
2194 puint
[0] = grub_swap_bytes32(0x56544c45);
2195 fmt1
= ventoy_get_env(name
);
2201 grub_memset(name
, 0, sizeof(name
));
2202 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2203 puint
[0] = grub_swap_bytes32(0x56544c45);
2204 fmt2
= ventoy_get_env(name
);
2206 grub_memset(name
, 0, sizeof(name
));
2207 puint
[1] = grub_swap_bytes32(0x5f434c52);
2208 puint
[0] = grub_swap_bytes32(0x56544c45);
2209 fmt3
= ventoy_get_env(name
);
2211 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2213 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2215 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2216 #pragma GCC diagnostic push
2217 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2218 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2219 fmt1
? fmt1
: fmtdata
,
2220 fmt2
? fmt2
: fmtdata
+ 4,
2221 value
? value
: "", plat
, guidstr
,
2222 fmt3
? fmt3
: fmtdata
+ 6);
2223 #pragma GCC diagnostic pop
2225 grub_memset(name
, 0, sizeof(name
));
2226 puint
[0] = grub_swap_bytes32(0x76746f79);
2227 puint
[2] = grub_swap_bytes32(0x656e7365);
2228 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2229 ventoy_set_env(name
, guidstr
);
2235 ventoy_password_get (char buf
[], unsigned buf_size
)
2237 unsigned i
, cur_len
= 0;
2239 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2243 key
= grub_getkey ();
2244 if (key
== '\n' || key
== '\r')
2247 if (key
== GRUB_TERM_ESC
)
2257 grub_term_restore_pos (pos
);
2258 for (i
= 0; i
< cur_len
; i
++)
2260 grub_term_restore_pos (pos
);
2262 for (i
= 0; i
< cur_len
; i
++)
2269 if (!grub_isprint (key
))
2272 if (cur_len
+ 2 < buf_size
)
2273 buf
[cur_len
++] = key
;
2278 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2284 return (key
!= GRUB_TERM_ESC
);
2287 static int ventoy_get_password(char buf
[], unsigned buf_size
)
2289 const char *env
= NULL
;
2291 env
= grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2292 if (env
&& env
[0] == '0' && env
[1] == 0)
2294 return grub_password_get(buf
, buf_size
);
2298 return ventoy_password_get(buf
, buf_size
);
2302 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2306 grub_uint8_t md5
[16];
2310 grub_memset(input
, 0, sizeof(input
));
2312 grub_printf("Enter password: ");
2315 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2317 ventoy_get_password(input
, 128);
2318 if (grub_strcmp(pwd
->text
, input
) == 0)
2323 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2325 ventoy_get_password(input
, 128);
2326 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2327 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2332 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2334 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2335 ventoy_get_password(input
+ offset
, 128);
2337 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2338 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2344 grub_printf("Invalid password!\n\n");
2351 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2353 img_info
*minimg
= NULL
;
2354 img_info
*img
= (img_info
*)(node
->firstiso
);
2356 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2358 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2373 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2375 img_iterator_node
*Minchild
= NULL
;
2376 img_iterator_node
*child
= node
->firstchild
;
2378 while (child
&& child
->parent
== node
)
2380 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2384 child
= child
->next
;
2389 Minchild
->select
= 1;
2395 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2398 img_info
*img
= NULL
;
2399 const char *dir_class
= NULL
;
2400 const char *dir_alias
= NULL
;
2401 img_iterator_node
*child
= NULL
;
2402 const menu_tip
*tip
= NULL
;
2404 if (node
->isocnt
== 0 || node
->done
== 1)
2409 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2411 offset
= node
->parent
->dirlen
;
2414 if (node
== &g_img_iterator_head
)
2416 if (g_default_menu_mode
== 0)
2418 if (g_tree_view_menu_style
== 0)
2420 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2421 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2422 " echo 'return ...' \n"
2423 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2427 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2428 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2429 " echo 'return ...' \n"
2430 "}\n", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2434 g_tree_script_pre
= g_tree_script_pos
;
2438 node
->dir
[node
->dirlen
- 1] = 0;
2439 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2442 dir_class
= "vtoydir";
2445 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2447 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2450 if (g_tree_view_menu_style
== 0)
2452 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2453 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2454 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2458 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2459 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2460 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2465 dir_alias
= node
->dir
+ offset
;
2467 if (g_tree_view_menu_style
== 0)
2469 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2470 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2471 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2475 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2476 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2477 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2481 if (g_tree_view_menu_style
== 0)
2483 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2484 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2485 " echo 'return ...' \n"
2486 "}\n", "<--", node
->dir
);
2490 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2491 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2492 " echo 'return ...' \n"
2497 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2499 ventoy_dynamic_tree_menu(child
);
2502 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2504 if (g_tree_view_menu_style
== 0)
2506 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2507 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2510 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2511 img
->unsupport
? "[***********] " : "",
2512 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2514 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2518 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2519 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2522 img
->unsupport
? "[***********] " : "",
2523 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2525 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2529 if (node
!= &g_img_iterator_head
)
2531 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2538 static int ventoy_set_default_menu(void)
2544 const char *strdata
= NULL
;
2545 img_info
*cur
= NULL
;
2546 img_info
*default_node
= NULL
;
2547 const char *default_image
= NULL
;
2549 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2550 if (default_image
&& default_image
[0] == '/')
2552 img_len
= grub_strlen(default_image
);
2554 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2556 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2568 if (0 == g_default_menu_mode
)
2570 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2574 def
= grub_strdup(default_image
);
2580 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2582 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2583 if (strdata
&& strdata
[0] == '/')
2585 pos
= def
+ grub_strlen(strdata
);
2596 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2599 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2603 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2611 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2613 img_info
*next
= NULL
;
2614 img_info
*cur
= g_ventoy_img_list
;
2627 g_ventoy_img_list
= NULL
;
2628 g_ventoy_img_count
= 0;
2630 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2633 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2636 img_info
*cur
= g_ventoy_img_list
;
2640 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2642 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2645 img_id
= grub_strtol(args
[0], NULL
, 10);
2646 if (img_id
>= g_ventoy_img_count
)
2648 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2651 debug("Find image %ld name \n", img_id
);
2653 while (cur
&& img_id
> 0)
2661 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2664 debug("image name is %s\n", cur
->name
);
2666 grub_env_set(args
[1], cur
->name
);
2668 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2671 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2675 img_info
*cur
= g_ventoy_img_list
;
2681 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2684 len
= (int)grub_strlen(args
[0]);
2688 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2697 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2700 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2701 grub_env_set("chosen", id
);
2702 grub_env_export("chosen");
2704 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2707 static char g_fake_vlnk_src
[512];
2708 static char g_fake_vlnk_dst
[512];
2709 static grub_uint64_t g_fake_vlnk_size
;
2710 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2716 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2718 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2719 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2721 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2723 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2726 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2732 g_fake_vlnk_src
[0] = 0;
2733 g_fake_vlnk_dst
[0] = 0;
2734 g_fake_vlnk_size
= 0;
2735 grub_file_vtoy_vlnk(NULL
, NULL
);
2737 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2741 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2746 const char *id
= NULL
;
2747 img_info
*cur
= NULL
;
2751 if (argc
< 1 || argc
> 3)
2753 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2756 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2758 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2759 grub_env_set(args
[0], pos
);
2762 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2763 grub_env_set(args
[1], value
);
2768 for (last
= pos
; *pos
; pos
++)
2775 grub_env_set(args
[2], last
+ 1);
2781 id
= grub_env_get("chosen");
2783 pos
= grub_strstr(id
, "VID_");
2786 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2790 cur
= g_ventoy_img_list
;
2795 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2798 grub_env_set(args
[0], cur
->path
);
2802 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2803 grub_env_set(args
[1], value
);
2808 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2809 grub_env_set(args
[2], cur
->name
);
2813 g_svd_replace_offset
= 0;
2815 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2819 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2823 grub_device_t dev
= NULL
;
2824 img_info
*cur
= NULL
;
2825 img_info
*tail
= NULL
;
2826 img_info
*min
= NULL
;
2827 img_info
*head
= NULL
;
2828 const char *strdata
= NULL
;
2829 char *device_name
= NULL
;
2831 img_iterator_node
*node
= NULL
;
2832 img_iterator_node
*tmp
= NULL
;
2838 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2841 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2843 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2848 g_enumerate_time_checked
= 0;
2849 g_enumerate_start_time_ms
= grub_get_time_ms();
2851 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2852 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2854 g_filt_dot_underscore_file
= 1;
2857 strdata
= ventoy_get_env("VTOY_FILT_TRASH_DIR");
2858 if (strdata
&& strdata
[0] == '0' && strdata
[1] == 0)
2860 g_filt_trash_dir
= 0;
2863 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2864 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2866 g_sort_case_sensitive
= 1;
2869 device_name
= grub_file_get_device_name(args
[0]);
2875 g_enum_dev
= dev
= grub_device_open(device_name
);
2881 g_enum_fs
= fs
= grub_fs_probe(dev
);
2887 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2889 debug("unsupported fs:<%s>\n", fs
->name
);
2890 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2894 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2896 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2897 if (strdata
&& strdata
[0] == '1')
2899 g_default_menu_mode
= 1;
2902 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2904 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2906 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2907 if (strdata
&& strdata
[0] == '/')
2909 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2910 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2912 g_img_iterator_head
.dir
[len
++] = '/';
2914 g_img_iterator_head
.dirlen
= len
;
2918 g_img_iterator_head
.dirlen
= 1;
2919 grub_strcpy(g_img_iterator_head
.dir
, "/");
2922 g_img_iterator_head
.tail
= &tail
;
2924 if (g_img_max_search_level
< 0)
2926 g_img_max_search_level
= GRUB_INT_MAX
;
2927 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2928 if (strdata
&& ventoy_is_decimal(strdata
))
2930 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2934 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2935 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2936 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2937 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2938 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2939 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2941 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2943 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2946 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2947 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2949 g_tree_view_menu_style
= 1;
2952 ventoy_set_default_menu();
2954 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2956 ventoy_dynamic_tree_menu(node
);
2960 node
= g_img_iterator_head
.next
;
2968 /* sort image list by image name */
2969 while (g_ventoy_img_list
)
2971 min
= g_ventoy_img_list
;
2972 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2974 if (ventoy_cmp_img(min
, cur
) > 0)
2982 min
->prev
->next
= min
->next
;
2987 min
->next
->prev
= min
->prev
;
2990 if (min
== g_ventoy_img_list
)
2992 g_ventoy_img_list
= min
->next
;
3010 g_ventoy_img_list
= head
;
3012 if (g_default_menu_mode
== 1)
3014 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
3015 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
3016 " echo 'return ...' \n"
3017 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_TREEVIEW"));
3020 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
3022 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
3023 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
3026 cur
->unsupport
? "[***********] " : "",
3027 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
3029 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
3032 g_tree_script_buf
[g_tree_script_pos
] = 0;
3033 g_list_script_buf
[g_list_script_pos
] = 0;
3035 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
3036 grub_env_set(args
[1], buf
);
3040 check_free(device_name
, grub_free
);
3041 check_free(dev
, grub_device_close
);
3043 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3046 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
3053 device_name
= grub_file_get_device_name(filename
);
3065 pos2
= grub_strstr(pos
, ",");
3068 pos2
= grub_strstr(pos
, ")");
3076 disk
= grub_disk_open(pos
);
3079 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3080 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3081 grub_disk_close(disk
);
3088 grub_free(device_name
);
3092 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3094 eltorito_descriptor desc
;
3096 grub_memset(&desc
, 0, sizeof(desc
));
3097 grub_file_seek(file
, 17 * 2048);
3098 grub_file_read(file
, &desc
, sizeof(desc
));
3100 if (desc
.type
!= 0 || desc
.version
!= 1)
3105 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3106 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3114 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3116 grub_uint8_t buf
[512];
3118 grub_file_seek(file
, sector
* 2048);
3119 grub_file_read(file
, buf
, sizeof(buf
));
3121 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3122 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3124 return *((grub_uint32_t
*)(buf
+ 40));
3130 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3134 grub_uint8_t buf
[512];
3135 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3137 grub_file_seek(file
, sector
* 2048);
3138 grub_file_read(file
, buf
, sizeof(buf
));
3140 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3142 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3146 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3151 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3153 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3155 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3159 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3161 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3166 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3168 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3170 if (buf
[36] == parttype
[i
])
3172 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3178 debug("%s does not contain efi eltorito\n", file
->name
);
3182 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3185 const char *fs
= NULL
;
3186 const char *val
= NULL
;
3187 const char *cdprompt
= NULL
;
3189 grub_uint8_t chksum
= 0;
3192 disk
= file
->device
->disk
;
3193 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3195 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3196 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3197 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3199 pos
= grub_strstr(file
->name
, "/");
3205 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3207 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3209 param
->vtoy_img_size
= file
->size
;
3211 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3212 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3214 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3216 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3217 param
->vtoy_reserved
[4] = 0;
3218 if (g_ventoy_chain_type
== 1) /* Windows */
3220 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3221 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3223 param
->vtoy_reserved
[4] = 1;
3227 fs
= ventoy_get_env("ventoy_fs_probe");
3228 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3230 param
->vtoy_reserved
[3] = 1;
3233 param
->vtoy_reserved
[5] = 0;
3234 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3235 if (val
&& val
[0] == '1' && val
[1] == 0)
3237 param
->vtoy_reserved
[5] = 1;
3240 /* ventoy_disk_signature used for vlnk */
3241 param
->vtoy_reserved
[6] = file
->vlnk
;
3242 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3244 /* calculate checksum */
3245 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3247 chksum
+= *((grub_uint8_t
*)param
+ i
);
3249 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3254 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3256 grub_uint32_t i
= 0;
3257 grub_uint64_t total
= 0;
3258 grub_uint64_t fileblk
= 0;
3259 ventoy_img_chunk
*chunk
= NULL
;
3261 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3263 chunk
= chunklist
->chunk
+ i
;
3265 if (chunk
->disk_start_sector
<= start
)
3267 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3271 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3274 fileblk
= (file
->size
+ 511) / 512;
3276 if (total
!= fileblk
)
3278 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3279 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3281 debug("maybe img file to be processed.\n");
3291 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3295 grub_uint32_t i
= 0;
3296 grub_uint32_t sector
= 0;
3297 grub_uint32_t count
= 0;
3298 grub_off_t size
= 0;
3299 grub_off_t read
= 0;
3301 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3302 if (fs_type
== ventoy_fs_exfat
)
3304 grub_fat_get_file_chunk(start
, file
, chunklist
);
3306 else if (fs_type
== ventoy_fs_ext
)
3308 grub_ext_get_file_chunk(start
, file
, chunklist
);
3312 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3313 file
->read_hook_data
= chunklist
;
3315 for (size
= file
->size
; size
> 0; size
-= read
)
3317 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3318 grub_file_read(file
, NULL
, read
);
3321 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3323 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3324 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3327 if (ventoy_fs_udf
== fs_type
)
3329 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3331 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3332 chunklist
->chunk
[i
].img_start_sector
= sector
;
3333 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3339 len
= (int)grub_strlen(file
->name
);
3340 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3341 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3342 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3343 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3345 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3347 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3357 chunklist
->chunk
[i
].img_start_sector
= sector
;
3358 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3366 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3370 grub_disk_addr_t start
;
3375 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3378 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3381 g_conf_replace_count
= 0;
3382 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3383 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3385 if (g_img_chunk_list
.chunk
)
3387 grub_free(g_img_chunk_list
.chunk
);
3390 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3392 grub_file_close(file
);
3393 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3396 /* get image chunk data */
3397 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3398 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3399 if (NULL
== g_img_chunk_list
.chunk
)
3401 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3404 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3405 g_img_chunk_list
.cur_chunk
= 0;
3407 start
= file
->device
->disk
->partition
->start
;
3409 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3411 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3412 grub_file_close(file
);
3416 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3419 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3420 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3421 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3424 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3428 grub_uint64_t offset
= 0;
3429 grub_uint32_t align
= 0;
3430 grub_file_t file
= NULL
;
3431 conf_replace
*node
= NULL
;
3432 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3433 ventoy_grub_param_file_replace
*replace
= NULL
;
3439 debug("select conf replace argc:%d\n", argc
);
3446 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3449 debug("Conf replace not found for %s\n", args
[1]);
3453 debug("Find %d conf replace for %s\n", n
, args
[1]);
3455 g_conf_replace_count
= n
;
3456 for (i
= 0; i
< n
; i
++)
3460 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3463 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3464 grub_file_close(file
);
3466 else if (node
->img
> 0)
3472 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3476 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3479 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3483 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3485 if (align
> vtoy_max_replace_file_size
)
3487 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3488 grub_file_close(file
);
3492 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3493 grub_file_close(file
);
3494 g_conf_replace_new_len
[i
] = (int)file
->size
;
3495 g_conf_replace_new_len_align
[i
] = align
;
3497 g_conf_replace_node
[i
] = node
;
3498 g_conf_replace_offset
[i
] = offset
+ 2;
3502 replace
= &(g_grub_param
->img_replace
[i
]);
3503 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3504 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3505 replace
->old_name_cnt
++;
3508 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3512 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3515 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3520 const char *ch
= var
;
3527 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3534 debug("Invalid variable letter <%c>\n", *ch
);
3541 debug("Invalid variable length:%d <%s>\n", n
, var
);
3545 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3554 grub_printf("\n=================== Variables Expansion ===================\n\n");
3557 grub_printf("<%s>: ", var
);
3560 while (i
< (len
- 1))
3563 if ((c
== '\n') || (c
== '\r'))
3573 else if (grub_isprint(c
))
3575 if (i
+ 1 < (len
- 1))
3577 grub_printf("%c", c
);
3587 expand
[i
- 1] = ' ';
3588 grub_printf("\r<%s>: %s", var
, expand
);
3591 grub_printf("\r<%s>: %s", var
, expand
);
3603 grub_snprintf(expand
, len
, "$$%s$$", var
);
3609 static int ventoy_auto_install_var_expand(install_template
*node
)
3617 char *newbuf
= NULL
;
3618 char *curline
= NULL
;
3619 char *nextline
= NULL
;
3620 grub_uint8_t
*code
= NULL
;
3622 var_node
*CurNode
= NULL
;
3623 var_node
*pVarList
= NULL
;
3625 code
= (grub_uint8_t
*)node
->filebuf
;
3627 if (node
->filelen
>= VTOY_SIZE_1MB
)
3629 debug("auto install script too long %d\n", node
->filelen
);
3633 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3635 debug("UCS-2 encoding NOT supported\n");
3639 start
= grub_strstr(node
->filebuf
, "$$");
3642 debug("no need to expand variable, no start.\n");
3646 end
= grub_strstr(start
+ 2, "$$");
3649 debug("no need to expand variable, no end.\n");
3653 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3654 newbuf
= grub_malloc(newlen
);
3657 debug("Failed to alloc newbuf %d\n", newlen
);
3661 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3663 nextline
= ventoy_get_line(curline
);
3665 start
= grub_strstr(curline
, "$$");
3668 end
= grub_strstr(start
+ 2, "$$");
3674 VTOY_APPEND_NEWBUF(curline
);
3676 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3678 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3680 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3687 value
[sizeof(value
) - 1] = 0;
3688 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3692 CurNode
= grub_zalloc(sizeof(var_node
));
3695 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3696 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3697 CurNode
->next
= pVarList
;
3703 VTOY_APPEND_NEWBUF(value
);
3705 VTOY_APPEND_NEWBUF(end
+ 2);
3709 VTOY_APPEND_NEWBUF(curline
);
3712 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3714 newbuf
[pos
- 1] = '\n';
3718 newbuf
[pos
++] = '\n';
3722 grub_free(node
->filebuf
);
3723 node
->filebuf
= newbuf
;
3724 node
->filelen
= pos
;
3728 CurNode
= pVarList
->next
;
3729 grub_free(pVarList
);
3736 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3742 grub_file_t file
= NULL
;
3743 char configfile
[128];
3744 install_template
*node
= NULL
;
3750 debug("select auto installation argc:%d\n", argc
);
3757 node
= ventoy_plugin_find_install_template(args
[0]);
3760 debug("Auto install template not found for %s\n", args
[0]);
3764 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3766 defidx
= node
->autosel
;
3767 if (node
->timeout
< 0)
3769 node
->cursel
= node
->autosel
- 1;
3770 debug("Auto install template auto select %d\n", node
->autosel
);
3775 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3781 if (node
->timeout
> 0)
3783 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3786 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3787 " echo %s\n}\n", "");
3789 for (i
= 0; i
< node
->templatenum
; i
++)
3791 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3793 ventoy_get_vmenu_title("VTLANG_AUTOINS_USE"),
3794 node
->templatepath
[i
].path
);
3797 g_ventoy_menu_esc
= 1;
3798 g_ventoy_suppress_esc
= 1;
3799 g_ventoy_suppress_esc_default
= defidx
;
3800 g_ventoy_secondary_menu_on
= 1;
3802 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3803 grub_script_execute_sourcecode(configfile
);
3805 g_ventoy_menu_esc
= 0;
3806 g_ventoy_suppress_esc
= 0;
3807 g_ventoy_suppress_esc_default
= 1;
3808 g_ventoy_secondary_menu_on
= 0;
3812 node
->cursel
= g_ventoy_last_entry
- 1;
3815 grub_check_free(node
->filebuf
);
3818 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3820 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3821 node
->templatepath
[node
->cursel
].path
);
3824 node
->filebuf
= grub_malloc(file
->size
+ 8);
3827 grub_file_read(file
, node
->filebuf
, file
->size
);
3828 grub_file_close(file
);
3830 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3831 node
->filelen
= (int)file
->size
;
3833 ventoy_auto_install_var_expand(node
);
3838 debug("Failed to open auto install script <%s%s>\n",
3839 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3843 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3846 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3852 char configfile
[128];
3853 persistence_config
*node
;
3859 debug("select persistence argc:%d\n", argc
);
3866 node
= ventoy_plugin_find_persistent(args
[0]);
3869 debug("Persistence image not found for %s\n", args
[0]);
3873 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3875 defidx
= node
->autosel
;
3876 if (node
->timeout
< 0)
3878 node
->cursel
= node
->autosel
- 1;
3879 debug("Persistence image auto select %d\n", node
->autosel
);
3884 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3890 if (node
->timeout
> 0)
3892 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3895 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_PERSIST\" --class=\"sel_persistence\" {\n"
3896 " echo %s\n}\n", "");
3898 for (i
= 0; i
< node
->backendnum
; i
++)
3900 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3902 ventoy_get_vmenu_title("VTLANG_PERSIST_USE"),
3903 node
->backendpath
[i
].path
);
3907 g_ventoy_menu_esc
= 1;
3908 g_ventoy_suppress_esc
= 1;
3909 g_ventoy_suppress_esc_default
= defidx
;
3910 g_ventoy_secondary_menu_on
= 1;
3912 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3913 grub_script_execute_sourcecode(configfile
);
3915 g_ventoy_menu_esc
= 0;
3916 g_ventoy_suppress_esc
= 0;
3917 g_ventoy_suppress_esc_default
= 1;
3918 g_ventoy_secondary_menu_on
= 0;
3922 node
->cursel
= g_ventoy_last_entry
- 1;
3924 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3927 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3930 ventoy_img_chunk
*cur
;
3936 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3938 cur
= g_img_chunk_list
.chunk
+ i
;
3939 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3940 cur
->img_start_sector
, cur
->img_end_sector
,
3941 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3945 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3948 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3952 ventoy_img_chunk_list chunklist
;
3957 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3960 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3963 /* get image chunk data */
3964 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3965 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3966 if (NULL
== chunklist
.chunk
)
3968 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3971 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3972 chunklist
.cur_chunk
= 0;
3974 ventoy_get_block_list(file
, &chunklist
, 0);
3976 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3978 grub_printf("########## UNSUPPORTED ###############\n");
3981 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3983 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3985 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3986 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3989 grub_printf("\n==================================\n");
3991 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3993 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3994 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3995 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3996 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3997 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
4001 grub_free(chunklist
.chunk
);
4002 grub_file_close(file
);
4004 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4007 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4010 ventoy_grub_param_file_replace
*replace
= NULL
;
4018 replace
= &(g_grub_param
->file_replace
);
4019 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
4021 replace
->old_name_cnt
= 0;
4022 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
4024 replace
->old_name_cnt
++;
4025 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
4028 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
4031 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4034 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4037 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
4043 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
4044 grub_env_set(args
[0], buf
);
4047 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4050 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4058 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4059 grub_printf("%s", g_list_script_buf
);
4063 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4064 grub_printf("%s", g_tree_script_buf
);
4070 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4072 img_info
*cur
= g_ventoy_img_list
;
4080 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4081 grub_printf("name:<%s>\n\n", cur
->name
);
4088 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4094 ventoy_plugin_dump_injection();
4099 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4105 ventoy_plugin_dump_auto_install();
4110 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4116 ventoy_plugin_dump_persistence();
4121 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4127 len1
= (int)grub_strlen(filename
);
4128 len2
= (int)grub_strlen(suffix
);
4135 for (i
= len1
- 1; i
>= 0; i
--)
4137 if (filename
[i
] == '.')
4148 if (filename
[i
- len2
- 1] != '_')
4153 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4161 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4167 if (argc
!= 1 && argc
!= 2)
4172 if (args
[0][0] == '0')
4174 if (g_ventoy_memdisk_mode
)
4179 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4186 else if (args
[0][0] == '1')
4188 return g_ventoy_iso_raw
? 0 : 1;
4190 else if (args
[0][0] == '2')
4192 return g_ventoy_iso_uefi_drv
? 0 : 1;
4194 else if (args
[0][0] == '3')
4196 if (g_ventoy_grub2_mode
)
4201 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4208 else if (args
[0][0] == '4')
4210 if (g_ventoy_wimboot_mode
)
4215 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4226 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4228 static int configfile_mode
= 0;
4229 char memfile
[128] = {0};
4236 * args[0]: 0:normal 1:configfile
4237 * args[1]: 0:list_buf 1:tree_buf
4242 debug("Invalid argc %d\n", argc
);
4248 if (args
[0][0] == '0')
4250 if (args
[1][0] == '0')
4252 grub_script_execute_sourcecode(g_list_script_buf
);
4256 grub_script_execute_sourcecode(g_tree_script_buf
);
4261 if (configfile_mode
)
4263 debug("Now already in F3 mode %d\n", configfile_mode
);
4267 if (args
[1][0] == '0')
4269 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4270 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4274 g_ventoy_last_entry
= -1;
4275 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4276 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4279 configfile_mode
= 1;
4280 grub_script_execute_sourcecode(memfile
);
4281 configfile_mode
= 0;
4287 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4298 g_ventoy_case_insensitive
= 1;
4299 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4300 g_ventoy_case_insensitive
= 0;
4306 grub_file_close(file
);
4312 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4317 const char *isopath
= NULL
;
4319 ventoy_mbr_head mbr
;
4326 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4329 isopath
= grub_env_get("vtoy_iso_part");
4332 debug("isopath is null %p\n", isopath
);
4336 debug("isopath is %s\n", isopath
);
4338 for (id
= 0; id
< 30 && (find
== 0); id
++)
4340 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4341 if (grub_strstr(isopath
, hdname
))
4343 debug("skip %s ...\n", hdname
);
4347 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4349 disk
= grub_disk_open(hdname
);
4352 debug("%s not exist\n", hdname
);
4356 grub_memset(&mbr
, 0, sizeof(mbr
));
4357 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4359 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4361 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4362 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4365 grub_env_set(args
[0], hdname
);
4369 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4373 debug("read %s failed\n", hdname
);
4376 grub_disk_close(disk
);
4382 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4393 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4396 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4399 debug("failed to open file %s\n", args
[0]);
4403 buf
= grub_malloc(len
);
4410 grub_file_read(file
, buf
, len
- 1);
4412 ventoy_get_line(buf
);
4413 ventoy_set_env(args
[1], buf
);
4417 grub_check_free(buf
);
4418 grub_file_close(file
);
4423 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4425 grub_uint64_t end_max
= 0;
4426 int *pCnt
= (int *)data
;
4431 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4432 "0 %llu linear /dev/ventoy %llu\n",
4433 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4435 end_max
= (partition
->len
+ partition
->start
) * 512;
4436 if (end_max
> g_part_end_max
)
4438 g_part_end_max
= end_max
;
4444 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4447 char *device_name
= NULL
;
4448 grub_device_t dev
= NULL
;
4453 g_part_list_pos
= 0;
4455 grub_env_unset("vtoy_img_part_file");
4462 device_name
= grub_file_get_device_name(args
[0]);
4465 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4469 dev
= grub_device_open(device_name
);
4472 debug("grub_device_open failed, %s\n", device_name
);
4476 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4478 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4479 grub_env_set("vtoy_img_part_file", buf
);
4481 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4482 grub_env_set("vtoy_img_part_cnt", buf
);
4484 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4485 grub_env_set("vtoy_img_max_part_end", buf
);
4489 check_free(device_name
, grub_free
);
4490 check_free(dev
, grub_device_close
);
4496 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4507 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4510 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4513 debug("failed to open file %s\n", args
[0]);
4517 buf
= grub_malloc(file
->size
+ 1);
4523 buf
[file
->size
] = 0;
4524 grub_file_read(file
, buf
, file
->size
);
4526 if (grub_strstr(buf
, args
[1]))
4533 grub_check_free(buf
);
4534 grub_file_close(file
);
4539 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4545 ventoy_iso9660_vd pvd
;
4552 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4555 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4558 debug("failed to open file %s\n", args
[0]);
4562 grub_file_seek(file
, 16 * 2048);
4563 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4564 if (len
!= sizeof(pvd
))
4566 debug("failed to read pvd %d\n", len
);
4570 grub_memset(buf
, 0, sizeof(buf
));
4571 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4572 ventoy_set_env(args
[1], buf
);
4574 grub_memset(buf
, 0, sizeof(buf
));
4575 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4576 ventoy_set_env(args
[2], buf
);
4580 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4581 ventoy_set_env(args
[3], buf
);
4584 grub_file_close(file
);
4589 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4600 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4603 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4606 debug("failed to open file %s\n", args
[0]);
4610 grub_memset(buf
, 0, sizeof(buf
));
4611 grub_file_seek(file
, 16 * 2048 + 813);
4612 len
= (int)grub_file_read(file
, buf
, 17);
4615 debug("failed to read create date %d\n", len
);
4619 ventoy_set_env(args
[1], buf
);
4622 grub_file_close(file
);
4627 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4633 ventoy_env_hook_root(1);
4638 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4644 ventoy_env_hook_root(0);
4649 #ifdef GRUB_MACHINE_EFI
4650 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4655 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4661 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4662 if (var
&& *var
== 1)
4670 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4679 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4684 grub_uint64_t FileSectors
= 0;
4685 ventoy_gpt_info
*gpt
= NULL
;
4686 ventoy_part_table
*pt
= NULL
;
4687 grub_uint8_t zeroguid
[16] = {0};
4692 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4695 debug("failed to open file %s\n", args
[0]);
4699 if (file
->size
% 512)
4701 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4705 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4711 FileSectors
= file
->size
/ 512;
4713 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4714 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4716 debug("This is EFI partition table\n");
4718 for (i
= 0; i
< 128; i
++)
4720 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4722 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4724 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4725 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4733 debug("This is MBR partition table\n");
4735 for (i
= 0; i
< 4; i
++)
4737 pt
= gpt
->MBR
.PartTbl
+ i
;
4738 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4740 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4741 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4742 (ulonglong
)FileSectors
);
4751 grub_file_close(file
);
4752 grub_check_free(gpt
);
4753 grub_errno
= GRUB_ERR_NONE
;
4757 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4766 for (i
= 0; i
< 500; i
++)
4768 ret
= grub_getkey_noblock();
4769 if (ret
== GRUB_TERM_NO_KEY
)
4778 grub_printf("\n\n Still have key input after clear.\n");
4786 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4793 int image_sector_size
;
4795 ventoy_chain_head
*chain
;
4796 ventoy_img_chunk
*chunk
;
4797 ventoy_os_param
*osparam
;
4798 ventoy_image_location
*location
;
4799 ventoy_image_disk_region
*region
;
4800 struct grub_acpi_table_header
*acpi
;
4809 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4811 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4817 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4819 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4821 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4825 img_chunk_num
= chain
->img_chunk_num
;
4827 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4828 datalen
= sizeof(ventoy_os_param
) + loclen
;
4830 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4831 acpi
= grub_zalloc(buflen
);
4837 /* Step1: Fill acpi table header */
4838 grub_memcpy(acpi
->signature
, "VTOY", 4);
4839 acpi
->length
= buflen
;
4841 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4842 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4844 acpi
->creator_id
[0] = 1;
4845 acpi
->creator_rev
= 1;
4847 /* Step2: Fill data */
4848 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4849 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4850 osparam
->vtoy_img_location_addr
= 0;
4851 osparam
->vtoy_img_location_len
= loclen
;
4852 osparam
->chksum
= 0;
4853 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4855 location
= (ventoy_image_location
*)(osparam
+ 1);
4856 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4857 location
->image_sector_size
= image_sector_size
;
4858 location
->disk_sector_size
= chain
->disk_sector_size
;
4859 location
->region_count
= img_chunk_num
;
4861 region
= location
->regions
;
4862 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4863 if (512 == image_sector_size
)
4865 for (i
= 0; i
< img_chunk_num
; i
++)
4867 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4868 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4869 region
->disk_start_sector
= chunk
->disk_start_sector
;
4876 for (i
= 0; i
< img_chunk_num
; i
++)
4878 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4879 region
->image_start_sector
= chunk
->img_start_sector
;
4880 region
->disk_start_sector
= chunk
->disk_start_sector
;
4886 /* Step3: Fill acpi checksum */
4888 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4890 /* load acpi table */
4891 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4892 grub_script_execute_sourcecode(cmd
);
4896 VENTOY_CMD_RETURN(0);
4899 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4905 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4906 g_ventoy_last_entry
= -1;
4911 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4917 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4922 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4924 const char *pos
= filename
+ 1;
4932 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4934 grub_strncpy((char *)data
, filename
, 128);
4945 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4948 char *device_name
= NULL
;
4949 grub_device_t dev
= NULL
;
4950 grub_fs_t fs
= NULL
;
4951 char buf
[128] = {0};
4957 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4961 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4963 device_name
= grub_file_get_device_name(args
[0]);
4966 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4970 dev
= grub_device_open(device_name
);
4973 debug("grub_device_open failed, %s\n", device_name
);
4977 fs
= grub_fs_probe(dev
);
4980 debug("grub_fs_probe failed, %s\n", device_name
);
4984 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4988 ventoy_set_env(args
[2], buf
);
4995 check_free(device_name
, grub_free
);
4996 check_free(dev
, grub_device_close
);
5001 int ventoy_load_part_table(const char *diskname
)
5008 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
5009 if (!g_ventoy_part_info
)
5014 disk
= grub_disk_open(diskname
);
5017 debug("Failed to open disk %s\n", diskname
);
5021 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
5023 g_ventoy_disk_bios_id
= disk
->id
;
5025 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
5026 grub_disk_close(disk
);
5028 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
5029 dev
= grub_device_open(name
);
5032 /* Check for official Ventoy device */
5033 ret
= ventoy_check_official_device(dev
);
5034 grub_device_close(dev
);
5042 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5043 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5048 static void ventoy_prompt_end(void)
5053 grub_printf("\n\n\n");
5054 grub_printf(" 1 --- Exit grub\n");
5055 grub_printf(" 2 --- Reboot\n");
5056 grub_printf(" 3 --- Shut down\n");
5057 grub_printf("Please enter your choice: ");
5063 if (c
>= '1' && c
<= '3')
5068 grub_printf("%c", c
);
5072 else if (c
== '\r' || c
== '\n')
5086 grub_script_execute_sourcecode("halt");
5095 grub_printf("\rPlease enter your choice: ");
5096 grub_printf("\rPlease enter your choice: ");
5103 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5110 ret
= ventoy_load_part_table(args
[0]);
5113 ventoy_prompt_end();
5116 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5117 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5122 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5125 const char *vcfg
= NULL
;
5130 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5133 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5134 grub_env_set(args
[1], vcfg
);
5139 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5147 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5150 grub_uint8_t zeroguid
[16] = {0};
5155 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5158 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5160 if (id
>= 1 && id
<= 128)
5162 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5170 if (id
>= 1 && id
<= 4)
5172 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5182 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5185 char *device_name
= NULL
;
5186 grub_device_t dev
= NULL
;
5187 grub_fs_t fs
= NULL
;
5192 debug("get fs label for %s\n", args
[0]);
5196 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5200 device_name
= grub_file_get_device_name(args
[0]);
5203 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5207 dev
= grub_device_open(device_name
);
5210 debug("grub_device_open failed, %s\n", device_name
);
5214 fs
= grub_fs_probe(dev
);
5215 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5217 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5221 fs
->fs_label(dev
, &label
);
5224 debug("label=<%s>\n", label
);
5225 ventoy_set_env(args
[1], label
);
5233 check_free(device_name
, grub_free
);
5234 check_free(dev
, grub_device_close
);
5239 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5243 grub_snprintf((char *)data
, 256, "%s", filename
);
5250 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5252 if (info
->dir
&& filename
&& filename
[0] != '.')
5254 grub_snprintf((char *)data
, 256, "%s", filename
);
5261 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5264 char *device_name
= NULL
;
5265 grub_device_t dev
= NULL
;
5266 grub_fs_t fs
= NULL
;
5267 char name
[256] ={0};
5271 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5275 device_name
= grub_file_get_device_name(args
[0]);
5278 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5282 dev
= grub_device_open(device_name
);
5285 debug("grub_device_open failed, %s\n", device_name
);
5289 fs
= grub_fs_probe(dev
);
5292 debug("grub_fs_probe failed, %s\n", device_name
);
5296 fs
->fs_dir(dev
, args
[1], hook
, name
);
5299 ventoy_set_env(args
[2], name
);
5306 check_free(device_name
, grub_free
);
5307 check_free(dev
, grub_device_close
);
5312 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5315 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5318 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5321 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5324 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5334 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5338 for (pos
= args
[0]; *pos
; pos
++)
5352 grub_env_set(args
[1], args
[0]);
5362 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5372 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5377 len
= (int)grub_strlen(buf
);
5378 for (i
= len
; i
> 0; i
--)
5380 if (buf
[i
- 1] == '/')
5382 grub_env_set(args
[1], buf
+ i
);
5387 grub_env_set(args
[1], buf
);
5392 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5394 struct grub_video_mode_info info
;
5401 if (!g_video_mode_list
)
5403 ventoy_enum_video_mode();
5406 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5408 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5412 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5415 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5417 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5418 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5420 VENTOY_CMD_RETURN(0);
5423 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5425 struct grub_video_mode_info info
;
5432 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5434 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5438 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5441 grub_env_set(args
[0], buf
);
5443 VENTOY_CMD_RETURN(0);
5446 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5454 if (!g_video_mode_list
)
5459 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5460 if (id
< g_video_mode_num
)
5462 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5463 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5466 grub_env_set(args
[1], buf
);
5468 VENTOY_CMD_RETURN(0);
5471 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5474 grub_uint32_t loadsector
= 0;
5477 grub_uint32_t boot_catlog
= 0;
5478 grub_uint8_t buf
[512];
5484 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5488 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5491 debug("failed to open %s\n", args
[0]);
5495 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5496 if (boot_catlog
== 0)
5498 debug("No bootcatlog found\n");
5499 grub_file_close(file
);
5503 grub_memset(buf
, 0, sizeof(buf
));
5504 grub_file_seek(file
, boot_catlog
* 2048);
5505 grub_file_read(file
, buf
, sizeof(buf
));
5506 grub_file_close(file
);
5508 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5510 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5512 if (buf
[i
+ 32] == 0x88)
5514 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5515 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5521 if (loadsector
== 0)
5523 debug("No EFI eltorito info found\n");
5527 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5528 grub_env_set(args
[1], value
);
5529 VENTOY_CMD_RETURN(0);
5532 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5537 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5539 if (pfsdir
->initrd
[0])
5544 curpos
= pfsdir
->curpos
;
5545 len
= grub_strlen(filename
);
5549 if ((len
== 1 && filename
[0] == '.') ||
5550 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5555 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5558 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5559 pfsdir
->curpos
= curpos
+ printlen
;
5560 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5561 pfsdir
->curpos
= curpos
;
5562 pfsdir
->fullpath
[curpos
] = 0;
5566 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5569 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5570 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5572 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5574 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5583 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5587 char *device_name
= NULL
;
5588 grub_device_t dev
= NULL
;
5589 grub_fs_t fs
= NULL
;
5590 replace_fs_dir
*pfsdir
= NULL
;
5596 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5600 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5606 device_name
= grub_file_get_device_name(args
[0]);
5612 dev
= grub_device_open(device_name
);
5618 fs
= grub_fs_probe(dev
);
5627 pfsdir
->fullpath
[0] = '/';
5628 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5630 if (pfsdir
->initrd
[0])
5632 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5634 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5636 if (pfsdir
->initrd
[i
] == '/')
5638 pfsdir
->initrd
[i
] = '\\';
5642 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5643 grub_env_set(args
[1], pos
);
5647 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5652 grub_check_free(pfsdir
);
5653 grub_check_free(device_name
);
5654 check_free(dev
, grub_device_close
);
5656 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5659 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5661 const char *pager
= NULL
;
5667 pager
= grub_env_get("pager");
5671 grub_env_set("pager", "1");
5673 else if (pager
[0] == '1')
5679 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5681 grub_env_set("pager", "1");
5684 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5687 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5693 if (g_pager_flag
== 1)
5695 grub_env_unset("pager");
5697 else if (g_pager_flag
== 2)
5699 grub_env_set("pager", g_old_pager
);
5702 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5705 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5707 if (g_json_case_mis_path
[0])
5712 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5714 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5720 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5723 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5725 if (g_json_case_mis_path
[0])
5730 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5732 if (grub_strcasecmp(filename
, "ventoy") == 0)
5734 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5735 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5736 if (g_json_case_mis_path
[0])
5746 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5749 char *device_name
= NULL
;
5750 grub_device_t dev
= NULL
;
5751 grub_fs_t fs
= NULL
;
5752 chk_case_fs_dir fs_dir
;
5758 device_name
= grub_file_get_device_name(args
[0]);
5764 dev
= grub_device_open(device_name
);
5770 fs
= grub_fs_probe(dev
);
5776 fstype
= ventoy_get_fs_type(fs
->name
);
5777 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5782 g_json_case_mis_path
[0] = 0;
5785 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5787 if (g_json_case_mis_path
[0])
5789 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5794 grub_check_free(device_name
);
5795 check_free(dev
, grub_device_close
);
5797 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5800 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5803 grub_partition_t part
;
5804 char priority_str
[3]; /* Maximum value 15 */
5808 if (argc
< 2 || argc
> 3)
5809 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5810 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5812 /* Open the disk if it exists */
5813 disk
= grub_disk_open (args
[0]);
5816 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5820 part
= grub_partition_probe (disk
, args
[1]);
5823 grub_disk_close (disk
);
5824 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5825 "No such partition");
5828 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5830 grub_disk_close (disk
);
5831 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5832 "Not a GPT partition");
5835 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5836 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5840 grub_env_set (args
[2], priority_str
);
5841 grub_env_export (args
[2]);
5845 grub_printf ("Priority is %s\n", priority_str
);
5848 grub_disk_close (disk
);
5849 return GRUB_ERR_NONE
;
5853 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5857 grub_file_t file
= NULL
;
5858 grub_uint32_t loadrba
= 0;
5859 grub_uint32_t boot_catlog
= 0;
5860 grub_uint8_t sector
[512];
5861 boot_info_table
*info
= NULL
;
5866 /* This also trigger a iso9660 fs parse */
5867 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5872 joliet
= grub_iso9660_is_joliet();
5878 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5881 debug("failed to open %s\n", args
[0]);
5885 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5886 if (boot_catlog
== 0)
5888 debug("no bootcatlog found %u\n", boot_catlog
);
5892 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5895 debug("no bios eltorito rba found %u\n", loadrba
);
5899 grub_file_seek(file
, loadrba
* 2048);
5900 grub_file_read(file
, sector
, 512);
5902 info
= (boot_info_table
*)sector
;
5903 if (info
->bi_data0
== 0x7c6ceafa &&
5904 info
->bi_data1
== 0x90900000 &&
5905 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5906 info
->bi_BootFileLocation
== loadrba
)
5908 debug("bootloader is syslinux, %u.\n", loadrba
);
5914 grub_file_close(file
);
5915 grub_errno
= GRUB_ERR_NONE
;
5919 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5922 ventoy_vlnk_part
*node
;
5928 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5930 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5931 ++n
, node
->device
, node
->disksig
,
5932 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5938 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5946 len
= (int)grub_strlen(args
[0]);
5947 if (grub_file_is_vlnk_suffix(args
[0], len
))
5956 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5959 const char *name
= NULL
;
5965 grub_env_unset(args
[1]);
5966 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5969 debug("VLNK SRC: <%s>\n", args
[0]);
5970 debug("VLNK DST: <%s>\n", name
);
5971 grub_env_set(args
[1], name
);
5979 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5983 grub_file_t file
= NULL
;
5994 len
= (int)grub_strlen(args
[0]);
5995 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5997 grub_printf("Invalid vlnk suffix\n");
6001 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
6004 grub_printf("Failed to open %s\n", args
[0]);
6008 if (file
->size
!= 32768)
6010 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
6014 grub_memset(&vlnk
, 0, sizeof(vlnk
));
6015 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
6017 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
6022 check_free(file
, grub_file_close
);
6023 grub_errno
= GRUB_ERR_NONE
;
6027 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6033 g_iso_vd_id_publisher
[0] = 0;
6034 g_iso_vd_id_prepare
[0] = 0;
6035 g_iso_vd_id_application
[0] = 0;
6040 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6044 grub_file_t file
= NULL
;
6049 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
6052 grub_printf("Failed to open %s\n", args
[0]);
6056 grub_file_seek(file
, 16 * 2048 + offset
);
6057 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
6060 grub_file_seek(file
, 16 * 2048 + offset
);
6061 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
6064 grub_file_seek(file
, 16 * 2048 + offset
);
6065 grub_file_read(file
, g_iso_vd_id_application
, 128);
6069 check_free(file
, grub_file_close
);
6070 grub_errno
= GRUB_ERR_NONE
;
6074 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6077 char *id
= g_iso_vd_id_publisher
;
6082 if (args
[0][0] == '1')
6084 id
= g_iso_vd_id_prepare
;
6086 else if (args
[0][0] == '2')
6088 id
= g_iso_vd_id_application
;
6091 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6096 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6101 grub_errno
= GRUB_ERR_NONE
;
6105 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6110 g_ventoy_fn_mutex
= 0;
6111 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
6113 g_ventoy_fn_mutex
= 1;
6116 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6119 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6121 grub_uint64_t total
;
6122 grub_uint64_t org_required
;
6123 grub_uint64_t new_required
;
6129 #ifdef GRUB_MACHINE_EFI
6130 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6131 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6132 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6133 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6138 grub_printf("Non EFI mode!\n");
6143 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6146 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6148 const char *env
= NULL
;
6153 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6158 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6159 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6160 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6161 ventoy_check_mode_by_name(args
[0], "vtnormal")
6167 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6168 if (env
&& env
[0] == '0' && env
[1] == 0)
6176 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6184 const char *env
= NULL
;
6185 ulonglong fsize
= 0;
6187 int seldata
[16] = {0};
6192 len
= 8 * VTOY_SIZE_1KB
;
6193 cmd
= (char *)grub_malloc(len
);
6199 g_vtoy_secondary_need_recover
= 0;
6200 grub_env_unset("VTOY_SECOND_EXIT");
6201 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6203 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6206 timeout
= (int)grub_strtol(env
, NULL
, 10);
6211 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6214 fsize
= grub_strtoull(args
[2], NULL
, 10);
6216 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6218 if (grub_strcmp(args
[1], "Unix") != 0)
6220 if (grub_strcmp(args
[1], "Windows") == 0)
6222 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6226 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6229 if (fsize
<= VTOY_SIZE_1GB
)
6231 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6235 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6236 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_RETURN_PRV_NOESC", "second_return"); seldata
[n
++] = 6;
6239 grub_errno
= GRUB_ERR_NONE
;
6240 g_ventoy_menu_esc
= 1;
6241 g_ventoy_suppress_esc
= 1;
6242 g_ventoy_suppress_esc_default
= 0;
6243 g_ventoy_secondary_menu_on
= 1;
6244 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6245 grub_script_execute_sourcecode(cfgfile
);
6246 g_ventoy_menu_esc
= 0;
6247 g_ventoy_suppress_esc
= 0;
6248 g_ventoy_suppress_esc_default
= 1;
6249 g_ventoy_secondary_menu_on
= 0;
6251 select
= seldata
[g_ventoy_last_entry
];
6255 g_ventoy_wimboot_mode
= 1;
6256 g_vtoy_secondary_need_recover
= 1;
6258 else if (select
== 3)
6260 g_ventoy_grub2_mode
= 1;
6261 g_vtoy_secondary_need_recover
= 2;
6263 else if (select
== 4)
6265 g_ventoy_memdisk_mode
= 1;
6266 g_vtoy_secondary_need_recover
= 3;
6268 else if (select
== 5)
6270 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6271 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6273 else if (select
== 6)
6275 grub_env_set("VTOY_SECOND_EXIT", "1");
6277 }while (select
== 5);
6280 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6283 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6289 if (g_vtoy_secondary_need_recover
== 1)
6291 g_ventoy_wimboot_mode
= 0;
6293 else if (g_vtoy_secondary_need_recover
== 2)
6295 g_ventoy_grub2_mode
= 0;
6297 else if (g_vtoy_secondary_need_recover
== 3)
6299 g_ventoy_memdisk_mode
= 0;
6302 g_vtoy_secondary_need_recover
= 0;
6304 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6307 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6312 if (args
[0][0] == '0')
6314 g_ventoy_case_insensitive
= 0;
6318 g_ventoy_case_insensitive
= 1;
6324 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6329 ventoy_plugin_load_menu_lang(1, args
[0]);
6330 VENTOY_CMD_RETURN(0);
6333 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6338 ventoy_plugin_load_menu_lang(0, args
[0]);
6339 VENTOY_CMD_RETURN(0);
6342 static int ventoy_chksum_pathcmp(int chktype
, char *rlpath
, char *rdpath
)
6349 pos1
= ventoy_str_basename(rlpath
);
6350 pos2
= ventoy_str_basename(rdpath
);
6351 return grub_strcmp(pos1
, pos2
);
6353 else if (chktype
== 3 || chktype
== 4)
6355 if (grub_strcmp(rlpath
, rdpath
) == 0 || grub_strcmp(rlpath
+ 1, rdpath
) == 0)
6364 static int ventoy_find_checksum
6379 char *currline
= NULL
;
6380 char *nextline
= NULL
;
6382 ulen
= (int)grub_strlen(uname
);
6384 /* read file to buffer */
6385 buf
= grub_malloc(file
->size
+ 4);
6390 grub_file_read(file
, buf
, file
->size
);
6391 buf
[file
->size
] = 0;
6393 /* parse each line */
6394 for (currline
= buf
; currline
; currline
= nextline
)
6396 nextline
= ventoy_get_line(currline
);
6397 VTOY_SKIP_SPACE(currline
);
6399 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6401 pos
= grub_strchr(currline
, '=');
6402 pos1
= grub_strchr(currline
, '(');
6403 pos2
= grub_strchr(currline
, ')');
6405 if (pos
&& pos1
&& pos2
)
6408 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6410 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6411 grub_memcpy(chksum
, pos
, retlen
);
6416 else if (ventoy_str_len_alnum(currline
, retlen
))
6418 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, retlen
);
6419 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6421 grub_memcpy(chksum
, currline
, retlen
);
6432 static int ventoy_check_chkfile(const char *isopart
, char *path
, const char *lchkname
, grub_file_t
*pfile
)
6438 grub_file_t file
= NULL
;
6440 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s.%s", isopart
, path
, lchkname
);
6446 cnt
= ventoy_str_chrcnt(path
, '/');
6449 pos
= grub_strrchr(path
, '/');
6453 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, path
);
6462 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6465 ret
= (cnt
> 1) ? 3 : 4;
6476 check_free(file
, grub_file_close
);
6481 static grub_err_t
ventoy_cmd_cmp_checksum(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6486 grub_file_t file
= NULL
;
6487 const char *calc_value
= NULL
;
6488 const char *isopart
= NULL
;
6490 char readchk
[256] = {0};
6491 char filebuf
[512] = {0};
6496 index
= (int)grub_strtol(args
[0], NULL
, 10);
6497 if (argc
!= 2 || index
< 0 || index
>= VTOY_CHKSUM_NUM
)
6502 grub_strncpy(uchkname
, g_lower_chksum_name
[index
], sizeof(uchkname
));
6503 ventoy_str_toupper(uchkname
);
6505 isopart
= grub_env_get("vtoy_iso_part");
6506 calc_value
= grub_env_get("VT_LAST_CHECK_SUM");
6508 chktype
= ventoy_check_chkfile(isopart
, args
[1], g_lower_chksum_name
[index
], &file
);
6511 grub_printf("\n\nNo checksum file found.\n");
6517 grub_snprintf(fchksum
, sizeof(fchksum
), ".%s", g_lower_chksum_name
[index
]);
6518 grub_memset(filebuf
, 0, sizeof(filebuf
));
6519 grub_file_read(file
, filebuf
, 511);
6521 pos
= grub_strchr(filebuf
, '=');
6524 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6525 grub_memcpy(readchk
, pos
, g_chksum_retlen
[index
]);
6529 grub_memcpy(readchk
, filebuf
, g_chksum_retlen
[index
]);
6532 else if (chktype
== 3 || chktype
== 4)
6534 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6535 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], chktype
, readchk
);
6536 if (readchk
[0] == 0)
6538 grub_printf("\n\n%s value not found in %s.\n", uchkname
, fchksum
);
6544 grub_snprintf(fchksum
, sizeof(fchksum
), "local VENTOY_CHECKSUM");
6545 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], chktype
, readchk
);
6546 if (readchk
[0] == 0)
6548 grub_file_close(file
);
6549 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6552 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6553 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], 3, readchk
);
6554 if (readchk
[0] == 0)
6556 grub_printf("\n\n%s value not found in both local and global VENTOY_CHECKSUM.\n", uchkname
);
6563 if (grub_strcasecmp(calc_value
, readchk
) == 0)
6565 grub_printf("\n\nCheck %s value with %s file. [ SUCCESS ]\n", uchkname
, fchksum
);
6569 grub_printf("\n\nCheck %s value with %s file. [ ERROR ]\n", uchkname
, fchksum
);
6570 grub_printf("The %s value in %s file is:\n%s\n", uchkname
, fchksum
, readchk
);
6575 check_free(file
, grub_file_close
);
6576 VENTOY_CMD_RETURN(0);
6579 static int ventoy_find_all_checksum
6584 int exists
[VTOY_CHKSUM_NUM
],
6596 char *currline
= NULL
;
6597 char *nextline
= NULL
;
6598 const char *uname
= NULL
;
6602 /* read file to buffer */
6603 buf
= grub_malloc(file
->size
+ 4);
6608 grub_file_read(file
, buf
, file
->size
);
6609 buf
[file
->size
] = 0;
6611 /* parse each line */
6612 for (currline
= buf
; currline
; currline
= nextline
)
6614 nextline
= ventoy_get_line(currline
);
6615 VTOY_SKIP_SPACE(currline
);
6617 for (i
= 0; i
< VTOY_CHKSUM_NUM
; i
++)
6624 uname
= g_lower_chksum_name
[i
];
6625 ulen
= g_lower_chksum_namelen
[i
];
6627 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6629 pos
= grub_strchr(currline
, '=');
6630 pos1
= grub_strchr(currline
, '(');
6631 pos2
= grub_strchr(currline
, ')');
6633 if (pos
&& pos1
&& pos2
)
6637 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6645 else if (ventoy_str_len_alnum(currline
, g_chksum_retlen
[i
]))
6647 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, g_chksum_retlen
[i
]);
6648 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6655 if (tot
>= VTOY_CHKSUM_NUM
)
6669 static grub_err_t
ventoy_cmd_vtoychksum_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6676 grub_file_t file
= NULL
;
6677 const char *isopart
= NULL
;
6678 int exists
[VTOY_CHKSUM_NUM
] = { 0, 0, 0, 0 };
6684 isopart
= grub_env_get("vtoy_iso_part");
6686 for (i
= 0; i
< VTOY_CHKSUM_NUM
; i
++)
6688 if (ventoy_check_file_exist("%s%s.%s", isopart
, args
[0], g_lower_chksum_name
[i
]))
6695 if (totexist
== VTOY_CHKSUM_NUM
)
6700 cnt
= ventoy_str_chrcnt(args
[0], '/');
6703 pos
= grub_strrchr(args
[0], '/');
6706 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, args
[0]);
6711 if (tip
== 0 && file
->size
> (32 * VTOY_SIZE_1KB
))
6714 grub_printf("Reading checksum file...\n");
6718 debug("parse local VENTOY_CHECKSUM\n");
6719 ventoy_find_all_checksum(file
, args
[0], 2, exists
, &totexist
);
6720 grub_file_close(file
);
6724 if (totexist
== VTOY_CHKSUM_NUM
)
6729 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6732 if (tip
== 0 && file
->size
> (32 * VTOY_SIZE_1KB
))
6735 grub_printf("Reading checksum file...\n");
6739 debug("parse global VENTOY_CHECKSUM\n");
6740 ventoy_find_all_checksum(file
, args
[0], (cnt
> 1) ? 3 : 4, exists
, &totexist
);
6741 grub_file_close(file
);
6746 ventoy_env_int_set("VT_EXIST_MD5", exists
[0]);
6747 ventoy_env_int_set("VT_EXIST_SHA1", exists
[1]);
6748 ventoy_env_int_set("VT_EXIST_SHA256", exists
[2]);
6749 ventoy_env_int_set("VT_EXIST_SHA512", exists
[3]);
6751 VENTOY_CMD_RETURN(0);
6755 static const char * ventoy_menu_lang_read_hook(struct grub_env_var
*var
, const char *val
)
6758 return ventoy_get_vmenu_title(val
);
6761 int ventoy_env_init(void)
6766 grub_env_set("vtdebug_flag", "");
6768 grub_register_vtoy_menu_lang_hook(ventoy_menu_lang_read_hook
);
6769 ventoy_ctrl_var_init();
6770 ventoy_global_var_init();
6772 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6773 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6774 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6775 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6777 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6780 ventoy_filt_register(0, ventoy_wrapper_open
);
6782 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6785 g_grub_param
->grub_env_get
= grub_env_get
;
6786 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6787 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6788 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6789 grub_env_set("env_param", buf
);
6790 grub_env_set("ventoy_env_param", buf
);
6792 grub_env_export("env_param");
6793 grub_env_export("ventoy_env_param");
6796 grub_env_export("vtoy_winpeshl_ini_addr");
6797 grub_env_export("vtoy_winpeshl_ini_size");
6799 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6800 grub_env_set("vtoy_chain_file_size", buf
);
6801 grub_env_export("vtoy_chain_file_size");
6803 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6804 grub_env_set("vtoy_chain_file_read", buf
);
6805 grub_env_export("vtoy_chain_file_read");
6807 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6808 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6809 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6811 grub_snprintf(buf
, sizeof(buf
), "%s-%s", GRUB_TARGET_CPU
, GRUB_PLATFORM
);
6812 grub_env_set("grub_cpu_platform", buf
);
6813 grub_env_export("grub_cpu_platform");
6820 static cmd_para ventoy_cmds
[] =
6822 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6823 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6824 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6825 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6826 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6827 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6828 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6829 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6830 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6831 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6832 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6833 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6834 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6835 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6836 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6837 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6838 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6839 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6840 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6841 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6842 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6843 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6844 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6845 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6846 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6847 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6848 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6850 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6851 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6852 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6853 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6854 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6855 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6856 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6858 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6859 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6860 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6861 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6862 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6863 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6864 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6865 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6866 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6867 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6870 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6871 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6872 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6873 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6874 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6875 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6876 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6877 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6878 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6879 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6880 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6882 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6883 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6884 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6885 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6886 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6887 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6888 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6890 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6891 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6892 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6893 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6894 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6895 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6896 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6897 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6898 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6899 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6901 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6902 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6903 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6904 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6905 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6906 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6907 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6908 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6909 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6911 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6912 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6913 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6914 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6917 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6918 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6919 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6921 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6922 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6923 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6926 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6927 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6928 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6929 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6930 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6931 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6932 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6933 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6934 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6935 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6936 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6937 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6938 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6939 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6941 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6942 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6943 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6944 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6945 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6946 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6947 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6948 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6949 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6950 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6951 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6952 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6954 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6955 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6956 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6957 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6958 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6959 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6960 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6961 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6962 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6963 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6964 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6965 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6966 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6967 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6968 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6969 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6970 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6971 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6972 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6973 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6974 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6975 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6976 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6977 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6978 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6979 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6980 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6981 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6982 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6983 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6984 { "vt_vtoychksum_exist", ventoy_cmd_vtoychksum_exist
, 0, NULL
, "", "", NULL
},
6985 { "vt_cmp_checksum", ventoy_cmd_cmp_checksum
, 0, NULL
, "", "", NULL
},
6986 { "vt_push_menu_lang", ventoy_cmd_push_menulang
, 0, NULL
, "", "", NULL
},
6987 { "vt_pop_menu_lang", ventoy_cmd_pop_menulang
, 0, NULL
, "", "", NULL
},
6991 int ventoy_register_all_cmd(void)
6994 cmd_para
*cur
= NULL
;
6996 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6998 cur
= ventoy_cmds
+ i
;
6999 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
7000 cur
->summary
, cur
->description
, cur
->parser
);
7006 int ventoy_unregister_all_cmd(void)
7010 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
7012 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);