1 /******************************************************************************
4 * Copyright (c) 2020, 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/efi.h>
41 #include <grub/time.h>
42 #include <grub/video.h>
43 #include <grub/acpi.h>
44 #include <grub/relocator.h>
45 #include <grub/charset.h>
46 #include <grub/ventoy.h>
47 #include "ventoy_def.h"
49 GRUB_MOD_LICENSE ("GPLv3+");
51 int g_ventoy_debug
= 0;
52 static int g_efi_os
= 0xFF;
53 initrd_info
*g_initrd_img_list
= NULL
;
54 initrd_info
*g_initrd_img_tail
= NULL
;
55 int g_initrd_img_count
= 0;
56 int g_valid_initrd_count
= 0;
57 int g_default_menu_mode
= 0;
58 int g_filt_dot_underscore_file
= 0;
59 static grub_file_t g_old_file
;
60 static int g_ventoy_last_entry_back
;
63 char g_img_swap_tmp_buf
[1024];
64 img_info g_img_swap_tmp
;
65 img_info
*g_ventoy_img_list
= NULL
;
67 int g_ventoy_img_count
= 0;
69 grub_device_t g_enum_dev
= NULL
;
70 grub_fs_t g_enum_fs
= NULL
;
71 img_iterator_node g_img_iterator_head
;
72 img_iterator_node
*g_img_iterator_tail
= NULL
;
74 grub_uint8_t g_ventoy_break_level
= 0;
75 grub_uint8_t g_ventoy_debug_level
= 0;
76 grub_uint8_t g_ventoy_chain_type
= 0;
78 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
79 grub_uint32_t g_ventoy_cpio_size
= 0;
80 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
81 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
83 ventoy_grub_param
*g_grub_param
= NULL
;
85 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
87 ventoy_img_chunk_list g_img_chunk_list
;
89 int g_wimboot_enable
= 0;
90 ventoy_img_chunk_list g_wimiso_chunk_list
;
91 char *g_wimiso_path
= NULL
;
93 int g_vhdboot_enable
= 0;
95 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
97 static char *g_tree_script_buf
= NULL
;
98 static int g_tree_script_pos
= 0;
100 static char *g_list_script_buf
= NULL
;
101 static int g_list_script_pos
= 0;
103 static char *g_part_list_buf
= NULL
;
104 static int g_part_list_pos
= 0;
106 static int g_video_mode_max
= 0;
107 static int g_video_mode_num
= 0;
108 static ventoy_video_mode
*g_video_mode_list
= NULL
;
110 static const char *g_menu_class
[] =
112 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
115 static const char *g_menu_prefix
[] =
117 "iso", "wim", "efi", "img", "vhd", "vtoy"
120 void ventoy_debug(const char *fmt
, ...)
124 va_start (args
, fmt
);
125 grub_vprintf (fmt
, args
);
129 void ventoy_debug_dump_guid(const char *prefix
, grub_uint8_t
*guid
)
139 for (i
= 0; i
< 16; i
++)
141 grub_printf("%02x ", guid
[i
]);
146 int ventoy_is_efi_os(void)
150 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
156 static int ventoy_get_fs_type(const char *fs
)
160 return ventoy_fs_max
;
162 else if (grub_strncmp(fs
, "exfat", 5) == 0)
164 return ventoy_fs_exfat
;
166 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
168 return ventoy_fs_ntfs
;
170 else if (grub_strncmp(fs
, "ext", 3) == 0)
172 return ventoy_fs_ext
;
174 else if (grub_strncmp(fs
, "xfs", 3) == 0)
176 return ventoy_fs_xfs
;
178 else if (grub_strncmp(fs
, "udf", 3) == 0)
180 return ventoy_fs_udf
;
182 else if (grub_strncmp(fs
, "fat", 3) == 0)
184 return ventoy_fs_fat
;
187 return ventoy_fs_max
;
190 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
209 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
211 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
215 static grub_err_t
ventoy_fs_close(grub_file_t file
)
217 grub_file_close(g_old_file
);
218 grub_free(file
->data
);
226 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
232 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
237 for (i
= 0; i
< g_video_mode_num
; i
++)
239 if (g_video_mode_list
[i
].width
== info
->width
&&
240 g_video_mode_list
[i
].height
== info
->height
&&
241 g_video_mode_list
[i
].bpp
== info
->bpp
)
247 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
248 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
249 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
252 if (g_video_mode_num
== g_video_mode_max
)
254 g_video_mode_max
*= 2;
255 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
261 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
263 if (v1
->bpp
== v2
->bpp
)
265 if (v1
->width
== v2
->width
)
267 if (v1
->height
== v2
->height
)
273 return (v1
->height
< v2
->height
) ? -1 : 1;
278 return (v1
->width
< v2
->width
) ? -1 : 1;
283 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
287 static int ventoy_enum_video_mode(void)
290 grub_video_adapter_t adapter
;
291 grub_video_driver_id_t id
;
292 ventoy_video_mode mode
;
294 g_video_mode_num
= 0;
295 g_video_mode_max
= 1024;
296 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
297 if (!g_video_mode_list
)
302 #ifdef GRUB_MACHINE_PCBIOS
303 grub_dl_load ("vbe");
306 id
= grub_video_get_driver_id ();
308 FOR_VIDEO_ADAPTERS (adapter
)
310 if (!adapter
->iterate
||
311 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
312 adapter
->init() != GRUB_ERR_NONE
)))
317 adapter
->iterate(ventoy_video_hook
, NULL
);
319 if (adapter
->id
!= id
)
325 /* sort video mode */
326 for (i
= 0; i
< g_video_mode_num
; i
++)
327 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
329 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
331 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
332 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
333 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
337 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
340 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
344 static struct grub_fs vtoy_fs
=
349 .fs_read
= ventoy_fs_read
,
350 .fs_close
= ventoy_fs_close
,
360 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
366 file
->data
= grub_malloc(rawFile
->size
+ 4096);
372 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
373 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
375 g_old_file
= rawFile
;
377 file
->size
= rawFile
->size
+ len
;
378 file
->device
= rawFile
->device
;
380 file
->not_easily_seekable
= 1;
385 static int ventoy_check_decimal_var(const char *name
, long *value
)
387 const char *value_str
= NULL
;
389 value_str
= grub_env_get(name
);
390 if (NULL
== value_str
)
392 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
395 if (!ventoy_is_decimal(value_str
))
397 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
400 *value
= grub_strtol(value_str
, NULL
, 10);
402 return GRUB_ERR_NONE
;
405 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
409 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
412 if (0 == grub_strcmp(args
[0], "on"))
415 grub_env_set("vtdebug_flag", "debug");
420 grub_env_set("vtdebug_flag", "");
423 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
426 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
430 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
432 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
433 grub_printf(" level:\r\n");
434 grub_printf(" 01/11: busybox / (+cat log)\r\n");
435 grub_printf(" 02/12: initrd / (+cat log)\r\n");
436 grub_printf(" 03/13: hook / (+cat log)\r\n");
438 grub_printf(" debug:\r\n");
439 grub_printf(" 0: debug is on\r\n");
440 grub_printf(" 1: debug is off\r\n");
442 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
445 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
447 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
449 g_ventoy_debug_level
= 1;
452 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
455 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
464 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
467 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
499 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
504 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
506 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
509 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
514 value_long
+= grub_strtol(args
[1], NULL
, 10);
516 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
517 grub_env_set(args
[0], buf
);
519 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
522 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
537 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
540 debug("failed to open file <%s> for udf check\n", args
[0]);
544 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
546 grub_env_set(args
[1], buf
);
548 grub_file_close(file
);
554 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
562 g_wimboot_enable
= 0;
563 grub_check_free(g_wimiso_path
);
564 grub_check_free(g_wimiso_chunk_list
.chunk
);
566 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
572 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
573 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
574 if (NULL
== g_wimiso_chunk_list
.chunk
)
576 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
579 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
580 g_wimiso_chunk_list
.cur_chunk
= 0;
582 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
584 g_wimboot_enable
= 1;
585 g_wimiso_path
= grub_strdup(args
[0]);
587 grub_file_close(file
);
592 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
598 grub_uint32_t offset
;
600 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
603 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
607 len
= (int)file
->size
;
609 data
= (char *)grub_malloc(file
->size
);
615 grub_file_read(file
, data
, file
->size
);
616 grub_file_close(file
);
618 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
619 grub_script_execute_sourcecode(exec
);
621 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
622 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
623 grub_file_close(file
);
625 grub_script_execute_sourcecode("loopback -d efiboot");
629 *direntoff
= offset
+ 2;
634 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
644 ventoy_iso9660_override
*dirent
;
653 totlen
= sizeof(ventoy_chain_head
);
655 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
657 debug("failed to load efiboot template %d\n", len
);
663 debug("efiboot template len:%d offset:%d\n", len
, offset
);
665 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
668 debug("failed to open file <%s>\n", args
[0]);
672 totlen
+= ventoy_align_2k(file
->size
);
674 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
675 dirent
->first_sector
= len
/ 2048;
676 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
677 dirent
->size
= (grub_uint32_t
)file
->size
;
678 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
680 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
682 #ifdef GRUB_MACHINE_EFI
683 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
685 data
= (char *)grub_malloc(totlen
);
688 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
690 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
691 grub_check_free(buf
);
693 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
694 grub_file_close(file
);
696 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
697 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
698 grub_env_set(name
, value
);
700 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
701 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
702 grub_env_set(name
, value
);
707 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
724 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
727 debug("failed to open file <%s>\n", args
[0]);
731 #ifdef GRUB_MACHINE_EFI
732 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
734 buf
= (char *)grub_malloc(file
->size
);
737 grub_file_read(file
, buf
, file
->size
);
739 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
740 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
741 grub_env_set(name
, value
);
743 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
744 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
745 grub_env_set(name
, value
);
747 grub_file_close(file
);
753 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
771 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
774 debug("failed to open file <%s> for udf check\n", args
[0]);
778 headlen
= sizeof(ventoy_chain_head
);
780 #ifdef GRUB_MACHINE_EFI
781 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
783 buf
= (char *)grub_malloc(headlen
+ file
->size
);
786 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
788 grub_file_read(file
, buf
+ headlen
, file
->size
);
790 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
791 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
792 grub_env_set(name
, value
);
794 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
795 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
796 grub_env_set(name
, value
);
798 grub_file_close(file
);
804 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
813 if (args
[0][0] == '1')
815 grub_iso9660_set_nojoliet(1);
819 grub_iso9660_set_nojoliet(0);
825 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
830 grub_uint8_t buf
[32];
841 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
844 debug("failed to open file <%s> for udf check\n", args
[0]);
848 for (i
= 16; i
< 32; i
++)
850 grub_file_seek(file
, i
* 2048);
851 grub_file_read(file
, buf
, sizeof(buf
));
859 grub_file_seek(file
, i
* 2048);
860 grub_file_read(file
, buf
, sizeof(buf
));
862 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
865 grub_file_seek(file
, i
* 2048);
866 grub_file_read(file
, buf
, sizeof(buf
));
868 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
869 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
875 grub_file_close(file
);
877 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
882 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
884 long value_long1
= 0;
885 long value_long2
= 0;
887 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
889 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
892 value_long1
= grub_strtol(args
[0], NULL
, 10);
893 value_long2
= grub_strtol(args
[2], NULL
, 10);
895 if (0 == grub_strcmp(args
[1], "eq"))
897 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
899 else if (0 == grub_strcmp(args
[1], "ne"))
901 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
903 else if (0 == grub_strcmp(args
[1], "gt"))
905 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
907 else if (0 == grub_strcmp(args
[1], "lt"))
909 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
911 else if (0 == grub_strcmp(args
[1], "ge"))
913 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
915 else if (0 == grub_strcmp(args
[1], "le"))
917 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
921 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
927 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
934 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
937 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
938 pos
= grub_strstr(buf
, ",");
944 grub_env_set(args
[1], buf
);
946 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
949 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
955 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
961 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
964 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
966 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
967 if (0 == grub_script_execute_sourcecode(buf
))
969 debug("file %s exist, ventoy_compatible YES\n", buf
);
970 grub_env_set("ventoy_compatible", "YES");
971 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
975 debug("file %s NOT exist\n", buf
);
979 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
980 pos
= grub_strstr(buf
, ")");
986 disk
= grub_disk_open(buf
);
989 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
990 grub_disk_close(disk
);
992 g_img_swap_tmp_buf
[703] = 0;
993 for (i
= 319; i
< 703; i
++)
995 if (g_img_swap_tmp_buf
[i
] == 'V' &&
996 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
998 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
999 grub_env_set("ventoy_compatible", "YES");
1000 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1006 debug("failed to open disk <%s>\n", buf
);
1009 grub_env_set("ventoy_compatible", "NO");
1010 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1013 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1019 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1024 if (grub_islower(c1
))
1026 c1
= c1
- 'a' + 'A';
1029 if (grub_islower(c2
))
1031 c2
= c2
- 'a' + 'A';
1043 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1045 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1047 grub_memcpy(img1
, img2
, sizeof(img_info
));
1048 img1
->next
= g_img_swap_tmp
.next
;
1049 img1
->prev
= g_img_swap_tmp
.prev
;
1051 g_img_swap_tmp
.next
= img2
->next
;
1052 g_img_swap_tmp
.prev
= img2
->prev
;
1053 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1056 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1060 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1065 for (i
= 0; i
< namelen
; i
++)
1067 if (filename
[i
] == ' ' || filename
[i
] == '\t')
1072 if ((grub_uint8_t
)(filename
[i
]) >= 127)
1081 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1085 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
1095 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1103 img_iterator_node
*tmp
;
1104 img_iterator_node
*new_node
;
1105 img_iterator_node
*node
= (img_iterator_node
*)data
;
1107 len
= grub_strlen(filename
);
1111 if ((len
== 1 && filename
[0] == '.') ||
1112 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1117 if (!ventoy_img_name_valid(filename
, len
))
1122 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1127 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1130 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1132 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1135 debug("Directory %s ignored...\n", new_node
->dir
);
1136 grub_free(new_node
);
1140 new_node
->tail
= node
->tail
;
1142 new_node
->parent
= node
;
1143 if (!node
->firstchild
)
1145 node
->firstchild
= new_node
;
1148 if (g_img_iterator_tail
)
1150 g_img_iterator_tail
->next
= new_node
;
1151 g_img_iterator_tail
= new_node
;
1155 g_img_iterator_head
.next
= new_node
;
1156 g_img_iterator_tail
= new_node
;
1162 debug("Find a file %s\n", filename
);
1168 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1170 type
= img_type_iso
;
1172 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1174 type
= img_type_wim
;
1176 else if (g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1177 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx")))
1179 type
= img_type_vhd
;
1181 #ifdef GRUB_MACHINE_EFI
1182 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1184 type
= img_type_efi
;
1187 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1189 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1191 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1192 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1197 type
= img_type_img
;
1199 else if (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1201 type
= img_type_vtoy
;
1208 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1213 img
= grub_zalloc(sizeof(img_info
));
1217 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1219 for (i
= 0; i
< (int)len
; i
++)
1221 if (filename
[i
] == ' ' || filename
[i
] == '\t' || (0 == grub_isprint(filename
[i
])))
1228 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1230 img
->size
= info
->size
;
1233 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1236 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1238 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1243 if (g_ventoy_img_list
)
1245 tail
= *(node
->tail
);
1251 g_ventoy_img_list
= img
;
1254 img
->id
= g_ventoy_img_count
;
1256 if (node
&& NULL
== node
->firstiso
)
1258 node
->firstiso
= img
;
1269 *((img_info
**)(node
->tail
)) = img
;
1270 g_ventoy_img_count
++;
1272 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1273 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1276 img
->class = g_menu_class
[type
];
1278 img
->menu_prefix
= g_menu_prefix
[type
];
1280 if (img_type_iso
== type
)
1282 if (ventoy_plugin_check_memdisk(img
->path
))
1284 img
->menu_prefix
= "miso";
1288 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1295 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1297 int len
= GRUB_UINT_MAX
;
1298 const char *value
= NULL
;
1299 char name
[32] = {0};
1300 char plat
[32] = {0};
1301 char guidstr
[32] = {0};
1302 ventoy_guid guid
= VENTOY_GUID
;
1303 const char *fmt1
= NULL
;
1304 const char *fmt2
= NULL
;
1305 const char *fmt3
= NULL
;
1306 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1307 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1308 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1309 const char fmtcode
[]={
1310 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1311 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1312 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1313 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1314 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1315 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1318 grub_memset(name
, 0, sizeof(name
));
1319 puint
[0] = grub_swap_bytes32(0x56454e54);
1320 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1321 puint
[2] = grub_swap_bytes32(0x45525349);
1322 puint
[1] = grub_swap_bytes32(0x4f595f56);
1323 value
= ventoy_get_env(name
);
1325 grub_memset(name
, 0, sizeof(name
));
1326 puint
[1] = grub_swap_bytes32(0x5f544f50);
1327 puint
[0] = grub_swap_bytes32(0x56544c45);
1328 fmt1
= ventoy_get_env(name
);
1334 grub_memset(name
, 0, sizeof(name
));
1335 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1336 puint
[0] = grub_swap_bytes32(0x56544c45);
1337 fmt2
= ventoy_get_env(name
);
1339 grub_memset(name
, 0, sizeof(name
));
1340 puint
[1] = grub_swap_bytes32(0x5f434c52);
1341 puint
[0] = grub_swap_bytes32(0x56544c45);
1342 fmt3
= ventoy_get_env(name
);
1344 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1346 #if defined (GRUB_MACHINE_EFI)
1347 puint2
[0] = grub_swap_bytes32(0x55454649);
1349 puint2
[0] = grub_swap_bytes32(0x42494f53);
1352 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1353 #pragma GCC diagnostic push
1354 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1355 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1356 fmt1
? fmt1
: fmtdata
,
1357 fmt2
? fmt2
: fmtdata
+ 4,
1358 value
? value
: "", plat
, guidstr
,
1359 fmt3
? fmt3
: fmtdata
+ 6);
1360 #pragma GCC diagnostic pop
1362 grub_memset(name
, 0, sizeof(name
));
1363 puint
[0] = grub_swap_bytes32(0x76746f79);
1364 puint
[2] = grub_swap_bytes32(0x656e7365);
1365 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1366 ventoy_set_env(name
, guidstr
);
1371 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1373 img_info
*minimg
= NULL
;
1374 img_info
*img
= (img_info
*)(node
->firstiso
);
1376 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1378 if (img
->select
== 0 && (NULL
== minimg
|| grub_strcmp(img
->name
, minimg
->name
) < 0))
1393 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1395 img_iterator_node
*Minchild
= NULL
;
1396 img_iterator_node
*child
= node
->firstchild
;
1398 while (child
&& child
->parent
== node
)
1400 if (child
->select
== 0 && (NULL
== Minchild
|| grub_strcmp(child
->dir
, Minchild
->dir
) < 0))
1404 child
= child
->next
;
1409 Minchild
->select
= 1;
1415 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1418 img_info
*img
= NULL
;
1419 const char *dir_class
= NULL
;
1420 const char *dir_alias
= NULL
;
1421 img_iterator_node
*child
= NULL
;
1423 if (node
->isocnt
== 0 || node
->done
== 1)
1428 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1430 offset
= node
->parent
->dirlen
;
1433 if (node
== &g_img_iterator_head
)
1435 if (g_default_menu_mode
== 0)
1437 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1438 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1439 " echo 'return ...' \n"
1445 node
->dir
[node
->dirlen
- 1] = 0;
1446 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1449 dir_class
= "vtoydir";
1452 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1455 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1456 "submenu \"%-10s %s\" --class=\"%s\" {\n",
1457 "DIR", dir_alias
, dir_class
);
1461 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1462 "submenu \"%-10s [%s]\" --class=\"%s\" {\n",
1463 "DIR", node
->dir
+ offset
, dir_class
);
1466 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1467 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1468 " echo 'return ...' \n"
1472 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1474 ventoy_dynamic_tree_menu(child
);
1477 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1479 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1480 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1483 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1484 img
->unsupport
? "[***********] " : "",
1485 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1487 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1490 if (node
!= &g_img_iterator_head
)
1492 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1499 int ventoy_check_device_result(int ret
)
1503 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
1504 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
1505 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
1509 grub_printf(VTOY_WARNING
"\n");
1510 grub_printf(VTOY_WARNING
"\n");
1511 grub_printf(VTOY_WARNING
"\n\n\n");
1513 grub_printf("Unsatisfied conditions detected for Ventoy.\n\n");
1514 grub_printf("This is NOT a standard Ventoy device and is NOT officially supported.\n\n");
1515 grub_printf("Recommend to follow the instructions in https://www.ventoy.net to use Ventoy.\n");
1517 grub_printf("\n\nWill exit after 10 seconds ...... ");
1525 int ventoy_check_device(grub_device_t dev
)
1528 grub_uint64_t offset
;
1533 struct grub_partition
*partition
;
1535 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
1537 return ventoy_check_device_result(1 | 0x1000);
1540 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
1541 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
1542 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_64", dev
->disk
->name
))
1544 return ventoy_check_device_result(2 | 0x1000);
1547 /* We must have partition 2 */
1548 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
1551 return ventoy_check_device_result(3 | 0x1000);
1554 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
1556 grub_file_close(file
);
1557 return ventoy_check_device_result(4 | 0x1000);
1560 partition
= dev
->disk
->partition
;
1561 if (partition
->number
!= 0 || partition
->start
!= 2048)
1563 return ventoy_check_device_result(5);
1566 offset
= partition
->start
+ partition
->len
;
1567 partition
= file
->device
->disk
->partition
;
1568 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
1570 grub_file_close(file
);
1571 return ventoy_check_device_result(6);
1573 grub_file_close(file
);
1575 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
1576 dev2
= grub_device_open(devname
);
1579 return ventoy_check_device_result(7);
1582 fs
= grub_fs_probe(dev2
);
1585 grub_device_close(dev2
);
1586 return ventoy_check_device_result(8);
1589 fs
->fs_label(dev2
, &label
);
1590 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
1592 grub_device_close(dev2
);
1593 return ventoy_check_device_result(9);
1596 grub_device_close(dev2
);
1597 return ventoy_check_device_result(0);
1600 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1604 grub_device_t dev
= NULL
;
1605 img_info
*cur
= NULL
;
1606 img_info
*tail
= NULL
;
1607 img_info
*default_node
= NULL
;
1608 const char *strdata
= NULL
;
1609 char *device_name
= NULL
;
1610 const char *default_image
= NULL
;
1613 img_iterator_node
*node
= NULL
;
1614 img_iterator_node
*tmp
= NULL
;
1620 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1623 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1625 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1628 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1629 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1631 g_filt_dot_underscore_file
= 1;
1634 device_name
= grub_file_get_device_name(args
[0]);
1640 g_enum_dev
= dev
= grub_device_open(device_name
);
1646 g_enum_fs
= fs
= grub_fs_probe(dev
);
1652 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1654 debug("unsupported fs:<%s>\n", fs
->name
);
1655 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1659 ventoy_set_env("vtoy_iso_fs", fs
->name
);
1661 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1662 if (strdata
&& strdata
[0] == '1')
1664 g_default_menu_mode
= 1;
1667 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1669 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1671 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1672 if (strdata
&& strdata
[0] == '/')
1674 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1675 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1677 g_img_iterator_head
.dir
[len
++] = '/';
1679 g_img_iterator_head
.dirlen
= len
;
1683 g_img_iterator_head
.dirlen
= 1;
1684 grub_strcpy(g_img_iterator_head
.dir
, "/");
1687 g_img_iterator_head
.tail
= &tail
;
1689 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1691 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1694 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1696 ventoy_dynamic_tree_menu(node
);
1700 node
= g_img_iterator_head
.next
;
1708 /* sort image list by image name */
1709 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1711 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1713 if (ventoy_cmp_img(cur
, tail
) > 0)
1715 ventoy_swap_img(cur
, tail
);
1720 if (g_default_menu_mode
== 1)
1722 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1723 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1724 " echo 'return ...' \n"
1728 if (g_default_menu_mode
== 0)
1730 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1733 img_len
= grub_strlen(default_image
);
1737 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1739 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1740 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1743 cur
->unsupport
? "[***********] " : "",
1744 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1746 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1748 if (g_default_menu_mode
== 0 && default_image
&& default_node
== NULL
)
1750 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1759 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1762 g_list_script_buf
[g_list_script_pos
] = 0;
1764 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1765 grub_env_set(args
[1], buf
);
1769 check_free(device_name
, grub_free
);
1770 check_free(dev
, grub_device_close
);
1772 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1776 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1778 img_info
*next
= NULL
;
1779 img_info
*cur
= g_ventoy_img_list
;
1792 g_ventoy_img_list
= NULL
;
1793 g_ventoy_img_count
= 0;
1795 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1798 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1801 img_info
*cur
= g_ventoy_img_list
;
1805 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1807 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1810 img_id
= grub_strtol(args
[0], NULL
, 10);
1811 if (img_id
>= g_ventoy_img_count
)
1813 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
1816 debug("Find image %ld name \n", img_id
);
1818 while (cur
&& img_id
> 0)
1826 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
1829 debug("image name is %s\n", cur
->name
);
1831 grub_env_set(args
[1], cur
->name
);
1833 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1836 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1841 const char *id
= NULL
;
1842 img_info
*cur
= g_ventoy_img_list
;
1846 if (argc
< 1 || argc
> 2)
1848 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
1851 id
= grub_env_get("chosen");
1853 pos
= grub_strstr(id
, "VID_");
1856 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
1860 img_id
= (int)grub_strtoul(id
, NULL
, 10);
1865 if (img_id
== cur
->id
)
1874 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
1877 grub_env_set(args
[0], cur
->path
);
1881 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
1882 grub_env_set(args
[1], value
);
1885 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1888 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
1895 device_name
= grub_file_get_device_name(filename
);
1907 pos2
= grub_strstr(pos
, ",");
1910 pos2
= grub_strstr(pos
, ")");
1918 disk
= grub_disk_open(pos
);
1921 grub_disk_read(disk
, 0, 0x180, 16, guid
);
1922 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
1923 grub_disk_close(disk
);
1930 grub_free(device_name
);
1934 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
1936 eltorito_descriptor desc
;
1938 grub_memset(&desc
, 0, sizeof(desc
));
1939 grub_file_seek(file
, 17 * 2048);
1940 grub_file_read(file
, &desc
, sizeof(desc
));
1942 if (desc
.type
!= 0 || desc
.version
!= 1)
1947 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
1948 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
1956 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
1960 grub_uint8_t buf
[512];
1962 grub_file_seek(file
, sector
* 2048);
1963 grub_file_read(file
, buf
, sizeof(buf
));
1965 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
1967 debug("%s efi eltorito in Validation Entry\n", file
->name
);
1971 if (buf
[0] == 0x01 && buf
[1] == 0x00)
1976 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
1978 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
1980 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1984 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
1986 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1991 debug("%s does not contain efi eltorito\n", file
->name
);
1995 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
1998 const char *fs
= NULL
;
1999 const char *cdprompt
= NULL
;
2001 grub_uint8_t chksum
= 0;
2004 disk
= file
->device
->disk
;
2005 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2007 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2008 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2009 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2011 pos
= grub_strstr(file
->name
, "/");
2017 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2019 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2021 param
->vtoy_img_size
= file
->size
;
2023 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2024 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2026 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2028 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2029 param
->vtoy_reserved
[4] = 0;
2030 if (g_ventoy_chain_type
== 1) /* Windows */
2032 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2033 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2035 param
->vtoy_reserved
[4] = 1;
2039 fs
= ventoy_get_env("ventoy_fs_probe");
2040 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2042 param
->vtoy_reserved
[3] = 1;
2045 /* calculate checksum */
2046 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2048 chksum
+= *((grub_uint8_t
*)param
+ i
);
2050 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2055 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2057 grub_uint32_t i
= 0;
2058 grub_uint64_t total
= 0;
2059 ventoy_img_chunk
*chunk
= NULL
;
2061 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2063 chunk
= chunklist
->chunk
+ i
;
2065 if (chunk
->disk_start_sector
<= start
)
2067 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2071 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2074 if (total
!= ((file
->size
+ 511) / 512))
2076 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
2083 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2087 grub_uint32_t i
= 0;
2088 grub_uint32_t sector
= 0;
2089 grub_uint32_t count
= 0;
2090 grub_off_t size
= 0;
2091 grub_off_t read
= 0;
2093 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2094 if (fs_type
== ventoy_fs_exfat
)
2096 grub_fat_get_file_chunk(start
, file
, chunklist
);
2098 else if (fs_type
== ventoy_fs_ext
)
2100 grub_ext_get_file_chunk(start
, file
, chunklist
);
2104 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2105 file
->read_hook_data
= chunklist
;
2107 for (size
= file
->size
; size
> 0; size
-= read
)
2109 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2110 grub_file_read(file
, NULL
, read
);
2113 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2115 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2116 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2119 if (ventoy_fs_udf
== fs_type
)
2121 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2123 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2124 chunklist
->chunk
[i
].img_start_sector
= sector
;
2125 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2131 len
= (int)grub_strlen(file
->name
);
2132 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2133 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2134 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2135 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2137 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2139 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2149 chunklist
->chunk
[i
].img_start_sector
= sector
;
2150 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2158 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2162 grub_disk_addr_t start
;
2167 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2170 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2173 if (g_img_chunk_list
.chunk
)
2175 grub_free(g_img_chunk_list
.chunk
);
2178 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2180 grub_file_close(file
);
2181 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2184 /* get image chunk data */
2185 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2186 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2187 if (NULL
== g_img_chunk_list
.chunk
)
2189 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2192 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2193 g_img_chunk_list
.cur_chunk
= 0;
2195 start
= file
->device
->disk
->partition
->start
;
2197 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2199 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2200 grub_file_close(file
);
2204 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2207 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2208 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2211 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2216 char configfile
[128];
2217 install_template
*node
= NULL
;
2223 debug("select auto installation argc:%d\n", argc
);
2230 node
= ventoy_plugin_find_install_template(args
[0]);
2233 debug("Auto install template not found for %s\n", args
[0]);
2237 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2239 node
->cursel
= node
->autosel
- 1;
2240 debug("Auto install template auto select %d\n", node
->autosel
);
2244 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2250 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2251 " echo %s\n}\n", "123");
2253 for (i
= 0; i
< node
->templatenum
; i
++)
2255 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2257 node
->templatepath
[i
].path
);
2260 g_ventoy_menu_esc
= 1;
2261 g_ventoy_suppress_esc
= 1;
2263 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2264 grub_script_execute_sourcecode(configfile
);
2266 g_ventoy_menu_esc
= 0;
2267 g_ventoy_suppress_esc
= 0;
2271 node
->cursel
= g_ventoy_last_entry
- 1;
2273 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2276 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2281 char configfile
[128];
2282 persistence_config
*node
;
2288 debug("select persistence argc:%d\n", argc
);
2295 node
= ventoy_plugin_find_persistent(args
[0]);
2298 debug("Persistence image not found for %s\n", args
[0]);
2302 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2304 node
->cursel
= node
->autosel
- 1;
2305 debug("Persistence image auto select %d\n", node
->autosel
);
2309 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2315 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2316 " echo %s\n}\n", "123");
2318 for (i
= 0; i
< node
->backendnum
; i
++)
2320 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2322 node
->backendpath
[i
].path
);
2326 g_ventoy_menu_esc
= 1;
2327 g_ventoy_suppress_esc
= 1;
2329 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2330 grub_script_execute_sourcecode(configfile
);
2332 g_ventoy_menu_esc
= 0;
2333 g_ventoy_suppress_esc
= 0;
2337 node
->cursel
= g_ventoy_last_entry
- 1;
2339 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2342 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2345 ventoy_img_chunk
*cur
;
2351 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2353 cur
= g_img_chunk_list
.chunk
+ i
;
2354 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2355 cur
->img_start_sector
, cur
->img_end_sector
,
2356 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2360 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2363 #ifdef GRUB_MACHINE_EFI
2364 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2372 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2375 ulong chain_len
= 0;
2376 char *chain_data
= NULL
;
2377 char *relocator_addr
= NULL
;
2378 grub_relocator_chunk_t ch
;
2379 struct grub_relocator
*relocator
= NULL
;
2380 char envbuf
[64] = { 0 };
2391 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2392 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2394 relocator
= grub_relocator_new ();
2397 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2401 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2402 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2406 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2407 grub_relocator_unload (relocator
);
2411 relocator_addr
= get_virtual_current_address(ch
);
2413 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2415 grub_relocator_unload (relocator
);
2417 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2418 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2420 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2424 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2428 ventoy_img_chunk_list chunklist
;
2433 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2436 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2439 /* get image chunk data */
2440 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2441 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2442 if (NULL
== chunklist
.chunk
)
2444 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2447 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2448 chunklist
.cur_chunk
= 0;
2450 ventoy_get_block_list(file
, &chunklist
, 0);
2452 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2454 grub_printf("########## UNSUPPORTED ###############\n");
2457 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2459 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2461 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2462 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2465 grub_printf("\n==================================\n");
2467 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2469 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2470 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2471 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2472 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2473 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2477 grub_free(chunklist
.chunk
);
2478 grub_file_close(file
);
2480 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2483 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2486 ventoy_grub_param_file_replace
*replace
= NULL
;
2494 replace
= &(g_grub_param
->file_replace
);
2495 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2497 replace
->old_name_cnt
= 0;
2498 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2500 replace
->old_name_cnt
++;
2501 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2504 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2507 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2510 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2518 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2519 grub_printf("%s", g_list_script_buf
);
2523 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2524 grub_printf("%s", g_tree_script_buf
);
2530 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2532 img_info
*cur
= g_ventoy_img_list
;
2540 grub_printf("path:<%s> id=%d\n", cur
->path
, cur
->id
);
2541 grub_printf("name:<%s>\n\n", cur
->name
);
2548 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2554 ventoy_plugin_dump_injection();
2559 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2565 ventoy_plugin_dump_auto_install();
2570 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2576 ventoy_plugin_dump_persistence();
2581 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2592 if (args
[0][0] == '0')
2594 return g_ventoy_memdisk_mode
? 0 : 1;
2596 else if (args
[0][0] == '1')
2598 return g_ventoy_iso_raw
? 0 : 1;
2600 else if (args
[0][0] == '2')
2602 return g_ventoy_iso_uefi_drv
? 0 : 1;
2608 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2610 static int configfile_mode
= 0;
2611 char memfile
[128] = {0};
2618 * args[0]: 0:normal 1:configfile
2619 * args[1]: 0:list_buf 1:tree_buf
2624 debug("Invalid argc %d\n", argc
);
2628 if (args
[0][0] == '0')
2630 if (args
[1][0] == '0')
2632 grub_script_execute_sourcecode(g_list_script_buf
);
2636 grub_script_execute_sourcecode(g_tree_script_buf
);
2641 if (configfile_mode
)
2643 debug("Now already in F3 mode %d\n", configfile_mode
);
2647 if (args
[1][0] == '0')
2649 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2650 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2654 g_ventoy_last_entry
= -1;
2655 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2656 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2659 configfile_mode
= 1;
2660 grub_script_execute_sourcecode(memfile
);
2661 configfile_mode
= 0;
2667 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2678 g_ventoy_case_insensitive
= 1;
2679 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2680 g_ventoy_case_insensitive
= 0;
2686 grub_file_close(file
);
2692 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2697 const char *isopath
= NULL
;
2699 ventoy_mbr_head mbr
;
2706 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2709 isopath
= grub_env_get("vtoy_iso_part");
2712 debug("isopath is null %p\n", isopath
);
2716 debug("isopath is %s\n", isopath
);
2718 for (id
= 0; id
< 30 && (find
== 0); id
++)
2720 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2721 if (grub_strstr(isopath
, hdname
))
2723 debug("skip %s ...\n", hdname
);
2727 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2729 disk
= grub_disk_open(hdname
);
2732 debug("%s not exist\n", hdname
);
2736 grub_memset(&mbr
, 0, sizeof(mbr
));
2737 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2739 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2741 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2742 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2745 grub_env_set(args
[0], hdname
);
2749 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2753 debug("read %s failed\n", hdname
);
2756 grub_disk_close(disk
);
2762 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2773 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2776 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2779 debug("failed to open file %s\n", args
[0]);
2783 buf
= grub_malloc(len
);
2790 grub_file_read(file
, buf
, len
- 1);
2792 ventoy_get_line(buf
);
2793 ventoy_set_env(args
[1], buf
);
2797 grub_check_free(buf
);
2798 grub_file_close(file
);
2803 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
2808 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
2809 "0 %llu linear /dev/ventoy %llu\n",
2810 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
2815 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2817 char *device_name
= NULL
;
2818 grub_device_t dev
= NULL
;
2823 g_part_list_pos
= 0;
2824 grub_env_unset("vtoy_img_part_file");
2831 device_name
= grub_file_get_device_name(args
[0]);
2834 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
2838 dev
= grub_device_open(device_name
);
2841 debug("grub_device_open failed, %s\n", device_name
);
2845 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
2847 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
2848 grub_env_set("vtoy_img_part_file", buf
);
2852 check_free(device_name
, grub_free
);
2853 check_free(dev
, grub_device_close
);
2859 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2870 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
2873 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2876 debug("failed to open file %s\n", args
[0]);
2880 buf
= grub_malloc(file
->size
+ 1);
2886 buf
[file
->size
] = 0;
2887 grub_file_read(file
, buf
, file
->size
);
2889 if (grub_strstr(buf
, args
[1]))
2896 grub_check_free(buf
);
2897 grub_file_close(file
);
2902 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2907 ventoy_iso9660_vd pvd
;
2914 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
2917 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2920 debug("failed to open file %s\n", args
[0]);
2924 grub_file_seek(file
, 16 * 2048);
2925 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
2926 if (len
!= sizeof(pvd
))
2928 debug("failed to read pvd %d\n", len
);
2932 grub_memset(buf
, 0, sizeof(buf
));
2933 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
2934 ventoy_set_env(args
[1], buf
);
2936 grub_memset(buf
, 0, sizeof(buf
));
2937 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
2938 ventoy_set_env(args
[2], buf
);
2941 grub_file_close(file
);
2946 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2957 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
2960 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2963 debug("failed to open file %s\n", args
[0]);
2967 grub_memset(buf
, 0, sizeof(buf
));
2968 grub_file_seek(file
, 16 * 2048 + 813);
2969 len
= (int)grub_file_read(file
, buf
, 17);
2972 debug("failed to read create date %d\n", len
);
2976 ventoy_set_env(args
[1], buf
);
2979 grub_file_close(file
);
2984 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2990 ventoy_env_hook_root(1);
2995 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3001 ventoy_env_hook_root(0);
3006 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3013 int image_sector_size
;
3015 ventoy_chain_head
*chain
;
3016 ventoy_img_chunk
*chunk
;
3017 ventoy_os_param
*osparam
;
3018 ventoy_image_location
*location
;
3019 ventoy_image_disk_region
*region
;
3020 struct grub_acpi_table_header
*acpi
;
3029 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3031 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3037 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3039 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3041 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3045 img_chunk_num
= chain
->img_chunk_num
;
3047 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3048 datalen
= sizeof(ventoy_os_param
) + loclen
;
3050 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3051 acpi
= grub_zalloc(buflen
);
3057 /* Step1: Fill acpi table header */
3058 grub_memcpy(acpi
->signature
, "VTOY", 4);
3059 acpi
->length
= buflen
;
3061 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3062 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3064 acpi
->creator_id
[0] = 1;
3065 acpi
->creator_rev
= 1;
3067 /* Step2: Fill data */
3068 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3069 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3070 osparam
->vtoy_img_location_addr
= 0;
3071 osparam
->vtoy_img_location_len
= loclen
;
3072 osparam
->chksum
= 0;
3073 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3075 location
= (ventoy_image_location
*)(osparam
+ 1);
3076 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3077 location
->image_sector_size
= image_sector_size
;
3078 location
->disk_sector_size
= chain
->disk_sector_size
;
3079 location
->region_count
= img_chunk_num
;
3081 region
= location
->regions
;
3082 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3083 if (512 == image_sector_size
)
3085 for (i
= 0; i
< img_chunk_num
; i
++)
3087 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3088 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3089 region
->disk_start_sector
= chunk
->disk_start_sector
;
3096 for (i
= 0; i
< img_chunk_num
; i
++)
3098 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3099 region
->image_start_sector
= chunk
->img_start_sector
;
3100 region
->disk_start_sector
= chunk
->disk_start_sector
;
3106 /* Step3: Fill acpi checksum */
3108 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3110 /* load acpi table */
3111 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3112 grub_script_execute_sourcecode(cmd
);
3116 VENTOY_CMD_RETURN(0);
3119 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3125 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3126 g_ventoy_last_entry
= -1;
3131 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3137 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3142 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3144 const char *pos
= filename
+ 1;
3152 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3154 grub_strncpy((char *)data
, filename
, 128);
3165 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3168 char *device_name
= NULL
;
3169 grub_device_t dev
= NULL
;
3170 grub_fs_t fs
= NULL
;
3171 char buf
[128] = {0};
3177 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
3181 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
3183 device_name
= grub_file_get_device_name(args
[0]);
3186 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3190 dev
= grub_device_open(device_name
);
3193 debug("grub_device_open failed, %s\n", device_name
);
3197 fs
= grub_fs_probe(dev
);
3200 debug("grub_fs_probe failed, %s\n", device_name
);
3204 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
3208 ventoy_set_env(args
[2], buf
);
3215 check_free(device_name
, grub_free
);
3216 check_free(dev
, grub_device_close
);
3221 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3231 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
3232 if (!g_ventoy_part_info
)
3237 disk
= grub_disk_open(args
[0]);
3240 debug("Failed to open disk %s\n", args
[0]);
3244 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
3245 grub_disk_close(disk
);
3247 grub_snprintf(name
, sizeof(name
), "%s,1", args
[0]);
3248 dev
= grub_device_open(name
);
3251 /* make sure that we are running in a correct Ventoy device */
3252 ret
= ventoy_check_device(dev
);
3253 grub_device_close(dev
);
3264 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3267 grub_uint8_t zeroguid
[16] = {0};
3272 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3275 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
3277 if (id
>= 1 && id
<= 128)
3279 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
3287 if (id
>= 1 && id
<= 4)
3289 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
3299 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3302 char *device_name
= NULL
;
3303 grub_device_t dev
= NULL
;
3304 grub_fs_t fs
= NULL
;
3311 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
3315 device_name
= grub_file_get_device_name(args
[0]);
3318 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3322 dev
= grub_device_open(device_name
);
3325 debug("grub_device_open failed, %s\n", device_name
);
3329 fs
= grub_fs_probe(dev
);
3332 debug("grub_fs_probe failed, %s\n", device_name
);
3336 fs
->fs_label(dev
, &label
);
3339 ventoy_set_env(args
[1], label
);
3347 check_free(device_name
, grub_free
);
3348 check_free(dev
, grub_device_close
);
3353 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3357 grub_snprintf((char *)data
, 256, "%s", filename
);
3365 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3368 char *device_name
= NULL
;
3369 grub_device_t dev
= NULL
;
3370 grub_fs_t fs
= NULL
;
3371 char name
[256] ={0};
3377 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc
);
3381 device_name
= grub_file_get_device_name(args
[0]);
3384 debug("grub_file_get_device_name failed, %s\n", args
[0]);
3388 dev
= grub_device_open(device_name
);
3391 debug("grub_device_open failed, %s\n", device_name
);
3395 fs
= grub_fs_probe(dev
);
3398 debug("grub_fs_probe failed, %s\n", device_name
);
3402 fs
->fs_dir(dev
, args
[1], ventoy_fs_enum_1st_file
, name
);
3405 ventoy_set_env(args
[2], name
);
3412 check_free(device_name
, grub_free
);
3413 check_free(dev
, grub_device_close
);
3418 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3428 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
3432 for (pos
= args
[0]; *pos
; pos
++)
3446 grub_env_set(args
[1], args
[0]);
3456 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3458 struct grub_video_mode_info info
;
3465 if (!g_video_mode_list
)
3467 ventoy_enum_video_mode();
3470 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3472 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
3476 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
3479 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
3481 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
3482 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
3484 VENTOY_CMD_RETURN(0);
3487 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3489 struct grub_video_mode_info info
;
3496 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
3498 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
3502 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
3505 grub_env_set(args
[0], buf
);
3507 VENTOY_CMD_RETURN(0);
3510 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3518 if (!g_video_mode_list
)
3523 id
= (int)grub_strtoul(args
[0], NULL
, 10);
3524 if (id
< g_video_mode_num
)
3526 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
3527 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
3530 grub_env_set(args
[1], buf
);
3532 VENTOY_CMD_RETURN(0);
3535 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
3537 grub_uint64_t size
= 0;
3540 char fullpath
[256] = {0};
3543 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3546 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
3549 debug("grub_file_open failed <%s>\n", fullpath
);
3555 grub_file_close(file
);
3559 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
3563 char fullpath
[256] = {0};
3566 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
3569 file
= grub_file_open(fullpath
, type
);
3572 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
3579 int ventoy_is_file_exist(const char *fmt
, ...)
3584 char buf
[256] = {0};
3586 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
3590 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3593 grub_strncpy(pos
+ len
, " ]", 2);
3595 debug("script exec %s\n", buf
);
3597 if (0 == grub_script_execute_sourcecode(buf
))
3605 int ventoy_is_dir_exist(const char *fmt
, ...)
3610 char buf
[256] = {0};
3612 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
3616 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
3619 grub_strncpy(pos
+ len
, " ]", 2);
3621 debug("script exec %s\n", buf
);
3623 if (0 == grub_script_execute_sourcecode(buf
))
3631 static int ventoy_env_init(void)
3635 grub_env_set("vtdebug_flag", "");
3637 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
3638 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3639 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3641 ventoy_filt_register(0, ventoy_wrapper_open
);
3643 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
3646 g_grub_param
->grub_env_get
= grub_env_get
;
3647 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
3648 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
3649 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
3650 grub_env_set("env_param", buf
);
3651 grub_env_set("ventoy_env_param", buf
);
3652 grub_env_export("ventoy_env_param");
3658 static cmd_para ventoy_cmds
[] =
3660 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
3661 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
3662 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
3663 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3664 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3665 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
3666 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
3667 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
3668 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
3669 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
3670 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
3671 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
3672 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
3673 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
3674 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
3675 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
3676 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
3677 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
3678 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
3679 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
3681 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
3682 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
3683 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
3684 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
3685 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
3686 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
3688 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
3689 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
3690 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
3691 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
3692 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
3693 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
3694 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
3695 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
3698 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
3699 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
3700 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
3701 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
3702 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
3703 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
3704 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
3705 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
3706 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
3707 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
3709 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
3710 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
3711 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
3712 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
3713 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
3714 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
3716 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3717 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3718 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
3719 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
3720 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
3721 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
3722 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
3723 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
3724 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
3725 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
3727 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
3728 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
3729 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
3730 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
3731 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
3732 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
3733 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
3735 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
3736 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
3737 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
3738 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
3741 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
3742 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
3744 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
3745 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
3746 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
3749 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
3750 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
3751 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
3752 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
3753 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
3754 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
3755 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
3756 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
3758 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
3759 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
3760 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
3766 GRUB_MOD_INIT(ventoy
)
3769 cmd_para
*cur
= NULL
;
3773 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3775 cur
= ventoy_cmds
+ i
;
3776 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
3777 cur
->summary
, cur
->description
, cur
->parser
);
3781 GRUB_MOD_FINI(ventoy
)
3785 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3787 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);