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/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 static grub_uint8_t g_check_mbr_data
[] = {
55 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 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 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
61 initrd_info
*g_initrd_img_list
= NULL
;
62 initrd_info
*g_initrd_img_tail
= NULL
;
63 int g_initrd_img_count
= 0;
64 int g_valid_initrd_count
= 0;
65 int g_default_menu_mode
= 0;
66 int g_filt_dot_underscore_file
= 0;
67 int g_sort_case_sensitive
= 0;
68 int g_tree_view_menu_style
= 0;
69 static grub_file_t g_old_file
;
70 static int g_ventoy_last_entry_back
;
73 char g_img_swap_tmp_buf
[1024];
74 img_info g_img_swap_tmp
;
75 img_info
*g_ventoy_img_list
= NULL
;
77 int g_ventoy_img_count
= 0;
79 grub_device_t g_enum_dev
= NULL
;
80 grub_fs_t g_enum_fs
= NULL
;
81 int g_img_max_search_level
= -1;
82 img_iterator_node g_img_iterator_head
;
83 img_iterator_node
*g_img_iterator_tail
= NULL
;
85 grub_uint8_t g_ventoy_break_level
= 0;
86 grub_uint8_t g_ventoy_debug_level
= 0;
87 grub_uint8_t g_ventoy_chain_type
= 0;
89 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
90 grub_uint32_t g_ventoy_cpio_size
= 0;
91 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
92 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
94 int g_plugin_image_list
= 0;
96 ventoy_grub_param
*g_grub_param
= NULL
;
98 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
100 ventoy_img_chunk_list g_img_chunk_list
;
102 int g_wimboot_enable
= 0;
103 ventoy_img_chunk_list g_wimiso_chunk_list
;
104 char *g_wimiso_path
= NULL
;
106 int g_vhdboot_enable
= 0;
108 grub_uint64_t g_conf_replace_offset
= 0;
109 grub_uint64_t g_svd_replace_offset
= 0;
110 conf_replace
*g_conf_replace_node
= NULL
;
111 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
112 int g_conf_replace_new_len
= 0;
113 int g_conf_replace_new_len_align
= 0;
115 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
116 grub_uint64_t g_ventoy_disk_size
= 0;
117 grub_uint64_t g_ventoy_disk_part_size
[2];
119 static char *g_tree_script_buf
= NULL
;
120 static int g_tree_script_pos
= 0;
122 static char *g_list_script_buf
= NULL
;
123 static int g_list_script_pos
= 0;
125 static char *g_part_list_buf
= NULL
;
126 static int g_part_list_pos
= 0;
127 static grub_uint64_t g_part_end_max
= 0;
129 static int g_video_mode_max
= 0;
130 static int g_video_mode_num
= 0;
131 static ventoy_video_mode
*g_video_mode_list
= NULL
;
133 static int g_enumerate_time_checked
= 0;
134 static grub_uint64_t g_enumerate_start_time_ms
;
135 static grub_uint64_t g_enumerate_finish_time_ms
;
136 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
138 static int g_pager_flag
= 0;
139 static char g_old_pager
[32];
141 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
143 static const char *g_menu_class
[] =
145 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
148 const char *g_menu_prefix
[img_type_max
] =
150 "iso", "wim", "efi", "img", "vhd", "vtoy"
153 static int g_vtoy_load_prompt
= 0;
154 static char g_vtoy_prompt_msg
[64];
156 static char g_json_case_mis_path
[32];
158 static int ventoy_get_fs_type(const char *fs
)
162 return ventoy_fs_max
;
164 else if (grub_strncmp(fs
, "exfat", 5) == 0)
166 return ventoy_fs_exfat
;
168 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
170 return ventoy_fs_ntfs
;
172 else if (grub_strncmp(fs
, "ext", 3) == 0)
174 return ventoy_fs_ext
;
176 else if (grub_strncmp(fs
, "xfs", 3) == 0)
178 return ventoy_fs_xfs
;
180 else if (grub_strncmp(fs
, "udf", 3) == 0)
182 return ventoy_fs_udf
;
184 else if (grub_strncmp(fs
, "fat", 3) == 0)
186 return ventoy_fs_fat
;
189 return ventoy_fs_max
;
192 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
211 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
213 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
217 static int ventoy_control_get_flag(const char *key
)
219 const char *val
= ventoy_get_env(key
);
221 if (val
&& val
[0] == '1' && val
[1] == 0)
228 static grub_err_t
ventoy_fs_close(grub_file_t file
)
230 grub_file_close(g_old_file
);
231 grub_free(file
->data
);
239 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
245 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
250 for (i
= 0; i
< g_video_mode_num
; i
++)
252 if (g_video_mode_list
[i
].width
== info
->width
&&
253 g_video_mode_list
[i
].height
== info
->height
&&
254 g_video_mode_list
[i
].bpp
== info
->bpp
)
260 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
261 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
262 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
265 if (g_video_mode_num
== g_video_mode_max
)
267 g_video_mode_max
*= 2;
268 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
274 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
276 if (v1
->bpp
== v2
->bpp
)
278 if (v1
->width
== v2
->width
)
280 if (v1
->height
== v2
->height
)
286 return (v1
->height
< v2
->height
) ? -1 : 1;
291 return (v1
->width
< v2
->width
) ? -1 : 1;
296 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
300 static int ventoy_enum_video_mode(void)
303 grub_video_adapter_t adapter
;
304 grub_video_driver_id_t id
;
305 ventoy_video_mode mode
;
307 g_video_mode_num
= 0;
308 g_video_mode_max
= 1024;
309 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
310 if (!g_video_mode_list
)
315 #ifdef GRUB_MACHINE_PCBIOS
316 grub_dl_load ("vbe");
319 id
= grub_video_get_driver_id ();
321 FOR_VIDEO_ADAPTERS (adapter
)
323 if (!adapter
->iterate
||
324 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
325 adapter
->init() != GRUB_ERR_NONE
)))
330 adapter
->iterate(ventoy_video_hook
, NULL
);
332 if (adapter
->id
!= id
)
338 /* sort video mode */
339 for (i
= 0; i
< g_video_mode_num
; i
++)
340 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
342 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
344 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
345 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
346 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
350 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
353 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
357 static struct grub_fs vtoy_fs
=
362 .fs_read
= ventoy_fs_read
,
363 .fs_close
= ventoy_fs_close
,
373 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
379 file
->data
= grub_malloc(rawFile
->size
+ 4096);
385 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
386 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
388 g_old_file
= rawFile
;
390 file
->size
= rawFile
->size
+ len
;
391 file
->device
= rawFile
->device
;
393 file
->not_easily_seekable
= 1;
398 static int ventoy_check_decimal_var(const char *name
, long *value
)
400 const char *value_str
= NULL
;
402 value_str
= grub_env_get(name
);
403 if (NULL
== value_str
)
405 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
408 if (!ventoy_is_decimal(value_str
))
410 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
413 *value
= grub_strtol(value_str
, NULL
, 10);
415 return GRUB_ERR_NONE
;
418 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
420 grub_uint64_t sectors
;
422 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
424 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
428 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
431 return sectors
* 512;
434 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
440 grub_uint32_t offset
;
442 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
445 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
449 len
= (int)file
->size
;
451 data
= (char *)grub_malloc(file
->size
);
457 grub_file_read(file
, data
, file
->size
);
458 grub_file_close(file
);
460 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
461 grub_script_execute_sourcecode(exec
);
463 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
464 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
465 grub_file_close(file
);
467 grub_script_execute_sourcecode("loopback -d efiboot");
471 *direntoff
= offset
+ 2;
476 static int ventoy_set_check_result(int ret
)
480 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
481 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
482 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
486 grub_printf(VTOY_WARNING
"\n");
487 grub_printf(VTOY_WARNING
"\n");
488 grub_printf(VTOY_WARNING
"\n\n\n");
490 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
491 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
493 grub_printf("\n\nWill exit after 10 seconds ...... ");
501 static int ventoy_check_official_device(grub_device_t dev
)
505 grub_uint64_t offset
;
508 grub_uint8_t mbr
[512];
512 struct grub_partition
*partition
;
514 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
516 return ventoy_set_check_result(1 | 0x1000);
519 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
520 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
521 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
523 #ifndef GRUB_MACHINE_EFI
524 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
525 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
526 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
528 return ventoy_set_check_result(2 | 0x1000);
537 /* We must have partition 2 */
540 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
544 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
548 return ventoy_set_check_result(3 | 0x1000);
551 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
553 grub_file_close(file
);
554 return ventoy_set_check_result(4 | 0x1000);
557 partition
= dev
->disk
->partition
;
558 if (partition
->number
!= 0 || partition
->start
!= 2048)
560 return ventoy_set_check_result(5);
565 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
567 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
568 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
569 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
571 grub_file_close(file
);
572 return ventoy_set_check_result(6);
577 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
578 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
579 PartTbl
[1].SectorCount
!= 65536)
581 grub_file_close(file
);
582 return ventoy_set_check_result(6);
588 offset
= partition
->start
+ partition
->len
;
589 partition
= file
->device
->disk
->partition
;
590 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
592 grub_file_close(file
);
593 return ventoy_set_check_result(7);
597 grub_file_close(file
);
601 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
602 dev2
= grub_device_open(devname
);
605 return ventoy_set_check_result(8);
608 fs
= grub_fs_probe(dev2
);
611 grub_device_close(dev2
);
612 return ventoy_set_check_result(9);
615 fs
->fs_label(dev2
, &label
);
616 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
618 grub_device_close(dev2
);
619 return ventoy_set_check_result(10);
622 grub_device_close(dev2
);
626 disk
= grub_disk_open(dev
->disk
->name
);
629 return ventoy_set_check_result(11);
632 grub_memset(mbr
, 0, 512);
633 grub_disk_read(disk
, 0, 0, 512, mbr
);
634 grub_disk_close(disk
);
636 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
638 return ventoy_set_check_result(12);
641 return ventoy_set_check_result(0);
644 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
648 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
658 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
660 grub_uint64_t size
= 0;
663 char fullpath
[256] = {0};
666 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
669 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
672 debug("grub_file_open failed <%s>\n", fullpath
);
678 grub_file_close(file
);
682 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
686 char fullpath
[256] = {0};
689 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
692 file
= grub_file_open(fullpath
, type
);
695 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
702 int ventoy_is_file_exist(const char *fmt
, ...)
709 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
713 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
716 grub_strncpy(pos
+ len
, "\" ]", 3);
718 debug("script exec %s\n", buf
);
720 if (0 == grub_script_execute_sourcecode(buf
))
728 int ventoy_is_dir_exist(const char *fmt
, ...)
735 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
739 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
742 grub_strncpy(pos
+ len
, "\" ]", 3);
744 debug("script exec %s\n", buf
);
746 if (0 == grub_script_execute_sourcecode(buf
))
754 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
757 grub_uint8_t
*outbuf
;
758 grub_uint8_t gzHdr
[10] =
760 0x1F, 0x8B, /* magic */
768 grub_memset(&s
, 0, sizeof(mz_stream
));
770 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
772 outbuf
= (grub_uint8_t
*)mem_out
;
774 mem_out_len
-= sizeof(gzHdr
) + 8;
775 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
776 outbuf
+= sizeof(gzHdr
);
778 s
.avail_in
= mem_in_len
;
781 s
.avail_out
= mem_out_len
;
784 mz_deflate(&s
, MZ_FINISH
);
788 outbuf
+= s
.total_out
;
789 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
790 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
792 return s
.total_out
+ sizeof(gzHdr
) + 8;
800 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
804 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
807 if (0 == grub_strcmp(args
[0], "on"))
810 grub_env_set("vtdebug_flag", "debug");
815 grub_env_set("vtdebug_flag", "");
818 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
821 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
825 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
827 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
828 grub_printf(" level:\r\n");
829 grub_printf(" 01/11: busybox / (+cat log)\r\n");
830 grub_printf(" 02/12: initrd / (+cat log)\r\n");
831 grub_printf(" 03/13: hook / (+cat log)\r\n");
833 grub_printf(" debug:\r\n");
834 grub_printf(" 0: debug is off\r\n");
835 grub_printf(" 1: debug is on\r\n");
837 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
840 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
842 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
844 g_ventoy_debug_level
= 1;
847 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
850 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
859 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
862 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
894 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
910 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
926 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
931 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
933 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
936 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
941 value_long
+= grub_strtol(args
[1], NULL
, 10);
943 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
944 grub_env_set(args
[0], buf
);
946 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
949 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
951 ulonglong value1
= 0;
952 ulonglong value2
= 0;
957 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
960 value1
= grub_strtoull(args
[0], NULL
, 10);
961 value2
= grub_strtoull(args
[1], NULL
, 10);
963 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
964 grub_env_set(args
[2], buf
);
966 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
969 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
984 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
987 debug("failed to open file <%s> for udf check\n", args
[0]);
991 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
993 grub_env_set(args
[1], buf
);
995 grub_file_close(file
);
1001 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1009 g_wimboot_enable
= 0;
1010 grub_check_free(g_wimiso_path
);
1011 grub_check_free(g_wimiso_chunk_list
.chunk
);
1013 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1019 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1020 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1021 if (NULL
== g_wimiso_chunk_list
.chunk
)
1023 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1026 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1027 g_wimiso_chunk_list
.cur_chunk
= 0;
1029 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1031 g_wimboot_enable
= 1;
1032 g_wimiso_path
= grub_strdup(args
[0]);
1034 grub_file_close(file
);
1039 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1049 ventoy_iso9660_override
*dirent
;
1058 totlen
= sizeof(ventoy_chain_head
);
1060 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1062 debug("failed to load efiboot template %d\n", len
);
1068 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1070 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1073 debug("failed to open file <%s>\n", args
[0]);
1077 totlen
+= ventoy_align_2k(file
->size
);
1079 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1080 dirent
->first_sector
= len
/ 2048;
1081 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1082 dirent
->size
= (grub_uint32_t
)file
->size
;
1083 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1085 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1087 #ifdef GRUB_MACHINE_EFI
1088 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1090 data
= (char *)grub_malloc(totlen
);
1093 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1095 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1096 grub_check_free(buf
);
1098 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1099 grub_file_close(file
);
1101 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1102 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1103 grub_env_set(name
, value
);
1105 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1106 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1107 grub_env_set(name
, value
);
1112 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1118 g_vtoy_load_prompt
= 0;
1119 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1121 if (argc
== 2 && args
[0][0] == '1')
1123 g_vtoy_load_prompt
= 1;
1124 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1127 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1130 int ventoy_need_prompt_load_file(void)
1132 return g_vtoy_load_prompt
;
1135 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1137 grub_uint64_t ro
= 0;
1138 grub_uint64_t div
= 0;
1139 grub_ssize_t left
= size
;
1140 char *cur
= (char *)buf
;
1142 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1145 while (left
>= VTOY_SIZE_2MB
)
1147 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1148 cur
+= VTOY_SIZE_2MB
;
1149 left
-= VTOY_SIZE_2MB
;
1151 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1152 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1158 grub_file_read(file
, cur
, left
);
1161 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1167 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1174 enum grub_file_type type
;
1185 if (grub_strcmp(args
[0], "nodecompress") == 0)
1187 type
= VENTOY_FILE_TYPE
;
1191 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1194 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1197 debug("failed to open file <%s>\n", args
[1]);
1201 #ifdef GRUB_MACHINE_EFI
1202 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1204 buf
= (char *)grub_malloc(file
->size
);
1209 grub_file_close(file
);
1213 if (g_vtoy_load_prompt
)
1215 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1219 grub_file_read(file
, buf
, file
->size
);
1222 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1223 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1224 grub_env_set(name
, value
);
1226 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1227 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1228 grub_env_set(name
, value
);
1230 grub_file_close(file
);
1236 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1254 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1257 debug("failed to open file <%s> for udf check\n", args
[0]);
1261 headlen
= sizeof(ventoy_chain_head
);
1263 #ifdef GRUB_MACHINE_EFI
1264 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1266 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1269 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1271 grub_file_read(file
, buf
+ headlen
, file
->size
);
1273 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1274 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1275 grub_env_set(name
, value
);
1277 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1278 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1279 grub_env_set(name
, value
);
1281 grub_file_close(file
);
1287 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1293 if (grub_iso9660_is_joliet())
1295 debug("This time has joliet process\n");
1304 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1313 if (args
[0][0] == '1')
1315 grub_iso9660_set_nojoliet(1);
1319 grub_iso9660_set_nojoliet(0);
1325 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1330 grub_uint8_t buf
[32];
1341 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1344 debug("failed to open file <%s> for udf check\n", args
[0]);
1348 for (i
= 16; i
< 32; i
++)
1350 grub_file_seek(file
, i
* 2048);
1351 grub_file_read(file
, buf
, sizeof(buf
));
1359 grub_file_seek(file
, i
* 2048);
1360 grub_file_read(file
, buf
, sizeof(buf
));
1362 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1365 grub_file_seek(file
, i
* 2048);
1366 grub_file_read(file
, buf
, sizeof(buf
));
1368 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1369 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1375 grub_file_close(file
);
1377 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1382 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1384 long value_long1
= 0;
1385 long value_long2
= 0;
1387 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1389 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1392 value_long1
= grub_strtol(args
[0], NULL
, 10);
1393 value_long2
= grub_strtol(args
[2], NULL
, 10);
1395 if (0 == grub_strcmp(args
[1], "eq"))
1397 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1399 else if (0 == grub_strcmp(args
[1], "ne"))
1401 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1403 else if (0 == grub_strcmp(args
[1], "gt"))
1405 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1407 else if (0 == grub_strcmp(args
[1], "lt"))
1409 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1411 else if (0 == grub_strcmp(args
[1], "ge"))
1413 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1415 else if (0 == grub_strcmp(args
[1], "le"))
1417 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1421 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1427 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1430 char buf
[128] = {0};
1434 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1437 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1438 pos
= grub_strstr(buf
, ",");
1444 grub_env_set(args
[1], buf
);
1446 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1449 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1455 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1461 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1464 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1466 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1467 if (0 == grub_script_execute_sourcecode(buf
))
1469 debug("file %s exist, ventoy_compatible YES\n", buf
);
1470 grub_env_set("ventoy_compatible", "YES");
1471 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1475 debug("file %s NOT exist\n", buf
);
1479 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1480 pos
= grub_strstr(buf
, ")");
1486 disk
= grub_disk_open(buf
);
1489 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1490 grub_disk_close(disk
);
1492 g_img_swap_tmp_buf
[703] = 0;
1493 for (i
= 318; i
< 703; i
++)
1495 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1496 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1498 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1499 grub_env_set("ventoy_compatible", "YES");
1500 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1506 debug("failed to open disk <%s>\n", buf
);
1509 grub_env_set("ventoy_compatible", "NO");
1510 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1513 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1519 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1521 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1524 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1529 if (0 == g_sort_case_sensitive
)
1531 if (grub_islower(c1
))
1533 c1
= c1
- 'a' + 'A';
1536 if (grub_islower(c2
))
1538 c2
= c2
- 'a' + 'A';
1551 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1557 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1559 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1562 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1567 if (0 == g_sort_case_sensitive
)
1569 if (grub_islower(c1
))
1571 c1
= c1
- 'a' + 'A';
1574 if (grub_islower(c2
))
1576 c2
= c2
- 'a' + 'A';
1589 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1591 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1593 grub_memcpy(img1
, img2
, sizeof(img_info
));
1594 img1
->next
= g_img_swap_tmp
.next
;
1595 img1
->prev
= g_img_swap_tmp
.prev
;
1597 g_img_swap_tmp
.next
= img2
->next
;
1598 g_img_swap_tmp
.prev
= img2
->prev
;
1599 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1602 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1606 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1614 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1623 const menu_tip
*tip
;
1624 img_iterator_node
*tmp
;
1625 img_iterator_node
*new_node
;
1626 img_iterator_node
*node
= (img_iterator_node
*)data
;
1628 if (g_enumerate_time_checked
== 0)
1630 g_enumerate_finish_time_ms
= grub_get_time_ms();
1631 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1634 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1636 g_enumerate_time_checked
= 1;
1640 len
= grub_strlen(filename
);
1644 if (node
->level
+ 1 > g_img_max_search_level
)
1649 if ((len
== 1 && filename
[0] == '.') ||
1650 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1655 if (!ventoy_img_name_valid(filename
, len
))
1660 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1665 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1667 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1668 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1671 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1676 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1679 new_node
->level
= node
->level
+ 1;
1680 new_node
->plugin_list_index
= index
;
1681 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1683 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1686 debug("Directory %s ignored...\n", new_node
->dir
);
1687 grub_free(new_node
);
1691 new_node
->tail
= node
->tail
;
1693 new_node
->parent
= node
;
1694 if (!node
->firstchild
)
1696 node
->firstchild
= new_node
;
1699 if (g_img_iterator_tail
)
1701 g_img_iterator_tail
->next
= new_node
;
1702 g_img_iterator_tail
= new_node
;
1706 g_img_iterator_head
.next
= new_node
;
1707 g_img_iterator_tail
= new_node
;
1713 debug("Find a file %s\n", filename
);
1719 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1721 type
= img_type_iso
;
1723 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1725 type
= img_type_wim
;
1727 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1728 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1730 type
= img_type_vhd
;
1732 #ifdef GRUB_MACHINE_EFI
1733 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1735 type
= img_type_efi
;
1738 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1740 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1742 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1743 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1748 type
= img_type_img
;
1750 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1752 type
= img_type_vtoy
;
1754 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1756 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1758 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1759 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1768 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1773 if (g_plugin_image_list
)
1775 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1776 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1777 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1779 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1782 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1784 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1789 img
= grub_zalloc(sizeof(img_info
));
1793 img
->plugin_list_index
= index
;
1794 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1796 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1798 img
->size
= info
->size
;
1801 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1804 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1806 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1811 if (g_ventoy_img_list
)
1813 tail
= *(node
->tail
);
1819 g_ventoy_img_list
= img
;
1822 img
->id
= g_ventoy_img_count
;
1824 if (node
&& NULL
== node
->firstiso
)
1826 node
->firstiso
= img
;
1837 *((img_info
**)(node
->tail
)) = img
;
1838 g_ventoy_img_count
++;
1840 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1842 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
1845 img
->tip1
= tip
->tip1
;
1846 img
->tip2
= tip
->tip2
;
1849 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1852 img
->class = g_menu_class
[type
];
1854 img
->menu_prefix
= g_menu_prefix
[type
];
1856 if (img_type_iso
== type
)
1858 if (ventoy_plugin_check_memdisk(img
->path
))
1860 img
->menu_prefix
= "miso";
1864 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1871 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1873 int len
= GRUB_UINT_MAX
;
1874 const char *value
= NULL
;
1875 char name
[32] = {0};
1876 char plat
[32] = {0};
1877 char guidstr
[32] = {0};
1878 ventoy_guid guid
= VENTOY_GUID
;
1879 const char *fmt1
= NULL
;
1880 const char *fmt2
= NULL
;
1881 const char *fmt3
= NULL
;
1882 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1883 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1884 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1885 const char fmtcode
[]={
1886 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1887 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1888 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1889 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1890 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1891 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1894 grub_memset(name
, 0, sizeof(name
));
1895 puint
[0] = grub_swap_bytes32(0x56454e54);
1896 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1897 puint
[2] = grub_swap_bytes32(0x45525349);
1898 puint
[1] = grub_swap_bytes32(0x4f595f56);
1899 value
= ventoy_get_env(name
);
1901 grub_memset(name
, 0, sizeof(name
));
1902 puint
[1] = grub_swap_bytes32(0x5f544f50);
1903 puint
[0] = grub_swap_bytes32(0x56544c45);
1904 fmt1
= ventoy_get_env(name
);
1910 grub_memset(name
, 0, sizeof(name
));
1911 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1912 puint
[0] = grub_swap_bytes32(0x56544c45);
1913 fmt2
= ventoy_get_env(name
);
1915 grub_memset(name
, 0, sizeof(name
));
1916 puint
[1] = grub_swap_bytes32(0x5f434c52);
1917 puint
[0] = grub_swap_bytes32(0x56544c45);
1918 fmt3
= ventoy_get_env(name
);
1920 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1922 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1924 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1925 #pragma GCC diagnostic push
1926 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1927 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1928 fmt1
? fmt1
: fmtdata
,
1929 fmt2
? fmt2
: fmtdata
+ 4,
1930 value
? value
: "", plat
, guidstr
,
1931 fmt3
? fmt3
: fmtdata
+ 6);
1932 #pragma GCC diagnostic pop
1934 grub_memset(name
, 0, sizeof(name
));
1935 puint
[0] = grub_swap_bytes32(0x76746f79);
1936 puint
[2] = grub_swap_bytes32(0x656e7365);
1937 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1938 ventoy_set_env(name
, guidstr
);
1943 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1947 grub_uint8_t md5
[16];
1951 grub_memset(input
, 0, sizeof(input
));
1953 grub_printf("Enter password: ");
1956 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1958 grub_password_get(input
, 128);
1959 if (grub_strcmp(pwd
->text
, input
) == 0)
1964 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1966 grub_password_get(input
, 128);
1967 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1968 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1973 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1975 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1976 grub_password_get(input
+ offset
, 128);
1978 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1979 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1985 grub_printf("Invalid password!\n\n");
1992 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1994 img_info
*minimg
= NULL
;
1995 img_info
*img
= (img_info
*)(node
->firstiso
);
1997 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1999 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2014 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2016 img_iterator_node
*Minchild
= NULL
;
2017 img_iterator_node
*child
= node
->firstchild
;
2019 while (child
&& child
->parent
== node
)
2021 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2025 child
= child
->next
;
2030 Minchild
->select
= 1;
2036 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2039 img_info
*img
= NULL
;
2040 const char *dir_class
= NULL
;
2041 const char *dir_alias
= NULL
;
2042 img_iterator_node
*child
= NULL
;
2043 const menu_tip
*tip
= NULL
;
2045 if (node
->isocnt
== 0 || node
->done
== 1)
2050 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2052 offset
= node
->parent
->dirlen
;
2055 if (node
== &g_img_iterator_head
)
2057 if (g_default_menu_mode
== 0)
2059 if (g_tree_view_menu_style
== 0)
2061 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2062 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2063 " echo 'return ...' \n"
2068 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2069 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2077 node
->dir
[node
->dirlen
- 1] = 0;
2078 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2081 dir_class
= "vtoydir";
2084 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2086 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2089 if (g_tree_view_menu_style
== 0)
2091 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2092 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2093 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2097 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2098 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2099 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2104 dir_alias
= node
->dir
+ offset
;
2106 if (g_tree_view_menu_style
== 0)
2108 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2109 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2110 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2114 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2115 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2116 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2120 if (g_tree_view_menu_style
== 0)
2122 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2123 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2124 " echo 'return ...' \n"
2129 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2130 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2136 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2138 ventoy_dynamic_tree_menu(child
);
2141 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2143 if (g_tree_view_menu_style
== 0)
2145 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2146 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2149 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2150 img
->unsupport
? "[***********] " : "",
2151 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2153 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2157 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2158 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2161 img
->unsupport
? "[***********] " : "",
2162 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2164 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2168 if (node
!= &g_img_iterator_head
)
2170 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2177 static int ventoy_set_default_menu(void)
2183 const char *strdata
= NULL
;
2184 img_info
*cur
= NULL
;
2185 img_info
*default_node
= NULL
;
2186 const char *default_image
= NULL
;
2188 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2189 if (default_image
&& default_image
[0] == '/')
2191 img_len
= grub_strlen(default_image
);
2193 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2195 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2207 if (0 == g_default_menu_mode
)
2209 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2213 def
= grub_strdup(default_image
);
2219 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2221 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2222 if (strdata
&& strdata
[0] == '/')
2224 pos
= def
+ grub_strlen(strdata
);
2235 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2238 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2242 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2250 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2252 img_info
*next
= NULL
;
2253 img_info
*cur
= g_ventoy_img_list
;
2266 g_ventoy_img_list
= NULL
;
2267 g_ventoy_img_count
= 0;
2269 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2272 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2275 img_info
*cur
= g_ventoy_img_list
;
2279 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2281 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2284 img_id
= grub_strtol(args
[0], NULL
, 10);
2285 if (img_id
>= g_ventoy_img_count
)
2287 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2290 debug("Find image %ld name \n", img_id
);
2292 while (cur
&& img_id
> 0)
2300 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2303 debug("image name is %s\n", cur
->name
);
2305 grub_env_set(args
[1], cur
->name
);
2307 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2310 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2314 img_info
*cur
= g_ventoy_img_list
;
2320 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2323 len
= (int)grub_strlen(args
[0]);
2327 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2336 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2339 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2340 grub_env_set("chosen", id
);
2341 grub_env_export("chosen");
2343 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2346 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2350 const char *id
= NULL
;
2351 img_info
*cur
= NULL
;
2355 if (argc
< 1 || argc
> 2)
2357 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2360 id
= grub_env_get("chosen");
2362 pos
= grub_strstr(id
, "VID_");
2365 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2369 cur
= g_ventoy_img_list
;
2374 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2377 grub_env_set(args
[0], cur
->path
);
2381 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2382 grub_env_set(args
[1], value
);
2385 g_svd_replace_offset
= 0;
2387 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2391 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2395 grub_device_t dev
= NULL
;
2396 img_info
*cur
= NULL
;
2397 img_info
*tail
= NULL
;
2398 img_info
*min
= NULL
;
2399 img_info
*head
= NULL
;
2400 const char *strdata
= NULL
;
2401 char *device_name
= NULL
;
2403 img_iterator_node
*node
= NULL
;
2404 img_iterator_node
*tmp
= NULL
;
2410 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2413 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2415 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2420 g_enumerate_time_checked
= 0;
2421 g_enumerate_start_time_ms
= grub_get_time_ms();
2423 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2424 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2426 g_filt_dot_underscore_file
= 1;
2429 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2430 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2432 g_sort_case_sensitive
= 1;
2435 device_name
= grub_file_get_device_name(args
[0]);
2441 g_enum_dev
= dev
= grub_device_open(device_name
);
2447 g_enum_fs
= fs
= grub_fs_probe(dev
);
2453 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2455 debug("unsupported fs:<%s>\n", fs
->name
);
2456 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2460 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2462 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2463 if (strdata
&& strdata
[0] == '1')
2465 g_default_menu_mode
= 1;
2468 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2470 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2472 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2473 if (strdata
&& strdata
[0] == '/')
2475 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2476 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2478 g_img_iterator_head
.dir
[len
++] = '/';
2480 g_img_iterator_head
.dirlen
= len
;
2484 g_img_iterator_head
.dirlen
= 1;
2485 grub_strcpy(g_img_iterator_head
.dir
, "/");
2488 g_img_iterator_head
.tail
= &tail
;
2490 if (g_img_max_search_level
< 0)
2492 g_img_max_search_level
= GRUB_INT_MAX
;
2493 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2494 if (strdata
&& ventoy_is_decimal(strdata
))
2496 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2500 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2501 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2502 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2503 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2504 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2505 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2507 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2509 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2512 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2513 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2515 g_tree_view_menu_style
= 1;
2518 ventoy_set_default_menu();
2520 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2522 ventoy_dynamic_tree_menu(node
);
2526 node
= g_img_iterator_head
.next
;
2534 /* sort image list by image name */
2535 while (g_ventoy_img_list
)
2537 min
= g_ventoy_img_list
;
2538 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2540 if (ventoy_cmp_img(min
, cur
) > 0)
2548 min
->prev
->next
= min
->next
;
2553 min
->next
->prev
= min
->prev
;
2556 if (min
== g_ventoy_img_list
)
2558 g_ventoy_img_list
= min
->next
;
2576 g_ventoy_img_list
= head
;
2578 if (g_default_menu_mode
== 1)
2580 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2581 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2582 " echo 'return ...' \n"
2586 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2588 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2589 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2592 cur
->unsupport
? "[***********] " : "",
2593 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2595 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2598 g_tree_script_buf
[g_tree_script_pos
] = 0;
2599 g_list_script_buf
[g_list_script_pos
] = 0;
2601 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2602 grub_env_set(args
[1], buf
);
2606 check_free(device_name
, grub_free
);
2607 check_free(dev
, grub_device_close
);
2609 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2612 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2619 device_name
= grub_file_get_device_name(filename
);
2631 pos2
= grub_strstr(pos
, ",");
2634 pos2
= grub_strstr(pos
, ")");
2642 disk
= grub_disk_open(pos
);
2645 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2646 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2647 grub_disk_close(disk
);
2654 grub_free(device_name
);
2658 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2660 eltorito_descriptor desc
;
2662 grub_memset(&desc
, 0, sizeof(desc
));
2663 grub_file_seek(file
, 17 * 2048);
2664 grub_file_read(file
, &desc
, sizeof(desc
));
2666 if (desc
.type
!= 0 || desc
.version
!= 1)
2671 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2672 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2680 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2682 grub_uint8_t buf
[512];
2684 grub_file_seek(file
, sector
* 2048);
2685 grub_file_read(file
, buf
, sizeof(buf
));
2687 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2688 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2690 return *((grub_uint32_t
*)(buf
+ 40));
2696 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2700 grub_uint8_t buf
[512];
2701 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2703 grub_file_seek(file
, sector
* 2048);
2704 grub_file_read(file
, buf
, sizeof(buf
));
2706 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2708 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2712 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2717 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2719 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2721 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2725 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2727 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2732 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2734 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2736 if (buf
[36] == parttype
[i
])
2738 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2744 debug("%s does not contain efi eltorito\n", file
->name
);
2748 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2751 const char *fs
= NULL
;
2752 const char *val
= NULL
;
2753 const char *cdprompt
= NULL
;
2755 grub_uint8_t chksum
= 0;
2758 disk
= file
->device
->disk
;
2759 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2761 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2762 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2763 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2765 pos
= grub_strstr(file
->name
, "/");
2771 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2773 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2775 param
->vtoy_img_size
= file
->size
;
2777 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2778 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2780 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2782 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2783 param
->vtoy_reserved
[4] = 0;
2784 if (g_ventoy_chain_type
== 1) /* Windows */
2786 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2787 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2789 param
->vtoy_reserved
[4] = 1;
2793 fs
= ventoy_get_env("ventoy_fs_probe");
2794 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2796 param
->vtoy_reserved
[3] = 1;
2799 param
->vtoy_reserved
[5] = 0;
2800 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
2801 if (val
&& val
[0] == '1' && val
[1] == 0)
2803 param
->vtoy_reserved
[5] = 1;
2806 /* calculate checksum */
2807 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2809 chksum
+= *((grub_uint8_t
*)param
+ i
);
2811 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2816 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2818 grub_uint32_t i
= 0;
2819 grub_uint64_t total
= 0;
2820 grub_uint64_t fileblk
= 0;
2821 ventoy_img_chunk
*chunk
= NULL
;
2823 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2825 chunk
= chunklist
->chunk
+ i
;
2827 if (chunk
->disk_start_sector
<= start
)
2829 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2833 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2836 fileblk
= (file
->size
+ 511) / 512;
2838 if (total
!= fileblk
)
2840 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2841 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2843 debug("maybe img file to be processed.\n");
2853 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2857 grub_uint32_t i
= 0;
2858 grub_uint32_t sector
= 0;
2859 grub_uint32_t count
= 0;
2860 grub_off_t size
= 0;
2861 grub_off_t read
= 0;
2863 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2864 if (fs_type
== ventoy_fs_exfat
)
2866 grub_fat_get_file_chunk(start
, file
, chunklist
);
2868 else if (fs_type
== ventoy_fs_ext
)
2870 grub_ext_get_file_chunk(start
, file
, chunklist
);
2874 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2875 file
->read_hook_data
= chunklist
;
2877 for (size
= file
->size
; size
> 0; size
-= read
)
2879 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2880 grub_file_read(file
, NULL
, read
);
2883 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2885 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2886 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2889 if (ventoy_fs_udf
== fs_type
)
2891 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2893 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2894 chunklist
->chunk
[i
].img_start_sector
= sector
;
2895 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2901 len
= (int)grub_strlen(file
->name
);
2902 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2903 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2904 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2905 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2907 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2909 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2919 chunklist
->chunk
[i
].img_start_sector
= sector
;
2920 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2928 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2932 grub_disk_addr_t start
;
2937 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2940 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2943 g_conf_replace_node
= NULL
;
2944 g_conf_replace_offset
= 0;
2946 if (g_img_chunk_list
.chunk
)
2948 grub_free(g_img_chunk_list
.chunk
);
2951 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2953 grub_file_close(file
);
2954 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2957 /* get image chunk data */
2958 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2959 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2960 if (NULL
== g_img_chunk_list
.chunk
)
2962 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2965 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2966 g_img_chunk_list
.cur_chunk
= 0;
2968 start
= file
->device
->disk
->partition
->start
;
2970 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2972 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2973 grub_file_close(file
);
2977 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2980 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2981 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
2982 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2985 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2987 grub_uint64_t offset
= 0;
2988 grub_uint32_t align
= 0;
2989 grub_file_t file
= NULL
;
2990 conf_replace
*node
= NULL
;
2996 debug("select conf replace argc:%d\n", argc
);
3003 node
= ventoy_plugin_find_conf_replace(args
[1]);
3006 debug("Conf replace not found for %s\n", args
[1]);
3010 debug("Find conf replace for %s\n", args
[1]);
3012 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3015 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3016 grub_file_close(file
);
3018 else if (node
->img
> 0)
3024 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3028 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3031 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3035 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3037 if (align
> vtoy_max_replace_file_size
)
3039 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3043 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3044 g_conf_replace_new_len
= (int)file
->size
;
3045 g_conf_replace_new_len_align
= align
;
3047 g_conf_replace_node
= node
;
3048 g_conf_replace_offset
= offset
+ 2;
3052 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3053 g_grub_param
->img_replace
.old_name_cnt
= 1;
3054 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3057 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3062 grub_file_close(file
);
3064 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3067 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3073 char configfile
[128];
3074 install_template
*node
= NULL
;
3080 debug("select auto installation argc:%d\n", argc
);
3087 node
= ventoy_plugin_find_install_template(args
[0]);
3090 debug("Auto install template not found for %s\n", args
[0]);
3094 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3096 defidx
= node
->autosel
;
3097 if (node
->timeout
< 0)
3099 node
->cursel
= node
->autosel
- 1;
3100 debug("Auto install template auto select %d\n", node
->autosel
);
3105 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3111 if (node
->timeout
> 0)
3113 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3116 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3117 " echo %s\n}\n", "");
3119 for (i
= 0; i
< node
->templatenum
; i
++)
3121 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3123 node
->templatepath
[i
].path
);
3126 g_ventoy_menu_esc
= 1;
3127 g_ventoy_suppress_esc
= 1;
3128 g_ventoy_suppress_esc_default
= defidx
;
3130 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3131 grub_script_execute_sourcecode(configfile
);
3133 g_ventoy_menu_esc
= 0;
3134 g_ventoy_suppress_esc
= 0;
3135 g_ventoy_suppress_esc_default
= 1;
3139 node
->cursel
= g_ventoy_last_entry
- 1;
3141 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3144 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3150 char configfile
[128];
3151 persistence_config
*node
;
3157 debug("select persistence argc:%d\n", argc
);
3164 node
= ventoy_plugin_find_persistent(args
[0]);
3167 debug("Persistence image not found for %s\n", args
[0]);
3171 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3173 defidx
= node
->autosel
;
3174 if (node
->timeout
< 0)
3176 node
->cursel
= node
->autosel
- 1;
3177 debug("Persistence image auto select %d\n", node
->autosel
);
3182 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3188 if (node
->timeout
> 0)
3190 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3193 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3194 " echo %s\n}\n", "");
3196 for (i
= 0; i
< node
->backendnum
; i
++)
3198 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3200 node
->backendpath
[i
].path
);
3204 g_ventoy_menu_esc
= 1;
3205 g_ventoy_suppress_esc
= 1;
3206 g_ventoy_suppress_esc_default
= defidx
;
3208 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3209 grub_script_execute_sourcecode(configfile
);
3211 g_ventoy_menu_esc
= 0;
3212 g_ventoy_suppress_esc
= 0;
3213 g_ventoy_suppress_esc_default
= 1;
3217 node
->cursel
= g_ventoy_last_entry
- 1;
3219 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3222 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3225 ventoy_img_chunk
*cur
;
3231 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3233 cur
= g_img_chunk_list
.chunk
+ i
;
3234 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3235 cur
->img_start_sector
, cur
->img_end_sector
,
3236 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3240 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3243 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3247 ventoy_img_chunk_list chunklist
;
3252 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3255 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3258 /* get image chunk data */
3259 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3260 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3261 if (NULL
== chunklist
.chunk
)
3263 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3266 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3267 chunklist
.cur_chunk
= 0;
3269 ventoy_get_block_list(file
, &chunklist
, 0);
3271 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3273 grub_printf("########## UNSUPPORTED ###############\n");
3276 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3278 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3280 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3281 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3284 grub_printf("\n==================================\n");
3286 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3288 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3289 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3290 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3291 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3292 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3296 grub_free(chunklist
.chunk
);
3297 grub_file_close(file
);
3299 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3302 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3305 ventoy_grub_param_file_replace
*replace
= NULL
;
3313 replace
= &(g_grub_param
->file_replace
);
3314 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3316 replace
->old_name_cnt
= 0;
3317 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3319 replace
->old_name_cnt
++;
3320 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3323 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3326 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3329 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3332 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3338 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3339 grub_env_set(args
[0], buf
);
3342 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3345 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3353 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3354 grub_printf("%s", g_list_script_buf
);
3358 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3359 grub_printf("%s", g_tree_script_buf
);
3365 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3367 img_info
*cur
= g_ventoy_img_list
;
3375 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3376 grub_printf("name:<%s>\n\n", cur
->name
);
3383 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3389 ventoy_plugin_dump_injection();
3394 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3400 ventoy_plugin_dump_auto_install();
3405 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3411 ventoy_plugin_dump_persistence();
3416 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3427 if (args
[0][0] == '0')
3429 return g_ventoy_memdisk_mode
? 0 : 1;
3431 else if (args
[0][0] == '1')
3433 return g_ventoy_iso_raw
? 0 : 1;
3435 else if (args
[0][0] == '2')
3437 return g_ventoy_iso_uefi_drv
? 0 : 1;
3439 else if (args
[0][0] == '3')
3441 return g_ventoy_grub2_mode
? 0 : 1;
3443 else if (args
[0][0] == '4')
3445 return g_ventoy_wimboot_mode
? 0 : 1;
3451 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3453 static int configfile_mode
= 0;
3454 char memfile
[128] = {0};
3461 * args[0]: 0:normal 1:configfile
3462 * args[1]: 0:list_buf 1:tree_buf
3467 debug("Invalid argc %d\n", argc
);
3473 if (args
[0][0] == '0')
3475 if (args
[1][0] == '0')
3477 grub_script_execute_sourcecode(g_list_script_buf
);
3481 grub_script_execute_sourcecode(g_tree_script_buf
);
3486 if (configfile_mode
)
3488 debug("Now already in F3 mode %d\n", configfile_mode
);
3492 if (args
[1][0] == '0')
3494 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3495 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3499 g_ventoy_last_entry
= -1;
3500 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3501 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3504 configfile_mode
= 1;
3505 grub_script_execute_sourcecode(memfile
);
3506 configfile_mode
= 0;
3512 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3523 g_ventoy_case_insensitive
= 1;
3524 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3525 g_ventoy_case_insensitive
= 0;
3531 grub_file_close(file
);
3537 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3542 const char *isopath
= NULL
;
3544 ventoy_mbr_head mbr
;
3551 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3554 isopath
= grub_env_get("vtoy_iso_part");
3557 debug("isopath is null %p\n", isopath
);
3561 debug("isopath is %s\n", isopath
);
3563 for (id
= 0; id
< 30 && (find
== 0); id
++)
3565 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3566 if (grub_strstr(isopath
, hdname
))
3568 debug("skip %s ...\n", hdname
);
3572 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3574 disk
= grub_disk_open(hdname
);
3577 debug("%s not exist\n", hdname
);
3581 grub_memset(&mbr
, 0, sizeof(mbr
));
3582 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3584 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3586 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3587 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3590 grub_env_set(args
[0], hdname
);
3594 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3598 debug("read %s failed\n", hdname
);
3601 grub_disk_close(disk
);
3607 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3618 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3621 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3624 debug("failed to open file %s\n", args
[0]);
3628 buf
= grub_malloc(len
);
3635 grub_file_read(file
, buf
, len
- 1);
3637 ventoy_get_line(buf
);
3638 ventoy_set_env(args
[1], buf
);
3642 grub_check_free(buf
);
3643 grub_file_close(file
);
3648 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3650 grub_uint64_t end_max
= 0;
3651 int *pCnt
= (int *)data
;
3656 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3657 "0 %llu linear /dev/ventoy %llu\n",
3658 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3660 end_max
= (partition
->len
+ partition
->start
) * 512;
3661 if (end_max
> g_part_end_max
)
3663 g_part_end_max
= end_max
;
3669 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3672 char *device_name
= NULL
;
3673 grub_device_t dev
= NULL
;
3678 g_part_list_pos
= 0;
3680 grub_env_unset("vtoy_img_part_file");
3687 device_name
= grub_file_get_device_name(args
[0]);
3690 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3694 dev
= grub_device_open(device_name
);
3697 debug("grub_device_open failed, %s\n", device_name
);
3701 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3703 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3704 grub_env_set("vtoy_img_part_file", buf
);
3706 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3707 grub_env_set("vtoy_img_part_cnt", buf
);
3709 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
3710 grub_env_set("vtoy_img_max_part_end", buf
);
3714 check_free(device_name
, grub_free
);
3715 check_free(dev
, grub_device_close
);
3721 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3732 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3735 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3738 debug("failed to open file %s\n", args
[0]);
3742 buf
= grub_malloc(file
->size
+ 1);
3748 buf
[file
->size
] = 0;
3749 grub_file_read(file
, buf
, file
->size
);
3751 if (grub_strstr(buf
, args
[1]))
3758 grub_check_free(buf
);
3759 grub_file_close(file
);
3764 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3770 ventoy_iso9660_vd pvd
;
3777 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3780 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3783 debug("failed to open file %s\n", args
[0]);
3787 grub_file_seek(file
, 16 * 2048);
3788 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3789 if (len
!= sizeof(pvd
))
3791 debug("failed to read pvd %d\n", len
);
3795 grub_memset(buf
, 0, sizeof(buf
));
3796 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3797 ventoy_set_env(args
[1], buf
);
3799 grub_memset(buf
, 0, sizeof(buf
));
3800 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3801 ventoy_set_env(args
[2], buf
);
3805 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3806 ventoy_set_env(args
[3], buf
);
3809 grub_file_close(file
);
3814 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3825 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3828 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3831 debug("failed to open file %s\n", args
[0]);
3835 grub_memset(buf
, 0, sizeof(buf
));
3836 grub_file_seek(file
, 16 * 2048 + 813);
3837 len
= (int)grub_file_read(file
, buf
, 17);
3840 debug("failed to read create date %d\n", len
);
3844 ventoy_set_env(args
[1], buf
);
3847 grub_file_close(file
);
3852 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3858 ventoy_env_hook_root(1);
3863 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3869 ventoy_env_hook_root(0);
3874 #ifdef GRUB_MACHINE_EFI
3875 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3880 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3886 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3887 if (var
&& *var
== 1)
3895 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3904 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3909 grub_uint64_t FileSectors
= 0;
3910 ventoy_gpt_info
*gpt
= NULL
;
3911 ventoy_part_table
*pt
= NULL
;
3912 grub_uint8_t zeroguid
[16] = {0};
3917 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3920 debug("failed to open file %s\n", args
[0]);
3924 if (file
->size
% 512)
3926 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3930 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3936 FileSectors
= file
->size
/ 512;
3938 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3939 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3941 debug("This is EFI partition table\n");
3943 for (i
= 0; i
< 128; i
++)
3945 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3947 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3949 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3950 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3958 debug("This is MBR partition table\n");
3960 for (i
= 0; i
< 4; i
++)
3962 pt
= gpt
->MBR
.PartTbl
+ i
;
3963 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3965 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3966 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3967 (ulonglong
)FileSectors
);
3976 grub_file_close(file
);
3977 grub_check_free(gpt
);
3978 grub_errno
= GRUB_ERR_NONE
;
3982 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3991 for (i
= 0; i
< 500; i
++)
3993 ret
= grub_getkey_noblock();
3994 if (ret
== GRUB_TERM_NO_KEY
)
4003 grub_printf("\n\n Still have key input after clear.\n");
4011 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4018 int image_sector_size
;
4020 ventoy_chain_head
*chain
;
4021 ventoy_img_chunk
*chunk
;
4022 ventoy_os_param
*osparam
;
4023 ventoy_image_location
*location
;
4024 ventoy_image_disk_region
*region
;
4025 struct grub_acpi_table_header
*acpi
;
4034 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4036 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4042 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4044 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4046 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4050 img_chunk_num
= chain
->img_chunk_num
;
4052 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4053 datalen
= sizeof(ventoy_os_param
) + loclen
;
4055 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4056 acpi
= grub_zalloc(buflen
);
4062 /* Step1: Fill acpi table header */
4063 grub_memcpy(acpi
->signature
, "VTOY", 4);
4064 acpi
->length
= buflen
;
4066 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4067 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4069 acpi
->creator_id
[0] = 1;
4070 acpi
->creator_rev
= 1;
4072 /* Step2: Fill data */
4073 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4074 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4075 osparam
->vtoy_img_location_addr
= 0;
4076 osparam
->vtoy_img_location_len
= loclen
;
4077 osparam
->chksum
= 0;
4078 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4080 location
= (ventoy_image_location
*)(osparam
+ 1);
4081 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4082 location
->image_sector_size
= image_sector_size
;
4083 location
->disk_sector_size
= chain
->disk_sector_size
;
4084 location
->region_count
= img_chunk_num
;
4086 region
= location
->regions
;
4087 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4088 if (512 == image_sector_size
)
4090 for (i
= 0; i
< img_chunk_num
; i
++)
4092 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4093 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4094 region
->disk_start_sector
= chunk
->disk_start_sector
;
4101 for (i
= 0; i
< img_chunk_num
; i
++)
4103 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4104 region
->image_start_sector
= chunk
->img_start_sector
;
4105 region
->disk_start_sector
= chunk
->disk_start_sector
;
4111 /* Step3: Fill acpi checksum */
4113 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4115 /* load acpi table */
4116 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4117 grub_script_execute_sourcecode(cmd
);
4121 VENTOY_CMD_RETURN(0);
4124 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4130 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4131 g_ventoy_last_entry
= -1;
4136 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4142 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4147 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4149 const char *pos
= filename
+ 1;
4157 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4159 grub_strncpy((char *)data
, filename
, 128);
4170 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4173 char *device_name
= NULL
;
4174 grub_device_t dev
= NULL
;
4175 grub_fs_t fs
= NULL
;
4176 char buf
[128] = {0};
4182 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4186 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4188 device_name
= grub_file_get_device_name(args
[0]);
4191 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4195 dev
= grub_device_open(device_name
);
4198 debug("grub_device_open failed, %s\n", device_name
);
4202 fs
= grub_fs_probe(dev
);
4205 debug("grub_fs_probe failed, %s\n", device_name
);
4209 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4213 ventoy_set_env(args
[2], buf
);
4220 check_free(device_name
, grub_free
);
4221 check_free(dev
, grub_device_close
);
4226 int ventoy_load_part_table(const char *diskname
)
4233 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4234 if (!g_ventoy_part_info
)
4239 disk
= grub_disk_open(diskname
);
4242 debug("Failed to open disk %s\n", diskname
);
4246 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4248 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4249 grub_disk_close(disk
);
4251 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4252 dev
= grub_device_open(name
);
4255 /* Check for official Ventoy device */
4256 ret
= ventoy_check_official_device(dev
);
4257 grub_device_close(dev
);
4265 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4266 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4271 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4278 ret
= ventoy_load_part_table(args
[0]);
4284 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4285 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4290 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4293 const char *vcfg
= NULL
;
4298 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4301 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4302 grub_env_set(args
[1], vcfg
);
4307 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4315 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4318 grub_uint8_t zeroguid
[16] = {0};
4323 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4326 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4328 if (id
>= 1 && id
<= 128)
4330 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4338 if (id
>= 1 && id
<= 4)
4340 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4350 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4353 char *device_name
= NULL
;
4354 grub_device_t dev
= NULL
;
4355 grub_fs_t fs
= NULL
;
4360 debug("get fs label for %s\n", args
[0]);
4364 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4368 device_name
= grub_file_get_device_name(args
[0]);
4371 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4375 dev
= grub_device_open(device_name
);
4378 debug("grub_device_open failed, %s\n", device_name
);
4382 fs
= grub_fs_probe(dev
);
4383 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4385 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4389 fs
->fs_label(dev
, &label
);
4392 debug("label=<%s>\n", label
);
4393 ventoy_set_env(args
[1], label
);
4401 check_free(device_name
, grub_free
);
4402 check_free(dev
, grub_device_close
);
4407 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4411 grub_snprintf((char *)data
, 256, "%s", filename
);
4418 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4420 if (info
->dir
&& filename
&& filename
[0] != '.')
4422 grub_snprintf((char *)data
, 256, "%s", filename
);
4429 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4432 char *device_name
= NULL
;
4433 grub_device_t dev
= NULL
;
4434 grub_fs_t fs
= NULL
;
4435 char name
[256] ={0};
4439 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4443 device_name
= grub_file_get_device_name(args
[0]);
4446 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4450 dev
= grub_device_open(device_name
);
4453 debug("grub_device_open failed, %s\n", device_name
);
4457 fs
= grub_fs_probe(dev
);
4460 debug("grub_fs_probe failed, %s\n", device_name
);
4464 fs
->fs_dir(dev
, args
[1], hook
, name
);
4467 ventoy_set_env(args
[2], name
);
4474 check_free(device_name
, grub_free
);
4475 check_free(dev
, grub_device_close
);
4480 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4483 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4486 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4489 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4492 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4502 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4506 for (pos
= args
[0]; *pos
; pos
++)
4520 grub_env_set(args
[1], args
[0]);
4530 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4540 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4545 len
= (int)grub_strlen(buf
);
4546 for (i
= len
; i
> 0; i
--)
4548 if (buf
[i
- 1] == '/')
4550 grub_env_set(args
[1], buf
+ i
);
4555 grub_env_set(args
[1], buf
);
4560 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4562 struct grub_video_mode_info info
;
4569 if (!g_video_mode_list
)
4571 ventoy_enum_video_mode();
4574 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4576 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4580 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4583 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4585 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4586 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4588 VENTOY_CMD_RETURN(0);
4591 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4593 struct grub_video_mode_info info
;
4600 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4602 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4606 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4609 grub_env_set(args
[0], buf
);
4611 VENTOY_CMD_RETURN(0);
4614 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4622 if (!g_video_mode_list
)
4627 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4628 if (id
< g_video_mode_num
)
4630 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4631 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4634 grub_env_set(args
[1], buf
);
4636 VENTOY_CMD_RETURN(0);
4639 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4642 grub_uint32_t loadsector
= 0;
4645 grub_uint32_t boot_catlog
= 0;
4646 grub_uint8_t buf
[512];
4652 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4656 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4659 debug("failed to open %s\n", args
[0]);
4663 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4664 if (boot_catlog
== 0)
4666 debug("No bootcatlog found\n");
4667 grub_file_close(file
);
4671 grub_memset(buf
, 0, sizeof(buf
));
4672 grub_file_seek(file
, boot_catlog
* 2048);
4673 grub_file_read(file
, buf
, sizeof(buf
));
4674 grub_file_close(file
);
4676 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4678 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4680 if (buf
[i
+ 32] == 0x88)
4682 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4683 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4689 if (loadsector
== 0)
4691 debug("No EFI eltorito info found\n");
4695 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4696 grub_env_set(args
[1], value
);
4697 VENTOY_CMD_RETURN(0);
4700 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4705 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4707 if (pfsdir
->initrd
[0])
4712 curpos
= pfsdir
->curpos
;
4713 len
= grub_strlen(filename
);
4717 if ((len
== 1 && filename
[0] == '.') ||
4718 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4723 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4726 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4727 pfsdir
->curpos
= curpos
+ printlen
;
4728 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4729 pfsdir
->curpos
= curpos
;
4730 pfsdir
->fullpath
[curpos
] = 0;
4734 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4737 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4738 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4740 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4742 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4751 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4755 char *device_name
= NULL
;
4756 grub_device_t dev
= NULL
;
4757 grub_fs_t fs
= NULL
;
4758 replace_fs_dir
*pfsdir
= NULL
;
4764 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4768 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4774 device_name
= grub_file_get_device_name(args
[0]);
4780 dev
= grub_device_open(device_name
);
4786 fs
= grub_fs_probe(dev
);
4795 pfsdir
->fullpath
[0] = '/';
4796 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4798 if (pfsdir
->initrd
[0])
4800 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4802 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4804 if (pfsdir
->initrd
[i
] == '/')
4806 pfsdir
->initrd
[i
] = '\\';
4810 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4811 grub_env_set(args
[1], pos
);
4815 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4820 grub_check_free(pfsdir
);
4821 grub_check_free(device_name
);
4822 check_free(dev
, grub_device_close
);
4824 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4827 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4829 const char *pager
= NULL
;
4835 pager
= grub_env_get("pager");
4839 grub_env_set("pager", "1");
4841 else if (pager
[0] == '1')
4847 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4849 grub_env_set("pager", "1");
4852 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4855 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4861 if (g_pager_flag
== 1)
4863 grub_env_unset("pager");
4865 else if (g_pager_flag
== 2)
4867 grub_env_set("pager", g_old_pager
);
4870 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4873 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4875 if (g_json_case_mis_path
[0])
4880 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
4882 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4888 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4891 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4893 if (g_json_case_mis_path
[0])
4898 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4900 if (grub_strcasecmp(filename
, "ventoy") == 0)
4902 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4903 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4904 if (g_json_case_mis_path
[0])
4914 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4917 char *device_name
= NULL
;
4918 grub_device_t dev
= NULL
;
4919 grub_fs_t fs
= NULL
;
4920 chk_case_fs_dir fs_dir
;
4926 device_name
= grub_file_get_device_name(args
[0]);
4932 dev
= grub_device_open(device_name
);
4938 fs
= grub_fs_probe(dev
);
4944 fstype
= ventoy_get_fs_type(fs
->name
);
4945 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4950 g_json_case_mis_path
[0] = 0;
4953 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4955 if (g_json_case_mis_path
[0])
4957 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4962 grub_check_free(device_name
);
4963 check_free(dev
, grub_device_close
);
4965 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4968 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4971 grub_partition_t part
;
4972 char priority_str
[3]; /* Maximum value 15 */
4976 if (argc
< 2 || argc
> 3)
4977 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4978 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4980 /* Open the disk if it exists */
4981 disk
= grub_disk_open (args
[0]);
4984 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4988 part
= grub_partition_probe (disk
, args
[1]);
4991 grub_disk_close (disk
);
4992 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4993 "No such partition");
4996 if (grub_strcmp (part
->partmap
->name
, "gpt"))
4998 grub_disk_close (disk
);
4999 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5000 "Not a GPT partition");
5003 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5004 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5008 grub_env_set (args
[2], priority_str
);
5009 grub_env_export (args
[2]);
5013 grub_printf ("Priority is %s\n", priority_str
);
5016 grub_disk_close (disk
);
5017 return GRUB_ERR_NONE
;
5021 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5025 grub_file_t file
= NULL
;
5026 grub_uint32_t loadrba
= 0;
5027 grub_uint32_t boot_catlog
= 0;
5028 grub_uint8_t sector
[512];
5029 boot_info_table
*info
= NULL
;
5034 /* This also trigger a iso9660 fs parse */
5035 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5040 joliet
= grub_iso9660_is_joliet();
5046 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5049 debug("failed to open %s\n", args
[0]);
5053 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5054 if (boot_catlog
== 0)
5056 debug("no bootcatlog found %u\n", boot_catlog
);
5060 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5063 debug("no bios eltorito rba found %u\n", loadrba
);
5067 grub_file_seek(file
, loadrba
* 2048);
5068 grub_file_read(file
, sector
, 512);
5070 info
= (boot_info_table
*)sector
;
5071 if (info
->bi_data0
== 0x7c6ceafa &&
5072 info
->bi_data1
== 0x90900000 &&
5073 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5074 info
->bi_BootFileLocation
== loadrba
)
5076 debug("bootloader is syslinux, %u.\n", loadrba
);
5082 grub_file_close(file
);
5083 grub_errno
= GRUB_ERR_NONE
;
5087 int ventoy_env_init(void)
5091 grub_env_set("vtdebug_flag", "");
5093 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5094 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5095 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5096 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5098 ventoy_filt_register(0, ventoy_wrapper_open
);
5100 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5103 g_grub_param
->grub_env_get
= grub_env_get
;
5104 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5105 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5106 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5107 grub_env_set("env_param", buf
);
5108 grub_env_set("ventoy_env_param", buf
);
5110 grub_env_export("env_param");
5111 grub_env_export("ventoy_env_param");
5114 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5115 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5117 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5118 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5120 grub_env_export("vtoy_winpeshl_ini_addr");
5121 grub_env_export("vtoy_winpeshl_ini_size");
5123 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5124 grub_env_set("vtoy_chain_file_size", buf
);
5125 grub_env_export("vtoy_chain_file_size");
5127 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5128 grub_env_set("vtoy_chain_file_read", buf
);
5129 grub_env_export("vtoy_chain_file_read");
5136 static cmd_para ventoy_cmds
[] =
5138 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5139 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5140 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5141 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5142 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5143 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5144 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5145 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5146 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5147 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5148 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5149 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5150 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5151 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5152 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5153 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5154 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5155 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5156 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5157 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5158 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5159 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5160 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5161 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5162 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5164 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5165 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5166 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5167 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5168 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5169 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5170 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5172 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5173 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5174 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5175 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5176 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5177 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5178 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5179 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5180 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5181 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5184 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5185 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5186 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5187 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5188 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5189 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5190 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5191 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5192 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5193 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5194 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5196 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5197 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5198 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5199 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5200 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5201 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5202 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5204 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5205 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5206 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5207 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5208 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5209 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5210 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5211 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5212 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5213 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5215 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5216 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5217 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5218 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5219 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5220 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5221 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5222 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5223 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5225 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5226 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5227 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5228 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5231 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5232 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5233 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5235 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5236 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5237 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5240 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5241 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5242 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5243 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5244 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5245 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5246 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5247 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5248 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5249 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5250 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5251 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5253 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5254 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5255 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5256 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5257 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5258 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5259 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5260 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5261 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5262 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5263 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5264 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5266 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5267 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5268 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5269 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5270 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5271 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5272 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5273 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5276 int ventoy_register_all_cmd(void)
5279 cmd_para
*cur
= NULL
;
5281 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5283 cur
= ventoy_cmds
+ i
;
5284 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5285 cur
->summary
, cur
->description
, cur
->parser
);
5291 int ventoy_unregister_all_cmd(void)
5295 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5297 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);