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 initrd_info
*g_initrd_img_list
= NULL
;
55 initrd_info
*g_initrd_img_tail
= NULL
;
56 int g_initrd_img_count
= 0;
57 int g_valid_initrd_count
= 0;
58 int g_default_menu_mode
= 0;
59 int g_filt_dot_underscore_file
= 0;
60 int g_sort_case_sensitive
= 0;
61 int g_tree_view_menu_style
= 0;
62 static grub_file_t g_old_file
;
63 static int g_ventoy_last_entry_back
;
66 char g_img_swap_tmp_buf
[1024];
67 img_info g_img_swap_tmp
;
68 img_info
*g_ventoy_img_list
= NULL
;
70 int g_ventoy_img_count
= 0;
72 grub_device_t g_enum_dev
= NULL
;
73 grub_fs_t g_enum_fs
= NULL
;
74 int g_img_max_search_level
= -1;
75 img_iterator_node g_img_iterator_head
;
76 img_iterator_node
*g_img_iterator_tail
= NULL
;
78 grub_uint8_t g_ventoy_break_level
= 0;
79 grub_uint8_t g_ventoy_debug_level
= 0;
80 grub_uint8_t g_ventoy_chain_type
= 0;
82 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
83 grub_uint32_t g_ventoy_cpio_size
= 0;
84 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
85 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
87 int g_plugin_image_list
= 0;
89 ventoy_grub_param
*g_grub_param
= NULL
;
91 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
93 ventoy_img_chunk_list g_img_chunk_list
;
95 int g_wimboot_enable
= 0;
96 ventoy_img_chunk_list g_wimiso_chunk_list
;
97 char *g_wimiso_path
= NULL
;
99 int g_vhdboot_enable
= 0;
101 grub_uint64_t g_conf_replace_offset
= 0;
102 grub_uint64_t g_svd_replace_offset
= 0;
103 conf_replace
*g_conf_replace_node
= NULL
;
104 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
105 int g_conf_replace_new_len
= 0;
106 int g_conf_replace_new_len_align
= 0;
108 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
109 grub_uint64_t g_ventoy_disk_size
= 0;
110 grub_uint64_t g_ventoy_disk_part_size
[2];
112 static char *g_tree_script_buf
= NULL
;
113 static int g_tree_script_pos
= 0;
115 static char *g_list_script_buf
= NULL
;
116 static int g_list_script_pos
= 0;
118 static char *g_part_list_buf
= NULL
;
119 static int g_part_list_pos
= 0;
121 static int g_video_mode_max
= 0;
122 static int g_video_mode_num
= 0;
123 static ventoy_video_mode
*g_video_mode_list
= NULL
;
125 static int g_enumerate_time_checked
= 0;
126 static grub_uint64_t g_enumerate_start_time_ms
;
127 static grub_uint64_t g_enumerate_finish_time_ms
;
128 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
130 static const char *g_menu_class
[] =
132 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
135 static const char *g_menu_prefix
[] =
137 "iso", "wim", "efi", "img", "vhd", "vtoy"
140 static int ventoy_get_fs_type(const char *fs
)
144 return ventoy_fs_max
;
146 else if (grub_strncmp(fs
, "exfat", 5) == 0)
148 return ventoy_fs_exfat
;
150 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
152 return ventoy_fs_ntfs
;
154 else if (grub_strncmp(fs
, "ext", 3) == 0)
156 return ventoy_fs_ext
;
158 else if (grub_strncmp(fs
, "xfs", 3) == 0)
160 return ventoy_fs_xfs
;
162 else if (grub_strncmp(fs
, "udf", 3) == 0)
164 return ventoy_fs_udf
;
166 else if (grub_strncmp(fs
, "fat", 3) == 0)
168 return ventoy_fs_fat
;
171 return ventoy_fs_max
;
174 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
193 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
195 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
199 static int ventoy_control_get_flag(const char *key
)
201 const char *val
= ventoy_get_env(key
);
203 if (val
&& val
[0] == '1' && val
[1] == 0)
210 static grub_err_t
ventoy_fs_close(grub_file_t file
)
212 grub_file_close(g_old_file
);
213 grub_free(file
->data
);
221 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
227 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
232 for (i
= 0; i
< g_video_mode_num
; i
++)
234 if (g_video_mode_list
[i
].width
== info
->width
&&
235 g_video_mode_list
[i
].height
== info
->height
&&
236 g_video_mode_list
[i
].bpp
== info
->bpp
)
242 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
243 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
244 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
247 if (g_video_mode_num
== g_video_mode_max
)
249 g_video_mode_max
*= 2;
250 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
256 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
258 if (v1
->bpp
== v2
->bpp
)
260 if (v1
->width
== v2
->width
)
262 if (v1
->height
== v2
->height
)
268 return (v1
->height
< v2
->height
) ? -1 : 1;
273 return (v1
->width
< v2
->width
) ? -1 : 1;
278 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
282 static int ventoy_enum_video_mode(void)
285 grub_video_adapter_t adapter
;
286 grub_video_driver_id_t id
;
287 ventoy_video_mode mode
;
289 g_video_mode_num
= 0;
290 g_video_mode_max
= 1024;
291 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
292 if (!g_video_mode_list
)
297 #ifdef GRUB_MACHINE_PCBIOS
298 grub_dl_load ("vbe");
301 id
= grub_video_get_driver_id ();
303 FOR_VIDEO_ADAPTERS (adapter
)
305 if (!adapter
->iterate
||
306 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
307 adapter
->init() != GRUB_ERR_NONE
)))
312 adapter
->iterate(ventoy_video_hook
, NULL
);
314 if (adapter
->id
!= id
)
320 /* sort video mode */
321 for (i
= 0; i
< g_video_mode_num
; i
++)
322 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
324 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
326 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
327 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
328 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
332 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
335 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
339 static struct grub_fs vtoy_fs
=
344 .fs_read
= ventoy_fs_read
,
345 .fs_close
= ventoy_fs_close
,
355 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
361 file
->data
= grub_malloc(rawFile
->size
+ 4096);
367 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
368 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
370 g_old_file
= rawFile
;
372 file
->size
= rawFile
->size
+ len
;
373 file
->device
= rawFile
->device
;
375 file
->not_easily_seekable
= 1;
380 static int ventoy_check_decimal_var(const char *name
, long *value
)
382 const char *value_str
= NULL
;
384 value_str
= grub_env_get(name
);
385 if (NULL
== value_str
)
387 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
390 if (!ventoy_is_decimal(value_str
))
392 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
395 *value
= grub_strtol(value_str
, NULL
, 10);
397 return GRUB_ERR_NONE
;
400 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
402 grub_uint64_t sectors
;
404 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
406 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
410 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
413 return sectors
* 512;
416 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
422 grub_uint32_t offset
;
424 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
427 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
431 len
= (int)file
->size
;
433 data
= (char *)grub_malloc(file
->size
);
439 grub_file_read(file
, data
, file
->size
);
440 grub_file_close(file
);
442 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
443 grub_script_execute_sourcecode(exec
);
445 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
446 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
447 grub_file_close(file
);
449 grub_script_execute_sourcecode("loopback -d efiboot");
453 *direntoff
= offset
+ 2;
458 static int ventoy_set_check_result(int ret
)
462 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
463 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
464 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
468 grub_printf(VTOY_WARNING
"\n");
469 grub_printf(VTOY_WARNING
"\n");
470 grub_printf(VTOY_WARNING
"\n\n\n");
472 grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret
);
473 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
475 grub_printf("\n\nWill exit after 10 seconds ...... ");
483 static int ventoy_check_official_device(grub_device_t dev
)
487 grub_uint64_t offset
;
492 struct grub_partition
*partition
;
494 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
496 return ventoy_set_check_result(1 | 0x1000);
499 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
500 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
501 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
503 #ifndef GRUB_MACHINE_EFI
504 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
505 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
506 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
508 return ventoy_set_check_result(2 | 0x1000);
517 /* We must have partition 2 */
520 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
524 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
528 return ventoy_set_check_result(3 | 0x1000);
531 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
533 grub_file_close(file
);
534 return ventoy_set_check_result(4 | 0x1000);
537 partition
= dev
->disk
->partition
;
538 if (partition
->number
!= 0 || partition
->start
!= 2048)
540 return ventoy_set_check_result(5);
545 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
547 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
548 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
549 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
551 grub_file_close(file
);
552 return ventoy_set_check_result(6);
557 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
558 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
559 PartTbl
[1].SectorCount
!= 65536)
561 grub_file_close(file
);
562 return ventoy_set_check_result(6);
568 offset
= partition
->start
+ partition
->len
;
569 partition
= file
->device
->disk
->partition
;
570 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
572 grub_file_close(file
);
573 return ventoy_set_check_result(7);
577 grub_file_close(file
);
581 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
582 dev2
= grub_device_open(devname
);
585 return ventoy_set_check_result(8);
588 fs
= grub_fs_probe(dev2
);
591 grub_device_close(dev2
);
592 return ventoy_set_check_result(9);
595 fs
->fs_label(dev2
, &label
);
596 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
598 grub_device_close(dev2
);
599 return ventoy_set_check_result(10);
602 grub_device_close(dev2
);
605 return ventoy_set_check_result(0);
608 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
612 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
622 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
624 grub_uint64_t size
= 0;
627 char fullpath
[256] = {0};
630 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
633 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
636 debug("grub_file_open failed <%s>\n", fullpath
);
642 grub_file_close(file
);
646 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
650 char fullpath
[256] = {0};
653 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
656 file
= grub_file_open(fullpath
, type
);
659 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
666 int ventoy_is_file_exist(const char *fmt
, ...)
673 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
677 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
680 grub_strncpy(pos
+ len
, "\" ]", 3);
682 debug("script exec %s\n", buf
);
684 if (0 == grub_script_execute_sourcecode(buf
))
692 int ventoy_is_dir_exist(const char *fmt
, ...)
699 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
703 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
706 grub_strncpy(pos
+ len
, "\" ]", 3);
708 debug("script exec %s\n", buf
);
710 if (0 == grub_script_execute_sourcecode(buf
))
718 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
721 grub_uint8_t
*outbuf
;
722 grub_uint8_t gzHdr
[10] =
724 0x1F, 0x8B, /* magic */
732 grub_memset(&s
, 0, sizeof(mz_stream
));
734 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
736 outbuf
= (grub_uint8_t
*)mem_out
;
738 mem_out_len
-= sizeof(gzHdr
) + 8;
739 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
740 outbuf
+= sizeof(gzHdr
);
742 s
.avail_in
= mem_in_len
;
745 s
.avail_out
= mem_out_len
;
748 mz_deflate(&s
, MZ_FINISH
);
752 outbuf
+= s
.total_out
;
753 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
754 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
756 return s
.total_out
+ sizeof(gzHdr
) + 8;
764 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
768 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
771 if (0 == grub_strcmp(args
[0], "on"))
774 grub_env_set("vtdebug_flag", "debug");
779 grub_env_set("vtdebug_flag", "");
782 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
785 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
789 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
791 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
792 grub_printf(" level:\r\n");
793 grub_printf(" 01/11: busybox / (+cat log)\r\n");
794 grub_printf(" 02/12: initrd / (+cat log)\r\n");
795 grub_printf(" 03/13: hook / (+cat log)\r\n");
797 grub_printf(" debug:\r\n");
798 grub_printf(" 0: debug is off\r\n");
799 grub_printf(" 1: debug is on\r\n");
801 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
804 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
806 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
808 g_ventoy_debug_level
= 1;
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
814 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
823 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
826 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
858 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
863 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
865 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
868 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
873 value_long
+= grub_strtol(args
[1], NULL
, 10);
875 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
876 grub_env_set(args
[0], buf
);
878 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
881 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
883 ulonglong value1
= 0;
884 ulonglong value2
= 0;
889 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
892 value1
= grub_strtoull(args
[0], NULL
, 10);
893 value2
= grub_strtoull(args
[1], NULL
, 10);
895 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
896 grub_env_set(args
[2], buf
);
898 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
901 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
916 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
919 debug("failed to open file <%s> for udf check\n", args
[0]);
923 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
925 grub_env_set(args
[1], buf
);
927 grub_file_close(file
);
933 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
941 g_wimboot_enable
= 0;
942 grub_check_free(g_wimiso_path
);
943 grub_check_free(g_wimiso_chunk_list
.chunk
);
945 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
951 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
952 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
953 if (NULL
== g_wimiso_chunk_list
.chunk
)
955 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
958 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
959 g_wimiso_chunk_list
.cur_chunk
= 0;
961 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
963 g_wimboot_enable
= 1;
964 g_wimiso_path
= grub_strdup(args
[0]);
966 grub_file_close(file
);
971 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
981 ventoy_iso9660_override
*dirent
;
990 totlen
= sizeof(ventoy_chain_head
);
992 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
994 debug("failed to load efiboot template %d\n", len
);
1000 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1002 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1005 debug("failed to open file <%s>\n", args
[0]);
1009 totlen
+= ventoy_align_2k(file
->size
);
1011 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1012 dirent
->first_sector
= len
/ 2048;
1013 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1014 dirent
->size
= (grub_uint32_t
)file
->size
;
1015 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1017 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1019 #ifdef GRUB_MACHINE_EFI
1020 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1022 data
= (char *)grub_malloc(totlen
);
1025 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1027 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1028 grub_check_free(buf
);
1030 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1031 grub_file_close(file
);
1033 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1034 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1035 grub_env_set(name
, value
);
1037 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1038 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1039 grub_env_set(name
, value
);
1044 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1061 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1064 debug("failed to open file <%s>\n", args
[0]);
1068 #ifdef GRUB_MACHINE_EFI
1069 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
1071 buf
= (char *)grub_malloc(file
->size
);
1074 grub_file_read(file
, buf
, file
->size
);
1076 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1077 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1078 grub_env_set(name
, value
);
1080 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1081 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1082 grub_env_set(name
, value
);
1084 grub_file_close(file
);
1090 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1108 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1111 debug("failed to open file <%s> for udf check\n", args
[0]);
1115 headlen
= sizeof(ventoy_chain_head
);
1117 #ifdef GRUB_MACHINE_EFI
1118 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1120 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1123 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1125 grub_file_read(file
, buf
+ headlen
, file
->size
);
1127 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1128 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1129 grub_env_set(name
, value
);
1131 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1132 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1133 grub_env_set(name
, value
);
1135 grub_file_close(file
);
1141 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1150 if (args
[0][0] == '1')
1152 grub_iso9660_set_nojoliet(1);
1156 grub_iso9660_set_nojoliet(0);
1162 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1167 grub_uint8_t buf
[32];
1178 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1181 debug("failed to open file <%s> for udf check\n", args
[0]);
1185 for (i
= 16; i
< 32; i
++)
1187 grub_file_seek(file
, i
* 2048);
1188 grub_file_read(file
, buf
, sizeof(buf
));
1196 grub_file_seek(file
, i
* 2048);
1197 grub_file_read(file
, buf
, sizeof(buf
));
1199 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1202 grub_file_seek(file
, i
* 2048);
1203 grub_file_read(file
, buf
, sizeof(buf
));
1205 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1206 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1212 grub_file_close(file
);
1214 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1219 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1221 long value_long1
= 0;
1222 long value_long2
= 0;
1224 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1226 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1229 value_long1
= grub_strtol(args
[0], NULL
, 10);
1230 value_long2
= grub_strtol(args
[2], NULL
, 10);
1232 if (0 == grub_strcmp(args
[1], "eq"))
1234 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1236 else if (0 == grub_strcmp(args
[1], "ne"))
1238 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1240 else if (0 == grub_strcmp(args
[1], "gt"))
1242 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1244 else if (0 == grub_strcmp(args
[1], "lt"))
1246 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1248 else if (0 == grub_strcmp(args
[1], "ge"))
1250 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1252 else if (0 == grub_strcmp(args
[1], "le"))
1254 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1258 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1264 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1267 char buf
[128] = {0};
1271 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1274 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1275 pos
= grub_strstr(buf
, ",");
1281 grub_env_set(args
[1], buf
);
1283 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1286 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1292 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1298 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1301 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1303 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1304 if (0 == grub_script_execute_sourcecode(buf
))
1306 debug("file %s exist, ventoy_compatible YES\n", buf
);
1307 grub_env_set("ventoy_compatible", "YES");
1308 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1312 debug("file %s NOT exist\n", buf
);
1316 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1317 pos
= grub_strstr(buf
, ")");
1323 disk
= grub_disk_open(buf
);
1326 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1327 grub_disk_close(disk
);
1329 g_img_swap_tmp_buf
[703] = 0;
1330 for (i
= 318; i
< 703; i
++)
1332 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1333 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1335 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1336 grub_env_set("ventoy_compatible", "YES");
1337 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1343 debug("failed to open disk <%s>\n", buf
);
1346 grub_env_set("ventoy_compatible", "NO");
1347 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1350 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1356 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1358 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1361 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1366 if (0 == g_sort_case_sensitive
)
1368 if (grub_islower(c1
))
1370 c1
= c1
- 'a' + 'A';
1373 if (grub_islower(c2
))
1375 c2
= c2
- 'a' + 'A';
1388 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1394 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1396 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1399 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1404 if (0 == g_sort_case_sensitive
)
1406 if (grub_islower(c1
))
1408 c1
= c1
- 'a' + 'A';
1411 if (grub_islower(c2
))
1413 c2
= c2
- 'a' + 'A';
1426 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1428 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1430 grub_memcpy(img1
, img2
, sizeof(img_info
));
1431 img1
->next
= g_img_swap_tmp
.next
;
1432 img1
->prev
= g_img_swap_tmp
.prev
;
1434 g_img_swap_tmp
.next
= img2
->next
;
1435 g_img_swap_tmp
.prev
= img2
->prev
;
1436 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1439 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1443 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1451 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1460 img_iterator_node
*tmp
;
1461 img_iterator_node
*new_node
;
1462 img_iterator_node
*node
= (img_iterator_node
*)data
;
1464 if (g_enumerate_time_checked
== 0)
1466 g_enumerate_finish_time_ms
= grub_get_time_ms();
1467 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1470 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1472 g_enumerate_time_checked
= 1;
1476 len
= grub_strlen(filename
);
1480 if (node
->level
+ 1 > g_img_max_search_level
)
1485 if ((len
== 1 && filename
[0] == '.') ||
1486 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1491 if (!ventoy_img_name_valid(filename
, len
))
1496 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1501 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1503 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1504 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1507 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1512 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1515 new_node
->level
= node
->level
+ 1;
1516 new_node
->plugin_list_index
= index
;
1517 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1519 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1522 debug("Directory %s ignored...\n", new_node
->dir
);
1523 grub_free(new_node
);
1527 new_node
->tail
= node
->tail
;
1529 new_node
->parent
= node
;
1530 if (!node
->firstchild
)
1532 node
->firstchild
= new_node
;
1535 if (g_img_iterator_tail
)
1537 g_img_iterator_tail
->next
= new_node
;
1538 g_img_iterator_tail
= new_node
;
1542 g_img_iterator_head
.next
= new_node
;
1543 g_img_iterator_tail
= new_node
;
1549 debug("Find a file %s\n", filename
);
1555 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1557 type
= img_type_iso
;
1559 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1561 type
= img_type_wim
;
1563 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1564 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1566 type
= img_type_vhd
;
1568 #ifdef GRUB_MACHINE_EFI
1569 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1571 type
= img_type_efi
;
1574 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1576 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1578 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1579 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1584 type
= img_type_img
;
1586 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1588 type
= img_type_vtoy
;
1590 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1592 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1594 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1595 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1604 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1609 if (g_plugin_image_list
)
1611 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1612 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1613 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1615 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1618 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1620 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1625 img
= grub_zalloc(sizeof(img_info
));
1629 img
->plugin_list_index
= index
;
1630 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1632 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1634 img
->size
= info
->size
;
1637 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1640 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1642 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1647 if (g_ventoy_img_list
)
1649 tail
= *(node
->tail
);
1655 g_ventoy_img_list
= img
;
1658 img
->id
= g_ventoy_img_count
;
1660 if (node
&& NULL
== node
->firstiso
)
1662 node
->firstiso
= img
;
1673 *((img_info
**)(node
->tail
)) = img
;
1674 g_ventoy_img_count
++;
1676 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1677 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1680 img
->class = g_menu_class
[type
];
1682 img
->menu_prefix
= g_menu_prefix
[type
];
1684 if (img_type_iso
== type
)
1686 if (ventoy_plugin_check_memdisk(img
->path
))
1688 img
->menu_prefix
= "miso";
1692 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1699 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1701 int len
= GRUB_UINT_MAX
;
1702 const char *value
= NULL
;
1703 char name
[32] = {0};
1704 char plat
[32] = {0};
1705 char guidstr
[32] = {0};
1706 ventoy_guid guid
= VENTOY_GUID
;
1707 const char *fmt1
= NULL
;
1708 const char *fmt2
= NULL
;
1709 const char *fmt3
= NULL
;
1710 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1711 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1712 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1713 const char fmtcode
[]={
1714 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1715 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1716 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1717 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1718 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1719 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1722 grub_memset(name
, 0, sizeof(name
));
1723 puint
[0] = grub_swap_bytes32(0x56454e54);
1724 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1725 puint
[2] = grub_swap_bytes32(0x45525349);
1726 puint
[1] = grub_swap_bytes32(0x4f595f56);
1727 value
= ventoy_get_env(name
);
1729 grub_memset(name
, 0, sizeof(name
));
1730 puint
[1] = grub_swap_bytes32(0x5f544f50);
1731 puint
[0] = grub_swap_bytes32(0x56544c45);
1732 fmt1
= ventoy_get_env(name
);
1738 grub_memset(name
, 0, sizeof(name
));
1739 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1740 puint
[0] = grub_swap_bytes32(0x56544c45);
1741 fmt2
= ventoy_get_env(name
);
1743 grub_memset(name
, 0, sizeof(name
));
1744 puint
[1] = grub_swap_bytes32(0x5f434c52);
1745 puint
[0] = grub_swap_bytes32(0x56544c45);
1746 fmt3
= ventoy_get_env(name
);
1748 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1750 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1752 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1753 #pragma GCC diagnostic push
1754 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1755 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1756 fmt1
? fmt1
: fmtdata
,
1757 fmt2
? fmt2
: fmtdata
+ 4,
1758 value
? value
: "", plat
, guidstr
,
1759 fmt3
? fmt3
: fmtdata
+ 6);
1760 #pragma GCC diagnostic pop
1762 grub_memset(name
, 0, sizeof(name
));
1763 puint
[0] = grub_swap_bytes32(0x76746f79);
1764 puint
[2] = grub_swap_bytes32(0x656e7365);
1765 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1766 ventoy_set_env(name
, guidstr
);
1771 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1775 grub_uint8_t md5
[16];
1779 grub_memset(input
, 0, sizeof(input
));
1781 grub_printf("Enter password: ");
1784 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1786 grub_password_get(input
, 128);
1787 if (grub_strcmp(pwd
->text
, input
) == 0)
1792 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1794 grub_password_get(input
, 128);
1795 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1796 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1801 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1803 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1804 grub_password_get(input
+ offset
, 128);
1806 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1807 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1813 grub_printf("Invalid password!\n\n");
1820 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1822 img_info
*minimg
= NULL
;
1823 img_info
*img
= (img_info
*)(node
->firstiso
);
1825 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1827 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1842 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1844 img_iterator_node
*Minchild
= NULL
;
1845 img_iterator_node
*child
= node
->firstchild
;
1847 while (child
&& child
->parent
== node
)
1849 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1853 child
= child
->next
;
1858 Minchild
->select
= 1;
1864 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1867 img_info
*img
= NULL
;
1868 const char *dir_class
= NULL
;
1869 const char *dir_alias
= NULL
;
1870 img_iterator_node
*child
= NULL
;
1872 if (node
->isocnt
== 0 || node
->done
== 1)
1877 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1879 offset
= node
->parent
->dirlen
;
1882 if (node
== &g_img_iterator_head
)
1884 if (g_default_menu_mode
== 0)
1886 if (g_tree_view_menu_style
== 0)
1888 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1889 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1890 " echo 'return ...' \n"
1895 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1896 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1904 node
->dir
[node
->dirlen
- 1] = 0;
1905 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
1908 dir_class
= "vtoydir";
1911 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1914 if (g_tree_view_menu_style
== 0)
1916 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1917 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1918 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1922 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1923 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1924 dir_alias
, dir_class
, node
->dir
+ offset
);
1929 dir_alias
= node
->dir
+ offset
;
1931 if (g_tree_view_menu_style
== 0)
1933 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1934 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1935 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
1939 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1940 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1941 dir_alias
, dir_class
, node
->dir
+ offset
);
1945 if (g_tree_view_menu_style
== 0)
1947 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1948 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1949 " echo 'return ...' \n"
1954 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1955 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1961 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1963 ventoy_dynamic_tree_menu(child
);
1966 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1968 if (g_tree_view_menu_style
== 0)
1970 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1971 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1974 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1975 img
->unsupport
? "[***********] " : "",
1976 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1978 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1982 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1983 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1986 img
->unsupport
? "[***********] " : "",
1987 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1989 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1993 if (node
!= &g_img_iterator_head
)
1995 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2002 static int ventoy_set_default_menu(void)
2008 const char *strdata
= NULL
;
2009 img_info
*cur
= NULL
;
2010 img_info
*default_node
= NULL
;
2011 const char *default_image
= NULL
;
2013 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2014 if (default_image
&& default_image
[0] == '/')
2016 img_len
= grub_strlen(default_image
);
2018 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2020 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2032 if (0 == g_default_menu_mode
)
2034 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
2038 def
= grub_strdup(default_image
);
2044 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2046 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2047 if (strdata
&& strdata
[0] == '/')
2049 pos
= def
+ grub_strlen(strdata
);
2060 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2063 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2067 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
2075 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2077 img_info
*next
= NULL
;
2078 img_info
*cur
= g_ventoy_img_list
;
2091 g_ventoy_img_list
= NULL
;
2092 g_ventoy_img_count
= 0;
2094 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2097 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2100 img_info
*cur
= g_ventoy_img_list
;
2104 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2106 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2109 img_id
= grub_strtol(args
[0], NULL
, 10);
2110 if (img_id
>= g_ventoy_img_count
)
2112 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2115 debug("Find image %ld name \n", img_id
);
2117 while (cur
&& img_id
> 0)
2125 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2128 debug("image name is %s\n", cur
->name
);
2130 grub_env_set(args
[1], cur
->name
);
2132 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2135 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2139 img_info
*cur
= g_ventoy_img_list
;
2145 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2148 len
= (int)grub_strlen(args
[0]);
2152 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2161 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2164 grub_snprintf(id
, sizeof(id
), "VID_%d", cur
->id
);
2165 grub_env_set("chosen", id
);
2166 grub_env_export("chosen");
2168 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2171 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2176 const char *id
= NULL
;
2177 img_info
*cur
= g_ventoy_img_list
;
2181 if (argc
< 1 || argc
> 2)
2183 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2186 id
= grub_env_get("chosen");
2188 pos
= grub_strstr(id
, "VID_");
2191 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2195 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2200 if (img_id
== cur
->id
)
2209 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2212 grub_env_set(args
[0], cur
->path
);
2216 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2217 grub_env_set(args
[1], value
);
2220 g_svd_replace_offset
= 0;
2222 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2226 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2230 grub_device_t dev
= NULL
;
2231 img_info
*cur
= NULL
;
2232 img_info
*tail
= NULL
;
2233 const char *strdata
= NULL
;
2234 char *device_name
= NULL
;
2236 img_iterator_node
*node
= NULL
;
2237 img_iterator_node
*tmp
= NULL
;
2243 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2246 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2248 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2253 g_enumerate_time_checked
= 0;
2254 g_enumerate_start_time_ms
= grub_get_time_ms();
2256 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2257 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2259 g_filt_dot_underscore_file
= 1;
2262 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2263 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2265 g_sort_case_sensitive
= 1;
2268 device_name
= grub_file_get_device_name(args
[0]);
2274 g_enum_dev
= dev
= grub_device_open(device_name
);
2280 g_enum_fs
= fs
= grub_fs_probe(dev
);
2286 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2288 debug("unsupported fs:<%s>\n", fs
->name
);
2289 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2293 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2295 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2296 if (strdata
&& strdata
[0] == '1')
2298 g_default_menu_mode
= 1;
2301 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2303 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2305 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2306 if (strdata
&& strdata
[0] == '/')
2308 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2309 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2311 g_img_iterator_head
.dir
[len
++] = '/';
2313 g_img_iterator_head
.dirlen
= len
;
2317 g_img_iterator_head
.dirlen
= 1;
2318 grub_strcpy(g_img_iterator_head
.dir
, "/");
2321 g_img_iterator_head
.tail
= &tail
;
2323 if (g_img_max_search_level
< 0)
2325 g_img_max_search_level
= GRUB_INT_MAX
;
2326 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2327 if (strdata
&& ventoy_is_decimal(strdata
))
2329 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2333 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2334 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2335 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2336 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2337 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2338 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2340 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2342 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2345 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2346 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2348 g_tree_view_menu_style
= 1;
2351 ventoy_set_default_menu();
2353 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2355 ventoy_dynamic_tree_menu(node
);
2359 node
= g_img_iterator_head
.next
;
2367 /* sort image list by image name */
2368 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2370 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2372 if (ventoy_cmp_img(cur
, tail
) > 0)
2374 ventoy_swap_img(cur
, tail
);
2379 if (g_default_menu_mode
== 1)
2381 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2382 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2383 " echo 'return ...' \n"
2387 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2389 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2390 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2393 cur
->unsupport
? "[***********] " : "",
2394 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2396 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2399 g_tree_script_buf
[g_tree_script_pos
] = 0;
2400 g_list_script_buf
[g_list_script_pos
] = 0;
2402 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2403 grub_env_set(args
[1], buf
);
2407 check_free(device_name
, grub_free
);
2408 check_free(dev
, grub_device_close
);
2410 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2413 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2420 device_name
= grub_file_get_device_name(filename
);
2432 pos2
= grub_strstr(pos
, ",");
2435 pos2
= grub_strstr(pos
, ")");
2443 disk
= grub_disk_open(pos
);
2446 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2447 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2448 grub_disk_close(disk
);
2455 grub_free(device_name
);
2459 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2461 eltorito_descriptor desc
;
2463 grub_memset(&desc
, 0, sizeof(desc
));
2464 grub_file_seek(file
, 17 * 2048);
2465 grub_file_read(file
, &desc
, sizeof(desc
));
2467 if (desc
.type
!= 0 || desc
.version
!= 1)
2472 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2473 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2481 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2485 grub_uint8_t buf
[512];
2486 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2488 grub_file_seek(file
, sector
* 2048);
2489 grub_file_read(file
, buf
, sizeof(buf
));
2491 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2493 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2497 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2502 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2504 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2506 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2510 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2512 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2517 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2519 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2521 if (buf
[36] == parttype
[i
])
2523 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2529 debug("%s does not contain efi eltorito\n", file
->name
);
2533 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2536 const char *fs
= NULL
;
2537 const char *cdprompt
= NULL
;
2539 grub_uint8_t chksum
= 0;
2542 disk
= file
->device
->disk
;
2543 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2545 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2546 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2547 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2549 pos
= grub_strstr(file
->name
, "/");
2555 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2557 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2559 param
->vtoy_img_size
= file
->size
;
2561 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2562 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2564 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2566 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2567 param
->vtoy_reserved
[4] = 0;
2568 if (g_ventoy_chain_type
== 1) /* Windows */
2570 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2571 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2573 param
->vtoy_reserved
[4] = 1;
2577 fs
= ventoy_get_env("ventoy_fs_probe");
2578 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2580 param
->vtoy_reserved
[3] = 1;
2583 /* calculate checksum */
2584 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2586 chksum
+= *((grub_uint8_t
*)param
+ i
);
2588 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2593 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2595 grub_uint32_t i
= 0;
2596 grub_uint64_t total
= 0;
2597 grub_uint64_t fileblk
= 0;
2598 ventoy_img_chunk
*chunk
= NULL
;
2600 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2602 chunk
= chunklist
->chunk
+ i
;
2604 if (chunk
->disk_start_sector
<= start
)
2606 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2610 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2613 fileblk
= (file
->size
+ 511) / 512;
2615 if (total
!= fileblk
)
2617 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2618 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2620 debug("maybe img file to be processed.\n");
2630 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2634 grub_uint32_t i
= 0;
2635 grub_uint32_t sector
= 0;
2636 grub_uint32_t count
= 0;
2637 grub_off_t size
= 0;
2638 grub_off_t read
= 0;
2640 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2641 if (fs_type
== ventoy_fs_exfat
)
2643 grub_fat_get_file_chunk(start
, file
, chunklist
);
2645 else if (fs_type
== ventoy_fs_ext
)
2647 grub_ext_get_file_chunk(start
, file
, chunklist
);
2651 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2652 file
->read_hook_data
= chunklist
;
2654 for (size
= file
->size
; size
> 0; size
-= read
)
2656 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2657 grub_file_read(file
, NULL
, read
);
2660 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2662 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2663 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2666 if (ventoy_fs_udf
== fs_type
)
2668 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2670 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2671 chunklist
->chunk
[i
].img_start_sector
= sector
;
2672 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2678 len
= (int)grub_strlen(file
->name
);
2679 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2680 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2681 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2682 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2684 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2686 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2696 chunklist
->chunk
[i
].img_start_sector
= sector
;
2697 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2705 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2709 grub_disk_addr_t start
;
2714 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2717 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2720 g_conf_replace_node
= NULL
;
2721 g_conf_replace_offset
= 0;
2723 if (g_img_chunk_list
.chunk
)
2725 grub_free(g_img_chunk_list
.chunk
);
2728 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2730 grub_file_close(file
);
2731 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2734 /* get image chunk data */
2735 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2736 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2737 if (NULL
== g_img_chunk_list
.chunk
)
2739 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2742 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2743 g_img_chunk_list
.cur_chunk
= 0;
2745 start
= file
->device
->disk
->partition
->start
;
2747 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2749 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2750 grub_file_close(file
);
2754 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2757 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2758 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2761 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2763 grub_uint64_t offset
= 0;
2764 grub_uint32_t align
= 0;
2765 grub_file_t file
= NULL
;
2766 conf_replace
*node
= NULL
;
2772 debug("select conf replace argc:%d\n", argc
);
2779 node
= ventoy_plugin_find_conf_replace(args
[1]);
2782 debug("Conf replace not found for %s\n", args
[1]);
2786 debug("Find conf replace for %s\n", args
[1]);
2788 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2791 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2795 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2796 grub_file_close(file
);
2798 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2801 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2805 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2807 if (align
> vtoy_max_replace_file_size
)
2809 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2813 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2814 g_conf_replace_new_len
= (int)file
->size
;
2815 g_conf_replace_new_len_align
= align
;
2817 g_conf_replace_node
= node
;
2818 g_conf_replace_offset
= offset
+ 2;
2820 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2825 grub_file_close(file
);
2827 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2830 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2835 char configfile
[128];
2836 install_template
*node
= NULL
;
2842 debug("select auto installation argc:%d\n", argc
);
2849 node
= ventoy_plugin_find_install_template(args
[0]);
2852 debug("Auto install template not found for %s\n", args
[0]);
2856 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2858 node
->cursel
= node
->autosel
- 1;
2859 debug("Auto install template auto select %d\n", node
->autosel
);
2863 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2869 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2870 " echo %s\n}\n", "123");
2872 for (i
= 0; i
< node
->templatenum
; i
++)
2874 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2876 node
->templatepath
[i
].path
);
2879 g_ventoy_menu_esc
= 1;
2880 g_ventoy_suppress_esc
= 1;
2882 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2883 grub_script_execute_sourcecode(configfile
);
2885 g_ventoy_menu_esc
= 0;
2886 g_ventoy_suppress_esc
= 0;
2890 node
->cursel
= g_ventoy_last_entry
- 1;
2892 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2895 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2900 char configfile
[128];
2901 persistence_config
*node
;
2907 debug("select persistence argc:%d\n", argc
);
2914 node
= ventoy_plugin_find_persistent(args
[0]);
2917 debug("Persistence image not found for %s\n", args
[0]);
2921 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2923 node
->cursel
= node
->autosel
- 1;
2924 debug("Persistence image auto select %d\n", node
->autosel
);
2928 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2934 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2935 " echo %s\n}\n", "123");
2937 for (i
= 0; i
< node
->backendnum
; i
++)
2939 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2941 node
->backendpath
[i
].path
);
2945 g_ventoy_menu_esc
= 1;
2946 g_ventoy_suppress_esc
= 1;
2948 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2949 grub_script_execute_sourcecode(configfile
);
2951 g_ventoy_menu_esc
= 0;
2952 g_ventoy_suppress_esc
= 0;
2956 node
->cursel
= g_ventoy_last_entry
- 1;
2958 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2961 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2964 ventoy_img_chunk
*cur
;
2970 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2972 cur
= g_img_chunk_list
.chunk
+ i
;
2973 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2974 cur
->img_start_sector
, cur
->img_end_sector
,
2975 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2979 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2982 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2986 ventoy_img_chunk_list chunklist
;
2991 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2994 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2997 /* get image chunk data */
2998 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2999 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3000 if (NULL
== chunklist
.chunk
)
3002 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3005 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3006 chunklist
.cur_chunk
= 0;
3008 ventoy_get_block_list(file
, &chunklist
, 0);
3010 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3012 grub_printf("########## UNSUPPORTED ###############\n");
3015 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3017 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3019 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3020 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3023 grub_printf("\n==================================\n");
3025 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3027 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3028 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3029 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3030 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3031 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3035 grub_free(chunklist
.chunk
);
3036 grub_file_close(file
);
3038 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3041 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3044 ventoy_grub_param_file_replace
*replace
= NULL
;
3052 replace
= &(g_grub_param
->file_replace
);
3053 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3055 replace
->old_name_cnt
= 0;
3056 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3058 replace
->old_name_cnt
++;
3059 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3062 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3065 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3068 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3076 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3077 grub_printf("%s", g_list_script_buf
);
3081 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3082 grub_printf("%s", g_tree_script_buf
);
3088 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3090 img_info
*cur
= g_ventoy_img_list
;
3098 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3099 grub_printf("name:<%s>\n\n", cur
->name
);
3106 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3112 ventoy_plugin_dump_injection();
3117 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3123 ventoy_plugin_dump_auto_install();
3128 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3134 ventoy_plugin_dump_persistence();
3139 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3150 if (args
[0][0] == '0')
3152 return g_ventoy_memdisk_mode
? 0 : 1;
3154 else if (args
[0][0] == '1')
3156 return g_ventoy_iso_raw
? 0 : 1;
3158 else if (args
[0][0] == '2')
3160 return g_ventoy_iso_uefi_drv
? 0 : 1;
3162 else if (args
[0][0] == '3')
3164 return g_ventoy_grub2_mode
? 0 : 1;
3170 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3172 static int configfile_mode
= 0;
3173 char memfile
[128] = {0};
3180 * args[0]: 0:normal 1:configfile
3181 * args[1]: 0:list_buf 1:tree_buf
3186 debug("Invalid argc %d\n", argc
);
3192 if (args
[0][0] == '0')
3194 if (args
[1][0] == '0')
3196 grub_script_execute_sourcecode(g_list_script_buf
);
3200 grub_script_execute_sourcecode(g_tree_script_buf
);
3205 if (configfile_mode
)
3207 debug("Now already in F3 mode %d\n", configfile_mode
);
3211 if (args
[1][0] == '0')
3213 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3214 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3218 g_ventoy_last_entry
= -1;
3219 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3220 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3223 configfile_mode
= 1;
3224 grub_script_execute_sourcecode(memfile
);
3225 configfile_mode
= 0;
3231 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3242 g_ventoy_case_insensitive
= 1;
3243 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3244 g_ventoy_case_insensitive
= 0;
3250 grub_file_close(file
);
3256 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3261 const char *isopath
= NULL
;
3263 ventoy_mbr_head mbr
;
3270 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3273 isopath
= grub_env_get("vtoy_iso_part");
3276 debug("isopath is null %p\n", isopath
);
3280 debug("isopath is %s\n", isopath
);
3282 for (id
= 0; id
< 30 && (find
== 0); id
++)
3284 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3285 if (grub_strstr(isopath
, hdname
))
3287 debug("skip %s ...\n", hdname
);
3291 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3293 disk
= grub_disk_open(hdname
);
3296 debug("%s not exist\n", hdname
);
3300 grub_memset(&mbr
, 0, sizeof(mbr
));
3301 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3303 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3305 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3306 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3309 grub_env_set(args
[0], hdname
);
3313 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3317 debug("read %s failed\n", hdname
);
3320 grub_disk_close(disk
);
3326 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3337 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3340 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3343 debug("failed to open file %s\n", args
[0]);
3347 buf
= grub_malloc(len
);
3354 grub_file_read(file
, buf
, len
- 1);
3356 ventoy_get_line(buf
);
3357 ventoy_set_env(args
[1], buf
);
3361 grub_check_free(buf
);
3362 grub_file_close(file
);
3367 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3372 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3373 "0 %llu linear /dev/ventoy %llu\n",
3374 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3379 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3381 char *device_name
= NULL
;
3382 grub_device_t dev
= NULL
;
3387 g_part_list_pos
= 0;
3388 grub_env_unset("vtoy_img_part_file");
3395 device_name
= grub_file_get_device_name(args
[0]);
3398 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3402 dev
= grub_device_open(device_name
);
3405 debug("grub_device_open failed, %s\n", device_name
);
3409 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3411 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3412 grub_env_set("vtoy_img_part_file", buf
);
3416 check_free(device_name
, grub_free
);
3417 check_free(dev
, grub_device_close
);
3423 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3434 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3437 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3440 debug("failed to open file %s\n", args
[0]);
3444 buf
= grub_malloc(file
->size
+ 1);
3450 buf
[file
->size
] = 0;
3451 grub_file_read(file
, buf
, file
->size
);
3453 if (grub_strstr(buf
, args
[1]))
3460 grub_check_free(buf
);
3461 grub_file_close(file
);
3466 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3472 ventoy_iso9660_vd pvd
;
3479 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3482 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3485 debug("failed to open file %s\n", args
[0]);
3489 grub_file_seek(file
, 16 * 2048);
3490 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3491 if (len
!= sizeof(pvd
))
3493 debug("failed to read pvd %d\n", len
);
3497 grub_memset(buf
, 0, sizeof(buf
));
3498 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3499 ventoy_set_env(args
[1], buf
);
3501 grub_memset(buf
, 0, sizeof(buf
));
3502 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3503 ventoy_set_env(args
[2], buf
);
3507 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3508 ventoy_set_env(args
[3], buf
);
3511 grub_file_close(file
);
3516 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3527 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3530 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3533 debug("failed to open file %s\n", args
[0]);
3537 grub_memset(buf
, 0, sizeof(buf
));
3538 grub_file_seek(file
, 16 * 2048 + 813);
3539 len
= (int)grub_file_read(file
, buf
, 17);
3542 debug("failed to read create date %d\n", len
);
3546 ventoy_set_env(args
[1], buf
);
3549 grub_file_close(file
);
3554 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3560 ventoy_env_hook_root(1);
3565 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3571 ventoy_env_hook_root(0);
3576 #ifdef GRUB_MACHINE_EFI
3577 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3582 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3588 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3589 if (var
&& *var
== 1)
3597 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3606 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3611 grub_uint64_t FileSectors
= 0;
3612 ventoy_gpt_info
*gpt
= NULL
;
3613 ventoy_part_table
*pt
= NULL
;
3614 grub_uint8_t zeroguid
[16] = {0};
3619 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3622 debug("failed to open file %s\n", args
[0]);
3626 if (file
->size
% 512)
3628 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3632 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3638 FileSectors
= file
->size
/ 512;
3640 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3641 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3643 debug("This is EFI partition table\n");
3645 for (i
= 0; i
< 128; i
++)
3647 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3649 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3651 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3652 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3660 debug("This is MBR partition table\n");
3662 for (i
= 0; i
< 4; i
++)
3664 pt
= gpt
->MBR
.PartTbl
+ i
;
3665 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3667 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3668 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3669 (ulonglong
)FileSectors
);
3678 grub_file_close(file
);
3679 grub_check_free(gpt
);
3680 grub_errno
= GRUB_ERR_NONE
;
3684 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3693 for (i
= 0; i
< 500; i
++)
3695 ret
= grub_getkey_noblock();
3696 if (ret
== GRUB_TERM_NO_KEY
)
3705 grub_printf("\n\n Still have key input after clear.\n");
3713 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3720 int image_sector_size
;
3722 ventoy_chain_head
*chain
;
3723 ventoy_img_chunk
*chunk
;
3724 ventoy_os_param
*osparam
;
3725 ventoy_image_location
*location
;
3726 ventoy_image_disk_region
*region
;
3727 struct grub_acpi_table_header
*acpi
;
3736 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3738 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3744 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3746 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3748 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3752 img_chunk_num
= chain
->img_chunk_num
;
3754 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3755 datalen
= sizeof(ventoy_os_param
) + loclen
;
3757 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3758 acpi
= grub_zalloc(buflen
);
3764 /* Step1: Fill acpi table header */
3765 grub_memcpy(acpi
->signature
, "VTOY", 4);
3766 acpi
->length
= buflen
;
3768 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3769 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3771 acpi
->creator_id
[0] = 1;
3772 acpi
->creator_rev
= 1;
3774 /* Step2: Fill data */
3775 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3776 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3777 osparam
->vtoy_img_location_addr
= 0;
3778 osparam
->vtoy_img_location_len
= loclen
;
3779 osparam
->chksum
= 0;
3780 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3782 location
= (ventoy_image_location
*)(osparam
+ 1);
3783 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3784 location
->image_sector_size
= image_sector_size
;
3785 location
->disk_sector_size
= chain
->disk_sector_size
;
3786 location
->region_count
= img_chunk_num
;
3788 region
= location
->regions
;
3789 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3790 if (512 == image_sector_size
)
3792 for (i
= 0; i
< img_chunk_num
; i
++)
3794 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3795 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3796 region
->disk_start_sector
= chunk
->disk_start_sector
;
3803 for (i
= 0; i
< img_chunk_num
; i
++)
3805 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3806 region
->image_start_sector
= chunk
->img_start_sector
;
3807 region
->disk_start_sector
= chunk
->disk_start_sector
;
3813 /* Step3: Fill acpi checksum */
3815 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3817 /* load acpi table */
3818 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3819 grub_script_execute_sourcecode(cmd
);
3823 VENTOY_CMD_RETURN(0);
3826 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3832 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3833 g_ventoy_last_entry
= -1;
3838 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3844 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3849 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3851 const char *pos
= filename
+ 1;
3859 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3861 grub_strncpy((char *)data
, filename
, 128);
3872 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3875 char *device_name
= NULL
;
3876 grub_device_t dev
= NULL
;
3877 grub_fs_t fs
= NULL
;
3878 char buf
[128] = {0};
3884 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3888 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3890 device_name
= grub_file_get_device_name(args
[0]);
3893 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3897 dev
= grub_device_open(device_name
);
3900 debug("grub_device_open failed, %s\n", device_name
);
3904 fs
= grub_fs_probe(dev
);
3907 debug("grub_fs_probe failed, %s\n", device_name
);
3911 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3915 ventoy_set_env(args
[2], buf
);
3922 check_free(device_name
, grub_free
);
3923 check_free(dev
, grub_device_close
);
3928 int ventoy_load_part_table(const char *diskname
)
3935 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3936 if (!g_ventoy_part_info
)
3941 disk
= grub_disk_open(diskname
);
3944 debug("Failed to open disk %s\n", diskname
);
3948 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
3950 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3951 grub_disk_close(disk
);
3953 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
3954 dev
= grub_device_open(name
);
3957 /* Check for official Ventoy device */
3958 ret
= ventoy_check_official_device(dev
);
3959 grub_device_close(dev
);
3967 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
3968 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
3973 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3980 ret
= ventoy_load_part_table(args
[0]);
3986 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
3987 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
3992 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3995 const char *vcfg
= NULL
;
4000 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4003 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4004 grub_env_set(args
[1], vcfg
);
4009 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4017 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4020 grub_uint8_t zeroguid
[16] = {0};
4025 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4028 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4030 if (id
>= 1 && id
<= 128)
4032 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4040 if (id
>= 1 && id
<= 4)
4042 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4052 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4055 char *device_name
= NULL
;
4056 grub_device_t dev
= NULL
;
4057 grub_fs_t fs
= NULL
;
4062 debug("get fs label for %s\n", args
[0]);
4066 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4070 device_name
= grub_file_get_device_name(args
[0]);
4073 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4077 dev
= grub_device_open(device_name
);
4080 debug("grub_device_open failed, %s\n", device_name
);
4084 fs
= grub_fs_probe(dev
);
4085 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4087 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4091 fs
->fs_label(dev
, &label
);
4094 debug("label=<%s>\n", label
);
4095 ventoy_set_env(args
[1], label
);
4103 check_free(device_name
, grub_free
);
4104 check_free(dev
, grub_device_close
);
4109 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4113 grub_snprintf((char *)data
, 256, "%s", filename
);
4121 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4124 char *device_name
= NULL
;
4125 grub_device_t dev
= NULL
;
4126 grub_fs_t fs
= NULL
;
4127 char name
[256] ={0};
4133 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
4137 device_name
= grub_file_get_device_name(args
[0]);
4140 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4144 dev
= grub_device_open(device_name
);
4147 debug("grub_device_open failed, %s\n", device_name
);
4151 fs
= grub_fs_probe(dev
);
4154 debug("grub_fs_probe failed, %s\n", device_name
);
4158 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
4161 ventoy_set_env(args
[2], name
);
4168 check_free(device_name
, grub_free
);
4169 check_free(dev
, grub_device_close
);
4174 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4184 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4188 for (pos
= args
[0]; *pos
; pos
++)
4202 grub_env_set(args
[1], args
[0]);
4212 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4222 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4227 len
= (int)grub_strlen(buf
);
4228 for (i
= len
; i
> 0; i
--)
4230 if (buf
[i
- 1] == '/')
4232 grub_env_set(args
[1], buf
+ i
);
4237 grub_env_set(args
[1], buf
);
4242 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4244 struct grub_video_mode_info info
;
4251 if (!g_video_mode_list
)
4253 ventoy_enum_video_mode();
4256 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4258 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4262 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4265 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4267 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4268 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4270 VENTOY_CMD_RETURN(0);
4273 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4275 struct grub_video_mode_info info
;
4282 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4284 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4288 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4291 grub_env_set(args
[0], buf
);
4293 VENTOY_CMD_RETURN(0);
4296 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4304 if (!g_video_mode_list
)
4309 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4310 if (id
< g_video_mode_num
)
4312 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4313 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4316 grub_env_set(args
[1], buf
);
4318 VENTOY_CMD_RETURN(0);
4321 int ventoy_env_init(void)
4325 grub_env_set("vtdebug_flag", "");
4327 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4328 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4329 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4330 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4332 ventoy_filt_register(0, ventoy_wrapper_open
);
4334 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4337 g_grub_param
->grub_env_get
= grub_env_get
;
4338 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4339 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4340 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4341 grub_env_set("env_param", buf
);
4342 grub_env_set("ventoy_env_param", buf
);
4344 grub_env_export("env_param");
4345 grub_env_export("ventoy_env_param");
4351 static cmd_para ventoy_cmds
[] =
4353 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4354 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4355 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4356 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4357 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4358 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4359 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4360 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4361 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4362 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4363 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4364 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4365 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4366 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4367 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4368 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4369 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4370 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4371 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4372 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4373 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4374 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4375 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4376 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4378 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4379 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4380 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4381 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4382 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4383 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4384 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4386 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4387 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4388 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4389 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4390 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4391 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4392 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4393 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4394 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4397 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4398 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4399 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4400 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4401 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4402 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4403 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4404 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4405 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4406 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4407 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4409 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4410 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4411 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4412 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4413 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4414 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4416 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4417 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4418 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4419 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4420 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4421 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4422 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4423 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4424 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4425 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4427 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4428 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4429 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4430 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4431 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4432 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4433 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4434 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4436 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4437 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4438 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4441 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4442 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4443 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4445 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4446 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4447 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4450 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4451 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4452 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4453 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4454 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
4455 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4456 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4457 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4458 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4459 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4460 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4462 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4463 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4464 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4465 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4466 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
4467 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
4471 int ventoy_register_all_cmd(void)
4474 cmd_para
*cur
= NULL
;
4476 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4478 cur
= ventoy_cmds
+ i
;
4479 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4480 cur
->summary
, cur
->description
, cur
->parser
);
4485 int ventoy_unregister_all_cmd(void)
4489 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4491 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);