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");
500 grub_printf(VTOY_WARNING
"\n");
501 grub_printf(VTOY_WARNING
"\n");
502 grub_printf(VTOY_WARNING
"\n\n\n");
504 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
505 grub_printf("Error message: <%s>\n\n", msg
);
506 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
508 grub_printf("\n\nWill exit after 10 seconds ...... ");
516 static int ventoy_check_official_device(grub_device_t dev
)
520 grub_uint64_t offset
;
523 grub_uint8_t mbr
[512];
527 struct grub_partition
*partition
;
529 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
531 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
534 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
535 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
536 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
538 #ifndef GRUB_MACHINE_EFI
539 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
541 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
543 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
545 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
547 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
549 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
558 /* We must have partition 2 */
561 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
565 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
569 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
572 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
574 grub_file_close(file
);
575 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
578 partition
= dev
->disk
->partition
;
579 if (partition
->number
!= 0 || partition
->start
!= 2048)
581 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
586 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
588 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
589 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
590 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
592 grub_file_close(file
);
593 return ventoy_set_check_result(6, "Disk partition layout check failed.");
598 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
599 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
600 PartTbl
[1].SectorCount
!= 65536)
602 grub_file_close(file
);
603 return ventoy_set_check_result(6, "Disk partition layout check failed.");
609 offset
= partition
->start
+ partition
->len
;
610 partition
= file
->device
->disk
->partition
;
611 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
613 grub_file_close(file
);
614 return ventoy_set_check_result(7, "Disk partition layout check failed.");
618 grub_file_close(file
);
622 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
623 dev2
= grub_device_open(devname
);
626 return ventoy_set_check_result(8, "Disk open failed");
629 fs
= grub_fs_probe(dev2
);
632 grub_device_close(dev2
);
633 return ventoy_set_check_result(9, "FS probe failed");
636 fs
->fs_label(dev2
, &label
);
637 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
639 grub_device_close(dev2
);
640 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
643 grub_device_close(dev2
);
647 disk
= grub_disk_open(dev
->disk
->name
);
650 return ventoy_set_check_result(11, "Disk open failed");
653 grub_memset(mbr
, 0, 512);
654 grub_disk_read(disk
, 0, 0, 512, mbr
);
655 grub_disk_close(disk
);
657 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
659 return ventoy_set_check_result(12, "MBR check failed");
662 return ventoy_set_check_result(0, NULL
);
665 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
669 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
679 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
681 grub_uint64_t size
= 0;
684 char fullpath
[256] = {0};
687 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
690 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
693 debug("grub_file_open failed <%s>\n", fullpath
);
699 grub_file_close(file
);
703 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
707 char fullpath
[512] = {0};
710 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
713 file
= grub_file_open(fullpath
, type
);
716 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
723 int ventoy_is_dir_exist(const char *fmt
, ...)
730 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
734 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
737 grub_strncpy(pos
+ len
, "\" ]", 3);
739 debug("script exec %s\n", buf
);
741 if (0 == grub_script_execute_sourcecode(buf
))
749 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
752 grub_uint8_t
*outbuf
;
753 grub_uint8_t gzHdr
[10] =
755 0x1F, 0x8B, /* magic */
763 grub_memset(&s
, 0, sizeof(mz_stream
));
765 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
767 outbuf
= (grub_uint8_t
*)mem_out
;
769 mem_out_len
-= sizeof(gzHdr
) + 8;
770 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
771 outbuf
+= sizeof(gzHdr
);
773 s
.avail_in
= mem_in_len
;
776 s
.avail_out
= mem_out_len
;
779 mz_deflate(&s
, MZ_FINISH
);
783 outbuf
+= s
.total_out
;
784 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
785 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
787 return s
.total_out
+ sizeof(gzHdr
) + 8;
795 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
799 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
802 if (0 == grub_strcmp(args
[0], "on"))
805 grub_env_set("vtdebug_flag", "debug");
810 grub_env_set("vtdebug_flag", "");
813 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
816 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
820 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
822 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
823 grub_printf(" level:\r\n");
824 grub_printf(" 01/11: busybox / (+cat log)\r\n");
825 grub_printf(" 02/12: initrd / (+cat log)\r\n");
826 grub_printf(" 03/13: hook / (+cat log)\r\n");
828 grub_printf(" debug:\r\n");
829 grub_printf(" 0: debug is off\r\n");
830 grub_printf(" 1: debug is on\r\n");
832 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
835 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
837 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
839 g_ventoy_debug_level
= 1;
842 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
845 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
854 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
857 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
889 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
905 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
921 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
926 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
928 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
931 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
936 value_long
+= grub_strtol(args
[1], NULL
, 10);
938 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
939 grub_env_set(args
[0], buf
);
941 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
944 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
946 ulonglong value1
= 0;
947 ulonglong value2
= 0;
952 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
955 value1
= grub_strtoull(args
[0], NULL
, 10);
956 value2
= grub_strtoull(args
[1], NULL
, 10);
958 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
959 grub_env_set(args
[2], buf
);
961 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
964 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
979 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
982 debug("failed to open file <%s> for udf check\n", args
[0]);
986 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
988 grub_env_set(args
[1], buf
);
990 grub_file_close(file
);
996 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1004 g_wimboot_enable
= 0;
1006 grub_check_free(g_wimiso_path
);
1007 grub_check_free(g_wimiso_chunk_list
.chunk
);
1009 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1015 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1016 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1017 if (NULL
== g_wimiso_chunk_list
.chunk
)
1019 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1022 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1023 g_wimiso_chunk_list
.cur_chunk
= 0;
1025 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1027 g_wimboot_enable
= 1;
1028 g_wimiso_path
= grub_strdup(args
[0]);
1029 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1030 grub_file_close(file
);
1035 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1043 ventoy_iso9660_override
*dirent
;
1052 totlen
= sizeof(ventoy_chain_head
);
1054 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1056 debug("failed to load efiboot template %d\n", len
);
1062 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1064 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1067 debug("failed to open file <%s>\n", args
[0]);
1071 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1076 totlen
+= ventoy_align_2k(file
->size
);
1078 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1079 dirent
->first_sector
= len
/ 2048;
1080 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1081 dirent
->size
= (grub_uint32_t
)file
->size
;
1082 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1084 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1086 #ifdef GRUB_MACHINE_EFI
1087 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1089 data
= (char *)grub_malloc(totlen
);
1092 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1094 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1095 grub_check_free(buf
);
1097 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1098 grub_file_close(file
);
1100 ventoy_memfile_env_set(args
[1], data
, (ulonglong
)totlen
);
1105 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1111 g_vtoy_load_prompt
= 0;
1112 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1114 if (argc
== 2 && args
[0][0] == '1')
1116 g_vtoy_load_prompt
= 1;
1117 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1120 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1123 int ventoy_need_prompt_load_file(void)
1125 return g_vtoy_load_prompt
;
1128 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1130 grub_uint64_t ro
= 0;
1131 grub_uint64_t div
= 0;
1132 grub_ssize_t left
= size
;
1133 char *cur
= (char *)buf
;
1135 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1138 while (left
>= VTOY_SIZE_2MB
)
1140 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1141 cur
+= VTOY_SIZE_2MB
;
1142 left
-= VTOY_SIZE_2MB
;
1144 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1149 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1155 grub_file_read(file
, cur
, left
);
1158 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1164 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1169 enum grub_file_type type
;
1180 if (grub_strcmp(args
[0], "nodecompress") == 0)
1182 type
= VENTOY_FILE_TYPE
;
1186 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1189 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1192 debug("failed to open file <%s>\n", args
[1]);
1196 #ifdef GRUB_MACHINE_EFI
1197 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1199 buf
= (char *)grub_malloc(file
->size
);
1204 grub_file_close(file
);
1208 if (g_vtoy_load_prompt
)
1210 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1214 grub_file_read(file
, buf
, file
->size
);
1217 ventoy_memfile_env_set(args
[2], buf
, (ulonglong
)(file
->size
));
1219 grub_file_close(file
);
1225 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1241 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1244 debug("failed to open file <%s> for udf check\n", args
[0]);
1248 headlen
= sizeof(ventoy_chain_head
);
1250 #ifdef GRUB_MACHINE_EFI
1251 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1253 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1256 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1258 grub_file_read(file
, buf
+ headlen
, file
->size
);
1260 ventoy_memfile_env_set(args
[1], buf
, (ulonglong
)(file
->size
));
1262 grub_file_close(file
);
1268 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1274 if (grub_iso9660_is_joliet())
1276 debug("This time has joliet process\n");
1285 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1294 if (args
[0][0] == '1')
1296 grub_iso9660_set_nojoliet(1);
1300 grub_iso9660_set_nojoliet(0);
1306 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1311 grub_uint8_t buf
[32];
1322 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1325 debug("failed to open file <%s> for udf check\n", args
[0]);
1329 for (i
= 16; i
< 32; i
++)
1331 grub_file_seek(file
, i
* 2048);
1332 grub_file_read(file
, buf
, sizeof(buf
));
1340 grub_file_seek(file
, i
* 2048);
1341 grub_file_read(file
, buf
, sizeof(buf
));
1343 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1346 grub_file_seek(file
, i
* 2048);
1347 grub_file_read(file
, buf
, sizeof(buf
));
1349 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1350 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1356 grub_file_close(file
);
1358 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1363 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1365 long value_long1
= 0;
1366 long value_long2
= 0;
1368 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1370 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1373 value_long1
= grub_strtol(args
[0], NULL
, 10);
1374 value_long2
= grub_strtol(args
[2], NULL
, 10);
1376 if (0 == grub_strcmp(args
[1], "eq"))
1378 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1380 else if (0 == grub_strcmp(args
[1], "ne"))
1382 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1384 else if (0 == grub_strcmp(args
[1], "gt"))
1386 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1388 else if (0 == grub_strcmp(args
[1], "lt"))
1390 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1392 else if (0 == grub_strcmp(args
[1], "ge"))
1394 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1396 else if (0 == grub_strcmp(args
[1], "le"))
1398 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1402 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1408 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1411 char buf
[128] = {0};
1415 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1418 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1419 pos
= grub_strstr(buf
, ",");
1425 grub_env_set(args
[1], buf
);
1427 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1430 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1436 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1442 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1445 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1447 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1448 if (0 == grub_script_execute_sourcecode(buf
))
1450 debug("file %s exist, ventoy_compatible YES\n", buf
);
1451 grub_env_set("ventoy_compatible", "YES");
1452 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1456 debug("file %s NOT exist\n", buf
);
1460 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1461 pos
= grub_strstr(buf
, ")");
1467 disk
= grub_disk_open(buf
);
1470 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1471 grub_disk_close(disk
);
1473 g_img_swap_tmp_buf
[703] = 0;
1474 for (i
= 318; i
< 703; i
++)
1476 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1477 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1479 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1480 grub_env_set("ventoy_compatible", "YES");
1481 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1487 debug("failed to open disk <%s>\n", buf
);
1490 grub_env_set("ventoy_compatible", "NO");
1491 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1494 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1500 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1502 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1505 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1510 if (0 == g_sort_case_sensitive
)
1512 if (grub_islower(c1
))
1514 c1
= c1
- 'a' + 'A';
1517 if (grub_islower(c2
))
1519 c2
= c2
- 'a' + 'A';
1532 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1538 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1540 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1543 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1548 if (0 == g_sort_case_sensitive
)
1550 if (grub_islower(c1
))
1552 c1
= c1
- 'a' + 'A';
1555 if (grub_islower(c2
))
1557 c2
= c2
- 'a' + 'A';
1570 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1572 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1574 grub_memcpy(img1
, img2
, sizeof(img_info
));
1575 img1
->next
= g_img_swap_tmp
.next
;
1576 img1
->prev
= g_img_swap_tmp
.prev
;
1578 g_img_swap_tmp
.next
= img2
->next
;
1579 g_img_swap_tmp
.prev
= img2
->prev
;
1580 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1583 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1587 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1595 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1597 ventoy_vlnk_part
*node
= NULL
;
1598 grub_uint32_t SelfSig
;
1599 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1601 /* skip Ventoy partition 1/2 */
1602 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1603 if (partition
->number
< 2 && SelfSig
== *pSig
)
1608 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1611 node
->disksig
= *pSig
;
1612 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1613 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1614 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1616 node
->next
= g_vlnk_part_list
;
1617 g_vlnk_part_list
= node
;
1623 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1630 disk
= grub_disk_open(name
);
1633 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1634 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1635 grub_disk_close(disk
);
1641 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1643 const char *fs
[ventoy_fs_max
+ 1] =
1645 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1650 cur
->dev
= grub_device_open(cur
->device
);
1655 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1661 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1666 char *disk
, *device
;
1667 grub_uint32_t readcrc
, calccrc
;
1668 ventoy_vlnk_part
*cur
;
1669 grub_fs_t fs
= NULL
;
1671 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1675 grub_printf("VLNK invalid guid\n");
1681 readcrc
= vlnk
->crc32
;
1683 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1684 if (readcrc
!= calccrc
)
1688 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1694 if (!g_vlnk_part_list
)
1696 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1699 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1701 if (cur
->disksig
== vlnk
->disk_signature
)
1705 if (cur
->partoffset
== vlnk
->part_offset
)
1708 device
= cur
->device
;
1710 if (cur
->probe
== 0)
1713 ventoy_vlnk_probe_fs(cur
);
1723 struct grub_file file
;
1725 grub_memset(&file
, 0, sizeof(file
));
1726 file
.device
= cur
->dev
;
1727 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1730 cur
->fs
->fs_close(&file
);
1731 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1740 grub_printf("\n==== VLNK Information ====\n"
1741 "Disk Signature: %08x\n"
1742 "Partition Offset: %llu\n"
1743 "File Path: <%s>\n\n",
1744 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1748 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1752 grub_printf("Disk Find: [ NO ]\n");
1757 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1761 grub_printf("Part Find: [ NO ]\n");
1763 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1766 grub_printf("VLNK File: <%s>\n", dst
);
1773 return (1 - filefind
);
1776 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1781 grub_file_t file
= NULL
;
1786 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1788 else if (dir
[0] == '/')
1790 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1794 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1797 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1803 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1804 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1805 grub_file_close(file
);
1807 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1809 rc
= grub_file_add_vlnk(src
, dst
);
1815 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1825 const menu_tip
*tip
;
1826 img_iterator_node
*tmp
;
1827 img_iterator_node
*new_node
;
1828 img_iterator_node
*node
= (img_iterator_node
*)data
;
1830 if (g_enumerate_time_checked
== 0)
1832 g_enumerate_finish_time_ms
= grub_get_time_ms();
1833 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1836 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1838 g_enumerate_time_checked
= 1;
1842 len
= grub_strlen(filename
);
1846 if (node
->level
+ 1 > g_img_max_search_level
)
1851 if ((len
== 1 && filename
[0] == '.') ||
1852 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1857 if (!ventoy_img_name_valid(filename
, len
))
1862 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1867 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1869 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1870 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1873 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1878 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1881 new_node
->level
= node
->level
+ 1;
1882 new_node
->plugin_list_index
= index
;
1883 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1885 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1888 debug("Directory %s ignored...\n", new_node
->dir
);
1889 grub_free(new_node
);
1893 new_node
->tail
= node
->tail
;
1895 new_node
->parent
= node
;
1896 if (!node
->firstchild
)
1898 node
->firstchild
= new_node
;
1901 if (g_img_iterator_tail
)
1903 g_img_iterator_tail
->next
= new_node
;
1904 g_img_iterator_tail
= new_node
;
1908 g_img_iterator_head
.next
= new_node
;
1909 g_img_iterator_tail
= new_node
;
1915 debug("Find a file %s\n", filename
);
1921 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1923 type
= img_type_iso
;
1925 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1927 type
= img_type_wim
;
1929 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1930 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1932 type
= img_type_vhd
;
1934 #ifdef GRUB_MACHINE_EFI
1935 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1937 type
= img_type_efi
;
1940 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1942 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1944 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1945 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1950 type
= img_type_img
;
1952 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1954 type
= img_type_vtoy
;
1956 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1958 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1960 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1961 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1970 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1975 if (g_plugin_image_list
)
1977 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1978 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1979 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1981 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1984 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1986 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1991 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
1993 if (grub_file_is_vlnk_suffix(filename
, len
))
1996 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2003 img
= grub_zalloc(sizeof(img_info
));
2007 img
->plugin_list_index
= index
;
2008 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2010 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2012 img
->size
= info
->size
;
2013 if (vlnk
|| 0 == img
->size
)
2015 if (node
->dir
[0] == '/')
2017 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2021 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2025 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2027 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2032 if (g_ventoy_img_list
)
2034 tail
= *(node
->tail
);
2040 g_ventoy_img_list
= img
;
2043 img
->id
= g_ventoy_img_count
;
2045 if (node
&& NULL
== node
->firstiso
)
2047 node
->firstiso
= img
;
2058 *((img_info
**)(node
->tail
)) = img
;
2059 g_ventoy_img_count
++;
2061 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2063 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2066 img
->tip1
= tip
->tip1
;
2067 img
->tip2
= tip
->tip2
;
2070 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2073 img
->class = g_menu_class
[type
];
2075 img
->menu_prefix
= g_menu_prefix
[type
];
2077 if (img_type_iso
== type
)
2079 if (ventoy_plugin_check_memdisk(img
->path
))
2081 img
->menu_prefix
= "miso";
2084 else if (img_type_img
== type
)
2086 if (ventoy_plugin_check_memdisk(img
->path
))
2088 img
->menu_prefix
= "mimg";
2092 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2099 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2101 int len
= GRUB_UINT_MAX
;
2102 const char *value
= NULL
;
2103 char name
[32] = {0};
2104 char plat
[32] = {0};
2105 char guidstr
[32] = {0};
2106 ventoy_guid guid
= VENTOY_GUID
;
2107 const char *fmt1
= NULL
;
2108 const char *fmt2
= NULL
;
2109 const char *fmt3
= NULL
;
2110 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2111 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2112 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2113 const char fmtcode
[]={
2114 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2115 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2116 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2117 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2118 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2119 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2122 grub_memset(name
, 0, sizeof(name
));
2123 puint
[0] = grub_swap_bytes32(0x56454e54);
2124 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2125 puint
[2] = grub_swap_bytes32(0x45525349);
2126 puint
[1] = grub_swap_bytes32(0x4f595f56);
2127 value
= ventoy_get_env(name
);
2129 grub_memset(name
, 0, sizeof(name
));
2130 puint
[1] = grub_swap_bytes32(0x5f544f50);
2131 puint
[0] = grub_swap_bytes32(0x56544c45);
2132 fmt1
= ventoy_get_env(name
);
2138 grub_memset(name
, 0, sizeof(name
));
2139 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2140 puint
[0] = grub_swap_bytes32(0x56544c45);
2141 fmt2
= ventoy_get_env(name
);
2143 grub_memset(name
, 0, sizeof(name
));
2144 puint
[1] = grub_swap_bytes32(0x5f434c52);
2145 puint
[0] = grub_swap_bytes32(0x56544c45);
2146 fmt3
= ventoy_get_env(name
);
2148 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2150 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2152 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2153 #pragma GCC diagnostic push
2154 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2155 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2156 fmt1
? fmt1
: fmtdata
,
2157 fmt2
? fmt2
: fmtdata
+ 4,
2158 value
? value
: "", plat
, guidstr
,
2159 fmt3
? fmt3
: fmtdata
+ 6);
2160 #pragma GCC diagnostic pop
2162 grub_memset(name
, 0, sizeof(name
));
2163 puint
[0] = grub_swap_bytes32(0x76746f79);
2164 puint
[2] = grub_swap_bytes32(0x656e7365);
2165 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2166 ventoy_set_env(name
, guidstr
);
2172 ventoy_password_get (char buf
[], unsigned buf_size
)
2174 unsigned i
, cur_len
= 0;
2176 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2180 key
= grub_getkey ();
2181 if (key
== '\n' || key
== '\r')
2184 if (key
== GRUB_TERM_ESC
)
2194 grub_term_restore_pos (pos
);
2195 for (i
= 0; i
< cur_len
; i
++)
2197 grub_term_restore_pos (pos
);
2199 for (i
= 0; i
< cur_len
; i
++)
2206 if (!grub_isprint (key
))
2209 if (cur_len
+ 2 < buf_size
)
2210 buf
[cur_len
++] = key
;
2215 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2221 return (key
!= GRUB_TERM_ESC
);
2224 static int ventoy_get_password(char buf
[], unsigned buf_size
)
2226 const char *env
= NULL
;
2228 env
= grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2229 if (env
&& env
[0] == '0' && env
[1] == 0)
2231 return grub_password_get(buf
, buf_size
);
2235 return ventoy_password_get(buf
, buf_size
);
2239 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2243 grub_uint8_t md5
[16];
2247 grub_memset(input
, 0, sizeof(input
));
2249 grub_printf("Enter password: ");
2252 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2254 ventoy_get_password(input
, 128);
2255 if (grub_strcmp(pwd
->text
, input
) == 0)
2260 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2262 ventoy_get_password(input
, 128);
2263 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2264 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2269 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2271 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2272 ventoy_get_password(input
+ offset
, 128);
2274 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2275 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2281 grub_printf("Invalid password!\n\n");
2288 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2290 img_info
*minimg
= NULL
;
2291 img_info
*img
= (img_info
*)(node
->firstiso
);
2293 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2295 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2310 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2312 img_iterator_node
*Minchild
= NULL
;
2313 img_iterator_node
*child
= node
->firstchild
;
2315 while (child
&& child
->parent
== node
)
2317 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2321 child
= child
->next
;
2326 Minchild
->select
= 1;
2332 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2335 img_info
*img
= NULL
;
2336 const char *dir_class
= NULL
;
2337 const char *dir_alias
= NULL
;
2338 img_iterator_node
*child
= NULL
;
2339 const menu_tip
*tip
= NULL
;
2341 if (node
->isocnt
== 0 || node
->done
== 1)
2346 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2348 offset
= node
->parent
->dirlen
;
2351 if (node
== &g_img_iterator_head
)
2353 if (g_default_menu_mode
== 0)
2355 if (g_tree_view_menu_style
== 0)
2357 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2358 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2359 " echo 'return ...' \n"
2360 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2364 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2365 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2366 " echo 'return ...' \n"
2367 "}\n", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2371 g_tree_script_pre
= g_tree_script_pos
;
2375 node
->dir
[node
->dirlen
- 1] = 0;
2376 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2379 dir_class
= "vtoydir";
2382 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2384 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2387 if (g_tree_view_menu_style
== 0)
2389 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2390 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2391 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2395 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2396 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2397 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2402 dir_alias
= node
->dir
+ offset
;
2404 if (g_tree_view_menu_style
== 0)
2406 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2407 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2408 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2412 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2413 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2414 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2418 if (g_tree_view_menu_style
== 0)
2420 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2421 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2422 " echo 'return ...' \n"
2423 "}\n", "<--", node
->dir
);
2427 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2428 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2429 " echo 'return ...' \n"
2434 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2436 ventoy_dynamic_tree_menu(child
);
2439 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2441 if (g_tree_view_menu_style
== 0)
2443 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2444 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2447 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2448 img
->unsupport
? "[***********] " : "",
2449 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2451 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2455 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2456 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2459 img
->unsupport
? "[***********] " : "",
2460 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2462 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2466 if (node
!= &g_img_iterator_head
)
2468 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2475 static int ventoy_set_default_menu(void)
2481 const char *strdata
= NULL
;
2482 img_info
*cur
= NULL
;
2483 img_info
*default_node
= NULL
;
2484 const char *default_image
= NULL
;
2486 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2487 if (default_image
&& default_image
[0] == '/')
2489 img_len
= grub_strlen(default_image
);
2491 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2493 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2505 if (0 == g_default_menu_mode
)
2507 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2511 def
= grub_strdup(default_image
);
2517 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2519 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2520 if (strdata
&& strdata
[0] == '/')
2522 pos
= def
+ grub_strlen(strdata
);
2533 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2536 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2540 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2548 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2550 img_info
*next
= NULL
;
2551 img_info
*cur
= g_ventoy_img_list
;
2564 g_ventoy_img_list
= NULL
;
2565 g_ventoy_img_count
= 0;
2567 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2570 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2573 img_info
*cur
= g_ventoy_img_list
;
2577 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2579 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2582 img_id
= grub_strtol(args
[0], NULL
, 10);
2583 if (img_id
>= g_ventoy_img_count
)
2585 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2588 debug("Find image %ld name \n", img_id
);
2590 while (cur
&& img_id
> 0)
2598 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2601 debug("image name is %s\n", cur
->name
);
2603 grub_env_set(args
[1], cur
->name
);
2605 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2608 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2612 img_info
*cur
= g_ventoy_img_list
;
2618 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2621 len
= (int)grub_strlen(args
[0]);
2625 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2634 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2637 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2638 grub_env_set("chosen", id
);
2639 grub_env_export("chosen");
2641 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2644 static char g_fake_vlnk_src
[512];
2645 static char g_fake_vlnk_dst
[512];
2646 static grub_uint64_t g_fake_vlnk_size
;
2647 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2653 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2655 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2656 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2658 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2660 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2663 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2669 g_fake_vlnk_src
[0] = 0;
2670 g_fake_vlnk_dst
[0] = 0;
2671 g_fake_vlnk_size
= 0;
2672 grub_file_vtoy_vlnk(NULL
, NULL
);
2674 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2678 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2683 const char *id
= NULL
;
2684 img_info
*cur
= NULL
;
2688 if (argc
< 1 || argc
> 3)
2690 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2693 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2695 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2696 grub_env_set(args
[0], pos
);
2699 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2700 grub_env_set(args
[1], value
);
2705 for (last
= pos
; *pos
; pos
++)
2712 grub_env_set(args
[2], last
+ 1);
2718 id
= grub_env_get("chosen");
2720 pos
= grub_strstr(id
, "VID_");
2723 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2727 cur
= g_ventoy_img_list
;
2732 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2735 grub_env_set(args
[0], cur
->path
);
2739 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2740 grub_env_set(args
[1], value
);
2745 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2746 grub_env_set(args
[2], cur
->name
);
2750 g_svd_replace_offset
= 0;
2752 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2756 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2760 grub_device_t dev
= NULL
;
2761 img_info
*cur
= NULL
;
2762 img_info
*tail
= NULL
;
2763 img_info
*min
= NULL
;
2764 img_info
*head
= NULL
;
2765 const char *strdata
= NULL
;
2766 char *device_name
= NULL
;
2768 img_iterator_node
*node
= NULL
;
2769 img_iterator_node
*tmp
= NULL
;
2775 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2778 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2780 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2785 g_enumerate_time_checked
= 0;
2786 g_enumerate_start_time_ms
= grub_get_time_ms();
2788 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2789 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2791 g_filt_dot_underscore_file
= 1;
2794 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2795 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2797 g_sort_case_sensitive
= 1;
2800 device_name
= grub_file_get_device_name(args
[0]);
2806 g_enum_dev
= dev
= grub_device_open(device_name
);
2812 g_enum_fs
= fs
= grub_fs_probe(dev
);
2818 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2820 debug("unsupported fs:<%s>\n", fs
->name
);
2821 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2825 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2827 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2828 if (strdata
&& strdata
[0] == '1')
2830 g_default_menu_mode
= 1;
2833 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2835 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2837 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2838 if (strdata
&& strdata
[0] == '/')
2840 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2841 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2843 g_img_iterator_head
.dir
[len
++] = '/';
2845 g_img_iterator_head
.dirlen
= len
;
2849 g_img_iterator_head
.dirlen
= 1;
2850 grub_strcpy(g_img_iterator_head
.dir
, "/");
2853 g_img_iterator_head
.tail
= &tail
;
2855 if (g_img_max_search_level
< 0)
2857 g_img_max_search_level
= GRUB_INT_MAX
;
2858 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2859 if (strdata
&& ventoy_is_decimal(strdata
))
2861 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2865 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2866 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2867 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2868 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2869 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2870 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2872 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2874 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2877 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2878 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2880 g_tree_view_menu_style
= 1;
2883 ventoy_set_default_menu();
2885 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2887 ventoy_dynamic_tree_menu(node
);
2891 node
= g_img_iterator_head
.next
;
2899 /* sort image list by image name */
2900 while (g_ventoy_img_list
)
2902 min
= g_ventoy_img_list
;
2903 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2905 if (ventoy_cmp_img(min
, cur
) > 0)
2913 min
->prev
->next
= min
->next
;
2918 min
->next
->prev
= min
->prev
;
2921 if (min
== g_ventoy_img_list
)
2923 g_ventoy_img_list
= min
->next
;
2941 g_ventoy_img_list
= head
;
2943 if (g_default_menu_mode
== 1)
2945 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2946 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2947 " echo 'return ...' \n"
2948 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_TREEVIEW"));
2951 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2953 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2954 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2957 cur
->unsupport
? "[***********] " : "",
2958 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2960 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2963 g_tree_script_buf
[g_tree_script_pos
] = 0;
2964 g_list_script_buf
[g_list_script_pos
] = 0;
2966 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2967 grub_env_set(args
[1], buf
);
2971 check_free(device_name
, grub_free
);
2972 check_free(dev
, grub_device_close
);
2974 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2977 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2984 device_name
= grub_file_get_device_name(filename
);
2996 pos2
= grub_strstr(pos
, ",");
2999 pos2
= grub_strstr(pos
, ")");
3007 disk
= grub_disk_open(pos
);
3010 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3011 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3012 grub_disk_close(disk
);
3019 grub_free(device_name
);
3023 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3025 eltorito_descriptor desc
;
3027 grub_memset(&desc
, 0, sizeof(desc
));
3028 grub_file_seek(file
, 17 * 2048);
3029 grub_file_read(file
, &desc
, sizeof(desc
));
3031 if (desc
.type
!= 0 || desc
.version
!= 1)
3036 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3037 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3045 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3047 grub_uint8_t buf
[512];
3049 grub_file_seek(file
, sector
* 2048);
3050 grub_file_read(file
, buf
, sizeof(buf
));
3052 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3053 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3055 return *((grub_uint32_t
*)(buf
+ 40));
3061 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3065 grub_uint8_t buf
[512];
3066 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3068 grub_file_seek(file
, sector
* 2048);
3069 grub_file_read(file
, buf
, sizeof(buf
));
3071 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3073 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3077 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3082 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3084 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3086 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3090 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3092 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3097 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3099 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3101 if (buf
[36] == parttype
[i
])
3103 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3109 debug("%s does not contain efi eltorito\n", file
->name
);
3113 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3116 const char *fs
= NULL
;
3117 const char *val
= NULL
;
3118 const char *cdprompt
= NULL
;
3120 grub_uint8_t chksum
= 0;
3123 disk
= file
->device
->disk
;
3124 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3126 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3127 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3128 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3130 pos
= grub_strstr(file
->name
, "/");
3136 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3138 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3140 param
->vtoy_img_size
= file
->size
;
3142 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3143 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3145 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3147 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3148 param
->vtoy_reserved
[4] = 0;
3149 if (g_ventoy_chain_type
== 1) /* Windows */
3151 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3152 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3154 param
->vtoy_reserved
[4] = 1;
3158 fs
= ventoy_get_env("ventoy_fs_probe");
3159 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3161 param
->vtoy_reserved
[3] = 1;
3164 param
->vtoy_reserved
[5] = 0;
3165 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3166 if (val
&& val
[0] == '1' && val
[1] == 0)
3168 param
->vtoy_reserved
[5] = 1;
3171 /* ventoy_disk_signature used for vlnk */
3172 param
->vtoy_reserved
[6] = file
->vlnk
;
3173 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3175 /* calculate checksum */
3176 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3178 chksum
+= *((grub_uint8_t
*)param
+ i
);
3180 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3185 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3187 grub_uint32_t i
= 0;
3188 grub_uint64_t total
= 0;
3189 grub_uint64_t fileblk
= 0;
3190 ventoy_img_chunk
*chunk
= NULL
;
3192 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3194 chunk
= chunklist
->chunk
+ i
;
3196 if (chunk
->disk_start_sector
<= start
)
3198 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3202 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3205 fileblk
= (file
->size
+ 511) / 512;
3207 if (total
!= fileblk
)
3209 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3210 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3212 debug("maybe img file to be processed.\n");
3222 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3226 grub_uint32_t i
= 0;
3227 grub_uint32_t sector
= 0;
3228 grub_uint32_t count
= 0;
3229 grub_off_t size
= 0;
3230 grub_off_t read
= 0;
3232 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3233 if (fs_type
== ventoy_fs_exfat
)
3235 grub_fat_get_file_chunk(start
, file
, chunklist
);
3237 else if (fs_type
== ventoy_fs_ext
)
3239 grub_ext_get_file_chunk(start
, file
, chunklist
);
3243 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3244 file
->read_hook_data
= chunklist
;
3246 for (size
= file
->size
; size
> 0; size
-= read
)
3248 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3249 grub_file_read(file
, NULL
, read
);
3252 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3254 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3255 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3258 if (ventoy_fs_udf
== fs_type
)
3260 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3262 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3263 chunklist
->chunk
[i
].img_start_sector
= sector
;
3264 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3270 len
= (int)grub_strlen(file
->name
);
3271 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3272 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3273 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3274 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3276 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3278 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3288 chunklist
->chunk
[i
].img_start_sector
= sector
;
3289 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3297 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3301 grub_disk_addr_t start
;
3306 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3309 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3312 g_conf_replace_count
= 0;
3313 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3314 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3316 if (g_img_chunk_list
.chunk
)
3318 grub_free(g_img_chunk_list
.chunk
);
3321 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3323 grub_file_close(file
);
3324 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3327 /* get image chunk data */
3328 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3329 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3330 if (NULL
== g_img_chunk_list
.chunk
)
3332 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3335 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3336 g_img_chunk_list
.cur_chunk
= 0;
3338 start
= file
->device
->disk
->partition
->start
;
3340 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3342 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3343 grub_file_close(file
);
3347 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3350 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3351 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3352 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3355 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3359 grub_uint64_t offset
= 0;
3360 grub_uint32_t align
= 0;
3361 grub_file_t file
= NULL
;
3362 conf_replace
*node
= NULL
;
3363 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3364 ventoy_grub_param_file_replace
*replace
= NULL
;
3370 debug("select conf replace argc:%d\n", argc
);
3377 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3380 debug("Conf replace not found for %s\n", args
[1]);
3384 debug("Find %d conf replace for %s\n", n
, args
[1]);
3386 g_conf_replace_count
= n
;
3387 for (i
= 0; i
< n
; i
++)
3391 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3394 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3395 grub_file_close(file
);
3397 else if (node
->img
> 0)
3403 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3407 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3410 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3414 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3416 if (align
> vtoy_max_replace_file_size
)
3418 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3419 grub_file_close(file
);
3423 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3424 grub_file_close(file
);
3425 g_conf_replace_new_len
[i
] = (int)file
->size
;
3426 g_conf_replace_new_len_align
[i
] = align
;
3428 g_conf_replace_node
[i
] = node
;
3429 g_conf_replace_offset
[i
] = offset
+ 2;
3433 replace
= &(g_grub_param
->img_replace
[i
]);
3434 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3435 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3436 replace
->old_name_cnt
++;
3439 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3443 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3446 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3451 const char *ch
= var
;
3458 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3465 debug("Invalid variable letter <%c>\n", *ch
);
3472 debug("Invalid variable length:%d <%s>\n", n
, var
);
3476 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3485 grub_printf("\n=================== Variables Expansion ===================\n\n");
3488 grub_printf("<%s>: ", var
);
3491 while (i
< (len
- 1))
3494 if ((c
== '\n') || (c
== '\r'))
3504 else if (grub_isprint(c
))
3506 if (i
+ 1 < (len
- 1))
3508 grub_printf("%c", c
);
3518 expand
[i
- 1] = ' ';
3519 grub_printf("\r<%s>: %s", var
, expand
);
3522 grub_printf("\r<%s>: %s", var
, expand
);
3534 grub_snprintf(expand
, len
, "$$%s$$", var
);
3540 static int ventoy_auto_install_var_expand(install_template
*node
)
3548 char *newbuf
= NULL
;
3549 char *curline
= NULL
;
3550 char *nextline
= NULL
;
3551 grub_uint8_t
*code
= NULL
;
3553 var_node
*CurNode
= NULL
;
3554 var_node
*pVarList
= NULL
;
3556 code
= (grub_uint8_t
*)node
->filebuf
;
3558 if (node
->filelen
>= VTOY_SIZE_1MB
)
3560 debug("auto install script too long %d\n", node
->filelen
);
3564 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3566 debug("UCS-2 encoding NOT supported\n");
3570 start
= grub_strstr(node
->filebuf
, "$$");
3573 debug("no need to expand variable, no start.\n");
3577 end
= grub_strstr(start
+ 2, "$$");
3580 debug("no need to expand variable, no end.\n");
3584 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3585 newbuf
= grub_malloc(newlen
);
3588 debug("Failed to alloc newbuf %d\n", newlen
);
3592 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3594 nextline
= ventoy_get_line(curline
);
3596 start
= grub_strstr(curline
, "$$");
3599 end
= grub_strstr(start
+ 2, "$$");
3605 VTOY_APPEND_NEWBUF(curline
);
3607 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3609 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3611 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3618 value
[sizeof(value
) - 1] = 0;
3619 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3623 CurNode
= grub_zalloc(sizeof(var_node
));
3626 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3627 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3628 CurNode
->next
= pVarList
;
3634 VTOY_APPEND_NEWBUF(value
);
3636 VTOY_APPEND_NEWBUF(end
+ 2);
3640 VTOY_APPEND_NEWBUF(curline
);
3643 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3645 newbuf
[pos
- 1] = '\n';
3649 newbuf
[pos
++] = '\n';
3653 grub_free(node
->filebuf
);
3654 node
->filebuf
= newbuf
;
3655 node
->filelen
= pos
;
3659 CurNode
= pVarList
->next
;
3660 grub_free(pVarList
);
3667 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3673 grub_file_t file
= NULL
;
3674 char configfile
[128];
3675 install_template
*node
= NULL
;
3681 debug("select auto installation argc:%d\n", argc
);
3688 node
= ventoy_plugin_find_install_template(args
[0]);
3691 debug("Auto install template not found for %s\n", args
[0]);
3695 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3697 defidx
= node
->autosel
;
3698 if (node
->timeout
< 0)
3700 node
->cursel
= node
->autosel
- 1;
3701 debug("Auto install template auto select %d\n", node
->autosel
);
3706 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3712 if (node
->timeout
> 0)
3714 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3717 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3718 " echo %s\n}\n", "");
3720 for (i
= 0; i
< node
->templatenum
; i
++)
3722 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3724 ventoy_get_vmenu_title("VTLANG_AUTOINS_USE"),
3725 node
->templatepath
[i
].path
);
3728 g_ventoy_menu_esc
= 1;
3729 g_ventoy_suppress_esc
= 1;
3730 g_ventoy_suppress_esc_default
= defidx
;
3732 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3733 grub_script_execute_sourcecode(configfile
);
3735 g_ventoy_menu_esc
= 0;
3736 g_ventoy_suppress_esc
= 0;
3737 g_ventoy_suppress_esc_default
= 1;
3741 node
->cursel
= g_ventoy_last_entry
- 1;
3744 grub_check_free(node
->filebuf
);
3747 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3749 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3750 node
->templatepath
[node
->cursel
].path
);
3753 node
->filebuf
= grub_malloc(file
->size
+ 8);
3756 grub_file_read(file
, node
->filebuf
, file
->size
);
3757 grub_file_close(file
);
3759 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3760 node
->filelen
= (int)file
->size
;
3762 ventoy_auto_install_var_expand(node
);
3767 debug("Failed to open auto install script <%s%s>\n",
3768 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3772 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3775 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3781 char configfile
[128];
3782 persistence_config
*node
;
3788 debug("select persistence argc:%d\n", argc
);
3795 node
= ventoy_plugin_find_persistent(args
[0]);
3798 debug("Persistence image not found for %s\n", args
[0]);
3802 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3804 defidx
= node
->autosel
;
3805 if (node
->timeout
< 0)
3807 node
->cursel
= node
->autosel
- 1;
3808 debug("Persistence image auto select %d\n", node
->autosel
);
3813 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3819 if (node
->timeout
> 0)
3821 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3824 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_PERSISTENCE\" --class=\"sel_persistence\" {\n"
3825 " echo %s\n}\n", "");
3827 for (i
= 0; i
< node
->backendnum
; i
++)
3829 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3831 ventoy_get_vmenu_title("VTLANG_PERSIST_USE"),
3832 node
->backendpath
[i
].path
);
3836 g_ventoy_menu_esc
= 1;
3837 g_ventoy_suppress_esc
= 1;
3838 g_ventoy_suppress_esc_default
= defidx
;
3840 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3841 grub_script_execute_sourcecode(configfile
);
3843 g_ventoy_menu_esc
= 0;
3844 g_ventoy_suppress_esc
= 0;
3845 g_ventoy_suppress_esc_default
= 1;
3849 node
->cursel
= g_ventoy_last_entry
- 1;
3851 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3854 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3857 ventoy_img_chunk
*cur
;
3863 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3865 cur
= g_img_chunk_list
.chunk
+ i
;
3866 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3867 cur
->img_start_sector
, cur
->img_end_sector
,
3868 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3872 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3875 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3879 ventoy_img_chunk_list chunklist
;
3884 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3887 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3890 /* get image chunk data */
3891 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3892 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3893 if (NULL
== chunklist
.chunk
)
3895 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3898 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3899 chunklist
.cur_chunk
= 0;
3901 ventoy_get_block_list(file
, &chunklist
, 0);
3903 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3905 grub_printf("########## UNSUPPORTED ###############\n");
3908 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3910 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3912 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3913 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3916 grub_printf("\n==================================\n");
3918 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3920 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3921 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3922 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3923 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3924 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3928 grub_free(chunklist
.chunk
);
3929 grub_file_close(file
);
3931 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3934 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3937 ventoy_grub_param_file_replace
*replace
= NULL
;
3945 replace
= &(g_grub_param
->file_replace
);
3946 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3948 replace
->old_name_cnt
= 0;
3949 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3951 replace
->old_name_cnt
++;
3952 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3955 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3958 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3961 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3964 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3970 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3971 grub_env_set(args
[0], buf
);
3974 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3977 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3985 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3986 grub_printf("%s", g_list_script_buf
);
3990 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3991 grub_printf("%s", g_tree_script_buf
);
3997 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3999 img_info
*cur
= g_ventoy_img_list
;
4007 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4008 grub_printf("name:<%s>\n\n", cur
->name
);
4015 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4021 ventoy_plugin_dump_injection();
4026 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4032 ventoy_plugin_dump_auto_install();
4037 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4043 ventoy_plugin_dump_persistence();
4048 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4054 len1
= (int)grub_strlen(filename
);
4055 len2
= (int)grub_strlen(suffix
);
4062 for (i
= len1
- 1; i
>= 0; i
--)
4064 if (filename
[i
] == '.')
4075 if (filename
[i
- len2
- 1] != '_')
4080 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4088 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4094 if (argc
!= 1 && argc
!= 2)
4099 if (args
[0][0] == '0')
4101 if (g_ventoy_memdisk_mode
)
4106 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4113 else if (args
[0][0] == '1')
4115 return g_ventoy_iso_raw
? 0 : 1;
4117 else if (args
[0][0] == '2')
4119 return g_ventoy_iso_uefi_drv
? 0 : 1;
4121 else if (args
[0][0] == '3')
4123 if (g_ventoy_grub2_mode
)
4128 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4135 else if (args
[0][0] == '4')
4137 if (g_ventoy_wimboot_mode
)
4142 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4153 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4155 static int configfile_mode
= 0;
4156 char memfile
[128] = {0};
4163 * args[0]: 0:normal 1:configfile
4164 * args[1]: 0:list_buf 1:tree_buf
4169 debug("Invalid argc %d\n", argc
);
4175 if (args
[0][0] == '0')
4177 if (args
[1][0] == '0')
4179 grub_script_execute_sourcecode(g_list_script_buf
);
4183 grub_script_execute_sourcecode(g_tree_script_buf
);
4188 if (configfile_mode
)
4190 debug("Now already in F3 mode %d\n", configfile_mode
);
4194 if (args
[1][0] == '0')
4196 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4197 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4201 g_ventoy_last_entry
= -1;
4202 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4203 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4206 configfile_mode
= 1;
4207 grub_script_execute_sourcecode(memfile
);
4208 configfile_mode
= 0;
4214 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4225 g_ventoy_case_insensitive
= 1;
4226 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4227 g_ventoy_case_insensitive
= 0;
4233 grub_file_close(file
);
4239 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4244 const char *isopath
= NULL
;
4246 ventoy_mbr_head mbr
;
4253 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4256 isopath
= grub_env_get("vtoy_iso_part");
4259 debug("isopath is null %p\n", isopath
);
4263 debug("isopath is %s\n", isopath
);
4265 for (id
= 0; id
< 30 && (find
== 0); id
++)
4267 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4268 if (grub_strstr(isopath
, hdname
))
4270 debug("skip %s ...\n", hdname
);
4274 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4276 disk
= grub_disk_open(hdname
);
4279 debug("%s not exist\n", hdname
);
4283 grub_memset(&mbr
, 0, sizeof(mbr
));
4284 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4286 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4288 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4289 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4292 grub_env_set(args
[0], hdname
);
4296 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4300 debug("read %s failed\n", hdname
);
4303 grub_disk_close(disk
);
4309 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4320 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4323 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4326 debug("failed to open file %s\n", args
[0]);
4330 buf
= grub_malloc(len
);
4337 grub_file_read(file
, buf
, len
- 1);
4339 ventoy_get_line(buf
);
4340 ventoy_set_env(args
[1], buf
);
4344 grub_check_free(buf
);
4345 grub_file_close(file
);
4350 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4352 grub_uint64_t end_max
= 0;
4353 int *pCnt
= (int *)data
;
4358 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4359 "0 %llu linear /dev/ventoy %llu\n",
4360 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4362 end_max
= (partition
->len
+ partition
->start
) * 512;
4363 if (end_max
> g_part_end_max
)
4365 g_part_end_max
= end_max
;
4371 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4374 char *device_name
= NULL
;
4375 grub_device_t dev
= NULL
;
4380 g_part_list_pos
= 0;
4382 grub_env_unset("vtoy_img_part_file");
4389 device_name
= grub_file_get_device_name(args
[0]);
4392 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4396 dev
= grub_device_open(device_name
);
4399 debug("grub_device_open failed, %s\n", device_name
);
4403 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4405 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4406 grub_env_set("vtoy_img_part_file", buf
);
4408 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4409 grub_env_set("vtoy_img_part_cnt", buf
);
4411 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4412 grub_env_set("vtoy_img_max_part_end", buf
);
4416 check_free(device_name
, grub_free
);
4417 check_free(dev
, grub_device_close
);
4423 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4434 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4437 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4440 debug("failed to open file %s\n", args
[0]);
4444 buf
= grub_malloc(file
->size
+ 1);
4450 buf
[file
->size
] = 0;
4451 grub_file_read(file
, buf
, file
->size
);
4453 if (grub_strstr(buf
, args
[1]))
4460 grub_check_free(buf
);
4461 grub_file_close(file
);
4466 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4472 ventoy_iso9660_vd pvd
;
4479 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4482 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4485 debug("failed to open file %s\n", args
[0]);
4489 grub_file_seek(file
, 16 * 2048);
4490 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4491 if (len
!= sizeof(pvd
))
4493 debug("failed to read pvd %d\n", len
);
4497 grub_memset(buf
, 0, sizeof(buf
));
4498 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4499 ventoy_set_env(args
[1], buf
);
4501 grub_memset(buf
, 0, sizeof(buf
));
4502 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4503 ventoy_set_env(args
[2], buf
);
4507 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4508 ventoy_set_env(args
[3], buf
);
4511 grub_file_close(file
);
4516 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4527 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4530 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4533 debug("failed to open file %s\n", args
[0]);
4537 grub_memset(buf
, 0, sizeof(buf
));
4538 grub_file_seek(file
, 16 * 2048 + 813);
4539 len
= (int)grub_file_read(file
, buf
, 17);
4542 debug("failed to read create date %d\n", len
);
4546 ventoy_set_env(args
[1], buf
);
4549 grub_file_close(file
);
4554 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4560 ventoy_env_hook_root(1);
4565 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4571 ventoy_env_hook_root(0);
4576 #ifdef GRUB_MACHINE_EFI
4577 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4582 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4588 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4589 if (var
&& *var
== 1)
4597 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4606 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4611 grub_uint64_t FileSectors
= 0;
4612 ventoy_gpt_info
*gpt
= NULL
;
4613 ventoy_part_table
*pt
= NULL
;
4614 grub_uint8_t zeroguid
[16] = {0};
4619 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4622 debug("failed to open file %s\n", args
[0]);
4626 if (file
->size
% 512)
4628 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4632 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4638 FileSectors
= file
->size
/ 512;
4640 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4641 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4643 debug("This is EFI partition table\n");
4645 for (i
= 0; i
< 128; i
++)
4647 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4649 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4651 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4652 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4660 debug("This is MBR partition table\n");
4662 for (i
= 0; i
< 4; i
++)
4664 pt
= gpt
->MBR
.PartTbl
+ i
;
4665 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4667 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4668 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4669 (ulonglong
)FileSectors
);
4678 grub_file_close(file
);
4679 grub_check_free(gpt
);
4680 grub_errno
= GRUB_ERR_NONE
;
4684 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4693 for (i
= 0; i
< 500; i
++)
4695 ret
= grub_getkey_noblock();
4696 if (ret
== GRUB_TERM_NO_KEY
)
4705 grub_printf("\n\n Still have key input after clear.\n");
4713 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4720 int image_sector_size
;
4722 ventoy_chain_head
*chain
;
4723 ventoy_img_chunk
*chunk
;
4724 ventoy_os_param
*osparam
;
4725 ventoy_image_location
*location
;
4726 ventoy_image_disk_region
*region
;
4727 struct grub_acpi_table_header
*acpi
;
4736 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4738 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4744 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4746 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4748 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4752 img_chunk_num
= chain
->img_chunk_num
;
4754 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4755 datalen
= sizeof(ventoy_os_param
) + loclen
;
4757 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4758 acpi
= grub_zalloc(buflen
);
4764 /* Step1: Fill acpi table header */
4765 grub_memcpy(acpi
->signature
, "VTOY", 4);
4766 acpi
->length
= buflen
;
4768 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4769 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4771 acpi
->creator_id
[0] = 1;
4772 acpi
->creator_rev
= 1;
4774 /* Step2: Fill data */
4775 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4776 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4777 osparam
->vtoy_img_location_addr
= 0;
4778 osparam
->vtoy_img_location_len
= loclen
;
4779 osparam
->chksum
= 0;
4780 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4782 location
= (ventoy_image_location
*)(osparam
+ 1);
4783 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4784 location
->image_sector_size
= image_sector_size
;
4785 location
->disk_sector_size
= chain
->disk_sector_size
;
4786 location
->region_count
= img_chunk_num
;
4788 region
= location
->regions
;
4789 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4790 if (512 == image_sector_size
)
4792 for (i
= 0; i
< img_chunk_num
; i
++)
4794 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4795 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4796 region
->disk_start_sector
= chunk
->disk_start_sector
;
4803 for (i
= 0; i
< img_chunk_num
; i
++)
4805 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4806 region
->image_start_sector
= chunk
->img_start_sector
;
4807 region
->disk_start_sector
= chunk
->disk_start_sector
;
4813 /* Step3: Fill acpi checksum */
4815 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4817 /* load acpi table */
4818 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4819 grub_script_execute_sourcecode(cmd
);
4823 VENTOY_CMD_RETURN(0);
4826 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4832 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4833 g_ventoy_last_entry
= -1;
4838 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4844 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4849 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4851 const char *pos
= filename
+ 1;
4859 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4861 grub_strncpy((char *)data
, filename
, 128);
4872 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4875 char *device_name
= NULL
;
4876 grub_device_t dev
= NULL
;
4877 grub_fs_t fs
= NULL
;
4878 char buf
[128] = {0};
4884 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4888 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4890 device_name
= grub_file_get_device_name(args
[0]);
4893 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4897 dev
= grub_device_open(device_name
);
4900 debug("grub_device_open failed, %s\n", device_name
);
4904 fs
= grub_fs_probe(dev
);
4907 debug("grub_fs_probe failed, %s\n", device_name
);
4911 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4915 ventoy_set_env(args
[2], buf
);
4922 check_free(device_name
, grub_free
);
4923 check_free(dev
, grub_device_close
);
4928 int ventoy_load_part_table(const char *diskname
)
4935 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4936 if (!g_ventoy_part_info
)
4941 disk
= grub_disk_open(diskname
);
4944 debug("Failed to open disk %s\n", diskname
);
4948 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4950 g_ventoy_disk_bios_id
= disk
->id
;
4952 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4953 grub_disk_close(disk
);
4955 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4956 dev
= grub_device_open(name
);
4959 /* Check for official Ventoy device */
4960 ret
= ventoy_check_official_device(dev
);
4961 grub_device_close(dev
);
4969 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4970 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4975 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4982 ret
= ventoy_load_part_table(args
[0]);
4988 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4989 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4994 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4997 const char *vcfg
= NULL
;
5002 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5005 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5006 grub_env_set(args
[1], vcfg
);
5011 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5019 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5022 grub_uint8_t zeroguid
[16] = {0};
5027 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5030 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5032 if (id
>= 1 && id
<= 128)
5034 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5042 if (id
>= 1 && id
<= 4)
5044 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5054 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5057 char *device_name
= NULL
;
5058 grub_device_t dev
= NULL
;
5059 grub_fs_t fs
= NULL
;
5064 debug("get fs label for %s\n", args
[0]);
5068 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5072 device_name
= grub_file_get_device_name(args
[0]);
5075 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5079 dev
= grub_device_open(device_name
);
5082 debug("grub_device_open failed, %s\n", device_name
);
5086 fs
= grub_fs_probe(dev
);
5087 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5089 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5093 fs
->fs_label(dev
, &label
);
5096 debug("label=<%s>\n", label
);
5097 ventoy_set_env(args
[1], label
);
5105 check_free(device_name
, grub_free
);
5106 check_free(dev
, grub_device_close
);
5111 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5115 grub_snprintf((char *)data
, 256, "%s", filename
);
5122 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5124 if (info
->dir
&& filename
&& filename
[0] != '.')
5126 grub_snprintf((char *)data
, 256, "%s", filename
);
5133 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5136 char *device_name
= NULL
;
5137 grub_device_t dev
= NULL
;
5138 grub_fs_t fs
= NULL
;
5139 char name
[256] ={0};
5143 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5147 device_name
= grub_file_get_device_name(args
[0]);
5150 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5154 dev
= grub_device_open(device_name
);
5157 debug("grub_device_open failed, %s\n", device_name
);
5161 fs
= grub_fs_probe(dev
);
5164 debug("grub_fs_probe failed, %s\n", device_name
);
5168 fs
->fs_dir(dev
, args
[1], hook
, name
);
5171 ventoy_set_env(args
[2], name
);
5178 check_free(device_name
, grub_free
);
5179 check_free(dev
, grub_device_close
);
5184 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5187 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5190 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5193 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5196 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5206 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5210 for (pos
= args
[0]; *pos
; pos
++)
5224 grub_env_set(args
[1], args
[0]);
5234 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5244 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5249 len
= (int)grub_strlen(buf
);
5250 for (i
= len
; i
> 0; i
--)
5252 if (buf
[i
- 1] == '/')
5254 grub_env_set(args
[1], buf
+ i
);
5259 grub_env_set(args
[1], buf
);
5264 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5266 struct grub_video_mode_info info
;
5273 if (!g_video_mode_list
)
5275 ventoy_enum_video_mode();
5278 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5280 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5284 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5287 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5289 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5290 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5292 VENTOY_CMD_RETURN(0);
5295 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5297 struct grub_video_mode_info info
;
5304 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5306 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5310 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5313 grub_env_set(args
[0], buf
);
5315 VENTOY_CMD_RETURN(0);
5318 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5326 if (!g_video_mode_list
)
5331 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5332 if (id
< g_video_mode_num
)
5334 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5335 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5338 grub_env_set(args
[1], buf
);
5340 VENTOY_CMD_RETURN(0);
5343 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5346 grub_uint32_t loadsector
= 0;
5349 grub_uint32_t boot_catlog
= 0;
5350 grub_uint8_t buf
[512];
5356 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5360 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5363 debug("failed to open %s\n", args
[0]);
5367 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5368 if (boot_catlog
== 0)
5370 debug("No bootcatlog found\n");
5371 grub_file_close(file
);
5375 grub_memset(buf
, 0, sizeof(buf
));
5376 grub_file_seek(file
, boot_catlog
* 2048);
5377 grub_file_read(file
, buf
, sizeof(buf
));
5378 grub_file_close(file
);
5380 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5382 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5384 if (buf
[i
+ 32] == 0x88)
5386 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5387 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5393 if (loadsector
== 0)
5395 debug("No EFI eltorito info found\n");
5399 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5400 grub_env_set(args
[1], value
);
5401 VENTOY_CMD_RETURN(0);
5404 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5409 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5411 if (pfsdir
->initrd
[0])
5416 curpos
= pfsdir
->curpos
;
5417 len
= grub_strlen(filename
);
5421 if ((len
== 1 && filename
[0] == '.') ||
5422 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5427 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5430 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5431 pfsdir
->curpos
= curpos
+ printlen
;
5432 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5433 pfsdir
->curpos
= curpos
;
5434 pfsdir
->fullpath
[curpos
] = 0;
5438 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5441 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5442 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5444 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5446 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5455 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5459 char *device_name
= NULL
;
5460 grub_device_t dev
= NULL
;
5461 grub_fs_t fs
= NULL
;
5462 replace_fs_dir
*pfsdir
= NULL
;
5468 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5472 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5478 device_name
= grub_file_get_device_name(args
[0]);
5484 dev
= grub_device_open(device_name
);
5490 fs
= grub_fs_probe(dev
);
5499 pfsdir
->fullpath
[0] = '/';
5500 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5502 if (pfsdir
->initrd
[0])
5504 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5506 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5508 if (pfsdir
->initrd
[i
] == '/')
5510 pfsdir
->initrd
[i
] = '\\';
5514 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5515 grub_env_set(args
[1], pos
);
5519 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5524 grub_check_free(pfsdir
);
5525 grub_check_free(device_name
);
5526 check_free(dev
, grub_device_close
);
5528 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5531 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5533 const char *pager
= NULL
;
5539 pager
= grub_env_get("pager");
5543 grub_env_set("pager", "1");
5545 else if (pager
[0] == '1')
5551 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5553 grub_env_set("pager", "1");
5556 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5559 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5565 if (g_pager_flag
== 1)
5567 grub_env_unset("pager");
5569 else if (g_pager_flag
== 2)
5571 grub_env_set("pager", g_old_pager
);
5574 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5577 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5579 if (g_json_case_mis_path
[0])
5584 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5586 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5592 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5595 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5597 if (g_json_case_mis_path
[0])
5602 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5604 if (grub_strcasecmp(filename
, "ventoy") == 0)
5606 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5607 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5608 if (g_json_case_mis_path
[0])
5618 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5621 char *device_name
= NULL
;
5622 grub_device_t dev
= NULL
;
5623 grub_fs_t fs
= NULL
;
5624 chk_case_fs_dir fs_dir
;
5630 device_name
= grub_file_get_device_name(args
[0]);
5636 dev
= grub_device_open(device_name
);
5642 fs
= grub_fs_probe(dev
);
5648 fstype
= ventoy_get_fs_type(fs
->name
);
5649 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5654 g_json_case_mis_path
[0] = 0;
5657 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5659 if (g_json_case_mis_path
[0])
5661 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5666 grub_check_free(device_name
);
5667 check_free(dev
, grub_device_close
);
5669 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5672 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5675 grub_partition_t part
;
5676 char priority_str
[3]; /* Maximum value 15 */
5680 if (argc
< 2 || argc
> 3)
5681 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5682 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5684 /* Open the disk if it exists */
5685 disk
= grub_disk_open (args
[0]);
5688 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5692 part
= grub_partition_probe (disk
, args
[1]);
5695 grub_disk_close (disk
);
5696 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5697 "No such partition");
5700 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5702 grub_disk_close (disk
);
5703 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5704 "Not a GPT partition");
5707 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5708 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5712 grub_env_set (args
[2], priority_str
);
5713 grub_env_export (args
[2]);
5717 grub_printf ("Priority is %s\n", priority_str
);
5720 grub_disk_close (disk
);
5721 return GRUB_ERR_NONE
;
5725 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5729 grub_file_t file
= NULL
;
5730 grub_uint32_t loadrba
= 0;
5731 grub_uint32_t boot_catlog
= 0;
5732 grub_uint8_t sector
[512];
5733 boot_info_table
*info
= NULL
;
5738 /* This also trigger a iso9660 fs parse */
5739 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5744 joliet
= grub_iso9660_is_joliet();
5750 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5753 debug("failed to open %s\n", args
[0]);
5757 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5758 if (boot_catlog
== 0)
5760 debug("no bootcatlog found %u\n", boot_catlog
);
5764 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5767 debug("no bios eltorito rba found %u\n", loadrba
);
5771 grub_file_seek(file
, loadrba
* 2048);
5772 grub_file_read(file
, sector
, 512);
5774 info
= (boot_info_table
*)sector
;
5775 if (info
->bi_data0
== 0x7c6ceafa &&
5776 info
->bi_data1
== 0x90900000 &&
5777 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5778 info
->bi_BootFileLocation
== loadrba
)
5780 debug("bootloader is syslinux, %u.\n", loadrba
);
5786 grub_file_close(file
);
5787 grub_errno
= GRUB_ERR_NONE
;
5791 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5794 ventoy_vlnk_part
*node
;
5800 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5802 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5803 ++n
, node
->device
, node
->disksig
,
5804 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5810 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5818 len
= (int)grub_strlen(args
[0]);
5819 if (grub_file_is_vlnk_suffix(args
[0], len
))
5828 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5831 const char *name
= NULL
;
5837 grub_env_unset(args
[1]);
5838 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5841 debug("VLNK SRC: <%s>\n", args
[0]);
5842 debug("VLNK DST: <%s>\n", name
);
5843 grub_env_set(args
[1], name
);
5851 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5855 grub_file_t file
= NULL
;
5866 len
= (int)grub_strlen(args
[0]);
5867 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5869 grub_printf("Invalid vlnk suffix\n");
5873 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5876 grub_printf("Failed to open %s\n", args
[0]);
5880 if (file
->size
!= 32768)
5882 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5886 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5887 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5889 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5894 check_free(file
, grub_file_close
);
5895 grub_errno
= GRUB_ERR_NONE
;
5899 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5905 g_iso_vd_id_publisher
[0] = 0;
5906 g_iso_vd_id_prepare
[0] = 0;
5907 g_iso_vd_id_application
[0] = 0;
5912 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5916 grub_file_t file
= NULL
;
5921 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5924 grub_printf("Failed to open %s\n", args
[0]);
5928 grub_file_seek(file
, 16 * 2048 + offset
);
5929 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5932 grub_file_seek(file
, 16 * 2048 + offset
);
5933 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5936 grub_file_seek(file
, 16 * 2048 + offset
);
5937 grub_file_read(file
, g_iso_vd_id_application
, 128);
5941 check_free(file
, grub_file_close
);
5942 grub_errno
= GRUB_ERR_NONE
;
5946 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5949 char *id
= g_iso_vd_id_publisher
;
5954 if (args
[0][0] == '1')
5956 id
= g_iso_vd_id_prepare
;
5958 else if (args
[0][0] == '2')
5960 id
= g_iso_vd_id_application
;
5963 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5968 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5973 grub_errno
= GRUB_ERR_NONE
;
5977 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5982 g_ventoy_fn_mutex
= 0;
5983 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5985 g_ventoy_fn_mutex
= 1;
5988 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5991 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5993 grub_uint64_t total
;
5994 grub_uint64_t org_required
;
5995 grub_uint64_t new_required
;
6001 #ifdef GRUB_MACHINE_EFI
6002 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6003 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6004 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6005 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6010 grub_printf("Non EFI mode!\n");
6015 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6018 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6020 const char *env
= NULL
;
6025 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6030 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6031 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6032 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6033 ventoy_check_mode_by_name(args
[0], "vtnormal")
6039 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6040 if (env
&& env
[0] == '0' && env
[1] == 0)
6048 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6056 const char *env
= NULL
;
6057 ulonglong fsize
= 0;
6059 int seldata
[16] = {0};
6064 len
= 8 * VTOY_SIZE_1KB
;
6065 cmd
= (char *)grub_malloc(len
);
6071 g_vtoy_secondary_need_recover
= 0;
6072 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6074 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6077 timeout
= (int)grub_strtol(env
, NULL
, 10);
6082 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6085 fsize
= grub_strtoull(args
[2], NULL
, 10);
6087 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6089 if (grub_strcmp(args
[1], "Unix") != 0)
6091 if (grub_strcmp(args
[1], "Windows") == 0)
6093 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6097 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6100 if (fsize
<= VTOY_SIZE_1GB
)
6102 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6106 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6109 g_ventoy_menu_esc
= 1;
6110 g_ventoy_suppress_esc
= 1;
6111 g_ventoy_suppress_esc_default
= 0;
6112 g_ventoy_secondary_menu_on
= 1;
6113 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6114 grub_script_execute_sourcecode(cfgfile
);
6115 g_ventoy_menu_esc
= 0;
6116 g_ventoy_suppress_esc
= 0;
6117 g_ventoy_suppress_esc_default
= 1;
6118 g_ventoy_secondary_menu_on
= 0;
6120 select
= seldata
[g_ventoy_last_entry
];
6124 g_ventoy_wimboot_mode
= 1;
6125 g_vtoy_secondary_need_recover
= 1;
6127 else if (select
== 3)
6129 g_ventoy_grub2_mode
= 1;
6130 g_vtoy_secondary_need_recover
= 2;
6132 else if (select
== 4)
6134 g_ventoy_memdisk_mode
= 1;
6135 g_vtoy_secondary_need_recover
= 3;
6137 else if (select
== 5)
6139 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6140 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6142 }while (select
== 5);
6148 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6154 if (g_vtoy_secondary_need_recover
== 1)
6156 g_ventoy_wimboot_mode
= 0;
6158 else if (g_vtoy_secondary_need_recover
== 2)
6160 g_ventoy_grub2_mode
= 0;
6162 else if (g_vtoy_secondary_need_recover
== 3)
6164 g_ventoy_memdisk_mode
= 0;
6167 g_vtoy_secondary_need_recover
= 0;
6169 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6172 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6177 if (args
[0][0] == '0')
6179 g_ventoy_case_insensitive
= 0;
6183 g_ventoy_case_insensitive
= 1;
6189 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6194 ventoy_plugin_load_menu_lang(1, args
[0]);
6195 VENTOY_CMD_RETURN(0);
6198 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6203 ventoy_plugin_load_menu_lang(0, args
[0]);
6204 VENTOY_CMD_RETURN(0);
6208 static const char * ventoy_menu_lang_read_hook(struct grub_env_var
*var
, const char *val
)
6211 return ventoy_get_vmenu_title(val
);
6214 static const char * ventoy_gfxmode_read_hook(struct grub_env_var
*var
, const char *val
)
6219 return g_vtoy_gfxmode
;
6222 static char * ventoy_gfxmode_write_hook(struct grub_env_var
*var
, const char *val
)
6226 grub_strncpy(g_vtoy_gfxmode
, val
, sizeof(g_vtoy_gfxmode
) - 1);
6227 return grub_strdup(val
);
6230 int ventoy_env_init(void)
6235 grub_env_set("vtdebug_flag", "");
6237 grub_register_variable_hook("gfxmode", ventoy_gfxmode_read_hook
, ventoy_gfxmode_write_hook
);
6238 grub_register_vtoy_menu_lang_hook(ventoy_menu_lang_read_hook
);
6240 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6241 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6242 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6243 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6245 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6248 ventoy_filt_register(0, ventoy_wrapper_open
);
6250 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6253 g_grub_param
->grub_env_get
= grub_env_get
;
6254 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6255 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6256 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6257 grub_env_set("env_param", buf
);
6258 grub_env_set("ventoy_env_param", buf
);
6260 grub_env_export("env_param");
6261 grub_env_export("ventoy_env_param");
6264 grub_env_export("vtoy_winpeshl_ini_addr");
6265 grub_env_export("vtoy_winpeshl_ini_size");
6267 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6268 grub_env_set("vtoy_chain_file_size", buf
);
6269 grub_env_export("vtoy_chain_file_size");
6271 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6272 grub_env_set("vtoy_chain_file_read", buf
);
6273 grub_env_export("vtoy_chain_file_read");
6275 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6276 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6277 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6279 grub_snprintf(buf
, sizeof(buf
), "%s-%s", GRUB_TARGET_CPU
, GRUB_PLATFORM
);
6280 grub_env_set("grub_cpu_platform", buf
);
6281 grub_env_export("grub_cpu_platform");
6288 static cmd_para ventoy_cmds
[] =
6290 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6291 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6292 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6293 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6294 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6295 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6296 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6297 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6298 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6299 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6300 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6301 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6302 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6303 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6304 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6305 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6306 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6307 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6308 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6309 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6310 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6311 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6312 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6313 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6314 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6315 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6316 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6318 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6319 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6320 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6321 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6322 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6323 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6324 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6326 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6327 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6328 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6329 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6330 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6331 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6332 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6333 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6334 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6335 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6338 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6339 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6340 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6341 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6342 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6343 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6344 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6345 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6346 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6347 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6348 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6350 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6351 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6352 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6353 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6354 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6355 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6356 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6358 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6359 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6360 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6361 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6362 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6363 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6364 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6365 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6366 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6367 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6369 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6370 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6371 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6372 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6373 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6374 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6375 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6376 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6377 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6379 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6380 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6381 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6382 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6385 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6386 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6387 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6389 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6390 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6391 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6394 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6395 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6396 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6397 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6398 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6399 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6400 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6401 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6402 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6403 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6404 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6405 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6406 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6407 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6409 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6410 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6411 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6412 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6413 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6414 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6415 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6416 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6417 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6418 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6419 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6420 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6422 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6423 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6424 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6425 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6426 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6427 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6428 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6429 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6430 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6431 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6432 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6433 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6434 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6435 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6436 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6437 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6438 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6439 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6440 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6441 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6442 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6443 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6444 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6445 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6446 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6447 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6448 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6449 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6450 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6451 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6455 int ventoy_register_all_cmd(void)
6458 cmd_para
*cur
= NULL
;
6460 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6462 cur
= ventoy_cmds
+ i
;
6463 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6464 cur
->summary
, cur
->description
, cur
->parser
);
6470 int ventoy_unregister_all_cmd(void)
6474 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6476 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);