1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/random.h>
49 #include <grub/ventoy.h>
50 #include "ventoy_def.h"
53 GRUB_MOD_LICENSE ("GPLv3+");
55 static grub_uint8_t g_check_mbr_data
[] = {
56 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
62 initrd_info
*g_initrd_img_list
= NULL
;
63 initrd_info
*g_initrd_img_tail
= NULL
;
64 int g_initrd_img_count
= 0;
65 int g_valid_initrd_count
= 0;
66 int g_default_menu_mode
= 0;
67 int g_filt_dot_underscore_file
= 0;
68 int g_sort_case_sensitive
= 0;
69 int g_tree_view_menu_style
= 0;
70 static grub_file_t g_old_file
;
71 static int g_ventoy_last_entry_back
;
74 char g_img_swap_tmp_buf
[1024];
75 img_info g_img_swap_tmp
;
76 img_info
*g_ventoy_img_list
= NULL
;
78 int g_ventoy_img_count
= 0;
80 grub_device_t g_enum_dev
= NULL
;
81 grub_fs_t g_enum_fs
= NULL
;
82 int g_img_max_search_level
= -1;
83 img_iterator_node g_img_iterator_head
;
84 img_iterator_node
*g_img_iterator_tail
= NULL
;
86 grub_uint8_t g_ventoy_break_level
= 0;
87 grub_uint8_t g_ventoy_debug_level
= 0;
88 grub_uint8_t g_ventoy_chain_type
= 0;
90 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
91 grub_uint32_t g_ventoy_cpio_size
= 0;
92 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
93 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
95 int g_plugin_image_list
= 0;
97 ventoy_grub_param
*g_grub_param
= NULL
;
99 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
101 ventoy_img_chunk_list g_img_chunk_list
;
103 int g_wimboot_enable
= 0;
104 ventoy_img_chunk_list g_wimiso_chunk_list
;
105 char *g_wimiso_path
= NULL
;
106 grub_uint32_t g_wimiso_size
= 0;
108 int g_vhdboot_enable
= 0;
110 grub_uint64_t g_svd_replace_offset
= 0;
112 int g_conf_replace_count
= 0;
113 grub_uint64_t g_conf_replace_offset
[VTOY_MAX_CONF_REPLACE
] = { 0 };
114 conf_replace
*g_conf_replace_node
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
115 grub_uint8_t
*g_conf_replace_new_buf
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
116 int g_conf_replace_new_len
[VTOY_MAX_CONF_REPLACE
] = { 0 };
117 int g_conf_replace_new_len_align
[VTOY_MAX_CONF_REPLACE
] = { 0 };
119 int g_ventoy_disk_bios_id
= 0;
120 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
121 grub_uint64_t g_ventoy_disk_size
= 0;
122 grub_uint64_t g_ventoy_disk_part_size
[2];
124 char *g_tree_script_buf
= NULL
;
125 int g_tree_script_pos
= 0;
126 int g_tree_script_pre
= 0;
128 static char *g_list_script_buf
= NULL
;
129 static int g_list_script_pos
= 0;
131 static char *g_part_list_buf
= NULL
;
132 static int g_part_list_pos
= 0;
133 static grub_uint64_t g_part_end_max
= 0;
135 static int g_video_mode_max
= 0;
136 static int g_video_mode_num
= 0;
137 static ventoy_video_mode
*g_video_mode_list
= NULL
;
139 static int g_enumerate_time_checked
= 0;
140 static grub_uint64_t g_enumerate_start_time_ms
;
141 static grub_uint64_t g_enumerate_finish_time_ms
;
142 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
144 static char g_iso_vd_id_publisher
[130];
145 static char g_iso_vd_id_prepare
[130];
146 static char g_iso_vd_id_application
[130];
148 static int g_pager_flag
= 0;
149 static char g_old_pager
[32];
151 static char g_vtoy_gfxmode
[64];
153 const char *g_menu_class
[img_type_max
] =
155 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
158 const char *g_menu_prefix
[img_type_max
] =
160 "iso", "wim", "efi", "img", "vhd", "vtoy"
163 static int g_vtoy_secondary_need_recover
= 0;
165 static int g_vtoy_load_prompt
= 0;
166 static char g_vtoy_prompt_msg
[64];
168 static char g_json_case_mis_path
[32];
170 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
172 int ventoy_get_fs_type(const char *fs
)
176 return ventoy_fs_max
;
178 else if (grub_strncmp(fs
, "exfat", 5) == 0)
180 return ventoy_fs_exfat
;
182 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
184 return ventoy_fs_ntfs
;
186 else if (grub_strncmp(fs
, "ext", 3) == 0)
188 return ventoy_fs_ext
;
190 else if (grub_strncmp(fs
, "xfs", 3) == 0)
192 return ventoy_fs_xfs
;
194 else if (grub_strncmp(fs
, "udf", 3) == 0)
196 return ventoy_fs_udf
;
198 else if (grub_strncmp(fs
, "fat", 3) == 0)
200 return ventoy_fs_fat
;
203 return ventoy_fs_max
;
206 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
225 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
227 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
231 static int ventoy_control_get_flag(const char *key
)
233 const char *val
= ventoy_get_env(key
);
235 if (val
&& val
[0] == '1' && val
[1] == 0)
242 static grub_err_t
ventoy_fs_close(grub_file_t file
)
244 grub_file_close(g_old_file
);
245 grub_free(file
->data
);
253 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
259 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
264 for (i
= 0; i
< g_video_mode_num
; i
++)
266 if (g_video_mode_list
[i
].width
== info
->width
&&
267 g_video_mode_list
[i
].height
== info
->height
&&
268 g_video_mode_list
[i
].bpp
== info
->bpp
)
274 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
275 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
276 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
279 if (g_video_mode_num
== g_video_mode_max
)
281 g_video_mode_max
*= 2;
282 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
288 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
290 if (v1
->bpp
== v2
->bpp
)
292 if (v1
->width
== v2
->width
)
294 if (v1
->height
== v2
->height
)
300 return (v1
->height
< v2
->height
) ? -1 : 1;
305 return (v1
->width
< v2
->width
) ? -1 : 1;
310 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
314 static int ventoy_enum_video_mode(void)
317 grub_video_adapter_t adapter
;
318 grub_video_driver_id_t id
;
319 ventoy_video_mode mode
;
321 g_video_mode_num
= 0;
322 g_video_mode_max
= 1024;
323 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
324 if (!g_video_mode_list
)
329 #ifdef GRUB_MACHINE_PCBIOS
330 grub_dl_load ("vbe");
333 id
= grub_video_get_driver_id ();
335 FOR_VIDEO_ADAPTERS (adapter
)
337 if (!adapter
->iterate
||
338 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
339 adapter
->init() != GRUB_ERR_NONE
)))
344 adapter
->iterate(ventoy_video_hook
, NULL
);
346 if (adapter
->id
!= id
)
352 /* sort video mode */
353 for (i
= 0; i
< g_video_mode_num
; i
++)
354 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
356 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
358 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
359 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
360 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
364 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
367 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
371 static struct grub_fs vtoy_fs
=
376 .fs_read
= ventoy_fs_read
,
377 .fs_close
= ventoy_fs_close
,
387 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
393 file
->data
= grub_malloc(rawFile
->size
+ 4096);
399 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
400 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
402 g_old_file
= rawFile
;
404 file
->size
= rawFile
->size
+ len
;
405 file
->device
= rawFile
->device
;
407 file
->not_easily_seekable
= 1;
412 static int ventoy_check_decimal_var(const char *name
, long *value
)
414 const char *value_str
= NULL
;
416 value_str
= grub_env_get(name
);
417 if (NULL
== value_str
)
419 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
422 if (!ventoy_is_decimal(value_str
))
424 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
427 *value
= grub_strtol(value_str
, NULL
, 10);
429 return GRUB_ERR_NONE
;
432 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
434 grub_uint64_t sectors
;
436 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
438 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
442 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
445 return sectors
* 512;
448 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
454 grub_uint32_t offset
;
456 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
459 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
463 len
= (int)file
->size
;
465 data
= (char *)grub_malloc(file
->size
);
471 grub_file_read(file
, data
, file
->size
);
472 grub_file_close(file
);
474 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
475 grub_script_execute_sourcecode(exec
);
477 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
478 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
479 grub_file_close(file
);
481 grub_script_execute_sourcecode("loopback -d efiboot");
485 *direntoff
= offset
+ 2;
490 static int ventoy_set_check_result(int ret
, const char *msg
)
494 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
495 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
496 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
501 grub_printf(VTOY_WARNING
"\n");
502 grub_printf(VTOY_WARNING
"\n");
503 grub_printf(VTOY_WARNING
"\n\n\n");
505 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
506 grub_printf("Error message: <%s>\n\n", msg
);
507 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
514 static int ventoy_check_official_device(grub_device_t dev
)
518 grub_uint64_t offset
;
521 grub_uint8_t mbr
[512];
525 struct grub_partition
*partition
;
527 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
529 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
532 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
533 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
534 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
536 #ifndef GRUB_MACHINE_EFI
537 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
539 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
541 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
543 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
545 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
547 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
556 /* We must have partition 2 */
559 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
563 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
567 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
570 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
572 grub_file_close(file
);
573 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
576 partition
= dev
->disk
->partition
;
577 if (partition
->number
!= 0 || partition
->start
!= 2048)
579 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
584 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
586 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
587 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
588 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
590 grub_file_close(file
);
591 return ventoy_set_check_result(6, "Disk partition layout check failed.");
596 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
597 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
598 PartTbl
[1].SectorCount
!= 65536)
600 grub_file_close(file
);
601 return ventoy_set_check_result(6, "Disk partition layout check failed.");
607 offset
= partition
->start
+ partition
->len
;
608 partition
= file
->device
->disk
->partition
;
609 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
611 grub_file_close(file
);
612 return ventoy_set_check_result(7, "Disk partition layout check failed.");
616 grub_file_close(file
);
620 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
621 dev2
= grub_device_open(devname
);
624 return ventoy_set_check_result(8, "Disk open failed");
627 fs
= grub_fs_probe(dev2
);
630 grub_device_close(dev2
);
631 return ventoy_set_check_result(9, "FS probe failed");
634 fs
->fs_label(dev2
, &label
);
635 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
637 grub_device_close(dev2
);
638 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
641 grub_device_close(dev2
);
645 disk
= grub_disk_open(dev
->disk
->name
);
648 return ventoy_set_check_result(11, "Disk open failed");
651 grub_memset(mbr
, 0, 512);
652 grub_disk_read(disk
, 0, 0, 512, mbr
);
653 grub_disk_close(disk
);
655 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
657 return ventoy_set_check_result(12, "MBR check failed");
660 return ventoy_set_check_result(0, NULL
);
663 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
667 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
677 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
679 grub_uint64_t size
= 0;
682 char fullpath
[256] = {0};
685 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
688 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
691 debug("grub_file_open failed <%s>\n", fullpath
);
697 grub_file_close(file
);
701 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
705 char fullpath
[512] = {0};
708 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
711 file
= grub_file_open(fullpath
, type
);
714 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
721 int ventoy_is_dir_exist(const char *fmt
, ...)
728 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
732 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
735 grub_strncpy(pos
+ len
, "\" ]", 3);
737 debug("script exec %s\n", buf
);
739 if (0 == grub_script_execute_sourcecode(buf
))
747 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
750 grub_uint8_t
*outbuf
;
751 grub_uint8_t gzHdr
[10] =
753 0x1F, 0x8B, /* magic */
761 grub_memset(&s
, 0, sizeof(mz_stream
));
763 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
765 outbuf
= (grub_uint8_t
*)mem_out
;
767 mem_out_len
-= sizeof(gzHdr
) + 8;
768 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
769 outbuf
+= sizeof(gzHdr
);
771 s
.avail_in
= mem_in_len
;
774 s
.avail_out
= mem_out_len
;
777 mz_deflate(&s
, MZ_FINISH
);
781 outbuf
+= s
.total_out
;
782 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
783 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
785 return s
.total_out
+ sizeof(gzHdr
) + 8;
793 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
797 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
800 if (0 == grub_strcmp(args
[0], "on"))
803 grub_env_set("vtdebug_flag", "debug");
808 grub_env_set("vtdebug_flag", "");
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
814 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
818 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
820 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
821 grub_printf(" level:\r\n");
822 grub_printf(" 01/11: busybox / (+cat log)\r\n");
823 grub_printf(" 02/12: initrd / (+cat log)\r\n");
824 grub_printf(" 03/13: hook / (+cat log)\r\n");
826 grub_printf(" debug:\r\n");
827 grub_printf(" 0: debug is off\r\n");
828 grub_printf(" 1: debug is on\r\n");
830 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
833 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
835 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
837 g_ventoy_debug_level
= 1;
840 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
843 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
852 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
855 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
887 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
903 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
919 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
924 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
926 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
929 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
934 value_long
+= grub_strtol(args
[1], NULL
, 10);
936 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
937 grub_env_set(args
[0], buf
);
939 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
942 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
944 ulonglong value1
= 0;
945 ulonglong value2
= 0;
950 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
953 value1
= grub_strtoull(args
[0], NULL
, 10);
954 value2
= grub_strtoull(args
[1], NULL
, 10);
956 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
957 grub_env_set(args
[2], buf
);
959 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
962 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
977 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
980 debug("failed to open file <%s> for udf check\n", args
[0]);
984 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
986 grub_env_set(args
[1], buf
);
988 grub_file_close(file
);
994 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1002 g_wimboot_enable
= 0;
1004 grub_check_free(g_wimiso_path
);
1005 grub_check_free(g_wimiso_chunk_list
.chunk
);
1007 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1013 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1014 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1015 if (NULL
== g_wimiso_chunk_list
.chunk
)
1017 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1020 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1021 g_wimiso_chunk_list
.cur_chunk
= 0;
1023 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1025 g_wimboot_enable
= 1;
1026 g_wimiso_path
= grub_strdup(args
[0]);
1027 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1028 grub_file_close(file
);
1033 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1041 ventoy_iso9660_override
*dirent
;
1050 totlen
= sizeof(ventoy_chain_head
);
1052 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1054 debug("failed to load efiboot template %d\n", len
);
1060 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1062 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1065 debug("failed to open file <%s>\n", args
[0]);
1069 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1074 totlen
+= ventoy_align_2k(file
->size
);
1076 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1077 dirent
->first_sector
= len
/ 2048;
1078 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1079 dirent
->size
= (grub_uint32_t
)file
->size
;
1080 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1082 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1084 #ifdef GRUB_MACHINE_EFI
1085 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1087 data
= (char *)grub_malloc(totlen
);
1090 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1092 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1093 grub_check_free(buf
);
1095 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1096 grub_file_close(file
);
1098 ventoy_memfile_env_set(args
[1], data
, (ulonglong
)totlen
);
1103 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1109 g_vtoy_load_prompt
= 0;
1110 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1112 if (argc
== 2 && args
[0][0] == '1')
1114 g_vtoy_load_prompt
= 1;
1115 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1118 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1121 int ventoy_need_prompt_load_file(void)
1123 return g_vtoy_load_prompt
;
1126 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1128 grub_uint64_t ro
= 0;
1129 grub_uint64_t div
= 0;
1130 grub_ssize_t left
= size
;
1131 char *cur
= (char *)buf
;
1133 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1136 while (left
>= VTOY_SIZE_2MB
)
1138 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1139 cur
+= VTOY_SIZE_2MB
;
1140 left
-= VTOY_SIZE_2MB
;
1142 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1147 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1153 grub_file_read(file
, cur
, left
);
1156 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1162 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1167 enum grub_file_type type
;
1178 if (grub_strcmp(args
[0], "nodecompress") == 0)
1180 type
= VENTOY_FILE_TYPE
;
1184 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1187 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1190 debug("failed to open file <%s>\n", args
[1]);
1194 #ifdef GRUB_MACHINE_EFI
1195 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1197 buf
= (char *)grub_malloc(file
->size
);
1202 grub_file_close(file
);
1206 if (g_vtoy_load_prompt
)
1208 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1212 grub_file_read(file
, buf
, file
->size
);
1215 ventoy_memfile_env_set(args
[2], buf
, (ulonglong
)(file
->size
));
1217 grub_file_close(file
);
1223 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1239 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1242 debug("failed to open file <%s> for udf check\n", args
[0]);
1246 headlen
= sizeof(ventoy_chain_head
);
1248 #ifdef GRUB_MACHINE_EFI
1249 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1251 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1254 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1256 grub_file_read(file
, buf
+ headlen
, file
->size
);
1258 ventoy_memfile_env_set(args
[1], buf
, (ulonglong
)(file
->size
));
1260 grub_file_close(file
);
1266 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1272 if (grub_iso9660_is_joliet())
1274 debug("This time has joliet process\n");
1283 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1292 if (args
[0][0] == '1')
1294 grub_iso9660_set_nojoliet(1);
1298 grub_iso9660_set_nojoliet(0);
1304 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1309 grub_uint8_t buf
[32];
1320 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1323 debug("failed to open file <%s> for udf check\n", args
[0]);
1327 for (i
= 16; i
< 32; i
++)
1329 grub_file_seek(file
, i
* 2048);
1330 grub_file_read(file
, buf
, sizeof(buf
));
1338 grub_file_seek(file
, i
* 2048);
1339 grub_file_read(file
, buf
, sizeof(buf
));
1341 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1344 grub_file_seek(file
, i
* 2048);
1345 grub_file_read(file
, buf
, sizeof(buf
));
1347 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1348 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1354 grub_file_close(file
);
1356 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1361 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1363 long value_long1
= 0;
1364 long value_long2
= 0;
1366 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1368 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1371 value_long1
= grub_strtol(args
[0], NULL
, 10);
1372 value_long2
= grub_strtol(args
[2], NULL
, 10);
1374 if (0 == grub_strcmp(args
[1], "eq"))
1376 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1378 else if (0 == grub_strcmp(args
[1], "ne"))
1380 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1382 else if (0 == grub_strcmp(args
[1], "gt"))
1384 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1386 else if (0 == grub_strcmp(args
[1], "lt"))
1388 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1390 else if (0 == grub_strcmp(args
[1], "ge"))
1392 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1394 else if (0 == grub_strcmp(args
[1], "le"))
1396 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1400 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1406 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1409 char buf
[128] = {0};
1413 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1416 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1417 pos
= grub_strstr(buf
, ",");
1423 grub_env_set(args
[1], buf
);
1425 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1428 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1434 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1440 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1443 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1445 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1446 if (0 == grub_script_execute_sourcecode(buf
))
1448 debug("file %s exist, ventoy_compatible YES\n", buf
);
1449 grub_env_set("ventoy_compatible", "YES");
1450 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1454 debug("file %s NOT exist\n", buf
);
1458 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1459 pos
= grub_strstr(buf
, ")");
1465 disk
= grub_disk_open(buf
);
1468 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1469 grub_disk_close(disk
);
1471 g_img_swap_tmp_buf
[703] = 0;
1472 for (i
= 318; i
< 703; i
++)
1474 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1475 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1477 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1478 grub_env_set("ventoy_compatible", "YES");
1479 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1485 debug("failed to open disk <%s>\n", buf
);
1488 grub_env_set("ventoy_compatible", "NO");
1489 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1492 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1498 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1500 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1503 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1508 if (0 == g_sort_case_sensitive
)
1510 if (grub_islower(c1
))
1512 c1
= c1
- 'a' + 'A';
1515 if (grub_islower(c2
))
1517 c2
= c2
- 'a' + 'A';
1530 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1536 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1538 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1541 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1546 if (0 == g_sort_case_sensitive
)
1548 if (grub_islower(c1
))
1550 c1
= c1
- 'a' + 'A';
1553 if (grub_islower(c2
))
1555 c2
= c2
- 'a' + 'A';
1568 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1570 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1572 grub_memcpy(img1
, img2
, sizeof(img_info
));
1573 img1
->next
= g_img_swap_tmp
.next
;
1574 img1
->prev
= g_img_swap_tmp
.prev
;
1576 g_img_swap_tmp
.next
= img2
->next
;
1577 g_img_swap_tmp
.prev
= img2
->prev
;
1578 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1581 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1585 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1593 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1595 ventoy_vlnk_part
*node
= NULL
;
1596 grub_uint32_t SelfSig
;
1597 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1599 /* skip Ventoy partition 1/2 */
1600 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1601 if (partition
->number
< 2 && SelfSig
== *pSig
)
1606 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1609 node
->disksig
= *pSig
;
1610 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1611 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1612 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1614 node
->next
= g_vlnk_part_list
;
1615 g_vlnk_part_list
= node
;
1621 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1628 disk
= grub_disk_open(name
);
1631 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1632 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1633 grub_disk_close(disk
);
1639 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1641 const char *fs
[ventoy_fs_max
+ 1] =
1643 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1648 cur
->dev
= grub_device_open(cur
->device
);
1653 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1659 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1664 char *disk
, *device
;
1665 grub_uint32_t readcrc
, calccrc
;
1666 ventoy_vlnk_part
*cur
;
1667 grub_fs_t fs
= NULL
;
1669 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1673 grub_printf("VLNK invalid guid\n");
1679 readcrc
= vlnk
->crc32
;
1681 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1682 if (readcrc
!= calccrc
)
1686 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1692 if (!g_vlnk_part_list
)
1694 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1697 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1699 if (cur
->disksig
== vlnk
->disk_signature
)
1703 if (cur
->partoffset
== vlnk
->part_offset
)
1706 device
= cur
->device
;
1708 if (cur
->probe
== 0)
1711 ventoy_vlnk_probe_fs(cur
);
1721 struct grub_file file
;
1723 grub_memset(&file
, 0, sizeof(file
));
1724 file
.device
= cur
->dev
;
1725 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1728 cur
->fs
->fs_close(&file
);
1729 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1738 grub_printf("\n==== VLNK Information ====\n"
1739 "Disk Signature: %08x\n"
1740 "Partition Offset: %llu\n"
1741 "File Path: <%s>\n\n",
1742 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1746 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1750 grub_printf("Disk Find: [ NO ]\n");
1755 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1759 grub_printf("Part Find: [ NO ]\n");
1761 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1764 grub_printf("VLNK File: <%s>\n", dst
);
1771 return (1 - filefind
);
1774 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1779 grub_file_t file
= NULL
;
1784 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1786 else if (dir
[0] == '/')
1788 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1792 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1795 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1801 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1802 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1803 grub_file_close(file
);
1805 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1807 rc
= grub_file_add_vlnk(src
, dst
);
1813 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1823 const menu_tip
*tip
;
1824 img_iterator_node
*tmp
;
1825 img_iterator_node
*new_node
;
1826 img_iterator_node
*node
= (img_iterator_node
*)data
;
1828 if (g_enumerate_time_checked
== 0)
1830 g_enumerate_finish_time_ms
= grub_get_time_ms();
1831 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1834 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1836 g_enumerate_time_checked
= 1;
1840 len
= grub_strlen(filename
);
1844 if (node
->level
+ 1 > g_img_max_search_level
)
1849 if ((len
== 1 && filename
[0] == '.') ||
1850 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1855 if (!ventoy_img_name_valid(filename
, len
))
1860 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1865 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1867 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1868 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1871 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1876 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1879 new_node
->level
= node
->level
+ 1;
1880 new_node
->plugin_list_index
= index
;
1881 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1883 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1886 debug("Directory %s ignored...\n", new_node
->dir
);
1887 grub_free(new_node
);
1891 new_node
->tail
= node
->tail
;
1893 new_node
->parent
= node
;
1894 if (!node
->firstchild
)
1896 node
->firstchild
= new_node
;
1899 if (g_img_iterator_tail
)
1901 g_img_iterator_tail
->next
= new_node
;
1902 g_img_iterator_tail
= new_node
;
1906 g_img_iterator_head
.next
= new_node
;
1907 g_img_iterator_tail
= new_node
;
1913 debug("Find a file %s\n", filename
);
1919 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1921 type
= img_type_iso
;
1923 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1925 type
= img_type_wim
;
1927 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1928 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1930 type
= img_type_vhd
;
1932 #ifdef GRUB_MACHINE_EFI
1933 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1935 type
= img_type_efi
;
1938 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1940 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1942 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1943 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1948 type
= img_type_img
;
1950 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1952 type
= img_type_vtoy
;
1954 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1956 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1958 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1959 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1968 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1973 if (g_plugin_image_list
)
1975 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1976 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1977 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1979 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1982 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1984 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1989 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
1991 if (grub_file_is_vlnk_suffix(filename
, len
))
1994 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2001 img
= grub_zalloc(sizeof(img_info
));
2005 img
->plugin_list_index
= index
;
2006 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2008 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2010 img
->size
= info
->size
;
2011 if (vlnk
|| 0 == img
->size
)
2013 if (node
->dir
[0] == '/')
2015 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2019 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2023 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2025 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2030 if (g_ventoy_img_list
)
2032 tail
= *(node
->tail
);
2038 g_ventoy_img_list
= img
;
2041 img
->id
= g_ventoy_img_count
;
2043 if (node
&& NULL
== node
->firstiso
)
2045 node
->firstiso
= img
;
2056 *((img_info
**)(node
->tail
)) = img
;
2057 g_ventoy_img_count
++;
2059 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2061 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2064 img
->tip1
= tip
->tip1
;
2065 img
->tip2
= tip
->tip2
;
2068 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2071 img
->class = g_menu_class
[type
];
2073 img
->menu_prefix
= g_menu_prefix
[type
];
2075 if (img_type_iso
== type
)
2077 if (ventoy_plugin_check_memdisk(img
->path
))
2079 img
->menu_prefix
= "miso";
2082 else if (img_type_img
== type
)
2084 if (ventoy_plugin_check_memdisk(img
->path
))
2086 img
->menu_prefix
= "mimg";
2090 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2097 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2099 int len
= GRUB_UINT_MAX
;
2100 const char *value
= NULL
;
2101 char name
[32] = {0};
2102 char plat
[32] = {0};
2103 char guidstr
[32] = {0};
2104 ventoy_guid guid
= VENTOY_GUID
;
2105 const char *fmt1
= NULL
;
2106 const char *fmt2
= NULL
;
2107 const char *fmt3
= NULL
;
2108 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2109 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2110 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2111 const char fmtcode
[]={
2112 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2113 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2114 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2115 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2116 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2117 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2120 grub_memset(name
, 0, sizeof(name
));
2121 puint
[0] = grub_swap_bytes32(0x56454e54);
2122 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2123 puint
[2] = grub_swap_bytes32(0x45525349);
2124 puint
[1] = grub_swap_bytes32(0x4f595f56);
2125 value
= ventoy_get_env(name
);
2127 grub_memset(name
, 0, sizeof(name
));
2128 puint
[1] = grub_swap_bytes32(0x5f544f50);
2129 puint
[0] = grub_swap_bytes32(0x56544c45);
2130 fmt1
= ventoy_get_env(name
);
2136 grub_memset(name
, 0, sizeof(name
));
2137 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2138 puint
[0] = grub_swap_bytes32(0x56544c45);
2139 fmt2
= ventoy_get_env(name
);
2141 grub_memset(name
, 0, sizeof(name
));
2142 puint
[1] = grub_swap_bytes32(0x5f434c52);
2143 puint
[0] = grub_swap_bytes32(0x56544c45);
2144 fmt3
= ventoy_get_env(name
);
2146 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2148 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2150 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2151 #pragma GCC diagnostic push
2152 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2153 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2154 fmt1
? fmt1
: fmtdata
,
2155 fmt2
? fmt2
: fmtdata
+ 4,
2156 value
? value
: "", plat
, guidstr
,
2157 fmt3
? fmt3
: fmtdata
+ 6);
2158 #pragma GCC diagnostic pop
2160 grub_memset(name
, 0, sizeof(name
));
2161 puint
[0] = grub_swap_bytes32(0x76746f79);
2162 puint
[2] = grub_swap_bytes32(0x656e7365);
2163 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2164 ventoy_set_env(name
, guidstr
);
2170 ventoy_password_get (char buf
[], unsigned buf_size
)
2172 unsigned i
, cur_len
= 0;
2174 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2178 key
= grub_getkey ();
2179 if (key
== '\n' || key
== '\r')
2182 if (key
== GRUB_TERM_ESC
)
2192 grub_term_restore_pos (pos
);
2193 for (i
= 0; i
< cur_len
; i
++)
2195 grub_term_restore_pos (pos
);
2197 for (i
= 0; i
< cur_len
; i
++)
2204 if (!grub_isprint (key
))
2207 if (cur_len
+ 2 < buf_size
)
2208 buf
[cur_len
++] = key
;
2213 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2219 return (key
!= GRUB_TERM_ESC
);
2222 static int ventoy_get_password(char buf
[], unsigned buf_size
)
2224 const char *env
= NULL
;
2226 env
= grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2227 if (env
&& env
[0] == '0' && env
[1] == 0)
2229 return grub_password_get(buf
, buf_size
);
2233 return ventoy_password_get(buf
, buf_size
);
2237 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2241 grub_uint8_t md5
[16];
2245 grub_memset(input
, 0, sizeof(input
));
2247 grub_printf("Enter password: ");
2250 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2252 ventoy_get_password(input
, 128);
2253 if (grub_strcmp(pwd
->text
, input
) == 0)
2258 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2260 ventoy_get_password(input
, 128);
2261 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2262 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2267 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2269 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2270 ventoy_get_password(input
+ offset
, 128);
2272 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2273 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2279 grub_printf("Invalid password!\n\n");
2286 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2288 img_info
*minimg
= NULL
;
2289 img_info
*img
= (img_info
*)(node
->firstiso
);
2291 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2293 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2308 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2310 img_iterator_node
*Minchild
= NULL
;
2311 img_iterator_node
*child
= node
->firstchild
;
2313 while (child
&& child
->parent
== node
)
2315 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2319 child
= child
->next
;
2324 Minchild
->select
= 1;
2330 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2333 img_info
*img
= NULL
;
2334 const char *dir_class
= NULL
;
2335 const char *dir_alias
= NULL
;
2336 img_iterator_node
*child
= NULL
;
2337 const menu_tip
*tip
= NULL
;
2339 if (node
->isocnt
== 0 || node
->done
== 1)
2344 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2346 offset
= node
->parent
->dirlen
;
2349 if (node
== &g_img_iterator_head
)
2351 if (g_default_menu_mode
== 0)
2353 if (g_tree_view_menu_style
== 0)
2355 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2356 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2357 " echo 'return ...' \n"
2358 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2362 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2363 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2364 " echo 'return ...' \n"
2365 "}\n", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2369 g_tree_script_pre
= g_tree_script_pos
;
2373 node
->dir
[node
->dirlen
- 1] = 0;
2374 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2377 dir_class
= "vtoydir";
2380 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2382 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2385 if (g_tree_view_menu_style
== 0)
2387 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2388 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2389 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2393 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2394 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2395 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2400 dir_alias
= node
->dir
+ offset
;
2402 if (g_tree_view_menu_style
== 0)
2404 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2405 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2406 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2410 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2411 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2412 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2416 if (g_tree_view_menu_style
== 0)
2418 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2419 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2420 " echo 'return ...' \n"
2421 "}\n", "<--", node
->dir
);
2425 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2426 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2427 " echo 'return ...' \n"
2432 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2434 ventoy_dynamic_tree_menu(child
);
2437 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2439 if (g_tree_view_menu_style
== 0)
2441 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2442 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2445 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2446 img
->unsupport
? "[***********] " : "",
2447 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2449 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2453 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2454 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2457 img
->unsupport
? "[***********] " : "",
2458 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2460 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2464 if (node
!= &g_img_iterator_head
)
2466 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2473 static int ventoy_set_default_menu(void)
2479 const char *strdata
= NULL
;
2480 img_info
*cur
= NULL
;
2481 img_info
*default_node
= NULL
;
2482 const char *default_image
= NULL
;
2484 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2485 if (default_image
&& default_image
[0] == '/')
2487 img_len
= grub_strlen(default_image
);
2489 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2491 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2503 if (0 == g_default_menu_mode
)
2505 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2509 def
= grub_strdup(default_image
);
2515 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2517 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2518 if (strdata
&& strdata
[0] == '/')
2520 pos
= def
+ grub_strlen(strdata
);
2531 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2534 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2538 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2546 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2548 img_info
*next
= NULL
;
2549 img_info
*cur
= g_ventoy_img_list
;
2562 g_ventoy_img_list
= NULL
;
2563 g_ventoy_img_count
= 0;
2565 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2568 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2571 img_info
*cur
= g_ventoy_img_list
;
2575 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2577 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2580 img_id
= grub_strtol(args
[0], NULL
, 10);
2581 if (img_id
>= g_ventoy_img_count
)
2583 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2586 debug("Find image %ld name \n", img_id
);
2588 while (cur
&& img_id
> 0)
2596 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2599 debug("image name is %s\n", cur
->name
);
2601 grub_env_set(args
[1], cur
->name
);
2603 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2606 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2610 img_info
*cur
= g_ventoy_img_list
;
2616 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2619 len
= (int)grub_strlen(args
[0]);
2623 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2632 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2635 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2636 grub_env_set("chosen", id
);
2637 grub_env_export("chosen");
2639 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2642 static char g_fake_vlnk_src
[512];
2643 static char g_fake_vlnk_dst
[512];
2644 static grub_uint64_t g_fake_vlnk_size
;
2645 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2651 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2653 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2654 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2656 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2658 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2661 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2667 g_fake_vlnk_src
[0] = 0;
2668 g_fake_vlnk_dst
[0] = 0;
2669 g_fake_vlnk_size
= 0;
2670 grub_file_vtoy_vlnk(NULL
, NULL
);
2672 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2676 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2681 const char *id
= NULL
;
2682 img_info
*cur
= NULL
;
2686 if (argc
< 1 || argc
> 3)
2688 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2691 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2693 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2694 grub_env_set(args
[0], pos
);
2697 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2698 grub_env_set(args
[1], value
);
2703 for (last
= pos
; *pos
; pos
++)
2710 grub_env_set(args
[2], last
+ 1);
2716 id
= grub_env_get("chosen");
2718 pos
= grub_strstr(id
, "VID_");
2721 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2725 cur
= g_ventoy_img_list
;
2730 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2733 grub_env_set(args
[0], cur
->path
);
2737 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2738 grub_env_set(args
[1], value
);
2743 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2744 grub_env_set(args
[2], cur
->name
);
2748 g_svd_replace_offset
= 0;
2750 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2754 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2758 grub_device_t dev
= NULL
;
2759 img_info
*cur
= NULL
;
2760 img_info
*tail
= NULL
;
2761 img_info
*min
= NULL
;
2762 img_info
*head
= NULL
;
2763 const char *strdata
= NULL
;
2764 char *device_name
= NULL
;
2766 img_iterator_node
*node
= NULL
;
2767 img_iterator_node
*tmp
= NULL
;
2773 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2776 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2778 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2783 g_enumerate_time_checked
= 0;
2784 g_enumerate_start_time_ms
= grub_get_time_ms();
2786 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2787 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2789 g_filt_dot_underscore_file
= 1;
2792 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2793 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2795 g_sort_case_sensitive
= 1;
2798 device_name
= grub_file_get_device_name(args
[0]);
2804 g_enum_dev
= dev
= grub_device_open(device_name
);
2810 g_enum_fs
= fs
= grub_fs_probe(dev
);
2816 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2818 debug("unsupported fs:<%s>\n", fs
->name
);
2819 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2823 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2825 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2826 if (strdata
&& strdata
[0] == '1')
2828 g_default_menu_mode
= 1;
2831 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2833 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2835 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2836 if (strdata
&& strdata
[0] == '/')
2838 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2839 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2841 g_img_iterator_head
.dir
[len
++] = '/';
2843 g_img_iterator_head
.dirlen
= len
;
2847 g_img_iterator_head
.dirlen
= 1;
2848 grub_strcpy(g_img_iterator_head
.dir
, "/");
2851 g_img_iterator_head
.tail
= &tail
;
2853 if (g_img_max_search_level
< 0)
2855 g_img_max_search_level
= GRUB_INT_MAX
;
2856 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2857 if (strdata
&& ventoy_is_decimal(strdata
))
2859 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2863 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2864 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2865 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2866 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2867 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2868 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2870 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2872 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2875 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2876 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2878 g_tree_view_menu_style
= 1;
2881 ventoy_set_default_menu();
2883 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2885 ventoy_dynamic_tree_menu(node
);
2889 node
= g_img_iterator_head
.next
;
2897 /* sort image list by image name */
2898 while (g_ventoy_img_list
)
2900 min
= g_ventoy_img_list
;
2901 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2903 if (ventoy_cmp_img(min
, cur
) > 0)
2911 min
->prev
->next
= min
->next
;
2916 min
->next
->prev
= min
->prev
;
2919 if (min
== g_ventoy_img_list
)
2921 g_ventoy_img_list
= min
->next
;
2939 g_ventoy_img_list
= head
;
2941 if (g_default_menu_mode
== 1)
2943 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2944 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2945 " echo 'return ...' \n"
2946 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_TREEVIEW"));
2949 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2951 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2952 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2955 cur
->unsupport
? "[***********] " : "",
2956 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2958 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2961 g_tree_script_buf
[g_tree_script_pos
] = 0;
2962 g_list_script_buf
[g_list_script_pos
] = 0;
2964 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2965 grub_env_set(args
[1], buf
);
2969 check_free(device_name
, grub_free
);
2970 check_free(dev
, grub_device_close
);
2972 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2975 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2982 device_name
= grub_file_get_device_name(filename
);
2994 pos2
= grub_strstr(pos
, ",");
2997 pos2
= grub_strstr(pos
, ")");
3005 disk
= grub_disk_open(pos
);
3008 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3009 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3010 grub_disk_close(disk
);
3017 grub_free(device_name
);
3021 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3023 eltorito_descriptor desc
;
3025 grub_memset(&desc
, 0, sizeof(desc
));
3026 grub_file_seek(file
, 17 * 2048);
3027 grub_file_read(file
, &desc
, sizeof(desc
));
3029 if (desc
.type
!= 0 || desc
.version
!= 1)
3034 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3035 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3043 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3045 grub_uint8_t buf
[512];
3047 grub_file_seek(file
, sector
* 2048);
3048 grub_file_read(file
, buf
, sizeof(buf
));
3050 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3051 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3053 return *((grub_uint32_t
*)(buf
+ 40));
3059 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3063 grub_uint8_t buf
[512];
3064 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3066 grub_file_seek(file
, sector
* 2048);
3067 grub_file_read(file
, buf
, sizeof(buf
));
3069 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3071 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3075 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3080 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3082 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3084 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3088 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3090 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3095 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3097 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3099 if (buf
[36] == parttype
[i
])
3101 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3107 debug("%s does not contain efi eltorito\n", file
->name
);
3111 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3114 const char *fs
= NULL
;
3115 const char *val
= NULL
;
3116 const char *cdprompt
= NULL
;
3118 grub_uint8_t chksum
= 0;
3121 disk
= file
->device
->disk
;
3122 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3124 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3125 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3126 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3128 pos
= grub_strstr(file
->name
, "/");
3134 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3136 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3138 param
->vtoy_img_size
= file
->size
;
3140 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3141 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3143 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3145 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3146 param
->vtoy_reserved
[4] = 0;
3147 if (g_ventoy_chain_type
== 1) /* Windows */
3149 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3150 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3152 param
->vtoy_reserved
[4] = 1;
3156 fs
= ventoy_get_env("ventoy_fs_probe");
3157 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3159 param
->vtoy_reserved
[3] = 1;
3162 param
->vtoy_reserved
[5] = 0;
3163 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3164 if (val
&& val
[0] == '1' && val
[1] == 0)
3166 param
->vtoy_reserved
[5] = 1;
3169 /* ventoy_disk_signature used for vlnk */
3170 param
->vtoy_reserved
[6] = file
->vlnk
;
3171 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3173 /* calculate checksum */
3174 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3176 chksum
+= *((grub_uint8_t
*)param
+ i
);
3178 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3183 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3185 grub_uint32_t i
= 0;
3186 grub_uint64_t total
= 0;
3187 grub_uint64_t fileblk
= 0;
3188 ventoy_img_chunk
*chunk
= NULL
;
3190 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3192 chunk
= chunklist
->chunk
+ i
;
3194 if (chunk
->disk_start_sector
<= start
)
3196 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3200 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3203 fileblk
= (file
->size
+ 511) / 512;
3205 if (total
!= fileblk
)
3207 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3208 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3210 debug("maybe img file to be processed.\n");
3220 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3224 grub_uint32_t i
= 0;
3225 grub_uint32_t sector
= 0;
3226 grub_uint32_t count
= 0;
3227 grub_off_t size
= 0;
3228 grub_off_t read
= 0;
3230 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3231 if (fs_type
== ventoy_fs_exfat
)
3233 grub_fat_get_file_chunk(start
, file
, chunklist
);
3235 else if (fs_type
== ventoy_fs_ext
)
3237 grub_ext_get_file_chunk(start
, file
, chunklist
);
3241 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3242 file
->read_hook_data
= chunklist
;
3244 for (size
= file
->size
; size
> 0; size
-= read
)
3246 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3247 grub_file_read(file
, NULL
, read
);
3250 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3252 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3253 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3256 if (ventoy_fs_udf
== fs_type
)
3258 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3260 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3261 chunklist
->chunk
[i
].img_start_sector
= sector
;
3262 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3268 len
= (int)grub_strlen(file
->name
);
3269 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3270 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3271 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3272 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3274 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3276 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3286 chunklist
->chunk
[i
].img_start_sector
= sector
;
3287 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3295 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3299 grub_disk_addr_t start
;
3304 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3307 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3310 g_conf_replace_count
= 0;
3311 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3312 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3314 if (g_img_chunk_list
.chunk
)
3316 grub_free(g_img_chunk_list
.chunk
);
3319 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3321 grub_file_close(file
);
3322 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3325 /* get image chunk data */
3326 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3327 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3328 if (NULL
== g_img_chunk_list
.chunk
)
3330 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3333 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3334 g_img_chunk_list
.cur_chunk
= 0;
3336 start
= file
->device
->disk
->partition
->start
;
3338 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3340 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3341 grub_file_close(file
);
3345 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3348 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3349 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3350 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3353 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3357 grub_uint64_t offset
= 0;
3358 grub_uint32_t align
= 0;
3359 grub_file_t file
= NULL
;
3360 conf_replace
*node
= NULL
;
3361 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3362 ventoy_grub_param_file_replace
*replace
= NULL
;
3368 debug("select conf replace argc:%d\n", argc
);
3375 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3378 debug("Conf replace not found for %s\n", args
[1]);
3382 debug("Find %d conf replace for %s\n", n
, args
[1]);
3384 g_conf_replace_count
= n
;
3385 for (i
= 0; i
< n
; i
++)
3389 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3392 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3393 grub_file_close(file
);
3395 else if (node
->img
> 0)
3401 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3405 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3408 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3412 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3414 if (align
> vtoy_max_replace_file_size
)
3416 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3417 grub_file_close(file
);
3421 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3422 grub_file_close(file
);
3423 g_conf_replace_new_len
[i
] = (int)file
->size
;
3424 g_conf_replace_new_len_align
[i
] = align
;
3426 g_conf_replace_node
[i
] = node
;
3427 g_conf_replace_offset
[i
] = offset
+ 2;
3431 replace
= &(g_grub_param
->img_replace
[i
]);
3432 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3433 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3434 replace
->old_name_cnt
++;
3437 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3441 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3444 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3449 const char *ch
= var
;
3456 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3463 debug("Invalid variable letter <%c>\n", *ch
);
3470 debug("Invalid variable length:%d <%s>\n", n
, var
);
3474 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3483 grub_printf("\n=================== Variables Expansion ===================\n\n");
3486 grub_printf("<%s>: ", var
);
3489 while (i
< (len
- 1))
3492 if ((c
== '\n') || (c
== '\r'))
3502 else if (grub_isprint(c
))
3504 if (i
+ 1 < (len
- 1))
3506 grub_printf("%c", c
);
3516 expand
[i
- 1] = ' ';
3517 grub_printf("\r<%s>: %s", var
, expand
);
3520 grub_printf("\r<%s>: %s", var
, expand
);
3532 grub_snprintf(expand
, len
, "$$%s$$", var
);
3538 static int ventoy_auto_install_var_expand(install_template
*node
)
3546 char *newbuf
= NULL
;
3547 char *curline
= NULL
;
3548 char *nextline
= NULL
;
3549 grub_uint8_t
*code
= NULL
;
3551 var_node
*CurNode
= NULL
;
3552 var_node
*pVarList
= NULL
;
3554 code
= (grub_uint8_t
*)node
->filebuf
;
3556 if (node
->filelen
>= VTOY_SIZE_1MB
)
3558 debug("auto install script too long %d\n", node
->filelen
);
3562 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3564 debug("UCS-2 encoding NOT supported\n");
3568 start
= grub_strstr(node
->filebuf
, "$$");
3571 debug("no need to expand variable, no start.\n");
3575 end
= grub_strstr(start
+ 2, "$$");
3578 debug("no need to expand variable, no end.\n");
3582 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3583 newbuf
= grub_malloc(newlen
);
3586 debug("Failed to alloc newbuf %d\n", newlen
);
3590 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3592 nextline
= ventoy_get_line(curline
);
3594 start
= grub_strstr(curline
, "$$");
3597 end
= grub_strstr(start
+ 2, "$$");
3603 VTOY_APPEND_NEWBUF(curline
);
3605 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3607 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3609 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3616 value
[sizeof(value
) - 1] = 0;
3617 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3621 CurNode
= grub_zalloc(sizeof(var_node
));
3624 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3625 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3626 CurNode
->next
= pVarList
;
3632 VTOY_APPEND_NEWBUF(value
);
3634 VTOY_APPEND_NEWBUF(end
+ 2);
3638 VTOY_APPEND_NEWBUF(curline
);
3641 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3643 newbuf
[pos
- 1] = '\n';
3647 newbuf
[pos
++] = '\n';
3651 grub_free(node
->filebuf
);
3652 node
->filebuf
= newbuf
;
3653 node
->filelen
= pos
;
3657 CurNode
= pVarList
->next
;
3658 grub_free(pVarList
);
3665 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3671 grub_file_t file
= NULL
;
3672 char configfile
[128];
3673 install_template
*node
= NULL
;
3679 debug("select auto installation argc:%d\n", argc
);
3686 node
= ventoy_plugin_find_install_template(args
[0]);
3689 debug("Auto install template not found for %s\n", args
[0]);
3693 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3695 defidx
= node
->autosel
;
3696 if (node
->timeout
< 0)
3698 node
->cursel
= node
->autosel
- 1;
3699 debug("Auto install template auto select %d\n", node
->autosel
);
3704 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3710 if (node
->timeout
> 0)
3712 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3715 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3716 " echo %s\n}\n", "");
3718 for (i
= 0; i
< node
->templatenum
; i
++)
3720 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3722 ventoy_get_vmenu_title("VTLANG_AUTOINS_USE"),
3723 node
->templatepath
[i
].path
);
3726 g_ventoy_menu_esc
= 1;
3727 g_ventoy_suppress_esc
= 1;
3728 g_ventoy_suppress_esc_default
= defidx
;
3730 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3731 grub_script_execute_sourcecode(configfile
);
3733 g_ventoy_menu_esc
= 0;
3734 g_ventoy_suppress_esc
= 0;
3735 g_ventoy_suppress_esc_default
= 1;
3739 node
->cursel
= g_ventoy_last_entry
- 1;
3742 grub_check_free(node
->filebuf
);
3745 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3747 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3748 node
->templatepath
[node
->cursel
].path
);
3751 node
->filebuf
= grub_malloc(file
->size
+ 8);
3754 grub_file_read(file
, node
->filebuf
, file
->size
);
3755 grub_file_close(file
);
3757 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3758 node
->filelen
= (int)file
->size
;
3760 ventoy_auto_install_var_expand(node
);
3765 debug("Failed to open auto install script <%s%s>\n",
3766 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3770 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3773 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3779 char configfile
[128];
3780 persistence_config
*node
;
3786 debug("select persistence argc:%d\n", argc
);
3793 node
= ventoy_plugin_find_persistent(args
[0]);
3796 debug("Persistence image not found for %s\n", args
[0]);
3800 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3802 defidx
= node
->autosel
;
3803 if (node
->timeout
< 0)
3805 node
->cursel
= node
->autosel
- 1;
3806 debug("Persistence image auto select %d\n", node
->autosel
);
3811 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3817 if (node
->timeout
> 0)
3819 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3822 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_PERSISTENCE\" --class=\"sel_persistence\" {\n"
3823 " echo %s\n}\n", "");
3825 for (i
= 0; i
< node
->backendnum
; i
++)
3827 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3829 ventoy_get_vmenu_title("VTLANG_PERSIST_USE"),
3830 node
->backendpath
[i
].path
);
3834 g_ventoy_menu_esc
= 1;
3835 g_ventoy_suppress_esc
= 1;
3836 g_ventoy_suppress_esc_default
= defidx
;
3838 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3839 grub_script_execute_sourcecode(configfile
);
3841 g_ventoy_menu_esc
= 0;
3842 g_ventoy_suppress_esc
= 0;
3843 g_ventoy_suppress_esc_default
= 1;
3847 node
->cursel
= g_ventoy_last_entry
- 1;
3849 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3852 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3855 ventoy_img_chunk
*cur
;
3861 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3863 cur
= g_img_chunk_list
.chunk
+ i
;
3864 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3865 cur
->img_start_sector
, cur
->img_end_sector
,
3866 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3870 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3873 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3877 ventoy_img_chunk_list chunklist
;
3882 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3885 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3888 /* get image chunk data */
3889 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3890 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3891 if (NULL
== chunklist
.chunk
)
3893 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3896 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3897 chunklist
.cur_chunk
= 0;
3899 ventoy_get_block_list(file
, &chunklist
, 0);
3901 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3903 grub_printf("########## UNSUPPORTED ###############\n");
3906 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3908 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3910 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3911 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3914 grub_printf("\n==================================\n");
3916 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3918 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3919 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3920 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3921 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3922 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3926 grub_free(chunklist
.chunk
);
3927 grub_file_close(file
);
3929 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3932 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3935 ventoy_grub_param_file_replace
*replace
= NULL
;
3943 replace
= &(g_grub_param
->file_replace
);
3944 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3946 replace
->old_name_cnt
= 0;
3947 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3949 replace
->old_name_cnt
++;
3950 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3953 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3956 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3959 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3962 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3968 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3969 grub_env_set(args
[0], buf
);
3972 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3975 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3983 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3984 grub_printf("%s", g_list_script_buf
);
3988 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3989 grub_printf("%s", g_tree_script_buf
);
3995 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3997 img_info
*cur
= g_ventoy_img_list
;
4005 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4006 grub_printf("name:<%s>\n\n", cur
->name
);
4013 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4019 ventoy_plugin_dump_injection();
4024 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4030 ventoy_plugin_dump_auto_install();
4035 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4041 ventoy_plugin_dump_persistence();
4046 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4052 len1
= (int)grub_strlen(filename
);
4053 len2
= (int)grub_strlen(suffix
);
4060 for (i
= len1
- 1; i
>= 0; i
--)
4062 if (filename
[i
] == '.')
4073 if (filename
[i
- len2
- 1] != '_')
4078 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4086 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4092 if (argc
!= 1 && argc
!= 2)
4097 if (args
[0][0] == '0')
4099 if (g_ventoy_memdisk_mode
)
4104 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4111 else if (args
[0][0] == '1')
4113 return g_ventoy_iso_raw
? 0 : 1;
4115 else if (args
[0][0] == '2')
4117 return g_ventoy_iso_uefi_drv
? 0 : 1;
4119 else if (args
[0][0] == '3')
4121 if (g_ventoy_grub2_mode
)
4126 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4133 else if (args
[0][0] == '4')
4135 if (g_ventoy_wimboot_mode
)
4140 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4151 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4153 static int configfile_mode
= 0;
4154 char memfile
[128] = {0};
4161 * args[0]: 0:normal 1:configfile
4162 * args[1]: 0:list_buf 1:tree_buf
4167 debug("Invalid argc %d\n", argc
);
4173 if (args
[0][0] == '0')
4175 if (args
[1][0] == '0')
4177 grub_script_execute_sourcecode(g_list_script_buf
);
4181 grub_script_execute_sourcecode(g_tree_script_buf
);
4186 if (configfile_mode
)
4188 debug("Now already in F3 mode %d\n", configfile_mode
);
4192 if (args
[1][0] == '0')
4194 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4195 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4199 g_ventoy_last_entry
= -1;
4200 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4201 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4204 configfile_mode
= 1;
4205 grub_script_execute_sourcecode(memfile
);
4206 configfile_mode
= 0;
4212 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4223 g_ventoy_case_insensitive
= 1;
4224 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4225 g_ventoy_case_insensitive
= 0;
4231 grub_file_close(file
);
4237 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4242 const char *isopath
= NULL
;
4244 ventoy_mbr_head mbr
;
4251 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4254 isopath
= grub_env_get("vtoy_iso_part");
4257 debug("isopath is null %p\n", isopath
);
4261 debug("isopath is %s\n", isopath
);
4263 for (id
= 0; id
< 30 && (find
== 0); id
++)
4265 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4266 if (grub_strstr(isopath
, hdname
))
4268 debug("skip %s ...\n", hdname
);
4272 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4274 disk
= grub_disk_open(hdname
);
4277 debug("%s not exist\n", hdname
);
4281 grub_memset(&mbr
, 0, sizeof(mbr
));
4282 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4284 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4286 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4287 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4290 grub_env_set(args
[0], hdname
);
4294 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4298 debug("read %s failed\n", hdname
);
4301 grub_disk_close(disk
);
4307 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4318 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4321 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4324 debug("failed to open file %s\n", args
[0]);
4328 buf
= grub_malloc(len
);
4335 grub_file_read(file
, buf
, len
- 1);
4337 ventoy_get_line(buf
);
4338 ventoy_set_env(args
[1], buf
);
4342 grub_check_free(buf
);
4343 grub_file_close(file
);
4348 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4350 grub_uint64_t end_max
= 0;
4351 int *pCnt
= (int *)data
;
4356 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4357 "0 %llu linear /dev/ventoy %llu\n",
4358 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4360 end_max
= (partition
->len
+ partition
->start
) * 512;
4361 if (end_max
> g_part_end_max
)
4363 g_part_end_max
= end_max
;
4369 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4372 char *device_name
= NULL
;
4373 grub_device_t dev
= NULL
;
4378 g_part_list_pos
= 0;
4380 grub_env_unset("vtoy_img_part_file");
4387 device_name
= grub_file_get_device_name(args
[0]);
4390 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4394 dev
= grub_device_open(device_name
);
4397 debug("grub_device_open failed, %s\n", device_name
);
4401 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4403 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4404 grub_env_set("vtoy_img_part_file", buf
);
4406 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4407 grub_env_set("vtoy_img_part_cnt", buf
);
4409 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4410 grub_env_set("vtoy_img_max_part_end", buf
);
4414 check_free(device_name
, grub_free
);
4415 check_free(dev
, grub_device_close
);
4421 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4432 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4435 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4438 debug("failed to open file %s\n", args
[0]);
4442 buf
= grub_malloc(file
->size
+ 1);
4448 buf
[file
->size
] = 0;
4449 grub_file_read(file
, buf
, file
->size
);
4451 if (grub_strstr(buf
, args
[1]))
4458 grub_check_free(buf
);
4459 grub_file_close(file
);
4464 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4470 ventoy_iso9660_vd pvd
;
4477 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4480 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4483 debug("failed to open file %s\n", args
[0]);
4487 grub_file_seek(file
, 16 * 2048);
4488 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4489 if (len
!= sizeof(pvd
))
4491 debug("failed to read pvd %d\n", len
);
4495 grub_memset(buf
, 0, sizeof(buf
));
4496 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4497 ventoy_set_env(args
[1], buf
);
4499 grub_memset(buf
, 0, sizeof(buf
));
4500 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4501 ventoy_set_env(args
[2], buf
);
4505 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4506 ventoy_set_env(args
[3], buf
);
4509 grub_file_close(file
);
4514 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4525 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4528 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4531 debug("failed to open file %s\n", args
[0]);
4535 grub_memset(buf
, 0, sizeof(buf
));
4536 grub_file_seek(file
, 16 * 2048 + 813);
4537 len
= (int)grub_file_read(file
, buf
, 17);
4540 debug("failed to read create date %d\n", len
);
4544 ventoy_set_env(args
[1], buf
);
4547 grub_file_close(file
);
4552 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4558 ventoy_env_hook_root(1);
4563 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4569 ventoy_env_hook_root(0);
4574 #ifdef GRUB_MACHINE_EFI
4575 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4580 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4586 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4587 if (var
&& *var
== 1)
4595 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4604 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4609 grub_uint64_t FileSectors
= 0;
4610 ventoy_gpt_info
*gpt
= NULL
;
4611 ventoy_part_table
*pt
= NULL
;
4612 grub_uint8_t zeroguid
[16] = {0};
4617 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4620 debug("failed to open file %s\n", args
[0]);
4624 if (file
->size
% 512)
4626 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4630 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4636 FileSectors
= file
->size
/ 512;
4638 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4639 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4641 debug("This is EFI partition table\n");
4643 for (i
= 0; i
< 128; i
++)
4645 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4647 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4649 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4650 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4658 debug("This is MBR partition table\n");
4660 for (i
= 0; i
< 4; i
++)
4662 pt
= gpt
->MBR
.PartTbl
+ i
;
4663 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4665 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4666 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4667 (ulonglong
)FileSectors
);
4676 grub_file_close(file
);
4677 grub_check_free(gpt
);
4678 grub_errno
= GRUB_ERR_NONE
;
4682 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4691 for (i
= 0; i
< 500; i
++)
4693 ret
= grub_getkey_noblock();
4694 if (ret
== GRUB_TERM_NO_KEY
)
4703 grub_printf("\n\n Still have key input after clear.\n");
4711 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4718 int image_sector_size
;
4720 ventoy_chain_head
*chain
;
4721 ventoy_img_chunk
*chunk
;
4722 ventoy_os_param
*osparam
;
4723 ventoy_image_location
*location
;
4724 ventoy_image_disk_region
*region
;
4725 struct grub_acpi_table_header
*acpi
;
4734 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4736 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4742 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4744 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4746 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4750 img_chunk_num
= chain
->img_chunk_num
;
4752 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4753 datalen
= sizeof(ventoy_os_param
) + loclen
;
4755 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4756 acpi
= grub_zalloc(buflen
);
4762 /* Step1: Fill acpi table header */
4763 grub_memcpy(acpi
->signature
, "VTOY", 4);
4764 acpi
->length
= buflen
;
4766 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4767 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4769 acpi
->creator_id
[0] = 1;
4770 acpi
->creator_rev
= 1;
4772 /* Step2: Fill data */
4773 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4774 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4775 osparam
->vtoy_img_location_addr
= 0;
4776 osparam
->vtoy_img_location_len
= loclen
;
4777 osparam
->chksum
= 0;
4778 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4780 location
= (ventoy_image_location
*)(osparam
+ 1);
4781 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4782 location
->image_sector_size
= image_sector_size
;
4783 location
->disk_sector_size
= chain
->disk_sector_size
;
4784 location
->region_count
= img_chunk_num
;
4786 region
= location
->regions
;
4787 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4788 if (512 == image_sector_size
)
4790 for (i
= 0; i
< img_chunk_num
; i
++)
4792 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4793 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4794 region
->disk_start_sector
= chunk
->disk_start_sector
;
4801 for (i
= 0; i
< img_chunk_num
; i
++)
4803 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4804 region
->image_start_sector
= chunk
->img_start_sector
;
4805 region
->disk_start_sector
= chunk
->disk_start_sector
;
4811 /* Step3: Fill acpi checksum */
4813 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4815 /* load acpi table */
4816 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4817 grub_script_execute_sourcecode(cmd
);
4821 VENTOY_CMD_RETURN(0);
4824 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4830 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4831 g_ventoy_last_entry
= -1;
4836 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4842 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4847 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4849 const char *pos
= filename
+ 1;
4857 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4859 grub_strncpy((char *)data
, filename
, 128);
4870 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4873 char *device_name
= NULL
;
4874 grub_device_t dev
= NULL
;
4875 grub_fs_t fs
= NULL
;
4876 char buf
[128] = {0};
4882 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4886 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4888 device_name
= grub_file_get_device_name(args
[0]);
4891 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4895 dev
= grub_device_open(device_name
);
4898 debug("grub_device_open failed, %s\n", device_name
);
4902 fs
= grub_fs_probe(dev
);
4905 debug("grub_fs_probe failed, %s\n", device_name
);
4909 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4913 ventoy_set_env(args
[2], buf
);
4920 check_free(device_name
, grub_free
);
4921 check_free(dev
, grub_device_close
);
4926 int ventoy_load_part_table(const char *diskname
)
4933 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4934 if (!g_ventoy_part_info
)
4939 disk
= grub_disk_open(diskname
);
4942 debug("Failed to open disk %s\n", diskname
);
4946 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4948 g_ventoy_disk_bios_id
= disk
->id
;
4950 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4951 grub_disk_close(disk
);
4953 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4954 dev
= grub_device_open(name
);
4957 /* Check for official Ventoy device */
4958 ret
= ventoy_check_official_device(dev
);
4959 grub_device_close(dev
);
4967 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4968 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4973 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4981 ret
= ventoy_load_part_table(args
[0]);
4984 grub_printf("\n\nPress r/h/e for the corresponding operation.\n");
4985 grub_printf(" r --- Reboot\n");
4986 grub_printf(" h --- Halt\n");
4987 grub_printf(" e --- Exit grub\n");
4999 grub_script_execute_sourcecode("halt");
5008 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5009 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5014 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5017 const char *vcfg
= NULL
;
5022 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5025 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5026 grub_env_set(args
[1], vcfg
);
5031 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5039 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5042 grub_uint8_t zeroguid
[16] = {0};
5047 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5050 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5052 if (id
>= 1 && id
<= 128)
5054 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5062 if (id
>= 1 && id
<= 4)
5064 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5074 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5077 char *device_name
= NULL
;
5078 grub_device_t dev
= NULL
;
5079 grub_fs_t fs
= NULL
;
5084 debug("get fs label for %s\n", args
[0]);
5088 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5092 device_name
= grub_file_get_device_name(args
[0]);
5095 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5099 dev
= grub_device_open(device_name
);
5102 debug("grub_device_open failed, %s\n", device_name
);
5106 fs
= grub_fs_probe(dev
);
5107 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5109 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5113 fs
->fs_label(dev
, &label
);
5116 debug("label=<%s>\n", label
);
5117 ventoy_set_env(args
[1], label
);
5125 check_free(device_name
, grub_free
);
5126 check_free(dev
, grub_device_close
);
5131 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5135 grub_snprintf((char *)data
, 256, "%s", filename
);
5142 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5144 if (info
->dir
&& filename
&& filename
[0] != '.')
5146 grub_snprintf((char *)data
, 256, "%s", filename
);
5153 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5156 char *device_name
= NULL
;
5157 grub_device_t dev
= NULL
;
5158 grub_fs_t fs
= NULL
;
5159 char name
[256] ={0};
5163 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5167 device_name
= grub_file_get_device_name(args
[0]);
5170 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5174 dev
= grub_device_open(device_name
);
5177 debug("grub_device_open failed, %s\n", device_name
);
5181 fs
= grub_fs_probe(dev
);
5184 debug("grub_fs_probe failed, %s\n", device_name
);
5188 fs
->fs_dir(dev
, args
[1], hook
, name
);
5191 ventoy_set_env(args
[2], name
);
5198 check_free(device_name
, grub_free
);
5199 check_free(dev
, grub_device_close
);
5204 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5207 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5210 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5213 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5216 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5226 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5230 for (pos
= args
[0]; *pos
; pos
++)
5244 grub_env_set(args
[1], args
[0]);
5254 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5264 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5269 len
= (int)grub_strlen(buf
);
5270 for (i
= len
; i
> 0; i
--)
5272 if (buf
[i
- 1] == '/')
5274 grub_env_set(args
[1], buf
+ i
);
5279 grub_env_set(args
[1], buf
);
5284 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5286 struct grub_video_mode_info info
;
5293 if (!g_video_mode_list
)
5295 ventoy_enum_video_mode();
5298 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5300 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5304 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5307 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5309 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5310 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5312 VENTOY_CMD_RETURN(0);
5315 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5317 struct grub_video_mode_info info
;
5324 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5326 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5330 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5333 grub_env_set(args
[0], buf
);
5335 VENTOY_CMD_RETURN(0);
5338 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5346 if (!g_video_mode_list
)
5351 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5352 if (id
< g_video_mode_num
)
5354 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5355 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5358 grub_env_set(args
[1], buf
);
5360 VENTOY_CMD_RETURN(0);
5363 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5366 grub_uint32_t loadsector
= 0;
5369 grub_uint32_t boot_catlog
= 0;
5370 grub_uint8_t buf
[512];
5376 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5380 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5383 debug("failed to open %s\n", args
[0]);
5387 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5388 if (boot_catlog
== 0)
5390 debug("No bootcatlog found\n");
5391 grub_file_close(file
);
5395 grub_memset(buf
, 0, sizeof(buf
));
5396 grub_file_seek(file
, boot_catlog
* 2048);
5397 grub_file_read(file
, buf
, sizeof(buf
));
5398 grub_file_close(file
);
5400 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5402 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5404 if (buf
[i
+ 32] == 0x88)
5406 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5407 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5413 if (loadsector
== 0)
5415 debug("No EFI eltorito info found\n");
5419 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5420 grub_env_set(args
[1], value
);
5421 VENTOY_CMD_RETURN(0);
5424 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5429 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5431 if (pfsdir
->initrd
[0])
5436 curpos
= pfsdir
->curpos
;
5437 len
= grub_strlen(filename
);
5441 if ((len
== 1 && filename
[0] == '.') ||
5442 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5447 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5450 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5451 pfsdir
->curpos
= curpos
+ printlen
;
5452 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5453 pfsdir
->curpos
= curpos
;
5454 pfsdir
->fullpath
[curpos
] = 0;
5458 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5461 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5462 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5464 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5466 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5475 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5479 char *device_name
= NULL
;
5480 grub_device_t dev
= NULL
;
5481 grub_fs_t fs
= NULL
;
5482 replace_fs_dir
*pfsdir
= NULL
;
5488 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5492 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5498 device_name
= grub_file_get_device_name(args
[0]);
5504 dev
= grub_device_open(device_name
);
5510 fs
= grub_fs_probe(dev
);
5519 pfsdir
->fullpath
[0] = '/';
5520 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5522 if (pfsdir
->initrd
[0])
5524 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5526 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5528 if (pfsdir
->initrd
[i
] == '/')
5530 pfsdir
->initrd
[i
] = '\\';
5534 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5535 grub_env_set(args
[1], pos
);
5539 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5544 grub_check_free(pfsdir
);
5545 grub_check_free(device_name
);
5546 check_free(dev
, grub_device_close
);
5548 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5551 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5553 const char *pager
= NULL
;
5559 pager
= grub_env_get("pager");
5563 grub_env_set("pager", "1");
5565 else if (pager
[0] == '1')
5571 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5573 grub_env_set("pager", "1");
5576 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5579 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5585 if (g_pager_flag
== 1)
5587 grub_env_unset("pager");
5589 else if (g_pager_flag
== 2)
5591 grub_env_set("pager", g_old_pager
);
5594 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5597 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5599 if (g_json_case_mis_path
[0])
5604 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5606 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5612 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5615 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5617 if (g_json_case_mis_path
[0])
5622 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5624 if (grub_strcasecmp(filename
, "ventoy") == 0)
5626 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5627 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5628 if (g_json_case_mis_path
[0])
5638 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5641 char *device_name
= NULL
;
5642 grub_device_t dev
= NULL
;
5643 grub_fs_t fs
= NULL
;
5644 chk_case_fs_dir fs_dir
;
5650 device_name
= grub_file_get_device_name(args
[0]);
5656 dev
= grub_device_open(device_name
);
5662 fs
= grub_fs_probe(dev
);
5668 fstype
= ventoy_get_fs_type(fs
->name
);
5669 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5674 g_json_case_mis_path
[0] = 0;
5677 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5679 if (g_json_case_mis_path
[0])
5681 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5686 grub_check_free(device_name
);
5687 check_free(dev
, grub_device_close
);
5689 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5692 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5695 grub_partition_t part
;
5696 char priority_str
[3]; /* Maximum value 15 */
5700 if (argc
< 2 || argc
> 3)
5701 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5702 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5704 /* Open the disk if it exists */
5705 disk
= grub_disk_open (args
[0]);
5708 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5712 part
= grub_partition_probe (disk
, args
[1]);
5715 grub_disk_close (disk
);
5716 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5717 "No such partition");
5720 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5722 grub_disk_close (disk
);
5723 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5724 "Not a GPT partition");
5727 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5728 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5732 grub_env_set (args
[2], priority_str
);
5733 grub_env_export (args
[2]);
5737 grub_printf ("Priority is %s\n", priority_str
);
5740 grub_disk_close (disk
);
5741 return GRUB_ERR_NONE
;
5745 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5749 grub_file_t file
= NULL
;
5750 grub_uint32_t loadrba
= 0;
5751 grub_uint32_t boot_catlog
= 0;
5752 grub_uint8_t sector
[512];
5753 boot_info_table
*info
= NULL
;
5758 /* This also trigger a iso9660 fs parse */
5759 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5764 joliet
= grub_iso9660_is_joliet();
5770 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5773 debug("failed to open %s\n", args
[0]);
5777 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5778 if (boot_catlog
== 0)
5780 debug("no bootcatlog found %u\n", boot_catlog
);
5784 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5787 debug("no bios eltorito rba found %u\n", loadrba
);
5791 grub_file_seek(file
, loadrba
* 2048);
5792 grub_file_read(file
, sector
, 512);
5794 info
= (boot_info_table
*)sector
;
5795 if (info
->bi_data0
== 0x7c6ceafa &&
5796 info
->bi_data1
== 0x90900000 &&
5797 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5798 info
->bi_BootFileLocation
== loadrba
)
5800 debug("bootloader is syslinux, %u.\n", loadrba
);
5806 grub_file_close(file
);
5807 grub_errno
= GRUB_ERR_NONE
;
5811 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5814 ventoy_vlnk_part
*node
;
5820 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5822 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5823 ++n
, node
->device
, node
->disksig
,
5824 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5830 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5838 len
= (int)grub_strlen(args
[0]);
5839 if (grub_file_is_vlnk_suffix(args
[0], len
))
5848 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5851 const char *name
= NULL
;
5857 grub_env_unset(args
[1]);
5858 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5861 debug("VLNK SRC: <%s>\n", args
[0]);
5862 debug("VLNK DST: <%s>\n", name
);
5863 grub_env_set(args
[1], name
);
5871 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5875 grub_file_t file
= NULL
;
5886 len
= (int)grub_strlen(args
[0]);
5887 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5889 grub_printf("Invalid vlnk suffix\n");
5893 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5896 grub_printf("Failed to open %s\n", args
[0]);
5900 if (file
->size
!= 32768)
5902 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5906 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5907 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5909 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5914 check_free(file
, grub_file_close
);
5915 grub_errno
= GRUB_ERR_NONE
;
5919 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5925 g_iso_vd_id_publisher
[0] = 0;
5926 g_iso_vd_id_prepare
[0] = 0;
5927 g_iso_vd_id_application
[0] = 0;
5932 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5936 grub_file_t file
= NULL
;
5941 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5944 grub_printf("Failed to open %s\n", args
[0]);
5948 grub_file_seek(file
, 16 * 2048 + offset
);
5949 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5952 grub_file_seek(file
, 16 * 2048 + offset
);
5953 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5956 grub_file_seek(file
, 16 * 2048 + offset
);
5957 grub_file_read(file
, g_iso_vd_id_application
, 128);
5961 check_free(file
, grub_file_close
);
5962 grub_errno
= GRUB_ERR_NONE
;
5966 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5969 char *id
= g_iso_vd_id_publisher
;
5974 if (args
[0][0] == '1')
5976 id
= g_iso_vd_id_prepare
;
5978 else if (args
[0][0] == '2')
5980 id
= g_iso_vd_id_application
;
5983 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5988 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5993 grub_errno
= GRUB_ERR_NONE
;
5997 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6002 g_ventoy_fn_mutex
= 0;
6003 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
6005 g_ventoy_fn_mutex
= 1;
6008 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6011 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6013 grub_uint64_t total
;
6014 grub_uint64_t org_required
;
6015 grub_uint64_t new_required
;
6021 #ifdef GRUB_MACHINE_EFI
6022 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6023 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6024 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6025 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6030 grub_printf("Non EFI mode!\n");
6035 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6038 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6040 const char *env
= NULL
;
6045 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6050 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6051 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6052 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6053 ventoy_check_mode_by_name(args
[0], "vtnormal")
6059 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6060 if (env
&& env
[0] == '0' && env
[1] == 0)
6068 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6076 const char *env
= NULL
;
6077 ulonglong fsize
= 0;
6079 int seldata
[16] = {0};
6084 len
= 8 * VTOY_SIZE_1KB
;
6085 cmd
= (char *)grub_malloc(len
);
6091 g_vtoy_secondary_need_recover
= 0;
6092 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6094 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6097 timeout
= (int)grub_strtol(env
, NULL
, 10);
6102 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6105 fsize
= grub_strtoull(args
[2], NULL
, 10);
6107 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6109 if (grub_strcmp(args
[1], "Unix") != 0)
6111 if (grub_strcmp(args
[1], "Windows") == 0)
6113 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6117 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6120 if (fsize
<= VTOY_SIZE_1GB
)
6122 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6126 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6129 g_ventoy_menu_esc
= 1;
6130 g_ventoy_suppress_esc
= 1;
6131 g_ventoy_suppress_esc_default
= 0;
6132 g_ventoy_secondary_menu_on
= 1;
6133 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6134 grub_script_execute_sourcecode(cfgfile
);
6135 g_ventoy_menu_esc
= 0;
6136 g_ventoy_suppress_esc
= 0;
6137 g_ventoy_suppress_esc_default
= 1;
6138 g_ventoy_secondary_menu_on
= 0;
6140 select
= seldata
[g_ventoy_last_entry
];
6144 g_ventoy_wimboot_mode
= 1;
6145 g_vtoy_secondary_need_recover
= 1;
6147 else if (select
== 3)
6149 g_ventoy_grub2_mode
= 1;
6150 g_vtoy_secondary_need_recover
= 2;
6152 else if (select
== 4)
6154 g_ventoy_memdisk_mode
= 1;
6155 g_vtoy_secondary_need_recover
= 3;
6157 else if (select
== 5)
6159 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6160 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6162 }while (select
== 5);
6168 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6174 if (g_vtoy_secondary_need_recover
== 1)
6176 g_ventoy_wimboot_mode
= 0;
6178 else if (g_vtoy_secondary_need_recover
== 2)
6180 g_ventoy_grub2_mode
= 0;
6182 else if (g_vtoy_secondary_need_recover
== 3)
6184 g_ventoy_memdisk_mode
= 0;
6187 g_vtoy_secondary_need_recover
= 0;
6189 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6192 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6197 if (args
[0][0] == '0')
6199 g_ventoy_case_insensitive
= 0;
6203 g_ventoy_case_insensitive
= 1;
6209 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6214 ventoy_plugin_load_menu_lang(1, args
[0]);
6215 VENTOY_CMD_RETURN(0);
6218 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6223 ventoy_plugin_load_menu_lang(0, args
[0]);
6224 VENTOY_CMD_RETURN(0);
6228 static const char * ventoy_menu_lang_read_hook(struct grub_env_var
*var
, const char *val
)
6231 return ventoy_get_vmenu_title(val
);
6234 static const char * ventoy_gfxmode_read_hook(struct grub_env_var
*var
, const char *val
)
6239 return g_vtoy_gfxmode
;
6242 static char * ventoy_gfxmode_write_hook(struct grub_env_var
*var
, const char *val
)
6246 grub_strncpy(g_vtoy_gfxmode
, val
, sizeof(g_vtoy_gfxmode
) - 1);
6247 return grub_strdup(val
);
6250 static ctrl_var_cfg g_ctrl_vars
[] =
6252 { "VTOY_WIN11_BYPASS_CHECK", 0 },
6253 { "VTOY_LINUX_REMOUNT", 0 },
6254 { "VTOY_SECONDARY_BOOT_MENU", 1 },
6258 static const char * ventoy_ctrl_var_read_hook(struct grub_env_var
*var
, const char *val
)
6262 for (i
= 0; g_ctrl_vars
[i
].name
; i
++)
6264 if (grub_strcmp(g_ctrl_vars
[i
].name
, var
->name
) == 0)
6266 return g_ctrl_vars
[i
].value
? "1" : "0";
6273 static char * ventoy_ctrl_var_write_hook(struct grub_env_var
*var
, const char *val
)
6277 for (i
= 0; g_ctrl_vars
[i
].name
; i
++)
6279 if (grub_strcmp(g_ctrl_vars
[i
].name
, var
->name
) == 0)
6281 if (val
&& val
[0] == '1' && val
[1] == 0)
6283 g_ctrl_vars
[i
].value
= 1;
6284 return grub_strdup("1");
6288 g_ctrl_vars
[i
].value
= 0;
6289 return grub_strdup("0");
6294 return grub_strdup(val
);
6297 static int ventoy_ctrl_var_init(void)
6301 for (i
= 0; g_ctrl_vars
[i
].name
; i
++)
6303 ventoy_env_export(g_ctrl_vars
[i
].name
, g_ctrl_vars
[i
].value
? "1" : "0");
6304 grub_register_variable_hook(g_ctrl_vars
[i
].name
, ventoy_ctrl_var_read_hook
, ventoy_ctrl_var_write_hook
);
6310 int ventoy_env_init(void)
6315 grub_env_set("vtdebug_flag", "");
6317 grub_register_variable_hook("gfxmode", ventoy_gfxmode_read_hook
, ventoy_gfxmode_write_hook
);
6318 grub_register_vtoy_menu_lang_hook(ventoy_menu_lang_read_hook
);
6320 ventoy_ctrl_var_init();
6322 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6323 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6324 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6325 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6327 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6330 ventoy_filt_register(0, ventoy_wrapper_open
);
6332 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6335 g_grub_param
->grub_env_get
= grub_env_get
;
6336 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6337 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6338 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6339 grub_env_set("env_param", buf
);
6340 grub_env_set("ventoy_env_param", buf
);
6342 grub_env_export("env_param");
6343 grub_env_export("ventoy_env_param");
6346 grub_env_export("vtoy_winpeshl_ini_addr");
6347 grub_env_export("vtoy_winpeshl_ini_size");
6349 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6350 grub_env_set("vtoy_chain_file_size", buf
);
6351 grub_env_export("vtoy_chain_file_size");
6353 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6354 grub_env_set("vtoy_chain_file_read", buf
);
6355 grub_env_export("vtoy_chain_file_read");
6357 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6358 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6359 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6361 grub_snprintf(buf
, sizeof(buf
), "%s-%s", GRUB_TARGET_CPU
, GRUB_PLATFORM
);
6362 grub_env_set("grub_cpu_platform", buf
);
6363 grub_env_export("grub_cpu_platform");
6370 static cmd_para ventoy_cmds
[] =
6372 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6373 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6374 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6375 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6376 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6377 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6378 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6379 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6380 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6381 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6382 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6383 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6384 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6385 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6386 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6387 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6388 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6389 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6390 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6391 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6392 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6393 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6394 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6395 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6396 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6397 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6398 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6400 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6401 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6402 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6403 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6404 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6405 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6406 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6408 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6409 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6410 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6411 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6412 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6413 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6414 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6415 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6416 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6417 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6420 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6421 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6422 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6423 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6424 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6425 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6426 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6427 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6428 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6429 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6430 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6432 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6433 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6434 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6435 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6436 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6437 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6438 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6440 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6441 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6442 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6443 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6444 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6445 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6446 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6447 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6448 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6449 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6451 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6452 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6453 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6454 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6455 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6456 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6457 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6458 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6459 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6461 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6462 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6463 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6464 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6467 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6468 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6469 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6471 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6472 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6473 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6476 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6477 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6478 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6479 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6480 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6481 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6482 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6483 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6484 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6485 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6486 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6487 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6488 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6489 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6491 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6492 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6493 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6494 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6495 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6496 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6497 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6498 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6499 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6500 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6501 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6502 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6504 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6505 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6506 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6507 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6508 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6509 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6510 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6511 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6512 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6513 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6514 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6515 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6516 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6517 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6518 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6519 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6520 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6521 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6522 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6523 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6524 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6525 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6526 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6527 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6528 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6529 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6530 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6531 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6532 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6533 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6537 int ventoy_register_all_cmd(void)
6540 cmd_para
*cur
= NULL
;
6542 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6544 cur
= ventoy_cmds
+ i
;
6545 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6546 cur
->summary
, cur
->description
, cur
->parser
);
6552 int ventoy_unregister_all_cmd(void)
6556 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6558 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);