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_load_prompt
= 0;
162 static char g_vtoy_prompt_msg
[64];
164 static char g_json_case_mis_path
[32];
166 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
168 int ventoy_get_fs_type(const char *fs
)
172 return ventoy_fs_max
;
174 else if (grub_strncmp(fs
, "exfat", 5) == 0)
176 return ventoy_fs_exfat
;
178 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
180 return ventoy_fs_ntfs
;
182 else if (grub_strncmp(fs
, "ext", 3) == 0)
184 return ventoy_fs_ext
;
186 else if (grub_strncmp(fs
, "xfs", 3) == 0)
188 return ventoy_fs_xfs
;
190 else if (grub_strncmp(fs
, "udf", 3) == 0)
192 return ventoy_fs_udf
;
194 else if (grub_strncmp(fs
, "fat", 3) == 0)
196 return ventoy_fs_fat
;
199 return ventoy_fs_max
;
202 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
221 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
223 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
227 static int ventoy_control_get_flag(const char *key
)
229 const char *val
= ventoy_get_env(key
);
231 if (val
&& val
[0] == '1' && val
[1] == 0)
238 static grub_err_t
ventoy_fs_close(grub_file_t file
)
240 grub_file_close(g_old_file
);
241 grub_free(file
->data
);
249 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
255 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
260 for (i
= 0; i
< g_video_mode_num
; i
++)
262 if (g_video_mode_list
[i
].width
== info
->width
&&
263 g_video_mode_list
[i
].height
== info
->height
&&
264 g_video_mode_list
[i
].bpp
== info
->bpp
)
270 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
271 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
272 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
275 if (g_video_mode_num
== g_video_mode_max
)
277 g_video_mode_max
*= 2;
278 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
284 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
286 if (v1
->bpp
== v2
->bpp
)
288 if (v1
->width
== v2
->width
)
290 if (v1
->height
== v2
->height
)
296 return (v1
->height
< v2
->height
) ? -1 : 1;
301 return (v1
->width
< v2
->width
) ? -1 : 1;
306 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
310 static int ventoy_enum_video_mode(void)
313 grub_video_adapter_t adapter
;
314 grub_video_driver_id_t id
;
315 ventoy_video_mode mode
;
317 g_video_mode_num
= 0;
318 g_video_mode_max
= 1024;
319 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
320 if (!g_video_mode_list
)
325 #ifdef GRUB_MACHINE_PCBIOS
326 grub_dl_load ("vbe");
329 id
= grub_video_get_driver_id ();
331 FOR_VIDEO_ADAPTERS (adapter
)
333 if (!adapter
->iterate
||
334 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
335 adapter
->init() != GRUB_ERR_NONE
)))
340 adapter
->iterate(ventoy_video_hook
, NULL
);
342 if (adapter
->id
!= id
)
348 /* sort video mode */
349 for (i
= 0; i
< g_video_mode_num
; i
++)
350 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
352 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
354 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
355 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
356 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
360 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
363 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
367 static struct grub_fs vtoy_fs
=
372 .fs_read
= ventoy_fs_read
,
373 .fs_close
= ventoy_fs_close
,
383 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
389 file
->data
= grub_malloc(rawFile
->size
+ 4096);
395 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
396 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
398 g_old_file
= rawFile
;
400 file
->size
= rawFile
->size
+ len
;
401 file
->device
= rawFile
->device
;
403 file
->not_easily_seekable
= 1;
408 static int ventoy_check_decimal_var(const char *name
, long *value
)
410 const char *value_str
= NULL
;
412 value_str
= grub_env_get(name
);
413 if (NULL
== value_str
)
415 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
418 if (!ventoy_is_decimal(value_str
))
420 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
423 *value
= grub_strtol(value_str
, NULL
, 10);
425 return GRUB_ERR_NONE
;
428 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
430 grub_uint64_t sectors
;
432 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
434 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
438 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
441 return sectors
* 512;
444 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
450 grub_uint32_t offset
;
452 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
455 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
459 len
= (int)file
->size
;
461 data
= (char *)grub_malloc(file
->size
);
467 grub_file_read(file
, data
, file
->size
);
468 grub_file_close(file
);
470 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
471 grub_script_execute_sourcecode(exec
);
473 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
474 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
475 grub_file_close(file
);
477 grub_script_execute_sourcecode("loopback -d efiboot");
481 *direntoff
= offset
+ 2;
486 static int ventoy_set_check_result(int ret
, const char *msg
)
490 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
491 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
492 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
496 grub_printf(VTOY_WARNING
"\n");
497 grub_printf(VTOY_WARNING
"\n");
498 grub_printf(VTOY_WARNING
"\n\n\n");
500 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
501 grub_printf("Error message: <%s>\n\n", msg
);
502 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
504 grub_printf("\n\nWill exit after 10 seconds ...... ");
512 static int ventoy_check_official_device(grub_device_t dev
)
516 grub_uint64_t offset
;
519 grub_uint8_t mbr
[512];
523 struct grub_partition
*partition
;
525 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
527 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
530 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
531 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
532 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
534 #ifndef GRUB_MACHINE_EFI
535 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
537 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
539 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
541 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
543 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
545 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
554 /* We must have partition 2 */
557 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
561 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
565 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
568 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
570 grub_file_close(file
);
571 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
574 partition
= dev
->disk
->partition
;
575 if (partition
->number
!= 0 || partition
->start
!= 2048)
577 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
582 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
584 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
585 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
586 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
588 grub_file_close(file
);
589 return ventoy_set_check_result(6, "Disk partition layout check failed.");
594 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
595 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
596 PartTbl
[1].SectorCount
!= 65536)
598 grub_file_close(file
);
599 return ventoy_set_check_result(6, "Disk partition layout check failed.");
605 offset
= partition
->start
+ partition
->len
;
606 partition
= file
->device
->disk
->partition
;
607 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
609 grub_file_close(file
);
610 return ventoy_set_check_result(7, "Disk partition layout check failed.");
614 grub_file_close(file
);
618 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
619 dev2
= grub_device_open(devname
);
622 return ventoy_set_check_result(8, "Disk open failed");
625 fs
= grub_fs_probe(dev2
);
628 grub_device_close(dev2
);
629 return ventoy_set_check_result(9, "FS probe failed");
632 fs
->fs_label(dev2
, &label
);
633 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
635 grub_device_close(dev2
);
636 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
639 grub_device_close(dev2
);
643 disk
= grub_disk_open(dev
->disk
->name
);
646 return ventoy_set_check_result(11, "Disk open failed");
649 grub_memset(mbr
, 0, 512);
650 grub_disk_read(disk
, 0, 0, 512, mbr
);
651 grub_disk_close(disk
);
653 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
655 return ventoy_set_check_result(12, "MBR check failed");
658 return ventoy_set_check_result(0, NULL
);
661 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
665 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
675 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
677 grub_uint64_t size
= 0;
680 char fullpath
[256] = {0};
683 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
686 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
689 debug("grub_file_open failed <%s>\n", fullpath
);
695 grub_file_close(file
);
699 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
703 char fullpath
[512] = {0};
706 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
709 file
= grub_file_open(fullpath
, type
);
712 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
719 int ventoy_is_dir_exist(const char *fmt
, ...)
726 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
730 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
733 grub_strncpy(pos
+ len
, "\" ]", 3);
735 debug("script exec %s\n", buf
);
737 if (0 == grub_script_execute_sourcecode(buf
))
745 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
748 grub_uint8_t
*outbuf
;
749 grub_uint8_t gzHdr
[10] =
751 0x1F, 0x8B, /* magic */
759 grub_memset(&s
, 0, sizeof(mz_stream
));
761 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
763 outbuf
= (grub_uint8_t
*)mem_out
;
765 mem_out_len
-= sizeof(gzHdr
) + 8;
766 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
767 outbuf
+= sizeof(gzHdr
);
769 s
.avail_in
= mem_in_len
;
772 s
.avail_out
= mem_out_len
;
775 mz_deflate(&s
, MZ_FINISH
);
779 outbuf
+= s
.total_out
;
780 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
781 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
783 return s
.total_out
+ sizeof(gzHdr
) + 8;
791 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
795 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
798 if (0 == grub_strcmp(args
[0], "on"))
801 grub_env_set("vtdebug_flag", "debug");
806 grub_env_set("vtdebug_flag", "");
809 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
812 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
816 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
818 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
819 grub_printf(" level:\r\n");
820 grub_printf(" 01/11: busybox / (+cat log)\r\n");
821 grub_printf(" 02/12: initrd / (+cat log)\r\n");
822 grub_printf(" 03/13: hook / (+cat log)\r\n");
824 grub_printf(" debug:\r\n");
825 grub_printf(" 0: debug is off\r\n");
826 grub_printf(" 1: debug is on\r\n");
828 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
831 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
833 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
835 g_ventoy_debug_level
= 1;
838 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
841 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
850 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
853 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
885 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
901 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
917 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
922 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
924 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
927 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
932 value_long
+= grub_strtol(args
[1], NULL
, 10);
934 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
935 grub_env_set(args
[0], buf
);
937 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
940 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
942 ulonglong value1
= 0;
943 ulonglong value2
= 0;
948 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
951 value1
= grub_strtoull(args
[0], NULL
, 10);
952 value2
= grub_strtoull(args
[1], NULL
, 10);
954 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
955 grub_env_set(args
[2], buf
);
957 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
960 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
975 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
978 debug("failed to open file <%s> for udf check\n", args
[0]);
982 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
984 grub_env_set(args
[1], buf
);
986 grub_file_close(file
);
992 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1000 g_wimboot_enable
= 0;
1002 grub_check_free(g_wimiso_path
);
1003 grub_check_free(g_wimiso_chunk_list
.chunk
);
1005 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1011 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1012 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1013 if (NULL
== g_wimiso_chunk_list
.chunk
)
1015 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1018 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1019 g_wimiso_chunk_list
.cur_chunk
= 0;
1021 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1023 g_wimboot_enable
= 1;
1024 g_wimiso_path
= grub_strdup(args
[0]);
1025 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1026 grub_file_close(file
);
1031 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1041 ventoy_iso9660_override
*dirent
;
1050 totlen
= sizeof(ventoy_chain_head
);
1052 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1054 debug("failed to load efiboot template %d\n", len
);
1060 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1062 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1065 debug("failed to open file <%s>\n", args
[0]);
1069 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1074 totlen
+= ventoy_align_2k(file
->size
);
1076 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1077 dirent
->first_sector
= len
/ 2048;
1078 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1079 dirent
->size
= (grub_uint32_t
)file
->size
;
1080 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1082 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1084 #ifdef GRUB_MACHINE_EFI
1085 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1087 data
= (char *)grub_malloc(totlen
);
1090 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1092 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1093 grub_check_free(buf
);
1095 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1096 grub_file_close(file
);
1098 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1099 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1100 grub_env_set(name
, value
);
1102 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1103 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1104 grub_env_set(name
, value
);
1109 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1115 g_vtoy_load_prompt
= 0;
1116 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1118 if (argc
== 2 && args
[0][0] == '1')
1120 g_vtoy_load_prompt
= 1;
1121 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1124 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1127 int ventoy_need_prompt_load_file(void)
1129 return g_vtoy_load_prompt
;
1132 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1134 grub_uint64_t ro
= 0;
1135 grub_uint64_t div
= 0;
1136 grub_ssize_t left
= size
;
1137 char *cur
= (char *)buf
;
1139 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1142 while (left
>= VTOY_SIZE_2MB
)
1144 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1145 cur
+= VTOY_SIZE_2MB
;
1146 left
-= VTOY_SIZE_2MB
;
1148 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1153 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1159 grub_file_read(file
, cur
, left
);
1162 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1168 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1175 enum grub_file_type type
;
1186 if (grub_strcmp(args
[0], "nodecompress") == 0)
1188 type
= VENTOY_FILE_TYPE
;
1192 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1195 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1198 debug("failed to open file <%s>\n", args
[1]);
1202 #ifdef GRUB_MACHINE_EFI
1203 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1205 buf
= (char *)grub_malloc(file
->size
);
1210 grub_file_close(file
);
1214 if (g_vtoy_load_prompt
)
1216 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1220 grub_file_read(file
, buf
, file
->size
);
1223 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1224 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1225 grub_env_set(name
, value
);
1227 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1228 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1229 grub_env_set(name
, value
);
1231 grub_file_close(file
);
1237 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1255 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1258 debug("failed to open file <%s> for udf check\n", args
[0]);
1262 headlen
= sizeof(ventoy_chain_head
);
1264 #ifdef GRUB_MACHINE_EFI
1265 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1267 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1270 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1272 grub_file_read(file
, buf
+ headlen
, file
->size
);
1274 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1275 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1276 grub_env_set(name
, value
);
1278 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1279 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1280 grub_env_set(name
, value
);
1282 grub_file_close(file
);
1288 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1294 if (grub_iso9660_is_joliet())
1296 debug("This time has joliet process\n");
1305 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1314 if (args
[0][0] == '1')
1316 grub_iso9660_set_nojoliet(1);
1320 grub_iso9660_set_nojoliet(0);
1326 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1331 grub_uint8_t buf
[32];
1342 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1345 debug("failed to open file <%s> for udf check\n", args
[0]);
1349 for (i
= 16; i
< 32; i
++)
1351 grub_file_seek(file
, i
* 2048);
1352 grub_file_read(file
, buf
, sizeof(buf
));
1360 grub_file_seek(file
, i
* 2048);
1361 grub_file_read(file
, buf
, sizeof(buf
));
1363 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1366 grub_file_seek(file
, i
* 2048);
1367 grub_file_read(file
, buf
, sizeof(buf
));
1369 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1370 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1376 grub_file_close(file
);
1378 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1383 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1385 long value_long1
= 0;
1386 long value_long2
= 0;
1388 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1390 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1393 value_long1
= grub_strtol(args
[0], NULL
, 10);
1394 value_long2
= grub_strtol(args
[2], NULL
, 10);
1396 if (0 == grub_strcmp(args
[1], "eq"))
1398 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1400 else if (0 == grub_strcmp(args
[1], "ne"))
1402 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1404 else if (0 == grub_strcmp(args
[1], "gt"))
1406 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1408 else if (0 == grub_strcmp(args
[1], "lt"))
1410 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1412 else if (0 == grub_strcmp(args
[1], "ge"))
1414 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1416 else if (0 == grub_strcmp(args
[1], "le"))
1418 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1422 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1428 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1431 char buf
[128] = {0};
1435 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1438 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1439 pos
= grub_strstr(buf
, ",");
1445 grub_env_set(args
[1], buf
);
1447 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1450 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1456 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1462 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1465 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1467 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1468 if (0 == grub_script_execute_sourcecode(buf
))
1470 debug("file %s exist, ventoy_compatible YES\n", buf
);
1471 grub_env_set("ventoy_compatible", "YES");
1472 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1476 debug("file %s NOT exist\n", buf
);
1480 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1481 pos
= grub_strstr(buf
, ")");
1487 disk
= grub_disk_open(buf
);
1490 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1491 grub_disk_close(disk
);
1493 g_img_swap_tmp_buf
[703] = 0;
1494 for (i
= 318; i
< 703; i
++)
1496 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1497 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1499 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1500 grub_env_set("ventoy_compatible", "YES");
1501 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1507 debug("failed to open disk <%s>\n", buf
);
1510 grub_env_set("ventoy_compatible", "NO");
1511 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1514 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1520 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1522 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1525 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1530 if (0 == g_sort_case_sensitive
)
1532 if (grub_islower(c1
))
1534 c1
= c1
- 'a' + 'A';
1537 if (grub_islower(c2
))
1539 c2
= c2
- 'a' + 'A';
1552 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1558 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1560 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1563 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1568 if (0 == g_sort_case_sensitive
)
1570 if (grub_islower(c1
))
1572 c1
= c1
- 'a' + 'A';
1575 if (grub_islower(c2
))
1577 c2
= c2
- 'a' + 'A';
1590 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1592 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1594 grub_memcpy(img1
, img2
, sizeof(img_info
));
1595 img1
->next
= g_img_swap_tmp
.next
;
1596 img1
->prev
= g_img_swap_tmp
.prev
;
1598 g_img_swap_tmp
.next
= img2
->next
;
1599 g_img_swap_tmp
.prev
= img2
->prev
;
1600 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1603 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1607 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1615 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1617 ventoy_vlnk_part
*node
= NULL
;
1618 grub_uint32_t SelfSig
;
1619 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1621 /* skip Ventoy partition 1/2 */
1622 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1623 if (partition
->number
< 2 && SelfSig
== *pSig
)
1628 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1631 node
->disksig
= *pSig
;
1632 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1633 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1634 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1636 node
->next
= g_vlnk_part_list
;
1637 g_vlnk_part_list
= node
;
1643 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1650 disk
= grub_disk_open(name
);
1653 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1654 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1655 grub_disk_close(disk
);
1661 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1663 const char *fs
[ventoy_fs_max
+ 1] =
1665 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1670 cur
->dev
= grub_device_open(cur
->device
);
1675 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1681 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1686 char *disk
, *device
;
1687 grub_uint32_t readcrc
, calccrc
;
1688 ventoy_vlnk_part
*cur
;
1689 grub_fs_t fs
= NULL
;
1691 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1695 grub_printf("VLNK invalid guid\n");
1701 readcrc
= vlnk
->crc32
;
1703 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1704 if (readcrc
!= calccrc
)
1708 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1714 if (!g_vlnk_part_list
)
1716 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1719 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1721 if (cur
->disksig
== vlnk
->disk_signature
)
1725 if (cur
->partoffset
== vlnk
->part_offset
)
1728 device
= cur
->device
;
1730 if (cur
->probe
== 0)
1733 ventoy_vlnk_probe_fs(cur
);
1743 struct grub_file file
;
1745 grub_memset(&file
, 0, sizeof(file
));
1746 file
.device
= cur
->dev
;
1747 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1750 cur
->fs
->fs_close(&file
);
1751 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1760 grub_printf("\n==== VLNK Information ====\n"
1761 "Disk Signature: %08x\n"
1762 "Partition Offset: %llu\n"
1763 "File Path: <%s>\n\n",
1764 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1768 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1772 grub_printf("Disk Find: [ NO ]\n");
1777 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1781 grub_printf("Part Find: [ NO ]\n");
1783 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1786 grub_printf("VLNK File: <%s>\n", dst
);
1793 return (1 - filefind
);
1796 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1801 grub_file_t file
= NULL
;
1806 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1808 else if (dir
[0] == '/')
1810 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1814 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1817 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1823 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1824 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1825 grub_file_close(file
);
1827 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1829 rc
= grub_file_add_vlnk(src
, dst
);
1835 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1845 const menu_tip
*tip
;
1846 img_iterator_node
*tmp
;
1847 img_iterator_node
*new_node
;
1848 img_iterator_node
*node
= (img_iterator_node
*)data
;
1850 if (g_enumerate_time_checked
== 0)
1852 g_enumerate_finish_time_ms
= grub_get_time_ms();
1853 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1856 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1858 g_enumerate_time_checked
= 1;
1862 len
= grub_strlen(filename
);
1866 if (node
->level
+ 1 > g_img_max_search_level
)
1871 if ((len
== 1 && filename
[0] == '.') ||
1872 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1877 if (!ventoy_img_name_valid(filename
, len
))
1882 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1887 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1889 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1890 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1893 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1898 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1901 new_node
->level
= node
->level
+ 1;
1902 new_node
->plugin_list_index
= index
;
1903 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1905 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1908 debug("Directory %s ignored...\n", new_node
->dir
);
1909 grub_free(new_node
);
1913 new_node
->tail
= node
->tail
;
1915 new_node
->parent
= node
;
1916 if (!node
->firstchild
)
1918 node
->firstchild
= new_node
;
1921 if (g_img_iterator_tail
)
1923 g_img_iterator_tail
->next
= new_node
;
1924 g_img_iterator_tail
= new_node
;
1928 g_img_iterator_head
.next
= new_node
;
1929 g_img_iterator_tail
= new_node
;
1935 debug("Find a file %s\n", filename
);
1941 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1943 type
= img_type_iso
;
1945 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1947 type
= img_type_wim
;
1949 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1950 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1952 type
= img_type_vhd
;
1954 #ifdef GRUB_MACHINE_EFI
1955 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1957 type
= img_type_efi
;
1960 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1962 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1964 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1965 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1970 type
= img_type_img
;
1972 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1974 type
= img_type_vtoy
;
1976 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1978 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1980 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1981 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1990 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1995 if (g_plugin_image_list
)
1997 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1998 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1999 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
2001 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2004 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2006 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2011 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2013 if (grub_file_is_vlnk_suffix(filename
, len
))
2016 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2023 img
= grub_zalloc(sizeof(img_info
));
2027 img
->plugin_list_index
= index
;
2028 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2030 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2032 img
->size
= info
->size
;
2033 if (vlnk
|| 0 == img
->size
)
2035 if (node
->dir
[0] == '/')
2037 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2041 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2045 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2047 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2052 if (g_ventoy_img_list
)
2054 tail
= *(node
->tail
);
2060 g_ventoy_img_list
= img
;
2063 img
->id
= g_ventoy_img_count
;
2065 if (node
&& NULL
== node
->firstiso
)
2067 node
->firstiso
= img
;
2078 *((img_info
**)(node
->tail
)) = img
;
2079 g_ventoy_img_count
++;
2081 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2083 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2086 img
->tip1
= tip
->tip1
;
2087 img
->tip2
= tip
->tip2
;
2090 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2093 img
->class = g_menu_class
[type
];
2095 img
->menu_prefix
= g_menu_prefix
[type
];
2097 if (img_type_iso
== type
)
2099 if (ventoy_plugin_check_memdisk(img
->path
))
2101 img
->menu_prefix
= "miso";
2105 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2112 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2114 int len
= GRUB_UINT_MAX
;
2115 const char *value
= NULL
;
2116 char name
[32] = {0};
2117 char plat
[32] = {0};
2118 char guidstr
[32] = {0};
2119 ventoy_guid guid
= VENTOY_GUID
;
2120 const char *fmt1
= NULL
;
2121 const char *fmt2
= NULL
;
2122 const char *fmt3
= NULL
;
2123 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2124 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2125 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2126 const char fmtcode
[]={
2127 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2128 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2129 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2130 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2131 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2132 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2135 grub_memset(name
, 0, sizeof(name
));
2136 puint
[0] = grub_swap_bytes32(0x56454e54);
2137 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2138 puint
[2] = grub_swap_bytes32(0x45525349);
2139 puint
[1] = grub_swap_bytes32(0x4f595f56);
2140 value
= ventoy_get_env(name
);
2142 grub_memset(name
, 0, sizeof(name
));
2143 puint
[1] = grub_swap_bytes32(0x5f544f50);
2144 puint
[0] = grub_swap_bytes32(0x56544c45);
2145 fmt1
= ventoy_get_env(name
);
2151 grub_memset(name
, 0, sizeof(name
));
2152 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2153 puint
[0] = grub_swap_bytes32(0x56544c45);
2154 fmt2
= ventoy_get_env(name
);
2156 grub_memset(name
, 0, sizeof(name
));
2157 puint
[1] = grub_swap_bytes32(0x5f434c52);
2158 puint
[0] = grub_swap_bytes32(0x56544c45);
2159 fmt3
= ventoy_get_env(name
);
2161 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2163 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2165 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2166 #pragma GCC diagnostic push
2167 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2168 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2169 fmt1
? fmt1
: fmtdata
,
2170 fmt2
? fmt2
: fmtdata
+ 4,
2171 value
? value
: "", plat
, guidstr
,
2172 fmt3
? fmt3
: fmtdata
+ 6);
2173 #pragma GCC diagnostic pop
2175 grub_memset(name
, 0, sizeof(name
));
2176 puint
[0] = grub_swap_bytes32(0x76746f79);
2177 puint
[2] = grub_swap_bytes32(0x656e7365);
2178 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2179 ventoy_set_env(name
, guidstr
);
2184 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2188 grub_uint8_t md5
[16];
2192 grub_memset(input
, 0, sizeof(input
));
2194 grub_printf("Enter password: ");
2197 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2199 grub_password_get(input
, 128);
2200 if (grub_strcmp(pwd
->text
, input
) == 0)
2205 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2207 grub_password_get(input
, 128);
2208 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2209 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2214 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2216 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2217 grub_password_get(input
+ offset
, 128);
2219 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2220 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2226 grub_printf("Invalid password!\n\n");
2233 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2235 img_info
*minimg
= NULL
;
2236 img_info
*img
= (img_info
*)(node
->firstiso
);
2238 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2240 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2255 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2257 img_iterator_node
*Minchild
= NULL
;
2258 img_iterator_node
*child
= node
->firstchild
;
2260 while (child
&& child
->parent
== node
)
2262 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2266 child
= child
->next
;
2271 Minchild
->select
= 1;
2277 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2280 img_info
*img
= NULL
;
2281 const char *dir_class
= NULL
;
2282 const char *dir_alias
= NULL
;
2283 img_iterator_node
*child
= NULL
;
2284 const menu_tip
*tip
= NULL
;
2286 if (node
->isocnt
== 0 || node
->done
== 1)
2291 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2293 offset
= node
->parent
->dirlen
;
2296 if (node
== &g_img_iterator_head
)
2298 if (g_default_menu_mode
== 0)
2300 if (g_tree_view_menu_style
== 0)
2302 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2303 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2304 " echo 'return ...' \n"
2309 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2310 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2311 " echo 'return ...' \n"
2316 g_tree_script_pre
= g_tree_script_pos
;
2320 node
->dir
[node
->dirlen
- 1] = 0;
2321 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2324 dir_class
= "vtoydir";
2327 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2329 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2332 if (g_tree_view_menu_style
== 0)
2334 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2335 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2336 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2340 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2341 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2342 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2347 dir_alias
= node
->dir
+ offset
;
2349 if (g_tree_view_menu_style
== 0)
2351 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2352 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2353 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2357 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2358 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2359 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2363 if (g_tree_view_menu_style
== 0)
2365 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2366 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2367 " echo 'return ...' \n"
2368 "}\n", "<--", node
->dir
);
2372 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2373 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2374 " echo 'return ...' \n"
2379 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2381 ventoy_dynamic_tree_menu(child
);
2384 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2386 if (g_tree_view_menu_style
== 0)
2388 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2389 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2392 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2393 img
->unsupport
? "[***********] " : "",
2394 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2396 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2400 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2401 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2404 img
->unsupport
? "[***********] " : "",
2405 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2407 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2411 if (node
!= &g_img_iterator_head
)
2413 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2420 static int ventoy_set_default_menu(void)
2426 const char *strdata
= NULL
;
2427 img_info
*cur
= NULL
;
2428 img_info
*default_node
= NULL
;
2429 const char *default_image
= NULL
;
2431 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2432 if (default_image
&& default_image
[0] == '/')
2434 img_len
= grub_strlen(default_image
);
2436 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2438 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2450 if (0 == g_default_menu_mode
)
2452 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2456 def
= grub_strdup(default_image
);
2462 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2464 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2465 if (strdata
&& strdata
[0] == '/')
2467 pos
= def
+ grub_strlen(strdata
);
2478 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2481 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2485 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2493 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2495 img_info
*next
= NULL
;
2496 img_info
*cur
= g_ventoy_img_list
;
2509 g_ventoy_img_list
= NULL
;
2510 g_ventoy_img_count
= 0;
2512 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2515 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2518 img_info
*cur
= g_ventoy_img_list
;
2522 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2524 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2527 img_id
= grub_strtol(args
[0], NULL
, 10);
2528 if (img_id
>= g_ventoy_img_count
)
2530 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2533 debug("Find image %ld name \n", img_id
);
2535 while (cur
&& img_id
> 0)
2543 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2546 debug("image name is %s\n", cur
->name
);
2548 grub_env_set(args
[1], cur
->name
);
2550 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2553 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2557 img_info
*cur
= g_ventoy_img_list
;
2563 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2566 len
= (int)grub_strlen(args
[0]);
2570 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2579 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2582 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2583 grub_env_set("chosen", id
);
2584 grub_env_export("chosen");
2586 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2589 static char g_fake_vlnk_src
[512];
2590 static char g_fake_vlnk_dst
[512];
2591 static grub_uint64_t g_fake_vlnk_size
;
2592 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2598 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2600 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2601 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2603 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2605 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2608 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2614 g_fake_vlnk_src
[0] = 0;
2615 g_fake_vlnk_dst
[0] = 0;
2616 g_fake_vlnk_size
= 0;
2617 grub_file_vtoy_vlnk(NULL
, NULL
);
2619 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2623 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2628 const char *id
= NULL
;
2629 img_info
*cur
= NULL
;
2633 if (argc
< 1 || argc
> 3)
2635 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2638 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2640 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2641 grub_env_set(args
[0], pos
);
2644 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2645 grub_env_set(args
[1], value
);
2650 for (last
= pos
; *pos
; pos
++)
2657 grub_env_set(args
[2], last
+ 1);
2663 id
= grub_env_get("chosen");
2665 pos
= grub_strstr(id
, "VID_");
2668 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2672 cur
= g_ventoy_img_list
;
2677 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2680 grub_env_set(args
[0], cur
->path
);
2684 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2685 grub_env_set(args
[1], value
);
2690 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2691 grub_env_set(args
[2], cur
->name
);
2695 g_svd_replace_offset
= 0;
2697 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2701 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2705 grub_device_t dev
= NULL
;
2706 img_info
*cur
= NULL
;
2707 img_info
*tail
= NULL
;
2708 img_info
*min
= NULL
;
2709 img_info
*head
= NULL
;
2710 const char *strdata
= NULL
;
2711 char *device_name
= NULL
;
2713 img_iterator_node
*node
= NULL
;
2714 img_iterator_node
*tmp
= NULL
;
2720 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2723 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2725 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2730 g_enumerate_time_checked
= 0;
2731 g_enumerate_start_time_ms
= grub_get_time_ms();
2733 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2734 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2736 g_filt_dot_underscore_file
= 1;
2739 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2740 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2742 g_sort_case_sensitive
= 1;
2745 device_name
= grub_file_get_device_name(args
[0]);
2751 g_enum_dev
= dev
= grub_device_open(device_name
);
2757 g_enum_fs
= fs
= grub_fs_probe(dev
);
2763 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2765 debug("unsupported fs:<%s>\n", fs
->name
);
2766 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2770 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2772 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2773 if (strdata
&& strdata
[0] == '1')
2775 g_default_menu_mode
= 1;
2778 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2780 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2782 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2783 if (strdata
&& strdata
[0] == '/')
2785 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2786 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2788 g_img_iterator_head
.dir
[len
++] = '/';
2790 g_img_iterator_head
.dirlen
= len
;
2794 g_img_iterator_head
.dirlen
= 1;
2795 grub_strcpy(g_img_iterator_head
.dir
, "/");
2798 g_img_iterator_head
.tail
= &tail
;
2800 if (g_img_max_search_level
< 0)
2802 g_img_max_search_level
= GRUB_INT_MAX
;
2803 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2804 if (strdata
&& ventoy_is_decimal(strdata
))
2806 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2810 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2811 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2812 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2813 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2814 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2815 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2817 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2819 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2822 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2823 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2825 g_tree_view_menu_style
= 1;
2828 ventoy_set_default_menu();
2830 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2832 ventoy_dynamic_tree_menu(node
);
2836 node
= g_img_iterator_head
.next
;
2844 /* sort image list by image name */
2845 while (g_ventoy_img_list
)
2847 min
= g_ventoy_img_list
;
2848 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2850 if (ventoy_cmp_img(min
, cur
) > 0)
2858 min
->prev
->next
= min
->next
;
2863 min
->next
->prev
= min
->prev
;
2866 if (min
== g_ventoy_img_list
)
2868 g_ventoy_img_list
= min
->next
;
2886 g_ventoy_img_list
= head
;
2888 if (g_default_menu_mode
== 1)
2890 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2891 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2892 " echo 'return ...' \n"
2896 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2898 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2899 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2902 cur
->unsupport
? "[***********] " : "",
2903 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2905 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2908 g_tree_script_buf
[g_tree_script_pos
] = 0;
2909 g_list_script_buf
[g_list_script_pos
] = 0;
2911 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2912 grub_env_set(args
[1], buf
);
2916 check_free(device_name
, grub_free
);
2917 check_free(dev
, grub_device_close
);
2919 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2922 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2929 device_name
= grub_file_get_device_name(filename
);
2941 pos2
= grub_strstr(pos
, ",");
2944 pos2
= grub_strstr(pos
, ")");
2952 disk
= grub_disk_open(pos
);
2955 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2956 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2957 grub_disk_close(disk
);
2964 grub_free(device_name
);
2968 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2970 eltorito_descriptor desc
;
2972 grub_memset(&desc
, 0, sizeof(desc
));
2973 grub_file_seek(file
, 17 * 2048);
2974 grub_file_read(file
, &desc
, sizeof(desc
));
2976 if (desc
.type
!= 0 || desc
.version
!= 1)
2981 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2982 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2990 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2992 grub_uint8_t buf
[512];
2994 grub_file_seek(file
, sector
* 2048);
2995 grub_file_read(file
, buf
, sizeof(buf
));
2997 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2998 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3000 return *((grub_uint32_t
*)(buf
+ 40));
3006 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3010 grub_uint8_t buf
[512];
3011 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3013 grub_file_seek(file
, sector
* 2048);
3014 grub_file_read(file
, buf
, sizeof(buf
));
3016 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3018 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3022 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3027 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3029 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3031 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3035 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3037 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3042 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3044 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3046 if (buf
[36] == parttype
[i
])
3048 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3054 debug("%s does not contain efi eltorito\n", file
->name
);
3058 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3061 const char *fs
= NULL
;
3062 const char *val
= NULL
;
3063 const char *cdprompt
= NULL
;
3065 grub_uint8_t chksum
= 0;
3068 disk
= file
->device
->disk
;
3069 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3071 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3072 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3073 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3075 pos
= grub_strstr(file
->name
, "/");
3081 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3083 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3085 param
->vtoy_img_size
= file
->size
;
3087 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3088 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3090 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3092 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3093 param
->vtoy_reserved
[4] = 0;
3094 if (g_ventoy_chain_type
== 1) /* Windows */
3096 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3097 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3099 param
->vtoy_reserved
[4] = 1;
3103 fs
= ventoy_get_env("ventoy_fs_probe");
3104 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3106 param
->vtoy_reserved
[3] = 1;
3109 param
->vtoy_reserved
[5] = 0;
3110 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3111 if (val
&& val
[0] == '1' && val
[1] == 0)
3113 param
->vtoy_reserved
[5] = 1;
3116 /* ventoy_disk_signature used for vlnk */
3117 param
->vtoy_reserved
[6] = file
->vlnk
;
3118 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3120 /* calculate checksum */
3121 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3123 chksum
+= *((grub_uint8_t
*)param
+ i
);
3125 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3130 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3132 grub_uint32_t i
= 0;
3133 grub_uint64_t total
= 0;
3134 grub_uint64_t fileblk
= 0;
3135 ventoy_img_chunk
*chunk
= NULL
;
3137 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3139 chunk
= chunklist
->chunk
+ i
;
3141 if (chunk
->disk_start_sector
<= start
)
3143 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3147 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3150 fileblk
= (file
->size
+ 511) / 512;
3152 if (total
!= fileblk
)
3154 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3155 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3157 debug("maybe img file to be processed.\n");
3167 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3171 grub_uint32_t i
= 0;
3172 grub_uint32_t sector
= 0;
3173 grub_uint32_t count
= 0;
3174 grub_off_t size
= 0;
3175 grub_off_t read
= 0;
3177 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3178 if (fs_type
== ventoy_fs_exfat
)
3180 grub_fat_get_file_chunk(start
, file
, chunklist
);
3182 else if (fs_type
== ventoy_fs_ext
)
3184 grub_ext_get_file_chunk(start
, file
, chunklist
);
3188 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3189 file
->read_hook_data
= chunklist
;
3191 for (size
= file
->size
; size
> 0; size
-= read
)
3193 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3194 grub_file_read(file
, NULL
, read
);
3197 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3199 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3200 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3203 if (ventoy_fs_udf
== fs_type
)
3205 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3207 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3208 chunklist
->chunk
[i
].img_start_sector
= sector
;
3209 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3215 len
= (int)grub_strlen(file
->name
);
3216 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3217 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3218 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3219 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3221 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3223 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3233 chunklist
->chunk
[i
].img_start_sector
= sector
;
3234 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3242 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3246 grub_disk_addr_t start
;
3251 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3254 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3257 g_conf_replace_count
= 0;
3258 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3259 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3261 if (g_img_chunk_list
.chunk
)
3263 grub_free(g_img_chunk_list
.chunk
);
3266 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3268 grub_file_close(file
);
3269 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3272 /* get image chunk data */
3273 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3274 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3275 if (NULL
== g_img_chunk_list
.chunk
)
3277 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3280 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3281 g_img_chunk_list
.cur_chunk
= 0;
3283 start
= file
->device
->disk
->partition
->start
;
3285 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3287 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3288 grub_file_close(file
);
3292 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3295 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3296 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3297 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3300 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3304 grub_uint64_t offset
= 0;
3305 grub_uint32_t align
= 0;
3306 grub_file_t file
= NULL
;
3307 conf_replace
*node
= NULL
;
3308 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3309 ventoy_grub_param_file_replace
*replace
= NULL
;
3315 debug("select conf replace argc:%d\n", argc
);
3322 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3325 debug("Conf replace not found for %s\n", args
[1]);
3329 debug("Find %d conf replace for %s\n", n
, args
[1]);
3331 g_conf_replace_count
= n
;
3332 for (i
= 0; i
< n
; i
++)
3336 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3339 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3340 grub_file_close(file
);
3342 else if (node
->img
> 0)
3348 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3352 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3355 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3359 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3361 if (align
> vtoy_max_replace_file_size
)
3363 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3364 grub_file_close(file
);
3368 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3369 grub_file_close(file
);
3370 g_conf_replace_new_len
[i
] = (int)file
->size
;
3371 g_conf_replace_new_len_align
[i
] = align
;
3373 g_conf_replace_node
[i
] = node
;
3374 g_conf_replace_offset
[i
] = offset
+ 2;
3378 replace
= &(g_grub_param
->img_replace
[i
]);
3379 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3380 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3381 replace
->old_name_cnt
++;
3384 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3388 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3391 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3396 const char *ch
= var
;
3403 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3410 debug("Invalid variable letter <%c>\n", *ch
);
3417 debug("Invalid variable length:%d <%s>\n", n
, var
);
3421 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3430 grub_printf("\n=================== Variables Expansion ===================\n\n");
3433 grub_printf("<%s>: ", var
);
3436 while (i
< (len
- 1))
3439 if ((c
== '\n') || (c
== '\r'))
3449 else if (grub_isprint(c
))
3451 if (i
+ 1 < (len
- 1))
3453 grub_printf("%c", c
);
3463 expand
[i
- 1] = ' ';
3464 grub_printf("\r<%s>: %s", var
, expand
);
3467 grub_printf("\r<%s>: %s", var
, expand
);
3479 grub_snprintf(expand
, len
, "$$%s$$", var
);
3485 static int ventoy_auto_install_var_expand(install_template
*node
)
3493 char *newbuf
= NULL
;
3494 char *curline
= NULL
;
3495 char *nextline
= NULL
;
3496 grub_uint8_t
*code
= NULL
;
3498 var_node
*CurNode
= NULL
;
3499 var_node
*pVarList
= NULL
;
3501 code
= (grub_uint8_t
*)node
->filebuf
;
3503 if (node
->filelen
>= VTOY_SIZE_1MB
)
3505 debug("auto install script too long %d\n", node
->filelen
);
3509 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3511 debug("UCS-2 encoding NOT supported\n");
3515 start
= grub_strstr(node
->filebuf
, "$$");
3518 debug("no need to expand variable, no start.\n");
3522 end
= grub_strstr(start
+ 2, "$$");
3525 debug("no need to expand variable, no end.\n");
3529 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3530 newbuf
= grub_malloc(newlen
);
3533 debug("Failed to alloc newbuf %d\n", newlen
);
3537 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3539 nextline
= ventoy_get_line(curline
);
3541 start
= grub_strstr(curline
, "$$");
3544 end
= grub_strstr(start
+ 2, "$$");
3550 VTOY_APPEND_NEWBUF(curline
);
3552 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3554 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3556 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3563 value
[sizeof(value
) - 1] = 0;
3564 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3568 CurNode
= grub_zalloc(sizeof(var_node
));
3571 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3572 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3573 CurNode
->next
= pVarList
;
3579 VTOY_APPEND_NEWBUF(value
);
3581 VTOY_APPEND_NEWBUF(end
+ 2);
3585 VTOY_APPEND_NEWBUF(curline
);
3588 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3590 newbuf
[pos
- 1] = '\n';
3594 newbuf
[pos
++] = '\n';
3598 grub_free(node
->filebuf
);
3599 node
->filebuf
= newbuf
;
3600 node
->filelen
= pos
;
3604 CurNode
= pVarList
->next
;
3605 grub_free(pVarList
);
3612 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3618 grub_file_t file
= NULL
;
3619 char configfile
[128];
3620 install_template
*node
= NULL
;
3626 debug("select auto installation argc:%d\n", argc
);
3633 node
= ventoy_plugin_find_install_template(args
[0]);
3636 debug("Auto install template not found for %s\n", args
[0]);
3640 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3642 defidx
= node
->autosel
;
3643 if (node
->timeout
< 0)
3645 node
->cursel
= node
->autosel
- 1;
3646 debug("Auto install template auto select %d\n", node
->autosel
);
3651 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3657 if (node
->timeout
> 0)
3659 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3662 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" --class=\"sel_auto_install\" {\n"
3663 " echo %s\n}\n", "");
3665 for (i
= 0; i
< node
->templatenum
; i
++)
3667 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" --class=\"sel_auto_install\" {\n"
3669 node
->templatepath
[i
].path
);
3672 g_ventoy_menu_esc
= 1;
3673 g_ventoy_suppress_esc
= 1;
3674 g_ventoy_suppress_esc_default
= defidx
;
3676 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3677 grub_script_execute_sourcecode(configfile
);
3679 g_ventoy_menu_esc
= 0;
3680 g_ventoy_suppress_esc
= 0;
3681 g_ventoy_suppress_esc_default
= 1;
3685 node
->cursel
= g_ventoy_last_entry
- 1;
3688 grub_check_free(node
->filebuf
);
3691 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3693 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3694 node
->templatepath
[node
->cursel
].path
);
3697 node
->filebuf
= grub_malloc(file
->size
+ 8);
3700 grub_file_read(file
, node
->filebuf
, file
->size
);
3701 grub_file_close(file
);
3703 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3704 node
->filelen
= (int)file
->size
;
3706 ventoy_auto_install_var_expand(node
);
3711 debug("Failed to open auto install script <%s%s>\n",
3712 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3716 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3719 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3725 char configfile
[128];
3726 persistence_config
*node
;
3732 debug("select persistence argc:%d\n", argc
);
3739 node
= ventoy_plugin_find_persistent(args
[0]);
3742 debug("Persistence image not found for %s\n", args
[0]);
3746 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3748 defidx
= node
->autosel
;
3749 if (node
->timeout
< 0)
3751 node
->cursel
= node
->autosel
- 1;
3752 debug("Persistence image auto select %d\n", node
->autosel
);
3757 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3763 if (node
->timeout
> 0)
3765 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3768 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" --class=\"sel_persistence\" {\n"
3769 " echo %s\n}\n", "");
3771 for (i
= 0; i
< node
->backendnum
; i
++)
3773 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" --class=\"sel_persistence\" {\n"
3775 node
->backendpath
[i
].path
);
3779 g_ventoy_menu_esc
= 1;
3780 g_ventoy_suppress_esc
= 1;
3781 g_ventoy_suppress_esc_default
= defidx
;
3783 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3784 grub_script_execute_sourcecode(configfile
);
3786 g_ventoy_menu_esc
= 0;
3787 g_ventoy_suppress_esc
= 0;
3788 g_ventoy_suppress_esc_default
= 1;
3792 node
->cursel
= g_ventoy_last_entry
- 1;
3794 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3797 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3800 ventoy_img_chunk
*cur
;
3806 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3808 cur
= g_img_chunk_list
.chunk
+ i
;
3809 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3810 cur
->img_start_sector
, cur
->img_end_sector
,
3811 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3815 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3818 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3822 ventoy_img_chunk_list chunklist
;
3827 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3830 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3833 /* get image chunk data */
3834 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3835 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3836 if (NULL
== chunklist
.chunk
)
3838 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3841 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3842 chunklist
.cur_chunk
= 0;
3844 ventoy_get_block_list(file
, &chunklist
, 0);
3846 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3848 grub_printf("########## UNSUPPORTED ###############\n");
3851 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3853 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3855 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3856 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3859 grub_printf("\n==================================\n");
3861 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3863 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3864 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3865 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3866 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3867 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3871 grub_free(chunklist
.chunk
);
3872 grub_file_close(file
);
3874 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3877 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3880 ventoy_grub_param_file_replace
*replace
= NULL
;
3888 replace
= &(g_grub_param
->file_replace
);
3889 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3891 replace
->old_name_cnt
= 0;
3892 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3894 replace
->old_name_cnt
++;
3895 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3898 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3901 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3904 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3907 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3913 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3914 grub_env_set(args
[0], buf
);
3917 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3920 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3928 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3929 grub_printf("%s", g_list_script_buf
);
3933 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3934 grub_printf("%s", g_tree_script_buf
);
3940 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3942 img_info
*cur
= g_ventoy_img_list
;
3950 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3951 grub_printf("name:<%s>\n\n", cur
->name
);
3958 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3964 ventoy_plugin_dump_injection();
3969 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3975 ventoy_plugin_dump_auto_install();
3980 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3986 ventoy_plugin_dump_persistence();
3991 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
3997 len1
= (int)grub_strlen(filename
);
3998 len2
= (int)grub_strlen(suffix
);
4005 for (i
= len1
- 1; i
>= 0; i
--)
4007 if (filename
[i
] == '.')
4018 if (filename
[i
- len2
- 1] != '_')
4023 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4031 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4037 if (argc
!= 1 && argc
!= 2)
4042 if (args
[0][0] == '0')
4044 if (g_ventoy_memdisk_mode
)
4049 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4056 else if (args
[0][0] == '1')
4058 return g_ventoy_iso_raw
? 0 : 1;
4060 else if (args
[0][0] == '2')
4062 return g_ventoy_iso_uefi_drv
? 0 : 1;
4064 else if (args
[0][0] == '3')
4066 if (g_ventoy_grub2_mode
)
4071 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4078 else if (args
[0][0] == '4')
4080 if (g_ventoy_wimboot_mode
)
4085 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4096 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4098 static int configfile_mode
= 0;
4099 char memfile
[128] = {0};
4106 * args[0]: 0:normal 1:configfile
4107 * args[1]: 0:list_buf 1:tree_buf
4112 debug("Invalid argc %d\n", argc
);
4118 if (args
[0][0] == '0')
4120 if (args
[1][0] == '0')
4122 grub_script_execute_sourcecode(g_list_script_buf
);
4126 grub_script_execute_sourcecode(g_tree_script_buf
);
4131 if (configfile_mode
)
4133 debug("Now already in F3 mode %d\n", configfile_mode
);
4137 if (args
[1][0] == '0')
4139 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4140 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4144 g_ventoy_last_entry
= -1;
4145 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4146 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4149 configfile_mode
= 1;
4150 grub_script_execute_sourcecode(memfile
);
4151 configfile_mode
= 0;
4157 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4168 g_ventoy_case_insensitive
= 1;
4169 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4170 g_ventoy_case_insensitive
= 0;
4176 grub_file_close(file
);
4182 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4187 const char *isopath
= NULL
;
4189 ventoy_mbr_head mbr
;
4196 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4199 isopath
= grub_env_get("vtoy_iso_part");
4202 debug("isopath is null %p\n", isopath
);
4206 debug("isopath is %s\n", isopath
);
4208 for (id
= 0; id
< 30 && (find
== 0); id
++)
4210 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4211 if (grub_strstr(isopath
, hdname
))
4213 debug("skip %s ...\n", hdname
);
4217 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4219 disk
= grub_disk_open(hdname
);
4222 debug("%s not exist\n", hdname
);
4226 grub_memset(&mbr
, 0, sizeof(mbr
));
4227 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4229 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4231 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4232 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4235 grub_env_set(args
[0], hdname
);
4239 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4243 debug("read %s failed\n", hdname
);
4246 grub_disk_close(disk
);
4252 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4263 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4266 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4269 debug("failed to open file %s\n", args
[0]);
4273 buf
= grub_malloc(len
);
4280 grub_file_read(file
, buf
, len
- 1);
4282 ventoy_get_line(buf
);
4283 ventoy_set_env(args
[1], buf
);
4287 grub_check_free(buf
);
4288 grub_file_close(file
);
4293 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4295 grub_uint64_t end_max
= 0;
4296 int *pCnt
= (int *)data
;
4301 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4302 "0 %llu linear /dev/ventoy %llu\n",
4303 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4305 end_max
= (partition
->len
+ partition
->start
) * 512;
4306 if (end_max
> g_part_end_max
)
4308 g_part_end_max
= end_max
;
4314 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4317 char *device_name
= NULL
;
4318 grub_device_t dev
= NULL
;
4323 g_part_list_pos
= 0;
4325 grub_env_unset("vtoy_img_part_file");
4332 device_name
= grub_file_get_device_name(args
[0]);
4335 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4339 dev
= grub_device_open(device_name
);
4342 debug("grub_device_open failed, %s\n", device_name
);
4346 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4348 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4349 grub_env_set("vtoy_img_part_file", buf
);
4351 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4352 grub_env_set("vtoy_img_part_cnt", buf
);
4354 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4355 grub_env_set("vtoy_img_max_part_end", buf
);
4359 check_free(device_name
, grub_free
);
4360 check_free(dev
, grub_device_close
);
4366 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4377 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4380 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4383 debug("failed to open file %s\n", args
[0]);
4387 buf
= grub_malloc(file
->size
+ 1);
4393 buf
[file
->size
] = 0;
4394 grub_file_read(file
, buf
, file
->size
);
4396 if (grub_strstr(buf
, args
[1]))
4403 grub_check_free(buf
);
4404 grub_file_close(file
);
4409 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4415 ventoy_iso9660_vd pvd
;
4422 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4425 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4428 debug("failed to open file %s\n", args
[0]);
4432 grub_file_seek(file
, 16 * 2048);
4433 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4434 if (len
!= sizeof(pvd
))
4436 debug("failed to read pvd %d\n", len
);
4440 grub_memset(buf
, 0, sizeof(buf
));
4441 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4442 ventoy_set_env(args
[1], buf
);
4444 grub_memset(buf
, 0, sizeof(buf
));
4445 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4446 ventoy_set_env(args
[2], buf
);
4450 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4451 ventoy_set_env(args
[3], buf
);
4454 grub_file_close(file
);
4459 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4470 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4473 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4476 debug("failed to open file %s\n", args
[0]);
4480 grub_memset(buf
, 0, sizeof(buf
));
4481 grub_file_seek(file
, 16 * 2048 + 813);
4482 len
= (int)grub_file_read(file
, buf
, 17);
4485 debug("failed to read create date %d\n", len
);
4489 ventoy_set_env(args
[1], buf
);
4492 grub_file_close(file
);
4497 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4503 ventoy_env_hook_root(1);
4508 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4514 ventoy_env_hook_root(0);
4519 #ifdef GRUB_MACHINE_EFI
4520 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4525 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4531 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4532 if (var
&& *var
== 1)
4540 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4549 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4554 grub_uint64_t FileSectors
= 0;
4555 ventoy_gpt_info
*gpt
= NULL
;
4556 ventoy_part_table
*pt
= NULL
;
4557 grub_uint8_t zeroguid
[16] = {0};
4562 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4565 debug("failed to open file %s\n", args
[0]);
4569 if (file
->size
% 512)
4571 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4575 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4581 FileSectors
= file
->size
/ 512;
4583 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4584 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4586 debug("This is EFI partition table\n");
4588 for (i
= 0; i
< 128; i
++)
4590 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4592 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4594 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4595 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4603 debug("This is MBR partition table\n");
4605 for (i
= 0; i
< 4; i
++)
4607 pt
= gpt
->MBR
.PartTbl
+ i
;
4608 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4610 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4611 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4612 (ulonglong
)FileSectors
);
4621 grub_file_close(file
);
4622 grub_check_free(gpt
);
4623 grub_errno
= GRUB_ERR_NONE
;
4627 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4636 for (i
= 0; i
< 500; i
++)
4638 ret
= grub_getkey_noblock();
4639 if (ret
== GRUB_TERM_NO_KEY
)
4648 grub_printf("\n\n Still have key input after clear.\n");
4656 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4663 int image_sector_size
;
4665 ventoy_chain_head
*chain
;
4666 ventoy_img_chunk
*chunk
;
4667 ventoy_os_param
*osparam
;
4668 ventoy_image_location
*location
;
4669 ventoy_image_disk_region
*region
;
4670 struct grub_acpi_table_header
*acpi
;
4679 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4681 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4687 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4689 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4691 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4695 img_chunk_num
= chain
->img_chunk_num
;
4697 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4698 datalen
= sizeof(ventoy_os_param
) + loclen
;
4700 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4701 acpi
= grub_zalloc(buflen
);
4707 /* Step1: Fill acpi table header */
4708 grub_memcpy(acpi
->signature
, "VTOY", 4);
4709 acpi
->length
= buflen
;
4711 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4712 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4714 acpi
->creator_id
[0] = 1;
4715 acpi
->creator_rev
= 1;
4717 /* Step2: Fill data */
4718 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4719 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4720 osparam
->vtoy_img_location_addr
= 0;
4721 osparam
->vtoy_img_location_len
= loclen
;
4722 osparam
->chksum
= 0;
4723 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4725 location
= (ventoy_image_location
*)(osparam
+ 1);
4726 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4727 location
->image_sector_size
= image_sector_size
;
4728 location
->disk_sector_size
= chain
->disk_sector_size
;
4729 location
->region_count
= img_chunk_num
;
4731 region
= location
->regions
;
4732 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4733 if (512 == image_sector_size
)
4735 for (i
= 0; i
< img_chunk_num
; i
++)
4737 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4738 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4739 region
->disk_start_sector
= chunk
->disk_start_sector
;
4746 for (i
= 0; i
< img_chunk_num
; i
++)
4748 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4749 region
->image_start_sector
= chunk
->img_start_sector
;
4750 region
->disk_start_sector
= chunk
->disk_start_sector
;
4756 /* Step3: Fill acpi checksum */
4758 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4760 /* load acpi table */
4761 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4762 grub_script_execute_sourcecode(cmd
);
4766 VENTOY_CMD_RETURN(0);
4769 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4775 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4776 g_ventoy_last_entry
= -1;
4781 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4787 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4792 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4794 const char *pos
= filename
+ 1;
4802 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4804 grub_strncpy((char *)data
, filename
, 128);
4815 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4818 char *device_name
= NULL
;
4819 grub_device_t dev
= NULL
;
4820 grub_fs_t fs
= NULL
;
4821 char buf
[128] = {0};
4827 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4831 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4833 device_name
= grub_file_get_device_name(args
[0]);
4836 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4840 dev
= grub_device_open(device_name
);
4843 debug("grub_device_open failed, %s\n", device_name
);
4847 fs
= grub_fs_probe(dev
);
4850 debug("grub_fs_probe failed, %s\n", device_name
);
4854 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4858 ventoy_set_env(args
[2], buf
);
4865 check_free(device_name
, grub_free
);
4866 check_free(dev
, grub_device_close
);
4871 int ventoy_load_part_table(const char *diskname
)
4878 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4879 if (!g_ventoy_part_info
)
4884 disk
= grub_disk_open(diskname
);
4887 debug("Failed to open disk %s\n", diskname
);
4891 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4893 g_ventoy_disk_bios_id
= disk
->id
;
4895 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4896 grub_disk_close(disk
);
4898 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4899 dev
= grub_device_open(name
);
4902 /* Check for official Ventoy device */
4903 ret
= ventoy_check_official_device(dev
);
4904 grub_device_close(dev
);
4912 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4913 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4918 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4925 ret
= ventoy_load_part_table(args
[0]);
4931 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4932 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4937 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4940 const char *vcfg
= NULL
;
4945 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4948 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4949 grub_env_set(args
[1], vcfg
);
4954 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4962 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4965 grub_uint8_t zeroguid
[16] = {0};
4970 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4973 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4975 if (id
>= 1 && id
<= 128)
4977 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4985 if (id
>= 1 && id
<= 4)
4987 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4997 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5000 char *device_name
= NULL
;
5001 grub_device_t dev
= NULL
;
5002 grub_fs_t fs
= NULL
;
5007 debug("get fs label for %s\n", args
[0]);
5011 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5015 device_name
= grub_file_get_device_name(args
[0]);
5018 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5022 dev
= grub_device_open(device_name
);
5025 debug("grub_device_open failed, %s\n", device_name
);
5029 fs
= grub_fs_probe(dev
);
5030 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5032 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5036 fs
->fs_label(dev
, &label
);
5039 debug("label=<%s>\n", label
);
5040 ventoy_set_env(args
[1], label
);
5048 check_free(device_name
, grub_free
);
5049 check_free(dev
, grub_device_close
);
5054 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5058 grub_snprintf((char *)data
, 256, "%s", filename
);
5065 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5067 if (info
->dir
&& filename
&& filename
[0] != '.')
5069 grub_snprintf((char *)data
, 256, "%s", filename
);
5076 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5079 char *device_name
= NULL
;
5080 grub_device_t dev
= NULL
;
5081 grub_fs_t fs
= NULL
;
5082 char name
[256] ={0};
5086 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5090 device_name
= grub_file_get_device_name(args
[0]);
5093 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5097 dev
= grub_device_open(device_name
);
5100 debug("grub_device_open failed, %s\n", device_name
);
5104 fs
= grub_fs_probe(dev
);
5107 debug("grub_fs_probe failed, %s\n", device_name
);
5111 fs
->fs_dir(dev
, args
[1], hook
, name
);
5114 ventoy_set_env(args
[2], name
);
5121 check_free(device_name
, grub_free
);
5122 check_free(dev
, grub_device_close
);
5127 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5130 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5133 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5136 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5139 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5149 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5153 for (pos
= args
[0]; *pos
; pos
++)
5167 grub_env_set(args
[1], args
[0]);
5177 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5187 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5192 len
= (int)grub_strlen(buf
);
5193 for (i
= len
; i
> 0; i
--)
5195 if (buf
[i
- 1] == '/')
5197 grub_env_set(args
[1], buf
+ i
);
5202 grub_env_set(args
[1], buf
);
5207 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5209 struct grub_video_mode_info info
;
5216 if (!g_video_mode_list
)
5218 ventoy_enum_video_mode();
5221 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5223 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5227 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5230 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5232 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5233 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5235 VENTOY_CMD_RETURN(0);
5238 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5240 struct grub_video_mode_info info
;
5247 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5249 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5253 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5256 grub_env_set(args
[0], buf
);
5258 VENTOY_CMD_RETURN(0);
5261 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5269 if (!g_video_mode_list
)
5274 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5275 if (id
< g_video_mode_num
)
5277 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5278 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5281 grub_env_set(args
[1], buf
);
5283 VENTOY_CMD_RETURN(0);
5286 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5289 grub_uint32_t loadsector
= 0;
5292 grub_uint32_t boot_catlog
= 0;
5293 grub_uint8_t buf
[512];
5299 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5303 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5306 debug("failed to open %s\n", args
[0]);
5310 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5311 if (boot_catlog
== 0)
5313 debug("No bootcatlog found\n");
5314 grub_file_close(file
);
5318 grub_memset(buf
, 0, sizeof(buf
));
5319 grub_file_seek(file
, boot_catlog
* 2048);
5320 grub_file_read(file
, buf
, sizeof(buf
));
5321 grub_file_close(file
);
5323 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5325 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5327 if (buf
[i
+ 32] == 0x88)
5329 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5330 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5336 if (loadsector
== 0)
5338 debug("No EFI eltorito info found\n");
5342 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5343 grub_env_set(args
[1], value
);
5344 VENTOY_CMD_RETURN(0);
5347 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5352 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5354 if (pfsdir
->initrd
[0])
5359 curpos
= pfsdir
->curpos
;
5360 len
= grub_strlen(filename
);
5364 if ((len
== 1 && filename
[0] == '.') ||
5365 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5370 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5373 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5374 pfsdir
->curpos
= curpos
+ printlen
;
5375 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5376 pfsdir
->curpos
= curpos
;
5377 pfsdir
->fullpath
[curpos
] = 0;
5381 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5384 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5385 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5387 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5389 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5398 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5402 char *device_name
= NULL
;
5403 grub_device_t dev
= NULL
;
5404 grub_fs_t fs
= NULL
;
5405 replace_fs_dir
*pfsdir
= NULL
;
5411 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5415 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5421 device_name
= grub_file_get_device_name(args
[0]);
5427 dev
= grub_device_open(device_name
);
5433 fs
= grub_fs_probe(dev
);
5442 pfsdir
->fullpath
[0] = '/';
5443 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5445 if (pfsdir
->initrd
[0])
5447 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5449 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5451 if (pfsdir
->initrd
[i
] == '/')
5453 pfsdir
->initrd
[i
] = '\\';
5457 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5458 grub_env_set(args
[1], pos
);
5462 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5467 grub_check_free(pfsdir
);
5468 grub_check_free(device_name
);
5469 check_free(dev
, grub_device_close
);
5471 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5474 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5476 const char *pager
= NULL
;
5482 pager
= grub_env_get("pager");
5486 grub_env_set("pager", "1");
5488 else if (pager
[0] == '1')
5494 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5496 grub_env_set("pager", "1");
5499 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5502 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5508 if (g_pager_flag
== 1)
5510 grub_env_unset("pager");
5512 else if (g_pager_flag
== 2)
5514 grub_env_set("pager", g_old_pager
);
5517 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5520 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5522 if (g_json_case_mis_path
[0])
5527 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5529 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5535 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5538 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5540 if (g_json_case_mis_path
[0])
5545 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5547 if (grub_strcasecmp(filename
, "ventoy") == 0)
5549 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5550 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5551 if (g_json_case_mis_path
[0])
5561 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5564 char *device_name
= NULL
;
5565 grub_device_t dev
= NULL
;
5566 grub_fs_t fs
= NULL
;
5567 chk_case_fs_dir fs_dir
;
5573 device_name
= grub_file_get_device_name(args
[0]);
5579 dev
= grub_device_open(device_name
);
5585 fs
= grub_fs_probe(dev
);
5591 fstype
= ventoy_get_fs_type(fs
->name
);
5592 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5597 g_json_case_mis_path
[0] = 0;
5600 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5602 if (g_json_case_mis_path
[0])
5604 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5609 grub_check_free(device_name
);
5610 check_free(dev
, grub_device_close
);
5612 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5615 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5618 grub_partition_t part
;
5619 char priority_str
[3]; /* Maximum value 15 */
5623 if (argc
< 2 || argc
> 3)
5624 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5625 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5627 /* Open the disk if it exists */
5628 disk
= grub_disk_open (args
[0]);
5631 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5635 part
= grub_partition_probe (disk
, args
[1]);
5638 grub_disk_close (disk
);
5639 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5640 "No such partition");
5643 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5645 grub_disk_close (disk
);
5646 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5647 "Not a GPT partition");
5650 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5651 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5655 grub_env_set (args
[2], priority_str
);
5656 grub_env_export (args
[2]);
5660 grub_printf ("Priority is %s\n", priority_str
);
5663 grub_disk_close (disk
);
5664 return GRUB_ERR_NONE
;
5668 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5672 grub_file_t file
= NULL
;
5673 grub_uint32_t loadrba
= 0;
5674 grub_uint32_t boot_catlog
= 0;
5675 grub_uint8_t sector
[512];
5676 boot_info_table
*info
= NULL
;
5681 /* This also trigger a iso9660 fs parse */
5682 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5687 joliet
= grub_iso9660_is_joliet();
5693 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5696 debug("failed to open %s\n", args
[0]);
5700 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5701 if (boot_catlog
== 0)
5703 debug("no bootcatlog found %u\n", boot_catlog
);
5707 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5710 debug("no bios eltorito rba found %u\n", loadrba
);
5714 grub_file_seek(file
, loadrba
* 2048);
5715 grub_file_read(file
, sector
, 512);
5717 info
= (boot_info_table
*)sector
;
5718 if (info
->bi_data0
== 0x7c6ceafa &&
5719 info
->bi_data1
== 0x90900000 &&
5720 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5721 info
->bi_BootFileLocation
== loadrba
)
5723 debug("bootloader is syslinux, %u.\n", loadrba
);
5729 grub_file_close(file
);
5730 grub_errno
= GRUB_ERR_NONE
;
5734 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5737 ventoy_vlnk_part
*node
;
5743 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5745 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5746 ++n
, node
->device
, node
->disksig
,
5747 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5753 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5761 len
= (int)grub_strlen(args
[0]);
5762 if (grub_file_is_vlnk_suffix(args
[0], len
))
5771 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5774 const char *name
= NULL
;
5780 grub_env_unset(args
[1]);
5781 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5784 debug("VLNK SRC: <%s>\n", args
[0]);
5785 debug("VLNK DST: <%s>\n", name
);
5786 grub_env_set(args
[1], name
);
5794 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5798 grub_file_t file
= NULL
;
5809 len
= (int)grub_strlen(args
[0]);
5810 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5812 grub_printf("Invalid vlnk suffix\n");
5816 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5819 grub_printf("Failed to open %s\n", args
[0]);
5823 if (file
->size
!= 32768)
5825 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5829 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5830 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5832 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5837 check_free(file
, grub_file_close
);
5838 grub_errno
= GRUB_ERR_NONE
;
5842 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5848 g_iso_vd_id_publisher
[0] = 0;
5849 g_iso_vd_id_prepare
[0] = 0;
5850 g_iso_vd_id_application
[0] = 0;
5855 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5859 grub_file_t file
= NULL
;
5864 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5867 grub_printf("Failed to open %s\n", args
[0]);
5871 grub_file_seek(file
, 16 * 2048 + offset
);
5872 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5875 grub_file_seek(file
, 16 * 2048 + offset
);
5876 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5879 grub_file_seek(file
, 16 * 2048 + offset
);
5880 grub_file_read(file
, g_iso_vd_id_application
, 128);
5884 check_free(file
, grub_file_close
);
5885 grub_errno
= GRUB_ERR_NONE
;
5889 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5892 char *id
= g_iso_vd_id_publisher
;
5897 if (args
[0][0] == '1')
5899 id
= g_iso_vd_id_prepare
;
5901 else if (args
[0][0] == '2')
5903 id
= g_iso_vd_id_application
;
5906 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5911 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5916 grub_errno
= GRUB_ERR_NONE
;
5920 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5925 g_ventoy_fn_mutex
= 0;
5926 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5928 g_ventoy_fn_mutex
= 1;
5931 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5934 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5936 grub_uint64_t total
;
5937 grub_uint64_t org_required
;
5938 grub_uint64_t new_required
;
5944 #ifdef GRUB_MACHINE_EFI
5945 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
5946 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
5947 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
5948 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
5953 grub_printf("Non EFI mode!\n");
5958 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5961 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5963 const char *env
= NULL
;
5968 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
5973 if (ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
5974 ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
5975 ventoy_check_mode_by_name(args
[0], "vtwimboot"))
5980 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
5981 if (env
&& env
[0] == '0' && env
[1] == 0)
5989 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5997 const char *env
= NULL
;
5998 ulonglong fsize
= 0;
6000 int seldata
[16] = {0};
6005 len
= 8 * VTOY_SIZE_1KB
;
6006 cmd
= (char *)grub_malloc(len
);
6012 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6014 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6017 timeout
= (int)grub_strtol(env
, NULL
, 10);
6022 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6025 fsize
= grub_strtoull(args
[2], NULL
, 10);
6027 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in normal mode", "second_normal"); seldata
[n
++] = 1;
6029 if (grub_strcmp(args
[1], "Unix") != 0)
6031 if (grub_strcmp(args
[1], "Windows") == 0)
6033 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in wimboot mode", "second_wimboot"); seldata
[n
++] = 2;
6037 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in grub2 mode", "second_grub2"); seldata
[n
++] = 3;
6040 if (fsize
<= VTOY_SIZE_1GB
)
6042 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in memdisk mode", "second_memdisk"); seldata
[n
++] = 4;
6046 vtoy_dummy_menuentry(cmd
, pos
, len
, "File checksum", "second_checksum"); seldata
[n
++] = 5;
6049 g_ventoy_menu_esc
= 1;
6050 g_ventoy_suppress_esc
= 1;
6051 g_ventoy_suppress_esc_default
= 0;
6052 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6053 grub_script_execute_sourcecode(cfgfile
);
6054 g_ventoy_menu_esc
= 0;
6055 g_ventoy_suppress_esc
= 0;
6056 g_ventoy_suppress_esc_default
= 1;
6058 select
= seldata
[g_ventoy_last_entry
];
6062 g_ventoy_wimboot_mode
= 1;
6064 else if (select
== 3)
6066 g_ventoy_grub2_mode
= 1;
6068 else if (select
== 4)
6070 g_ventoy_memdisk_mode
= 1;
6072 else if (select
== 5)
6074 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6075 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6077 }while (select
== 5);
6083 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6088 if (args
[0][0] == '0')
6090 g_ventoy_case_insensitive
= 0;
6094 g_ventoy_case_insensitive
= 1;
6100 int ventoy_env_init(void)
6105 grub_env_set("vtdebug_flag", "");
6107 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6108 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6109 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6110 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6112 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6115 ventoy_filt_register(0, ventoy_wrapper_open
);
6117 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6120 g_grub_param
->grub_env_get
= grub_env_get
;
6121 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6122 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6123 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6124 grub_env_set("env_param", buf
);
6125 grub_env_set("ventoy_env_param", buf
);
6127 grub_env_export("env_param");
6128 grub_env_export("ventoy_env_param");
6131 grub_env_export("vtoy_winpeshl_ini_addr");
6132 grub_env_export("vtoy_winpeshl_ini_size");
6134 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6135 grub_env_set("vtoy_chain_file_size", buf
);
6136 grub_env_export("vtoy_chain_file_size");
6138 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6139 grub_env_set("vtoy_chain_file_read", buf
);
6140 grub_env_export("vtoy_chain_file_read");
6147 static cmd_para ventoy_cmds
[] =
6149 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6150 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6151 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6152 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6153 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6154 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6155 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6156 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6157 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6158 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6159 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6160 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6161 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6162 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6163 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6164 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6165 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6166 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6167 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6168 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6169 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6170 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6171 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6172 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6173 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6174 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6175 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6177 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6178 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6179 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6180 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6181 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6182 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6183 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6185 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6186 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6187 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6188 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6189 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6190 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6191 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6192 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6193 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6194 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6197 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6198 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6199 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6200 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6201 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6202 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6203 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6204 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6205 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6206 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6207 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6209 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6210 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6211 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6212 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6213 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6214 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6215 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6217 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6218 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6219 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6220 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6221 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6222 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6223 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6224 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6225 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6226 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6228 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6229 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6230 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6231 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6232 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6233 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6234 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6235 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6236 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6238 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6239 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6240 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6241 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6244 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6245 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6246 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6248 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6249 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6250 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6253 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6254 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6255 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6256 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6257 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6258 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6259 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6260 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6261 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6262 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6263 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6264 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6265 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6266 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6268 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6269 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6270 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6271 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6272 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6273 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6274 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6275 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6276 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6277 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6278 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6279 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6281 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6282 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6283 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6284 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6285 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6286 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6287 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6288 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6289 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6290 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6291 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6292 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6293 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6294 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6295 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6296 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6297 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6298 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6299 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6300 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6301 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6302 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6303 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6304 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6305 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6308 int ventoy_register_all_cmd(void)
6311 cmd_para
*cur
= NULL
;
6313 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6315 cur
= ventoy_cmds
+ i
;
6316 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6317 cur
->summary
, cur
->description
, cur
->parser
);
6323 int ventoy_unregister_all_cmd(void)
6327 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6329 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);