1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/random.h>
49 #include <grub/ventoy.h>
50 #include "ventoy_def.h"
53 GRUB_MOD_LICENSE ("GPLv3+");
55 static grub_uint8_t g_check_mbr_data
[] = {
56 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
62 initrd_info
*g_initrd_img_list
= NULL
;
63 initrd_info
*g_initrd_img_tail
= NULL
;
64 int g_initrd_img_count
= 0;
65 int g_valid_initrd_count
= 0;
66 int g_default_menu_mode
= 0;
67 int g_filt_dot_underscore_file
= 0;
68 int g_sort_case_sensitive
= 0;
69 int g_tree_view_menu_style
= 0;
70 static grub_file_t g_old_file
;
71 static int g_ventoy_last_entry_back
;
74 char g_img_swap_tmp_buf
[1024];
75 img_info g_img_swap_tmp
;
76 img_info
*g_ventoy_img_list
= NULL
;
78 int g_ventoy_img_count
= 0;
80 grub_device_t g_enum_dev
= NULL
;
81 grub_fs_t g_enum_fs
= NULL
;
82 int g_img_max_search_level
= -1;
83 img_iterator_node g_img_iterator_head
;
84 img_iterator_node
*g_img_iterator_tail
= NULL
;
86 grub_uint8_t g_ventoy_break_level
= 0;
87 grub_uint8_t g_ventoy_debug_level
= 0;
88 grub_uint8_t g_ventoy_chain_type
= 0;
90 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
91 grub_uint32_t g_ventoy_cpio_size
= 0;
92 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
93 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
95 int g_plugin_image_list
= 0;
97 ventoy_grub_param
*g_grub_param
= NULL
;
99 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
101 ventoy_img_chunk_list g_img_chunk_list
;
103 int g_wimboot_enable
= 0;
104 ventoy_img_chunk_list g_wimiso_chunk_list
;
105 char *g_wimiso_path
= NULL
;
106 grub_uint32_t g_wimiso_size
= 0;
108 int g_vhdboot_enable
= 0;
110 grub_uint64_t g_svd_replace_offset
= 0;
112 int g_conf_replace_count
= 0;
113 grub_uint64_t g_conf_replace_offset
[VTOY_MAX_CONF_REPLACE
] = { 0 };
114 conf_replace
*g_conf_replace_node
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
115 grub_uint8_t
*g_conf_replace_new_buf
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
116 int g_conf_replace_new_len
[VTOY_MAX_CONF_REPLACE
] = { 0 };
117 int g_conf_replace_new_len_align
[VTOY_MAX_CONF_REPLACE
] = { 0 };
119 int g_ventoy_disk_bios_id
= 0;
120 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
121 grub_uint64_t g_ventoy_disk_size
= 0;
122 grub_uint64_t g_ventoy_disk_part_size
[2];
124 char *g_tree_script_buf
= NULL
;
125 int g_tree_script_pos
= 0;
126 int g_tree_script_pre
= 0;
128 static char *g_list_script_buf
= NULL
;
129 static int g_list_script_pos
= 0;
131 static char *g_part_list_buf
= NULL
;
132 static int g_part_list_pos
= 0;
133 static grub_uint64_t g_part_end_max
= 0;
135 static int g_video_mode_max
= 0;
136 static int g_video_mode_num
= 0;
137 static ventoy_video_mode
*g_video_mode_list
= NULL
;
139 static int g_enumerate_time_checked
= 0;
140 static grub_uint64_t g_enumerate_start_time_ms
;
141 static grub_uint64_t g_enumerate_finish_time_ms
;
142 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
144 static char g_iso_vd_id_publisher
[130];
145 static char g_iso_vd_id_prepare
[130];
146 static char g_iso_vd_id_application
[130];
148 static int g_pager_flag
= 0;
149 static char g_old_pager
[32];
151 const char *g_menu_class
[img_type_max
] =
153 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
156 const char *g_menu_prefix
[img_type_max
] =
158 "iso", "wim", "efi", "img", "vhd", "vtoy"
161 static int g_vtoy_secondary_need_recover
= 0;
163 static int g_vtoy_load_prompt
= 0;
164 static char g_vtoy_prompt_msg
[64];
166 static char g_json_case_mis_path
[32];
168 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
170 int ventoy_get_fs_type(const char *fs
)
174 return ventoy_fs_max
;
176 else if (grub_strncmp(fs
, "exfat", 5) == 0)
178 return ventoy_fs_exfat
;
180 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
182 return ventoy_fs_ntfs
;
184 else if (grub_strncmp(fs
, "ext", 3) == 0)
186 return ventoy_fs_ext
;
188 else if (grub_strncmp(fs
, "xfs", 3) == 0)
190 return ventoy_fs_xfs
;
192 else if (grub_strncmp(fs
, "udf", 3) == 0)
194 return ventoy_fs_udf
;
196 else if (grub_strncmp(fs
, "fat", 3) == 0)
198 return ventoy_fs_fat
;
201 return ventoy_fs_max
;
204 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
223 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
225 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
229 static int ventoy_control_get_flag(const char *key
)
231 const char *val
= ventoy_get_env(key
);
233 if (val
&& val
[0] == '1' && val
[1] == 0)
240 static grub_err_t
ventoy_fs_close(grub_file_t file
)
242 grub_file_close(g_old_file
);
243 grub_free(file
->data
);
251 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
257 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
262 for (i
= 0; i
< g_video_mode_num
; i
++)
264 if (g_video_mode_list
[i
].width
== info
->width
&&
265 g_video_mode_list
[i
].height
== info
->height
&&
266 g_video_mode_list
[i
].bpp
== info
->bpp
)
272 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
273 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
274 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
277 if (g_video_mode_num
== g_video_mode_max
)
279 g_video_mode_max
*= 2;
280 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
286 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
288 if (v1
->bpp
== v2
->bpp
)
290 if (v1
->width
== v2
->width
)
292 if (v1
->height
== v2
->height
)
298 return (v1
->height
< v2
->height
) ? -1 : 1;
303 return (v1
->width
< v2
->width
) ? -1 : 1;
308 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
312 static int ventoy_enum_video_mode(void)
315 grub_video_adapter_t adapter
;
316 grub_video_driver_id_t id
;
317 ventoy_video_mode mode
;
319 g_video_mode_num
= 0;
320 g_video_mode_max
= 1024;
321 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
322 if (!g_video_mode_list
)
327 #ifdef GRUB_MACHINE_PCBIOS
328 grub_dl_load ("vbe");
331 id
= grub_video_get_driver_id ();
333 FOR_VIDEO_ADAPTERS (adapter
)
335 if (!adapter
->iterate
||
336 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
337 adapter
->init() != GRUB_ERR_NONE
)))
342 adapter
->iterate(ventoy_video_hook
, NULL
);
344 if (adapter
->id
!= id
)
350 /* sort video mode */
351 for (i
= 0; i
< g_video_mode_num
; i
++)
352 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
354 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
356 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
357 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
358 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
362 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
365 static int ventoy_pre_parse_data(char *src
, int size
)
371 if (size
< 20 || grub_strncmp(src
, "ventoy_left_top_color", 21))
377 while (*pos
&& *pos
!= '\r' && *pos
!= '\n')
385 if (grub_strlen(src
) > 200)
390 grub_snprintf(buf
, sizeof(buf
),
391 "regexp -s 1:%s -s 2:%s -s 3:%s \"@([^@]*)@([^@]*)@([^@]*)@\" \"%s\"",
392 ventoy_left_key
, ventoy_top_key
, ventoy_color_key
, src
);
394 grub_script_execute_sourcecode(buf
);
401 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
405 static struct grub_fs vtoy_fs
=
410 .fs_read
= ventoy_fs_read
,
411 .fs_close
= ventoy_fs_close
,
421 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
427 file
->data
= grub_malloc(rawFile
->size
+ 4096);
433 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
434 ventoy_pre_parse_data((char *)file
->data
, (int)rawFile
->size
);
435 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
437 g_old_file
= rawFile
;
439 file
->size
= rawFile
->size
+ len
;
440 file
->device
= rawFile
->device
;
442 file
->not_easily_seekable
= 1;
447 static int ventoy_check_decimal_var(const char *name
, long *value
)
449 const char *value_str
= NULL
;
451 value_str
= grub_env_get(name
);
452 if (NULL
== value_str
)
454 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
457 if (!ventoy_is_decimal(value_str
))
459 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
462 *value
= grub_strtol(value_str
, NULL
, 10);
464 return GRUB_ERR_NONE
;
467 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
469 grub_uint64_t sectors
;
471 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
473 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
477 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
480 return sectors
* 512;
483 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
489 grub_uint32_t offset
;
491 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
494 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
498 len
= (int)file
->size
;
500 data
= (char *)grub_malloc(file
->size
);
506 grub_file_read(file
, data
, file
->size
);
507 grub_file_close(file
);
509 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
510 grub_script_execute_sourcecode(exec
);
512 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
513 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
514 grub_file_close(file
);
516 grub_script_execute_sourcecode("loopback -d efiboot");
520 *direntoff
= offset
+ 2;
525 static int ventoy_set_check_result(int ret
, const char *msg
)
529 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
530 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
531 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
536 grub_printf(VTOY_WARNING
"\n");
537 grub_printf(VTOY_WARNING
"\n");
538 grub_printf(VTOY_WARNING
"\n\n\n");
540 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
541 grub_printf("Error message: <%s>\n\n", msg
);
542 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
549 static int ventoy_check_official_device(grub_device_t dev
)
553 grub_uint64_t offset
;
556 grub_uint8_t mbr
[512];
560 struct grub_partition
*partition
;
562 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
564 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
567 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
568 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
569 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
571 #ifndef GRUB_MACHINE_EFI
572 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
574 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
576 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
578 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
580 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
582 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
591 /* We must have partition 2 */
594 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
598 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
602 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
605 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
607 grub_file_close(file
);
608 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
611 partition
= dev
->disk
->partition
;
612 if (partition
->number
!= 0 || partition
->start
!= 2048)
614 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
619 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
621 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
622 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
623 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
625 grub_file_close(file
);
626 return ventoy_set_check_result(6, "Disk partition layout check failed.");
631 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
632 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
633 PartTbl
[1].SectorCount
!= 65536)
635 grub_file_close(file
);
636 return ventoy_set_check_result(6, "Disk partition layout check failed.");
642 offset
= partition
->start
+ partition
->len
;
643 partition
= file
->device
->disk
->partition
;
644 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
646 grub_file_close(file
);
647 return ventoy_set_check_result(7, "Disk partition layout check failed.");
651 grub_file_close(file
);
655 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
656 dev2
= grub_device_open(devname
);
659 return ventoy_set_check_result(8, "Disk open failed");
662 fs
= grub_fs_probe(dev2
);
665 grub_device_close(dev2
);
666 return ventoy_set_check_result(9, "FS probe failed");
669 fs
->fs_label(dev2
, &label
);
670 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
672 grub_device_close(dev2
);
673 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
676 grub_device_close(dev2
);
680 disk
= grub_disk_open(dev
->disk
->name
);
683 return ventoy_set_check_result(11, "Disk open failed");
686 grub_memset(mbr
, 0, 512);
687 grub_disk_read(disk
, 0, 0, 512, mbr
);
688 grub_disk_close(disk
);
690 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
692 return ventoy_set_check_result(12, "MBR check failed");
695 return ventoy_set_check_result(0, NULL
);
698 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
702 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
712 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
714 grub_uint64_t size
= 0;
717 char fullpath
[256] = {0};
720 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
723 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
726 debug("grub_file_open failed <%s>\n", fullpath
);
732 grub_file_close(file
);
736 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
740 char fullpath
[512] = {0};
743 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
746 file
= grub_file_open(fullpath
, type
);
749 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
756 int ventoy_is_dir_exist(const char *fmt
, ...)
763 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
767 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
770 grub_strncpy(pos
+ len
, "\" ]", 3);
772 debug("script exec %s\n", buf
);
774 if (0 == grub_script_execute_sourcecode(buf
))
782 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
785 grub_uint8_t
*outbuf
;
786 grub_uint8_t gzHdr
[10] =
788 0x1F, 0x8B, /* magic */
796 grub_memset(&s
, 0, sizeof(mz_stream
));
798 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
800 outbuf
= (grub_uint8_t
*)mem_out
;
802 mem_out_len
-= sizeof(gzHdr
) + 8;
803 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
804 outbuf
+= sizeof(gzHdr
);
806 s
.avail_in
= mem_in_len
;
809 s
.avail_out
= mem_out_len
;
812 mz_deflate(&s
, MZ_FINISH
);
816 outbuf
+= s
.total_out
;
817 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
818 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
820 return s
.total_out
+ sizeof(gzHdr
) + 8;
828 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
832 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
835 if (0 == grub_strcmp(args
[0], "on"))
838 grub_env_set("vtdebug_flag", "debug");
843 grub_env_set("vtdebug_flag", "");
846 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
849 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
853 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
855 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
856 grub_printf(" level:\r\n");
857 grub_printf(" 01/11: busybox / (+cat log)\r\n");
858 grub_printf(" 02/12: initrd / (+cat log)\r\n");
859 grub_printf(" 03/13: hook / (+cat log)\r\n");
861 grub_printf(" debug:\r\n");
862 grub_printf(" 0: debug is off\r\n");
863 grub_printf(" 1: debug is on\r\n");
865 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
868 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
870 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
872 g_ventoy_debug_level
= 1;
875 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
878 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
887 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
890 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
922 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
938 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
954 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
959 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
961 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
964 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
969 value_long
+= grub_strtol(args
[1], NULL
, 10);
971 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
972 grub_env_set(args
[0], buf
);
974 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
977 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
979 ulonglong value1
= 0;
980 ulonglong value2
= 0;
985 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
988 value1
= grub_strtoull(args
[0], NULL
, 10);
989 value2
= grub_strtoull(args
[1], NULL
, 10);
991 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
992 grub_env_set(args
[2], buf
);
994 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
997 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1012 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1015 debug("failed to open file <%s> for udf check\n", args
[0]);
1019 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
1021 grub_env_set(args
[1], buf
);
1023 grub_file_close(file
);
1029 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1037 g_wimboot_enable
= 0;
1039 grub_check_free(g_wimiso_path
);
1040 grub_check_free(g_wimiso_chunk_list
.chunk
);
1042 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1048 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1049 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1050 if (NULL
== g_wimiso_chunk_list
.chunk
)
1052 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1055 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1056 g_wimiso_chunk_list
.cur_chunk
= 0;
1058 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1060 g_wimboot_enable
= 1;
1061 g_wimiso_path
= grub_strdup(args
[0]);
1062 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1063 grub_file_close(file
);
1068 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1076 ventoy_iso9660_override
*dirent
;
1085 totlen
= sizeof(ventoy_chain_head
);
1087 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1089 debug("failed to load efiboot template %d\n", len
);
1095 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1097 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1100 debug("failed to open file <%s>\n", args
[0]);
1104 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1109 totlen
+= ventoy_align_2k(file
->size
);
1111 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1112 dirent
->first_sector
= len
/ 2048;
1113 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1114 dirent
->size
= (grub_uint32_t
)file
->size
;
1115 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1117 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1119 #ifdef GRUB_MACHINE_EFI
1120 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1122 data
= (char *)grub_malloc(totlen
);
1125 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1127 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1128 grub_check_free(buf
);
1130 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1131 grub_file_close(file
);
1133 ventoy_memfile_env_set(args
[1], data
, (ulonglong
)totlen
);
1138 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1144 g_vtoy_load_prompt
= 0;
1145 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1147 if (argc
== 2 && args
[0][0] == '1')
1149 g_vtoy_load_prompt
= 1;
1150 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1153 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1156 int ventoy_need_prompt_load_file(void)
1158 return g_vtoy_load_prompt
;
1161 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1163 grub_uint64_t ro
= 0;
1164 grub_uint64_t div
= 0;
1165 grub_ssize_t left
= size
;
1166 char *cur
= (char *)buf
;
1168 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1171 while (left
>= VTOY_SIZE_2MB
)
1173 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1174 cur
+= VTOY_SIZE_2MB
;
1175 left
-= VTOY_SIZE_2MB
;
1177 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1182 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1188 grub_file_read(file
, cur
, left
);
1191 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1197 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1202 enum grub_file_type type
;
1213 if (grub_strcmp(args
[0], "nodecompress") == 0)
1215 type
= VENTOY_FILE_TYPE
;
1219 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1222 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1225 debug("failed to open file <%s>\n", args
[1]);
1229 #ifdef GRUB_MACHINE_EFI
1230 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1232 buf
= (char *)grub_malloc(file
->size
);
1237 grub_file_close(file
);
1241 if (g_vtoy_load_prompt
)
1243 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1247 grub_file_read(file
, buf
, file
->size
);
1250 ventoy_memfile_env_set(args
[2], buf
, (ulonglong
)(file
->size
));
1252 grub_file_close(file
);
1258 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1274 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1277 debug("failed to open file <%s> for udf check\n", args
[0]);
1281 headlen
= sizeof(ventoy_chain_head
);
1283 #ifdef GRUB_MACHINE_EFI
1284 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1286 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1289 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1291 grub_file_read(file
, buf
+ headlen
, file
->size
);
1293 ventoy_memfile_env_set(args
[1], buf
, (ulonglong
)(file
->size
));
1295 grub_file_close(file
);
1301 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1307 if (grub_iso9660_is_joliet())
1309 debug("This time has joliet process\n");
1318 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1327 if (args
[0][0] == '1')
1329 grub_iso9660_set_nojoliet(1);
1333 grub_iso9660_set_nojoliet(0);
1339 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1344 grub_uint8_t buf
[32];
1355 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1358 debug("failed to open file <%s> for udf check\n", args
[0]);
1362 for (i
= 16; i
< 32; i
++)
1364 grub_file_seek(file
, i
* 2048);
1365 grub_file_read(file
, buf
, sizeof(buf
));
1373 grub_file_seek(file
, i
* 2048);
1374 grub_file_read(file
, buf
, sizeof(buf
));
1376 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1379 grub_file_seek(file
, i
* 2048);
1380 grub_file_read(file
, buf
, sizeof(buf
));
1382 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1383 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1389 grub_file_close(file
);
1391 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1396 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1398 long value_long1
= 0;
1399 long value_long2
= 0;
1401 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1403 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1406 value_long1
= grub_strtol(args
[0], NULL
, 10);
1407 value_long2
= grub_strtol(args
[2], NULL
, 10);
1409 if (0 == grub_strcmp(args
[1], "eq"))
1411 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1413 else if (0 == grub_strcmp(args
[1], "ne"))
1415 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1417 else if (0 == grub_strcmp(args
[1], "gt"))
1419 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1421 else if (0 == grub_strcmp(args
[1], "lt"))
1423 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1425 else if (0 == grub_strcmp(args
[1], "ge"))
1427 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1429 else if (0 == grub_strcmp(args
[1], "le"))
1431 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1435 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1441 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1444 char buf
[128] = {0};
1448 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1451 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1452 pos
= grub_strstr(buf
, ",");
1458 grub_env_set(args
[1], buf
);
1460 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1463 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1469 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1475 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1478 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1480 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1481 if (0 == grub_script_execute_sourcecode(buf
))
1483 debug("file %s exist, ventoy_compatible YES\n", buf
);
1484 grub_env_set("ventoy_compatible", "YES");
1485 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1489 debug("file %s NOT exist\n", buf
);
1493 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1494 pos
= grub_strstr(buf
, ")");
1500 disk
= grub_disk_open(buf
);
1503 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1504 grub_disk_close(disk
);
1506 g_img_swap_tmp_buf
[703] = 0;
1507 for (i
= 318; i
< 703; i
++)
1509 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1510 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1512 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1513 grub_env_set("ventoy_compatible", "YES");
1514 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1520 debug("failed to open disk <%s>\n", buf
);
1523 grub_env_set("ventoy_compatible", "NO");
1524 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1527 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1533 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1535 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1538 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1543 if (0 == g_sort_case_sensitive
)
1545 if (grub_islower(c1
))
1547 c1
= c1
- 'a' + 'A';
1550 if (grub_islower(c2
))
1552 c2
= c2
- 'a' + 'A';
1565 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1571 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1573 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1576 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1581 if (0 == g_sort_case_sensitive
)
1583 if (grub_islower(c1
))
1585 c1
= c1
- 'a' + 'A';
1588 if (grub_islower(c2
))
1590 c2
= c2
- 'a' + 'A';
1603 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1605 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1607 grub_memcpy(img1
, img2
, sizeof(img_info
));
1608 img1
->next
= g_img_swap_tmp
.next
;
1609 img1
->prev
= g_img_swap_tmp
.prev
;
1611 g_img_swap_tmp
.next
= img2
->next
;
1612 g_img_swap_tmp
.prev
= img2
->prev
;
1613 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1616 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1620 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1628 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1630 ventoy_vlnk_part
*node
= NULL
;
1631 grub_uint32_t SelfSig
;
1632 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1634 /* skip Ventoy partition 1/2 */
1635 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1636 if (partition
->number
< 2 && SelfSig
== *pSig
)
1641 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1644 node
->disksig
= *pSig
;
1645 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1646 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1647 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1649 node
->next
= g_vlnk_part_list
;
1650 g_vlnk_part_list
= node
;
1656 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1663 disk
= grub_disk_open(name
);
1666 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1667 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1668 grub_disk_close(disk
);
1674 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1676 const char *fs
[ventoy_fs_max
+ 1] =
1678 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1683 cur
->dev
= grub_device_open(cur
->device
);
1688 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1694 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1699 char *disk
, *device
;
1700 grub_uint32_t readcrc
, calccrc
;
1701 ventoy_vlnk_part
*cur
;
1702 grub_fs_t fs
= NULL
;
1704 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1708 grub_printf("VLNK invalid guid\n");
1714 readcrc
= vlnk
->crc32
;
1716 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1717 if (readcrc
!= calccrc
)
1721 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1727 if (!g_vlnk_part_list
)
1729 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1732 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1734 if (cur
->disksig
== vlnk
->disk_signature
)
1738 if (cur
->partoffset
== vlnk
->part_offset
)
1741 device
= cur
->device
;
1743 if (cur
->probe
== 0)
1746 ventoy_vlnk_probe_fs(cur
);
1756 struct grub_file file
;
1758 grub_memset(&file
, 0, sizeof(file
));
1759 file
.device
= cur
->dev
;
1760 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1763 cur
->fs
->fs_close(&file
);
1764 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1773 grub_printf("\n==== VLNK Information ====\n"
1774 "Disk Signature: %08x\n"
1775 "Partition Offset: %llu\n"
1776 "File Path: <%s>\n\n",
1777 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1781 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1785 grub_printf("Disk Find: [ NO ]\n");
1790 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1794 grub_printf("Part Find: [ NO ]\n");
1796 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1799 grub_printf("VLNK File: <%s>\n", dst
);
1806 return (1 - filefind
);
1809 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1814 grub_file_t file
= NULL
;
1819 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1821 else if (dir
[0] == '/')
1823 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1827 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1830 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1836 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1837 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1838 grub_file_close(file
);
1840 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1842 rc
= grub_file_add_vlnk(src
, dst
);
1848 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1858 const menu_tip
*tip
;
1859 img_iterator_node
*tmp
;
1860 img_iterator_node
*new_node
;
1861 img_iterator_node
*node
= (img_iterator_node
*)data
;
1863 if (g_enumerate_time_checked
== 0)
1865 g_enumerate_finish_time_ms
= grub_get_time_ms();
1866 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1869 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1871 g_enumerate_time_checked
= 1;
1875 len
= grub_strlen(filename
);
1879 if (node
->level
+ 1 > g_img_max_search_level
)
1884 if ((len
== 1 && filename
[0] == '.') ||
1885 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1890 if (!ventoy_img_name_valid(filename
, len
))
1895 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1900 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1902 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1903 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1906 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1911 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1914 new_node
->level
= node
->level
+ 1;
1915 new_node
->plugin_list_index
= index
;
1916 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1918 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1921 debug("Directory %s ignored...\n", new_node
->dir
);
1922 grub_free(new_node
);
1926 new_node
->tail
= node
->tail
;
1928 new_node
->parent
= node
;
1929 if (!node
->firstchild
)
1931 node
->firstchild
= new_node
;
1934 if (g_img_iterator_tail
)
1936 g_img_iterator_tail
->next
= new_node
;
1937 g_img_iterator_tail
= new_node
;
1941 g_img_iterator_head
.next
= new_node
;
1942 g_img_iterator_tail
= new_node
;
1948 debug("Find a file %s\n", filename
);
1954 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1956 type
= img_type_iso
;
1958 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1960 type
= img_type_wim
;
1962 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1963 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1965 type
= img_type_vhd
;
1967 #ifdef GRUB_MACHINE_EFI
1968 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1970 type
= img_type_efi
;
1973 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1975 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1977 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1978 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1983 type
= img_type_img
;
1985 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1987 type
= img_type_vtoy
;
1989 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1991 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1993 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1994 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
2003 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
2008 if (g_plugin_image_list
)
2010 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2011 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
2012 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
2014 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2017 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2019 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2024 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2026 if (grub_file_is_vlnk_suffix(filename
, len
))
2029 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2036 img
= grub_zalloc(sizeof(img_info
));
2040 img
->plugin_list_index
= index
;
2041 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2043 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2045 img
->size
= info
->size
;
2046 if (vlnk
|| 0 == img
->size
)
2048 if (node
->dir
[0] == '/')
2050 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2054 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2058 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2060 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2065 if (g_ventoy_img_list
)
2067 tail
= *(node
->tail
);
2073 g_ventoy_img_list
= img
;
2076 img
->id
= g_ventoy_img_count
;
2078 if (node
&& NULL
== node
->firstiso
)
2080 node
->firstiso
= img
;
2091 *((img_info
**)(node
->tail
)) = img
;
2092 g_ventoy_img_count
++;
2094 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2096 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2099 img
->tip1
= tip
->tip1
;
2100 img
->tip2
= tip
->tip2
;
2103 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2106 img
->class = g_menu_class
[type
];
2108 img
->menu_prefix
= g_menu_prefix
[type
];
2110 if (img_type_iso
== type
)
2112 if (ventoy_plugin_check_memdisk(img
->path
))
2114 img
->menu_prefix
= "miso";
2117 else if (img_type_img
== type
)
2119 if (ventoy_plugin_check_memdisk(img
->path
))
2121 img
->menu_prefix
= "mimg";
2125 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2132 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2134 int len
= GRUB_UINT_MAX
;
2135 const char *value
= NULL
;
2136 char name
[32] = {0};
2137 char plat
[32] = {0};
2138 char guidstr
[32] = {0};
2139 ventoy_guid guid
= VENTOY_GUID
;
2140 const char *fmt1
= NULL
;
2141 const char *fmt2
= NULL
;
2142 const char *fmt3
= NULL
;
2143 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2144 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2145 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2146 const char fmtcode
[]={
2147 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2148 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2149 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2150 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2151 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2152 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2155 grub_memset(name
, 0, sizeof(name
));
2156 puint
[0] = grub_swap_bytes32(0x56454e54);
2157 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2158 puint
[2] = grub_swap_bytes32(0x45525349);
2159 puint
[1] = grub_swap_bytes32(0x4f595f56);
2160 value
= ventoy_get_env(name
);
2162 grub_memset(name
, 0, sizeof(name
));
2163 puint
[1] = grub_swap_bytes32(0x5f544f50);
2164 puint
[0] = grub_swap_bytes32(0x56544c45);
2165 fmt1
= ventoy_get_env(name
);
2171 grub_memset(name
, 0, sizeof(name
));
2172 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2173 puint
[0] = grub_swap_bytes32(0x56544c45);
2174 fmt2
= ventoy_get_env(name
);
2176 grub_memset(name
, 0, sizeof(name
));
2177 puint
[1] = grub_swap_bytes32(0x5f434c52);
2178 puint
[0] = grub_swap_bytes32(0x56544c45);
2179 fmt3
= ventoy_get_env(name
);
2181 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2183 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2185 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2186 #pragma GCC diagnostic push
2187 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2188 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2189 fmt1
? fmt1
: fmtdata
,
2190 fmt2
? fmt2
: fmtdata
+ 4,
2191 value
? value
: "", plat
, guidstr
,
2192 fmt3
? fmt3
: fmtdata
+ 6);
2193 #pragma GCC diagnostic pop
2195 grub_memset(name
, 0, sizeof(name
));
2196 puint
[0] = grub_swap_bytes32(0x76746f79);
2197 puint
[2] = grub_swap_bytes32(0x656e7365);
2198 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2199 ventoy_set_env(name
, guidstr
);
2205 ventoy_password_get (char buf
[], unsigned buf_size
)
2207 unsigned i
, cur_len
= 0;
2209 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2213 key
= grub_getkey ();
2214 if (key
== '\n' || key
== '\r')
2217 if (key
== GRUB_TERM_ESC
)
2227 grub_term_restore_pos (pos
);
2228 for (i
= 0; i
< cur_len
; i
++)
2230 grub_term_restore_pos (pos
);
2232 for (i
= 0; i
< cur_len
; i
++)
2239 if (!grub_isprint (key
))
2242 if (cur_len
+ 2 < buf_size
)
2243 buf
[cur_len
++] = key
;
2248 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2254 return (key
!= GRUB_TERM_ESC
);
2257 static int ventoy_get_password(char buf
[], unsigned buf_size
)
2259 const char *env
= NULL
;
2261 env
= grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2262 if (env
&& env
[0] == '0' && env
[1] == 0)
2264 return grub_password_get(buf
, buf_size
);
2268 return ventoy_password_get(buf
, buf_size
);
2272 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2276 grub_uint8_t md5
[16];
2280 grub_memset(input
, 0, sizeof(input
));
2282 grub_printf("Enter password: ");
2285 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2287 ventoy_get_password(input
, 128);
2288 if (grub_strcmp(pwd
->text
, input
) == 0)
2293 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2295 ventoy_get_password(input
, 128);
2296 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2297 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2302 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2304 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2305 ventoy_get_password(input
+ offset
, 128);
2307 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2308 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2314 grub_printf("Invalid password!\n\n");
2321 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2323 img_info
*minimg
= NULL
;
2324 img_info
*img
= (img_info
*)(node
->firstiso
);
2326 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2328 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2343 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2345 img_iterator_node
*Minchild
= NULL
;
2346 img_iterator_node
*child
= node
->firstchild
;
2348 while (child
&& child
->parent
== node
)
2350 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2354 child
= child
->next
;
2359 Minchild
->select
= 1;
2365 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2368 img_info
*img
= NULL
;
2369 const char *dir_class
= NULL
;
2370 const char *dir_alias
= NULL
;
2371 img_iterator_node
*child
= NULL
;
2372 const menu_tip
*tip
= NULL
;
2374 if (node
->isocnt
== 0 || node
->done
== 1)
2379 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2381 offset
= node
->parent
->dirlen
;
2384 if (node
== &g_img_iterator_head
)
2386 if (g_default_menu_mode
== 0)
2388 if (g_tree_view_menu_style
== 0)
2390 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2391 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2392 " echo 'return ...' \n"
2393 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2397 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2398 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2399 " echo 'return ...' \n"
2400 "}\n", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2404 g_tree_script_pre
= g_tree_script_pos
;
2408 node
->dir
[node
->dirlen
- 1] = 0;
2409 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2412 dir_class
= "vtoydir";
2415 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2417 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2420 if (g_tree_view_menu_style
== 0)
2422 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2423 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2424 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2428 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2429 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2430 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2435 dir_alias
= node
->dir
+ offset
;
2437 if (g_tree_view_menu_style
== 0)
2439 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2440 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2441 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2445 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2446 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2447 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2451 if (g_tree_view_menu_style
== 0)
2453 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2454 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2455 " echo 'return ...' \n"
2456 "}\n", "<--", node
->dir
);
2460 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2461 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2462 " echo 'return ...' \n"
2467 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2469 ventoy_dynamic_tree_menu(child
);
2472 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2474 if (g_tree_view_menu_style
== 0)
2476 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2477 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2480 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2481 img
->unsupport
? "[***********] " : "",
2482 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2484 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2488 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2489 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2492 img
->unsupport
? "[***********] " : "",
2493 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2495 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2499 if (node
!= &g_img_iterator_head
)
2501 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2508 static int ventoy_set_default_menu(void)
2514 const char *strdata
= NULL
;
2515 img_info
*cur
= NULL
;
2516 img_info
*default_node
= NULL
;
2517 const char *default_image
= NULL
;
2519 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2520 if (default_image
&& default_image
[0] == '/')
2522 img_len
= grub_strlen(default_image
);
2524 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2526 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2538 if (0 == g_default_menu_mode
)
2540 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2544 def
= grub_strdup(default_image
);
2550 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2552 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2553 if (strdata
&& strdata
[0] == '/')
2555 pos
= def
+ grub_strlen(strdata
);
2566 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2569 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2573 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2581 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2583 img_info
*next
= NULL
;
2584 img_info
*cur
= g_ventoy_img_list
;
2597 g_ventoy_img_list
= NULL
;
2598 g_ventoy_img_count
= 0;
2600 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2603 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2606 img_info
*cur
= g_ventoy_img_list
;
2610 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2612 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2615 img_id
= grub_strtol(args
[0], NULL
, 10);
2616 if (img_id
>= g_ventoy_img_count
)
2618 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2621 debug("Find image %ld name \n", img_id
);
2623 while (cur
&& img_id
> 0)
2631 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2634 debug("image name is %s\n", cur
->name
);
2636 grub_env_set(args
[1], cur
->name
);
2638 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2641 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2645 img_info
*cur
= g_ventoy_img_list
;
2651 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2654 len
= (int)grub_strlen(args
[0]);
2658 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2667 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2670 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2671 grub_env_set("chosen", id
);
2672 grub_env_export("chosen");
2674 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2677 static char g_fake_vlnk_src
[512];
2678 static char g_fake_vlnk_dst
[512];
2679 static grub_uint64_t g_fake_vlnk_size
;
2680 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2686 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2688 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2689 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2691 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2693 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2696 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2702 g_fake_vlnk_src
[0] = 0;
2703 g_fake_vlnk_dst
[0] = 0;
2704 g_fake_vlnk_size
= 0;
2705 grub_file_vtoy_vlnk(NULL
, NULL
);
2707 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2711 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2716 const char *id
= NULL
;
2717 img_info
*cur
= NULL
;
2721 if (argc
< 1 || argc
> 3)
2723 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2726 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2728 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2729 grub_env_set(args
[0], pos
);
2732 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2733 grub_env_set(args
[1], value
);
2738 for (last
= pos
; *pos
; pos
++)
2745 grub_env_set(args
[2], last
+ 1);
2751 id
= grub_env_get("chosen");
2753 pos
= grub_strstr(id
, "VID_");
2756 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2760 cur
= g_ventoy_img_list
;
2765 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2768 grub_env_set(args
[0], cur
->path
);
2772 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2773 grub_env_set(args
[1], value
);
2778 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2779 grub_env_set(args
[2], cur
->name
);
2783 g_svd_replace_offset
= 0;
2785 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2789 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2793 grub_device_t dev
= NULL
;
2794 img_info
*cur
= NULL
;
2795 img_info
*tail
= NULL
;
2796 img_info
*min
= NULL
;
2797 img_info
*head
= NULL
;
2798 const char *strdata
= NULL
;
2799 char *device_name
= NULL
;
2801 img_iterator_node
*node
= NULL
;
2802 img_iterator_node
*tmp
= NULL
;
2808 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2811 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2813 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2818 g_enumerate_time_checked
= 0;
2819 g_enumerate_start_time_ms
= grub_get_time_ms();
2821 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2822 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2824 g_filt_dot_underscore_file
= 1;
2827 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2828 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2830 g_sort_case_sensitive
= 1;
2833 device_name
= grub_file_get_device_name(args
[0]);
2839 g_enum_dev
= dev
= grub_device_open(device_name
);
2845 g_enum_fs
= fs
= grub_fs_probe(dev
);
2851 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2853 debug("unsupported fs:<%s>\n", fs
->name
);
2854 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2858 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2860 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2861 if (strdata
&& strdata
[0] == '1')
2863 g_default_menu_mode
= 1;
2866 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2868 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2870 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2871 if (strdata
&& strdata
[0] == '/')
2873 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2874 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2876 g_img_iterator_head
.dir
[len
++] = '/';
2878 g_img_iterator_head
.dirlen
= len
;
2882 g_img_iterator_head
.dirlen
= 1;
2883 grub_strcpy(g_img_iterator_head
.dir
, "/");
2886 g_img_iterator_head
.tail
= &tail
;
2888 if (g_img_max_search_level
< 0)
2890 g_img_max_search_level
= GRUB_INT_MAX
;
2891 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2892 if (strdata
&& ventoy_is_decimal(strdata
))
2894 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2898 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2899 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2900 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2901 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2902 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2903 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2905 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2907 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2910 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2911 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2913 g_tree_view_menu_style
= 1;
2916 ventoy_set_default_menu();
2918 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2920 ventoy_dynamic_tree_menu(node
);
2924 node
= g_img_iterator_head
.next
;
2932 /* sort image list by image name */
2933 while (g_ventoy_img_list
)
2935 min
= g_ventoy_img_list
;
2936 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2938 if (ventoy_cmp_img(min
, cur
) > 0)
2946 min
->prev
->next
= min
->next
;
2951 min
->next
->prev
= min
->prev
;
2954 if (min
== g_ventoy_img_list
)
2956 g_ventoy_img_list
= min
->next
;
2974 g_ventoy_img_list
= head
;
2976 if (g_default_menu_mode
== 1)
2978 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2979 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2980 " echo 'return ...' \n"
2981 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_TREEVIEW"));
2984 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2986 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2987 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2990 cur
->unsupport
? "[***********] " : "",
2991 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2993 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2996 g_tree_script_buf
[g_tree_script_pos
] = 0;
2997 g_list_script_buf
[g_list_script_pos
] = 0;
2999 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
3000 grub_env_set(args
[1], buf
);
3004 check_free(device_name
, grub_free
);
3005 check_free(dev
, grub_device_close
);
3007 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3010 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
3017 device_name
= grub_file_get_device_name(filename
);
3029 pos2
= grub_strstr(pos
, ",");
3032 pos2
= grub_strstr(pos
, ")");
3040 disk
= grub_disk_open(pos
);
3043 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3044 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3045 grub_disk_close(disk
);
3052 grub_free(device_name
);
3056 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3058 eltorito_descriptor desc
;
3060 grub_memset(&desc
, 0, sizeof(desc
));
3061 grub_file_seek(file
, 17 * 2048);
3062 grub_file_read(file
, &desc
, sizeof(desc
));
3064 if (desc
.type
!= 0 || desc
.version
!= 1)
3069 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3070 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3078 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3080 grub_uint8_t buf
[512];
3082 grub_file_seek(file
, sector
* 2048);
3083 grub_file_read(file
, buf
, sizeof(buf
));
3085 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3086 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3088 return *((grub_uint32_t
*)(buf
+ 40));
3094 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3098 grub_uint8_t buf
[512];
3099 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3101 grub_file_seek(file
, sector
* 2048);
3102 grub_file_read(file
, buf
, sizeof(buf
));
3104 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3106 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3110 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3115 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3117 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3119 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3123 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3125 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3130 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3132 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3134 if (buf
[36] == parttype
[i
])
3136 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3142 debug("%s does not contain efi eltorito\n", file
->name
);
3146 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3149 const char *fs
= NULL
;
3150 const char *val
= NULL
;
3151 const char *cdprompt
= NULL
;
3153 grub_uint8_t chksum
= 0;
3156 disk
= file
->device
->disk
;
3157 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3159 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3160 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3161 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3163 pos
= grub_strstr(file
->name
, "/");
3169 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3171 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3173 param
->vtoy_img_size
= file
->size
;
3175 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3176 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3178 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3180 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3181 param
->vtoy_reserved
[4] = 0;
3182 if (g_ventoy_chain_type
== 1) /* Windows */
3184 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3185 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3187 param
->vtoy_reserved
[4] = 1;
3191 fs
= ventoy_get_env("ventoy_fs_probe");
3192 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3194 param
->vtoy_reserved
[3] = 1;
3197 param
->vtoy_reserved
[5] = 0;
3198 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3199 if (val
&& val
[0] == '1' && val
[1] == 0)
3201 param
->vtoy_reserved
[5] = 1;
3204 /* ventoy_disk_signature used for vlnk */
3205 param
->vtoy_reserved
[6] = file
->vlnk
;
3206 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3208 /* calculate checksum */
3209 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3211 chksum
+= *((grub_uint8_t
*)param
+ i
);
3213 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3218 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3220 grub_uint32_t i
= 0;
3221 grub_uint64_t total
= 0;
3222 grub_uint64_t fileblk
= 0;
3223 ventoy_img_chunk
*chunk
= NULL
;
3225 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3227 chunk
= chunklist
->chunk
+ i
;
3229 if (chunk
->disk_start_sector
<= start
)
3231 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3235 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3238 fileblk
= (file
->size
+ 511) / 512;
3240 if (total
!= fileblk
)
3242 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3243 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3245 debug("maybe img file to be processed.\n");
3255 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3259 grub_uint32_t i
= 0;
3260 grub_uint32_t sector
= 0;
3261 grub_uint32_t count
= 0;
3262 grub_off_t size
= 0;
3263 grub_off_t read
= 0;
3265 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3266 if (fs_type
== ventoy_fs_exfat
)
3268 grub_fat_get_file_chunk(start
, file
, chunklist
);
3270 else if (fs_type
== ventoy_fs_ext
)
3272 grub_ext_get_file_chunk(start
, file
, chunklist
);
3276 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3277 file
->read_hook_data
= chunklist
;
3279 for (size
= file
->size
; size
> 0; size
-= read
)
3281 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3282 grub_file_read(file
, NULL
, read
);
3285 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3287 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3288 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3291 if (ventoy_fs_udf
== fs_type
)
3293 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3295 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3296 chunklist
->chunk
[i
].img_start_sector
= sector
;
3297 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3303 len
= (int)grub_strlen(file
->name
);
3304 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3305 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3306 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3307 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3309 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3311 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3321 chunklist
->chunk
[i
].img_start_sector
= sector
;
3322 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3330 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3334 grub_disk_addr_t start
;
3339 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3342 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3345 g_conf_replace_count
= 0;
3346 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3347 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3349 if (g_img_chunk_list
.chunk
)
3351 grub_free(g_img_chunk_list
.chunk
);
3354 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3356 grub_file_close(file
);
3357 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3360 /* get image chunk data */
3361 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3362 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3363 if (NULL
== g_img_chunk_list
.chunk
)
3365 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3368 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3369 g_img_chunk_list
.cur_chunk
= 0;
3371 start
= file
->device
->disk
->partition
->start
;
3373 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3375 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3376 grub_file_close(file
);
3380 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3383 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3384 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3385 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3388 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3392 grub_uint64_t offset
= 0;
3393 grub_uint32_t align
= 0;
3394 grub_file_t file
= NULL
;
3395 conf_replace
*node
= NULL
;
3396 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3397 ventoy_grub_param_file_replace
*replace
= NULL
;
3403 debug("select conf replace argc:%d\n", argc
);
3410 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3413 debug("Conf replace not found for %s\n", args
[1]);
3417 debug("Find %d conf replace for %s\n", n
, args
[1]);
3419 g_conf_replace_count
= n
;
3420 for (i
= 0; i
< n
; i
++)
3424 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3427 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3428 grub_file_close(file
);
3430 else if (node
->img
> 0)
3436 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3440 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3443 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3447 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3449 if (align
> vtoy_max_replace_file_size
)
3451 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3452 grub_file_close(file
);
3456 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3457 grub_file_close(file
);
3458 g_conf_replace_new_len
[i
] = (int)file
->size
;
3459 g_conf_replace_new_len_align
[i
] = align
;
3461 g_conf_replace_node
[i
] = node
;
3462 g_conf_replace_offset
[i
] = offset
+ 2;
3466 replace
= &(g_grub_param
->img_replace
[i
]);
3467 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3468 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3469 replace
->old_name_cnt
++;
3472 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3476 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3479 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3484 const char *ch
= var
;
3491 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3498 debug("Invalid variable letter <%c>\n", *ch
);
3505 debug("Invalid variable length:%d <%s>\n", n
, var
);
3509 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3518 grub_printf("\n=================== Variables Expansion ===================\n\n");
3521 grub_printf("<%s>: ", var
);
3524 while (i
< (len
- 1))
3527 if ((c
== '\n') || (c
== '\r'))
3537 else if (grub_isprint(c
))
3539 if (i
+ 1 < (len
- 1))
3541 grub_printf("%c", c
);
3551 expand
[i
- 1] = ' ';
3552 grub_printf("\r<%s>: %s", var
, expand
);
3555 grub_printf("\r<%s>: %s", var
, expand
);
3567 grub_snprintf(expand
, len
, "$$%s$$", var
);
3573 static int ventoy_auto_install_var_expand(install_template
*node
)
3581 char *newbuf
= NULL
;
3582 char *curline
= NULL
;
3583 char *nextline
= NULL
;
3584 grub_uint8_t
*code
= NULL
;
3586 var_node
*CurNode
= NULL
;
3587 var_node
*pVarList
= NULL
;
3589 code
= (grub_uint8_t
*)node
->filebuf
;
3591 if (node
->filelen
>= VTOY_SIZE_1MB
)
3593 debug("auto install script too long %d\n", node
->filelen
);
3597 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3599 debug("UCS-2 encoding NOT supported\n");
3603 start
= grub_strstr(node
->filebuf
, "$$");
3606 debug("no need to expand variable, no start.\n");
3610 end
= grub_strstr(start
+ 2, "$$");
3613 debug("no need to expand variable, no end.\n");
3617 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3618 newbuf
= grub_malloc(newlen
);
3621 debug("Failed to alloc newbuf %d\n", newlen
);
3625 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3627 nextline
= ventoy_get_line(curline
);
3629 start
= grub_strstr(curline
, "$$");
3632 end
= grub_strstr(start
+ 2, "$$");
3638 VTOY_APPEND_NEWBUF(curline
);
3640 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3642 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3644 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3651 value
[sizeof(value
) - 1] = 0;
3652 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3656 CurNode
= grub_zalloc(sizeof(var_node
));
3659 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3660 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3661 CurNode
->next
= pVarList
;
3667 VTOY_APPEND_NEWBUF(value
);
3669 VTOY_APPEND_NEWBUF(end
+ 2);
3673 VTOY_APPEND_NEWBUF(curline
);
3676 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3678 newbuf
[pos
- 1] = '\n';
3682 newbuf
[pos
++] = '\n';
3686 grub_free(node
->filebuf
);
3687 node
->filebuf
= newbuf
;
3688 node
->filelen
= pos
;
3692 CurNode
= pVarList
->next
;
3693 grub_free(pVarList
);
3700 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3706 grub_file_t file
= NULL
;
3707 char configfile
[128];
3708 install_template
*node
= NULL
;
3714 debug("select auto installation argc:%d\n", argc
);
3721 node
= ventoy_plugin_find_install_template(args
[0]);
3724 debug("Auto install template not found for %s\n", args
[0]);
3728 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3730 defidx
= node
->autosel
;
3731 if (node
->timeout
< 0)
3733 node
->cursel
= node
->autosel
- 1;
3734 debug("Auto install template auto select %d\n", node
->autosel
);
3739 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3745 if (node
->timeout
> 0)
3747 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3750 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3751 " echo %s\n}\n", "");
3753 for (i
= 0; i
< node
->templatenum
; i
++)
3755 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3757 ventoy_get_vmenu_title("VTLANG_AUTOINS_USE"),
3758 node
->templatepath
[i
].path
);
3761 g_ventoy_menu_esc
= 1;
3762 g_ventoy_suppress_esc
= 1;
3763 g_ventoy_suppress_esc_default
= defidx
;
3765 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3766 grub_script_execute_sourcecode(configfile
);
3768 g_ventoy_menu_esc
= 0;
3769 g_ventoy_suppress_esc
= 0;
3770 g_ventoy_suppress_esc_default
= 1;
3774 node
->cursel
= g_ventoy_last_entry
- 1;
3777 grub_check_free(node
->filebuf
);
3780 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3782 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3783 node
->templatepath
[node
->cursel
].path
);
3786 node
->filebuf
= grub_malloc(file
->size
+ 8);
3789 grub_file_read(file
, node
->filebuf
, file
->size
);
3790 grub_file_close(file
);
3792 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3793 node
->filelen
= (int)file
->size
;
3795 ventoy_auto_install_var_expand(node
);
3800 debug("Failed to open auto install script <%s%s>\n",
3801 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3805 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3808 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3814 char configfile
[128];
3815 persistence_config
*node
;
3821 debug("select persistence argc:%d\n", argc
);
3828 node
= ventoy_plugin_find_persistent(args
[0]);
3831 debug("Persistence image not found for %s\n", args
[0]);
3835 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3837 defidx
= node
->autosel
;
3838 if (node
->timeout
< 0)
3840 node
->cursel
= node
->autosel
- 1;
3841 debug("Persistence image auto select %d\n", node
->autosel
);
3846 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3852 if (node
->timeout
> 0)
3854 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3857 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_PERSISTENCE\" --class=\"sel_persistence\" {\n"
3858 " echo %s\n}\n", "");
3860 for (i
= 0; i
< node
->backendnum
; i
++)
3862 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3864 ventoy_get_vmenu_title("VTLANG_PERSIST_USE"),
3865 node
->backendpath
[i
].path
);
3869 g_ventoy_menu_esc
= 1;
3870 g_ventoy_suppress_esc
= 1;
3871 g_ventoy_suppress_esc_default
= defidx
;
3873 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3874 grub_script_execute_sourcecode(configfile
);
3876 g_ventoy_menu_esc
= 0;
3877 g_ventoy_suppress_esc
= 0;
3878 g_ventoy_suppress_esc_default
= 1;
3882 node
->cursel
= g_ventoy_last_entry
- 1;
3884 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3887 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3890 ventoy_img_chunk
*cur
;
3896 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3898 cur
= g_img_chunk_list
.chunk
+ i
;
3899 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3900 cur
->img_start_sector
, cur
->img_end_sector
,
3901 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3905 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3908 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3912 ventoy_img_chunk_list chunklist
;
3917 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3920 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3923 /* get image chunk data */
3924 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3925 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3926 if (NULL
== chunklist
.chunk
)
3928 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3931 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3932 chunklist
.cur_chunk
= 0;
3934 ventoy_get_block_list(file
, &chunklist
, 0);
3936 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3938 grub_printf("########## UNSUPPORTED ###############\n");
3941 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3943 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3945 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3946 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3949 grub_printf("\n==================================\n");
3951 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3953 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3954 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3955 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3956 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3957 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3961 grub_free(chunklist
.chunk
);
3962 grub_file_close(file
);
3964 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3967 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3970 ventoy_grub_param_file_replace
*replace
= NULL
;
3978 replace
= &(g_grub_param
->file_replace
);
3979 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3981 replace
->old_name_cnt
= 0;
3982 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3984 replace
->old_name_cnt
++;
3985 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3988 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3991 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3994 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3997 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
4003 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
4004 grub_env_set(args
[0], buf
);
4007 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4010 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4018 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4019 grub_printf("%s", g_list_script_buf
);
4023 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4024 grub_printf("%s", g_tree_script_buf
);
4030 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4032 img_info
*cur
= g_ventoy_img_list
;
4040 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4041 grub_printf("name:<%s>\n\n", cur
->name
);
4048 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4054 ventoy_plugin_dump_injection();
4059 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4065 ventoy_plugin_dump_auto_install();
4070 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4076 ventoy_plugin_dump_persistence();
4081 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4087 len1
= (int)grub_strlen(filename
);
4088 len2
= (int)grub_strlen(suffix
);
4095 for (i
= len1
- 1; i
>= 0; i
--)
4097 if (filename
[i
] == '.')
4108 if (filename
[i
- len2
- 1] != '_')
4113 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4121 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4127 if (argc
!= 1 && argc
!= 2)
4132 if (args
[0][0] == '0')
4134 if (g_ventoy_memdisk_mode
)
4139 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4146 else if (args
[0][0] == '1')
4148 return g_ventoy_iso_raw
? 0 : 1;
4150 else if (args
[0][0] == '2')
4152 return g_ventoy_iso_uefi_drv
? 0 : 1;
4154 else if (args
[0][0] == '3')
4156 if (g_ventoy_grub2_mode
)
4161 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4168 else if (args
[0][0] == '4')
4170 if (g_ventoy_wimboot_mode
)
4175 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4186 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4188 static int configfile_mode
= 0;
4189 char memfile
[128] = {0};
4196 * args[0]: 0:normal 1:configfile
4197 * args[1]: 0:list_buf 1:tree_buf
4202 debug("Invalid argc %d\n", argc
);
4208 if (args
[0][0] == '0')
4210 if (args
[1][0] == '0')
4212 grub_script_execute_sourcecode(g_list_script_buf
);
4216 grub_script_execute_sourcecode(g_tree_script_buf
);
4221 if (configfile_mode
)
4223 debug("Now already in F3 mode %d\n", configfile_mode
);
4227 if (args
[1][0] == '0')
4229 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4230 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4234 g_ventoy_last_entry
= -1;
4235 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4236 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4239 configfile_mode
= 1;
4240 grub_script_execute_sourcecode(memfile
);
4241 configfile_mode
= 0;
4247 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4258 g_ventoy_case_insensitive
= 1;
4259 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4260 g_ventoy_case_insensitive
= 0;
4266 grub_file_close(file
);
4272 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4277 const char *isopath
= NULL
;
4279 ventoy_mbr_head mbr
;
4286 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4289 isopath
= grub_env_get("vtoy_iso_part");
4292 debug("isopath is null %p\n", isopath
);
4296 debug("isopath is %s\n", isopath
);
4298 for (id
= 0; id
< 30 && (find
== 0); id
++)
4300 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4301 if (grub_strstr(isopath
, hdname
))
4303 debug("skip %s ...\n", hdname
);
4307 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4309 disk
= grub_disk_open(hdname
);
4312 debug("%s not exist\n", hdname
);
4316 grub_memset(&mbr
, 0, sizeof(mbr
));
4317 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4319 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4321 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4322 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4325 grub_env_set(args
[0], hdname
);
4329 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4333 debug("read %s failed\n", hdname
);
4336 grub_disk_close(disk
);
4342 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4353 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4356 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4359 debug("failed to open file %s\n", args
[0]);
4363 buf
= grub_malloc(len
);
4370 grub_file_read(file
, buf
, len
- 1);
4372 ventoy_get_line(buf
);
4373 ventoy_set_env(args
[1], buf
);
4377 grub_check_free(buf
);
4378 grub_file_close(file
);
4383 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4385 grub_uint64_t end_max
= 0;
4386 int *pCnt
= (int *)data
;
4391 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4392 "0 %llu linear /dev/ventoy %llu\n",
4393 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4395 end_max
= (partition
->len
+ partition
->start
) * 512;
4396 if (end_max
> g_part_end_max
)
4398 g_part_end_max
= end_max
;
4404 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4407 char *device_name
= NULL
;
4408 grub_device_t dev
= NULL
;
4413 g_part_list_pos
= 0;
4415 grub_env_unset("vtoy_img_part_file");
4422 device_name
= grub_file_get_device_name(args
[0]);
4425 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4429 dev
= grub_device_open(device_name
);
4432 debug("grub_device_open failed, %s\n", device_name
);
4436 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4438 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4439 grub_env_set("vtoy_img_part_file", buf
);
4441 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4442 grub_env_set("vtoy_img_part_cnt", buf
);
4444 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4445 grub_env_set("vtoy_img_max_part_end", buf
);
4449 check_free(device_name
, grub_free
);
4450 check_free(dev
, grub_device_close
);
4456 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4467 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4470 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4473 debug("failed to open file %s\n", args
[0]);
4477 buf
= grub_malloc(file
->size
+ 1);
4483 buf
[file
->size
] = 0;
4484 grub_file_read(file
, buf
, file
->size
);
4486 if (grub_strstr(buf
, args
[1]))
4493 grub_check_free(buf
);
4494 grub_file_close(file
);
4499 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4505 ventoy_iso9660_vd pvd
;
4512 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4515 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4518 debug("failed to open file %s\n", args
[0]);
4522 grub_file_seek(file
, 16 * 2048);
4523 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4524 if (len
!= sizeof(pvd
))
4526 debug("failed to read pvd %d\n", len
);
4530 grub_memset(buf
, 0, sizeof(buf
));
4531 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4532 ventoy_set_env(args
[1], buf
);
4534 grub_memset(buf
, 0, sizeof(buf
));
4535 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4536 ventoy_set_env(args
[2], buf
);
4540 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4541 ventoy_set_env(args
[3], buf
);
4544 grub_file_close(file
);
4549 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4560 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4563 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4566 debug("failed to open file %s\n", args
[0]);
4570 grub_memset(buf
, 0, sizeof(buf
));
4571 grub_file_seek(file
, 16 * 2048 + 813);
4572 len
= (int)grub_file_read(file
, buf
, 17);
4575 debug("failed to read create date %d\n", len
);
4579 ventoy_set_env(args
[1], buf
);
4582 grub_file_close(file
);
4587 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4593 ventoy_env_hook_root(1);
4598 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4604 ventoy_env_hook_root(0);
4609 #ifdef GRUB_MACHINE_EFI
4610 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4615 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4621 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4622 if (var
&& *var
== 1)
4630 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4639 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4644 grub_uint64_t FileSectors
= 0;
4645 ventoy_gpt_info
*gpt
= NULL
;
4646 ventoy_part_table
*pt
= NULL
;
4647 grub_uint8_t zeroguid
[16] = {0};
4652 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4655 debug("failed to open file %s\n", args
[0]);
4659 if (file
->size
% 512)
4661 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4665 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4671 FileSectors
= file
->size
/ 512;
4673 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4674 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4676 debug("This is EFI partition table\n");
4678 for (i
= 0; i
< 128; i
++)
4680 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4682 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4684 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4685 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4693 debug("This is MBR partition table\n");
4695 for (i
= 0; i
< 4; i
++)
4697 pt
= gpt
->MBR
.PartTbl
+ i
;
4698 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4700 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4701 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4702 (ulonglong
)FileSectors
);
4711 grub_file_close(file
);
4712 grub_check_free(gpt
);
4713 grub_errno
= GRUB_ERR_NONE
;
4717 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4726 for (i
= 0; i
< 500; i
++)
4728 ret
= grub_getkey_noblock();
4729 if (ret
== GRUB_TERM_NO_KEY
)
4738 grub_printf("\n\n Still have key input after clear.\n");
4746 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4753 int image_sector_size
;
4755 ventoy_chain_head
*chain
;
4756 ventoy_img_chunk
*chunk
;
4757 ventoy_os_param
*osparam
;
4758 ventoy_image_location
*location
;
4759 ventoy_image_disk_region
*region
;
4760 struct grub_acpi_table_header
*acpi
;
4769 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4771 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4777 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4779 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4781 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4785 img_chunk_num
= chain
->img_chunk_num
;
4787 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4788 datalen
= sizeof(ventoy_os_param
) + loclen
;
4790 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4791 acpi
= grub_zalloc(buflen
);
4797 /* Step1: Fill acpi table header */
4798 grub_memcpy(acpi
->signature
, "VTOY", 4);
4799 acpi
->length
= buflen
;
4801 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4802 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4804 acpi
->creator_id
[0] = 1;
4805 acpi
->creator_rev
= 1;
4807 /* Step2: Fill data */
4808 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4809 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4810 osparam
->vtoy_img_location_addr
= 0;
4811 osparam
->vtoy_img_location_len
= loclen
;
4812 osparam
->chksum
= 0;
4813 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4815 location
= (ventoy_image_location
*)(osparam
+ 1);
4816 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4817 location
->image_sector_size
= image_sector_size
;
4818 location
->disk_sector_size
= chain
->disk_sector_size
;
4819 location
->region_count
= img_chunk_num
;
4821 region
= location
->regions
;
4822 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4823 if (512 == image_sector_size
)
4825 for (i
= 0; i
< img_chunk_num
; i
++)
4827 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4828 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4829 region
->disk_start_sector
= chunk
->disk_start_sector
;
4836 for (i
= 0; i
< img_chunk_num
; i
++)
4838 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4839 region
->image_start_sector
= chunk
->img_start_sector
;
4840 region
->disk_start_sector
= chunk
->disk_start_sector
;
4846 /* Step3: Fill acpi checksum */
4848 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4850 /* load acpi table */
4851 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4852 grub_script_execute_sourcecode(cmd
);
4856 VENTOY_CMD_RETURN(0);
4859 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4865 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4866 g_ventoy_last_entry
= -1;
4871 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4877 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4882 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4884 const char *pos
= filename
+ 1;
4892 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4894 grub_strncpy((char *)data
, filename
, 128);
4905 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4908 char *device_name
= NULL
;
4909 grub_device_t dev
= NULL
;
4910 grub_fs_t fs
= NULL
;
4911 char buf
[128] = {0};
4917 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4921 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4923 device_name
= grub_file_get_device_name(args
[0]);
4926 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4930 dev
= grub_device_open(device_name
);
4933 debug("grub_device_open failed, %s\n", device_name
);
4937 fs
= grub_fs_probe(dev
);
4940 debug("grub_fs_probe failed, %s\n", device_name
);
4944 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4948 ventoy_set_env(args
[2], buf
);
4955 check_free(device_name
, grub_free
);
4956 check_free(dev
, grub_device_close
);
4961 int ventoy_load_part_table(const char *diskname
)
4968 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4969 if (!g_ventoy_part_info
)
4974 disk
= grub_disk_open(diskname
);
4977 debug("Failed to open disk %s\n", diskname
);
4981 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4983 g_ventoy_disk_bios_id
= disk
->id
;
4985 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4986 grub_disk_close(disk
);
4988 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4989 dev
= grub_device_open(name
);
4992 /* Check for official Ventoy device */
4993 ret
= ventoy_check_official_device(dev
);
4994 grub_device_close(dev
);
5002 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5003 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5008 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5016 ret
= ventoy_load_part_table(args
[0]);
5019 grub_printf("\n\nPress r/h/e for the corresponding operation.\n");
5020 grub_printf(" r --- Reboot\n");
5021 grub_printf(" h --- Halt\n");
5022 grub_printf(" e --- Exit grub\n");
5034 grub_script_execute_sourcecode("halt");
5043 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5044 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5049 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5052 const char *vcfg
= NULL
;
5057 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5060 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5061 grub_env_set(args
[1], vcfg
);
5066 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5074 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5077 grub_uint8_t zeroguid
[16] = {0};
5082 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5085 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5087 if (id
>= 1 && id
<= 128)
5089 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5097 if (id
>= 1 && id
<= 4)
5099 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5109 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5112 char *device_name
= NULL
;
5113 grub_device_t dev
= NULL
;
5114 grub_fs_t fs
= NULL
;
5119 debug("get fs label for %s\n", args
[0]);
5123 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5127 device_name
= grub_file_get_device_name(args
[0]);
5130 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5134 dev
= grub_device_open(device_name
);
5137 debug("grub_device_open failed, %s\n", device_name
);
5141 fs
= grub_fs_probe(dev
);
5142 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5144 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5148 fs
->fs_label(dev
, &label
);
5151 debug("label=<%s>\n", label
);
5152 ventoy_set_env(args
[1], label
);
5160 check_free(device_name
, grub_free
);
5161 check_free(dev
, grub_device_close
);
5166 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5170 grub_snprintf((char *)data
, 256, "%s", filename
);
5177 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5179 if (info
->dir
&& filename
&& filename
[0] != '.')
5181 grub_snprintf((char *)data
, 256, "%s", filename
);
5188 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5191 char *device_name
= NULL
;
5192 grub_device_t dev
= NULL
;
5193 grub_fs_t fs
= NULL
;
5194 char name
[256] ={0};
5198 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5202 device_name
= grub_file_get_device_name(args
[0]);
5205 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5209 dev
= grub_device_open(device_name
);
5212 debug("grub_device_open failed, %s\n", device_name
);
5216 fs
= grub_fs_probe(dev
);
5219 debug("grub_fs_probe failed, %s\n", device_name
);
5223 fs
->fs_dir(dev
, args
[1], hook
, name
);
5226 ventoy_set_env(args
[2], name
);
5233 check_free(device_name
, grub_free
);
5234 check_free(dev
, grub_device_close
);
5239 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5242 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5245 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5248 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5251 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5261 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5265 for (pos
= args
[0]; *pos
; pos
++)
5279 grub_env_set(args
[1], args
[0]);
5289 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5299 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5304 len
= (int)grub_strlen(buf
);
5305 for (i
= len
; i
> 0; i
--)
5307 if (buf
[i
- 1] == '/')
5309 grub_env_set(args
[1], buf
+ i
);
5314 grub_env_set(args
[1], buf
);
5319 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5321 struct grub_video_mode_info info
;
5328 if (!g_video_mode_list
)
5330 ventoy_enum_video_mode();
5333 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5335 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5339 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5342 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5344 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5345 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5347 VENTOY_CMD_RETURN(0);
5350 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5352 struct grub_video_mode_info info
;
5359 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5361 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5365 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5368 grub_env_set(args
[0], buf
);
5370 VENTOY_CMD_RETURN(0);
5373 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5381 if (!g_video_mode_list
)
5386 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5387 if (id
< g_video_mode_num
)
5389 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5390 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5393 grub_env_set(args
[1], buf
);
5395 VENTOY_CMD_RETURN(0);
5398 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5401 grub_uint32_t loadsector
= 0;
5404 grub_uint32_t boot_catlog
= 0;
5405 grub_uint8_t buf
[512];
5411 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5415 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5418 debug("failed to open %s\n", args
[0]);
5422 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5423 if (boot_catlog
== 0)
5425 debug("No bootcatlog found\n");
5426 grub_file_close(file
);
5430 grub_memset(buf
, 0, sizeof(buf
));
5431 grub_file_seek(file
, boot_catlog
* 2048);
5432 grub_file_read(file
, buf
, sizeof(buf
));
5433 grub_file_close(file
);
5435 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5437 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5439 if (buf
[i
+ 32] == 0x88)
5441 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5442 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5448 if (loadsector
== 0)
5450 debug("No EFI eltorito info found\n");
5454 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5455 grub_env_set(args
[1], value
);
5456 VENTOY_CMD_RETURN(0);
5459 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5464 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5466 if (pfsdir
->initrd
[0])
5471 curpos
= pfsdir
->curpos
;
5472 len
= grub_strlen(filename
);
5476 if ((len
== 1 && filename
[0] == '.') ||
5477 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5482 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5485 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5486 pfsdir
->curpos
= curpos
+ printlen
;
5487 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5488 pfsdir
->curpos
= curpos
;
5489 pfsdir
->fullpath
[curpos
] = 0;
5493 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5496 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5497 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5499 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5501 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5510 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5514 char *device_name
= NULL
;
5515 grub_device_t dev
= NULL
;
5516 grub_fs_t fs
= NULL
;
5517 replace_fs_dir
*pfsdir
= NULL
;
5523 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5527 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5533 device_name
= grub_file_get_device_name(args
[0]);
5539 dev
= grub_device_open(device_name
);
5545 fs
= grub_fs_probe(dev
);
5554 pfsdir
->fullpath
[0] = '/';
5555 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5557 if (pfsdir
->initrd
[0])
5559 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5561 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5563 if (pfsdir
->initrd
[i
] == '/')
5565 pfsdir
->initrd
[i
] = '\\';
5569 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5570 grub_env_set(args
[1], pos
);
5574 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5579 grub_check_free(pfsdir
);
5580 grub_check_free(device_name
);
5581 check_free(dev
, grub_device_close
);
5583 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5586 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5588 const char *pager
= NULL
;
5594 pager
= grub_env_get("pager");
5598 grub_env_set("pager", "1");
5600 else if (pager
[0] == '1')
5606 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5608 grub_env_set("pager", "1");
5611 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5614 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5620 if (g_pager_flag
== 1)
5622 grub_env_unset("pager");
5624 else if (g_pager_flag
== 2)
5626 grub_env_set("pager", g_old_pager
);
5629 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5632 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5634 if (g_json_case_mis_path
[0])
5639 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5641 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5647 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5650 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5652 if (g_json_case_mis_path
[0])
5657 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5659 if (grub_strcasecmp(filename
, "ventoy") == 0)
5661 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5662 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5663 if (g_json_case_mis_path
[0])
5673 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5676 char *device_name
= NULL
;
5677 grub_device_t dev
= NULL
;
5678 grub_fs_t fs
= NULL
;
5679 chk_case_fs_dir fs_dir
;
5685 device_name
= grub_file_get_device_name(args
[0]);
5691 dev
= grub_device_open(device_name
);
5697 fs
= grub_fs_probe(dev
);
5703 fstype
= ventoy_get_fs_type(fs
->name
);
5704 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5709 g_json_case_mis_path
[0] = 0;
5712 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5714 if (g_json_case_mis_path
[0])
5716 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5721 grub_check_free(device_name
);
5722 check_free(dev
, grub_device_close
);
5724 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5727 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5730 grub_partition_t part
;
5731 char priority_str
[3]; /* Maximum value 15 */
5735 if (argc
< 2 || argc
> 3)
5736 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5737 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5739 /* Open the disk if it exists */
5740 disk
= grub_disk_open (args
[0]);
5743 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5747 part
= grub_partition_probe (disk
, args
[1]);
5750 grub_disk_close (disk
);
5751 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5752 "No such partition");
5755 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5757 grub_disk_close (disk
);
5758 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5759 "Not a GPT partition");
5762 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5763 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5767 grub_env_set (args
[2], priority_str
);
5768 grub_env_export (args
[2]);
5772 grub_printf ("Priority is %s\n", priority_str
);
5775 grub_disk_close (disk
);
5776 return GRUB_ERR_NONE
;
5780 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5784 grub_file_t file
= NULL
;
5785 grub_uint32_t loadrba
= 0;
5786 grub_uint32_t boot_catlog
= 0;
5787 grub_uint8_t sector
[512];
5788 boot_info_table
*info
= NULL
;
5793 /* This also trigger a iso9660 fs parse */
5794 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5799 joliet
= grub_iso9660_is_joliet();
5805 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5808 debug("failed to open %s\n", args
[0]);
5812 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5813 if (boot_catlog
== 0)
5815 debug("no bootcatlog found %u\n", boot_catlog
);
5819 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5822 debug("no bios eltorito rba found %u\n", loadrba
);
5826 grub_file_seek(file
, loadrba
* 2048);
5827 grub_file_read(file
, sector
, 512);
5829 info
= (boot_info_table
*)sector
;
5830 if (info
->bi_data0
== 0x7c6ceafa &&
5831 info
->bi_data1
== 0x90900000 &&
5832 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5833 info
->bi_BootFileLocation
== loadrba
)
5835 debug("bootloader is syslinux, %u.\n", loadrba
);
5841 grub_file_close(file
);
5842 grub_errno
= GRUB_ERR_NONE
;
5846 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5849 ventoy_vlnk_part
*node
;
5855 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5857 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5858 ++n
, node
->device
, node
->disksig
,
5859 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5865 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5873 len
= (int)grub_strlen(args
[0]);
5874 if (grub_file_is_vlnk_suffix(args
[0], len
))
5883 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5886 const char *name
= NULL
;
5892 grub_env_unset(args
[1]);
5893 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5896 debug("VLNK SRC: <%s>\n", args
[0]);
5897 debug("VLNK DST: <%s>\n", name
);
5898 grub_env_set(args
[1], name
);
5906 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5910 grub_file_t file
= NULL
;
5921 len
= (int)grub_strlen(args
[0]);
5922 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5924 grub_printf("Invalid vlnk suffix\n");
5928 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5931 grub_printf("Failed to open %s\n", args
[0]);
5935 if (file
->size
!= 32768)
5937 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5941 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5942 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5944 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5949 check_free(file
, grub_file_close
);
5950 grub_errno
= GRUB_ERR_NONE
;
5954 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5960 g_iso_vd_id_publisher
[0] = 0;
5961 g_iso_vd_id_prepare
[0] = 0;
5962 g_iso_vd_id_application
[0] = 0;
5967 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5971 grub_file_t file
= NULL
;
5976 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5979 grub_printf("Failed to open %s\n", args
[0]);
5983 grub_file_seek(file
, 16 * 2048 + offset
);
5984 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5987 grub_file_seek(file
, 16 * 2048 + offset
);
5988 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5991 grub_file_seek(file
, 16 * 2048 + offset
);
5992 grub_file_read(file
, g_iso_vd_id_application
, 128);
5996 check_free(file
, grub_file_close
);
5997 grub_errno
= GRUB_ERR_NONE
;
6001 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6004 char *id
= g_iso_vd_id_publisher
;
6009 if (args
[0][0] == '1')
6011 id
= g_iso_vd_id_prepare
;
6013 else if (args
[0][0] == '2')
6015 id
= g_iso_vd_id_application
;
6018 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6023 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6028 grub_errno
= GRUB_ERR_NONE
;
6032 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6037 g_ventoy_fn_mutex
= 0;
6038 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
6040 g_ventoy_fn_mutex
= 1;
6043 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6046 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6048 grub_uint64_t total
;
6049 grub_uint64_t org_required
;
6050 grub_uint64_t new_required
;
6056 #ifdef GRUB_MACHINE_EFI
6057 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6058 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6059 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6060 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6065 grub_printf("Non EFI mode!\n");
6070 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6073 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6075 const char *env
= NULL
;
6080 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6085 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6086 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6087 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6088 ventoy_check_mode_by_name(args
[0], "vtnormal")
6094 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6095 if (env
&& env
[0] == '0' && env
[1] == 0)
6103 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6111 const char *env
= NULL
;
6112 ulonglong fsize
= 0;
6114 int seldata
[16] = {0};
6119 len
= 8 * VTOY_SIZE_1KB
;
6120 cmd
= (char *)grub_malloc(len
);
6126 g_vtoy_secondary_need_recover
= 0;
6127 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6129 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6132 timeout
= (int)grub_strtol(env
, NULL
, 10);
6137 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6140 fsize
= grub_strtoull(args
[2], NULL
, 10);
6142 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6144 if (grub_strcmp(args
[1], "Unix") != 0)
6146 if (grub_strcmp(args
[1], "Windows") == 0)
6148 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6152 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6155 if (fsize
<= VTOY_SIZE_1GB
)
6157 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6161 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6164 g_ventoy_menu_esc
= 1;
6165 g_ventoy_suppress_esc
= 1;
6166 g_ventoy_suppress_esc_default
= 0;
6167 g_ventoy_secondary_menu_on
= 1;
6168 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6169 grub_script_execute_sourcecode(cfgfile
);
6170 g_ventoy_menu_esc
= 0;
6171 g_ventoy_suppress_esc
= 0;
6172 g_ventoy_suppress_esc_default
= 1;
6173 g_ventoy_secondary_menu_on
= 0;
6175 select
= seldata
[g_ventoy_last_entry
];
6179 g_ventoy_wimboot_mode
= 1;
6180 g_vtoy_secondary_need_recover
= 1;
6182 else if (select
== 3)
6184 g_ventoy_grub2_mode
= 1;
6185 g_vtoy_secondary_need_recover
= 2;
6187 else if (select
== 4)
6189 g_ventoy_memdisk_mode
= 1;
6190 g_vtoy_secondary_need_recover
= 3;
6192 else if (select
== 5)
6194 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6195 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6197 }while (select
== 5);
6203 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6209 if (g_vtoy_secondary_need_recover
== 1)
6211 g_ventoy_wimboot_mode
= 0;
6213 else if (g_vtoy_secondary_need_recover
== 2)
6215 g_ventoy_grub2_mode
= 0;
6217 else if (g_vtoy_secondary_need_recover
== 3)
6219 g_ventoy_memdisk_mode
= 0;
6222 g_vtoy_secondary_need_recover
= 0;
6224 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6227 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6232 if (args
[0][0] == '0')
6234 g_ventoy_case_insensitive
= 0;
6238 g_ventoy_case_insensitive
= 1;
6244 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6249 ventoy_plugin_load_menu_lang(1, args
[0]);
6250 VENTOY_CMD_RETURN(0);
6253 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6258 ventoy_plugin_load_menu_lang(0, args
[0]);
6259 VENTOY_CMD_RETURN(0);
6263 static const char * ventoy_menu_lang_read_hook(struct grub_env_var
*var
, const char *val
)
6266 return ventoy_get_vmenu_title(val
);
6269 int ventoy_env_init(void)
6274 grub_env_set("vtdebug_flag", "");
6276 grub_register_vtoy_menu_lang_hook(ventoy_menu_lang_read_hook
);
6277 ventoy_ctrl_var_init();
6278 ventoy_global_var_init();
6280 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6281 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6282 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6283 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6285 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6288 ventoy_filt_register(0, ventoy_wrapper_open
);
6290 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6293 g_grub_param
->grub_env_get
= grub_env_get
;
6294 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6295 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6296 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6297 grub_env_set("env_param", buf
);
6298 grub_env_set("ventoy_env_param", buf
);
6300 grub_env_export("env_param");
6301 grub_env_export("ventoy_env_param");
6304 grub_env_export("vtoy_winpeshl_ini_addr");
6305 grub_env_export("vtoy_winpeshl_ini_size");
6307 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6308 grub_env_set("vtoy_chain_file_size", buf
);
6309 grub_env_export("vtoy_chain_file_size");
6311 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6312 grub_env_set("vtoy_chain_file_read", buf
);
6313 grub_env_export("vtoy_chain_file_read");
6315 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6316 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6317 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6319 grub_snprintf(buf
, sizeof(buf
), "%s-%s", GRUB_TARGET_CPU
, GRUB_PLATFORM
);
6320 grub_env_set("grub_cpu_platform", buf
);
6321 grub_env_export("grub_cpu_platform");
6328 static cmd_para ventoy_cmds
[] =
6330 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6331 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6332 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6333 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6334 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6335 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6336 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6337 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6338 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6339 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6340 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6341 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6342 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6343 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6344 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6345 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6346 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6347 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6348 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6349 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6350 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6351 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6352 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6353 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6354 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6355 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6356 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6358 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6359 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6360 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6361 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6362 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6363 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6364 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6366 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6367 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6368 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6369 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6370 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6371 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6372 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6373 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6374 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6375 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6378 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6379 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6380 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6381 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6382 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6383 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6384 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6385 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6386 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6387 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6388 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6390 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6391 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6392 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6393 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6394 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6395 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6396 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6398 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6399 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6400 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6401 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6402 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6403 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6404 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6405 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6406 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6407 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6409 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6410 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6411 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6412 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6413 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6414 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6415 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6416 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6417 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6419 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6420 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6421 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6422 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6425 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6426 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6427 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6429 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6430 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6431 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6434 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6435 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6436 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6437 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6438 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6439 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6440 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6441 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6442 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6443 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6444 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6445 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6446 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6447 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6449 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6450 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6451 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6452 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6453 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6454 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6455 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6456 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6457 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6458 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6459 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6460 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6462 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6463 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6464 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6465 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6466 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6467 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6468 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6469 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6470 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6471 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6472 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6473 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6474 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6475 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6476 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6477 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6478 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6479 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6480 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6481 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6482 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6483 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6484 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6485 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6486 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6487 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6488 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6489 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6490 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6491 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6495 int ventoy_register_all_cmd(void)
6498 cmd_para
*cur
= NULL
;
6500 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6502 cur
= ventoy_cmds
+ i
;
6503 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6504 cur
->summary
, cur
->description
, cur
->parser
);
6510 int ventoy_unregister_all_cmd(void)
6514 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6516 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);