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/relocator.h>
43 #include <grub/ventoy.h>
44 #include "ventoy_def.h"
46 GRUB_MOD_LICENSE ("GPLv3+");
48 int g_ventoy_debug
= 0;
49 static int g_efi_os
= 0xFF;
50 initrd_info
*g_initrd_img_list
= NULL
;
51 initrd_info
*g_initrd_img_tail
= NULL
;
52 int g_initrd_img_count
= 0;
53 int g_valid_initrd_count
= 0;
54 int g_default_menu_mode
= 0;
55 int g_filt_dot_underscore_file
= 0;
56 static grub_file_t g_old_file
;
59 char g_img_swap_tmp_buf
[1024];
60 img_info g_img_swap_tmp
;
61 img_info
*g_ventoy_img_list
= NULL
;
63 int g_ventoy_img_count
= 0;
65 grub_device_t g_enum_dev
= NULL
;
66 grub_fs_t g_enum_fs
= NULL
;
67 img_iterator_node g_img_iterator_head
;
68 img_iterator_node
*g_img_iterator_tail
= NULL
;
70 grub_uint8_t g_ventoy_break_level
= 0;
71 grub_uint8_t g_ventoy_debug_level
= 0;
72 grub_uint8_t g_ventoy_chain_type
= 0;
74 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
75 grub_uint32_t g_ventoy_cpio_size
= 0;
76 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
77 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
79 ventoy_grub_param
*g_grub_param
= NULL
;
81 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
83 ventoy_img_chunk_list g_img_chunk_list
;
85 int g_wimboot_enable
= 0;
86 ventoy_img_chunk_list g_wimiso_chunk_list
;
87 char *g_wimiso_path
= NULL
;
89 static char *g_tree_script_buf
= NULL
;
90 static int g_tree_script_pos
= 0;
92 static char *g_list_script_buf
= NULL
;
93 static int g_list_script_pos
= 0;
95 static const char *g_menu_class
[] =
97 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg"
100 static const char *g_menu_prefix
[] =
102 "iso", "wim", "efi", "img"
105 void ventoy_debug(const char *fmt
, ...)
109 va_start (args
, fmt
);
110 grub_vprintf (fmt
, args
);
114 int ventoy_is_efi_os(void)
118 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
124 static int ventoy_get_fs_type(const char *fs
)
128 return ventoy_fs_max
;
130 else if (grub_strncmp(fs
, "exfat", 5) == 0)
132 return ventoy_fs_exfat
;
134 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
136 return ventoy_fs_ntfs
;
138 else if (grub_strncmp(fs
, "ext", 3) == 0)
140 return ventoy_fs_ext
;
142 else if (grub_strncmp(fs
, "xfs", 3) == 0)
144 return ventoy_fs_xfs
;
146 else if (grub_strncmp(fs
, "udf", 3) == 0)
148 return ventoy_fs_udf
;
150 else if (grub_strncmp(fs
, "fat", 3) == 0)
152 return ventoy_fs_fat
;
155 return ventoy_fs_max
;
158 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
177 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
179 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
183 static grub_err_t
ventoy_fs_close(grub_file_t file
)
185 grub_file_close(g_old_file
);
186 grub_free(file
->data
);
194 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
198 static struct grub_fs vtoy_fs
=
203 .fs_read
= ventoy_fs_read
,
204 .fs_close
= ventoy_fs_close
,
214 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
220 file
->data
= grub_malloc(rawFile
->size
+ 4096);
226 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
227 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
229 g_old_file
= rawFile
;
231 file
->size
= rawFile
->size
+ len
;
232 file
->device
= rawFile
->device
;
234 file
->not_easily_seekable
= 1;
239 static int ventoy_check_decimal_var(const char *name
, long *value
)
241 const char *value_str
= NULL
;
243 value_str
= grub_env_get(name
);
244 if (NULL
== value_str
)
246 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
249 if (!ventoy_is_decimal(value_str
))
251 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
254 *value
= grub_strtol(value_str
, NULL
, 10);
256 return GRUB_ERR_NONE
;
259 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
263 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
266 if (0 == grub_strcmp(args
[0], "on"))
269 grub_env_set("vtdebug_flag", "debug");
274 grub_env_set("vtdebug_flag", "");
277 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
280 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
284 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
286 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
287 grub_printf(" level:\r\n");
288 grub_printf(" 01/11: busybox / (+cat log)\r\n");
289 grub_printf(" 02/12: initrd / (+cat log)\r\n");
290 grub_printf(" 03/13: hook / (+cat log)\r\n");
292 grub_printf(" debug:\r\n");
293 grub_printf(" 0: debug is on\r\n");
294 grub_printf(" 1: debug is off\r\n");
296 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
299 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
301 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
303 g_ventoy_debug_level
= 1;
306 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
309 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
318 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
321 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
353 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
358 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
360 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
363 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
368 value_long
+= grub_strtol(args
[1], NULL
, 10);
370 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
371 grub_env_set(args
[0], buf
);
373 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
376 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
391 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
394 debug("failed to open file <%s> for udf check\n", args
[0]);
398 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
400 grub_env_set(args
[1], buf
);
402 grub_file_close(file
);
408 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
416 g_wimboot_enable
= 0;
417 grub_check_free(g_wimiso_path
);
418 grub_check_free(g_wimiso_chunk_list
.chunk
);
420 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
426 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
427 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
428 if (NULL
== g_wimiso_chunk_list
.chunk
)
430 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
433 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
434 g_wimiso_chunk_list
.cur_chunk
= 0;
436 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
438 g_wimboot_enable
= 1;
439 g_wimiso_path
= grub_strdup(args
[0]);
441 grub_file_close(file
);
446 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
452 grub_uint32_t offset
;
454 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
457 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
461 len
= (int)file
->size
;
463 data
= (char *)grub_malloc(file
->size
);
469 grub_file_read(file
, data
, file
->size
);
470 grub_file_close(file
);
472 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
473 grub_script_execute_sourcecode(exec
);
475 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
476 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
477 grub_file_close(file
);
479 grub_script_execute_sourcecode("loopback -d efiboot");
483 *direntoff
= offset
+ 2;
488 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
498 ventoy_iso9660_override
*dirent
;
507 totlen
= sizeof(ventoy_chain_head
);
509 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
511 debug("failed to load efiboot template %d\n", len
);
517 debug("efiboot template len:%d offset:%d\n", len
, offset
);
519 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
522 debug("failed to open file <%s>\n", args
[0]);
526 totlen
+= ventoy_align_2k(file
->size
);
528 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
529 dirent
->first_sector
= len
/ 2048;
530 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
531 dirent
->size
= (grub_uint32_t
)file
->size
;
532 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
534 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
536 #ifdef GRUB_MACHINE_EFI
537 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
539 data
= (char *)grub_malloc(totlen
);
542 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
544 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
545 grub_check_free(buf
);
547 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
548 grub_file_close(file
);
550 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
551 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
552 grub_env_set(name
, value
);
554 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
555 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
556 grub_env_set(name
, value
);
561 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
578 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
581 debug("failed to open file <%s>\n", args
[0]);
585 #ifdef GRUB_MACHINE_EFI
586 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
588 buf
= (char *)grub_malloc(file
->size
);
591 grub_file_read(file
, buf
, file
->size
);
593 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
594 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
595 grub_env_set(name
, value
);
597 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
598 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
599 grub_env_set(name
, value
);
601 grub_file_close(file
);
607 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
625 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
628 debug("failed to open file <%s> for udf check\n", args
[0]);
632 headlen
= sizeof(ventoy_chain_head
);
634 #ifdef GRUB_MACHINE_EFI
635 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
637 buf
= (char *)grub_malloc(headlen
+ file
->size
);
640 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
642 grub_file_read(file
, buf
+ headlen
, file
->size
);
644 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
645 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
646 grub_env_set(name
, value
);
648 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
649 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
650 grub_env_set(name
, value
);
652 grub_file_close(file
);
658 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
667 if (args
[0][0] == '1')
669 grub_iso9660_set_nojoliet(1);
673 grub_iso9660_set_nojoliet(0);
679 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
684 grub_uint8_t buf
[32];
695 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
698 debug("failed to open file <%s> for udf check\n", args
[0]);
702 for (i
= 16; i
< 32; i
++)
704 grub_file_seek(file
, i
* 2048);
705 grub_file_read(file
, buf
, sizeof(buf
));
713 grub_file_seek(file
, i
* 2048);
714 grub_file_read(file
, buf
, sizeof(buf
));
716 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
719 grub_file_seek(file
, i
* 2048);
720 grub_file_read(file
, buf
, sizeof(buf
));
722 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
723 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
729 grub_file_close(file
);
731 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
736 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
738 long value_long1
= 0;
739 long value_long2
= 0;
741 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
743 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
746 value_long1
= grub_strtol(args
[0], NULL
, 10);
747 value_long2
= grub_strtol(args
[2], NULL
, 10);
749 if (0 == grub_strcmp(args
[1], "eq"))
751 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
753 else if (0 == grub_strcmp(args
[1], "ne"))
755 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
757 else if (0 == grub_strcmp(args
[1], "gt"))
759 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
761 else if (0 == grub_strcmp(args
[1], "lt"))
763 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
765 else if (0 == grub_strcmp(args
[1], "ge"))
767 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
769 else if (0 == grub_strcmp(args
[1], "le"))
771 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
775 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
781 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
788 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
791 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
792 pos
= grub_strstr(buf
, ",");
798 grub_env_set(args
[1], buf
);
800 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
803 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
809 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
815 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
818 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
820 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
821 if (0 == grub_script_execute_sourcecode(buf
))
823 debug("file %s exist, ventoy_compatible YES\n", buf
);
824 grub_env_set("ventoy_compatible", "YES");
825 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
829 debug("file %s NOT exist\n", buf
);
833 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
834 pos
= grub_strstr(buf
, ")");
840 disk
= grub_disk_open(buf
);
843 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
844 grub_disk_close(disk
);
846 g_img_swap_tmp_buf
[703] = 0;
847 for (i
= 319; i
< 703; i
++)
849 if (g_img_swap_tmp_buf
[i
] == 'V' &&
850 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
852 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
853 grub_env_set("ventoy_compatible", "YES");
854 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
860 debug("failed to open disk <%s>\n", buf
);
863 grub_env_set("ventoy_compatible", "NO");
864 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
867 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
873 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
878 if (grub_islower(c1
))
883 if (grub_islower(c2
))
897 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
899 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
901 grub_memcpy(img1
, img2
, sizeof(img_info
));
902 img1
->next
= g_img_swap_tmp
.next
;
903 img1
->prev
= g_img_swap_tmp
.prev
;
905 g_img_swap_tmp
.next
= img2
->next
;
906 g_img_swap_tmp
.prev
= img2
->prev
;
907 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
910 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
914 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
919 for (i
= 0; i
< namelen
; i
++)
921 if (filename
[i
] == ' ' || filename
[i
] == '\t')
926 if ((grub_uint8_t
)(filename
[i
]) >= 127)
935 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
939 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
949 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
957 img_iterator_node
*tmp
;
958 img_iterator_node
*new_node
;
959 img_iterator_node
*node
= (img_iterator_node
*)data
;
961 len
= grub_strlen(filename
);
965 if ((len
== 1 && filename
[0] == '.') ||
966 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
971 if (!ventoy_img_name_valid(filename
, len
))
976 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
981 new_node
= grub_zalloc(sizeof(img_iterator_node
));
984 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
986 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
989 debug("Directory %s ignored...\n", new_node
->dir
);
994 new_node
->tail
= node
->tail
;
996 new_node
->parent
= node
;
997 if (!node
->firstchild
)
999 node
->firstchild
= new_node
;
1002 if (g_img_iterator_tail
)
1004 g_img_iterator_tail
->next
= new_node
;
1005 g_img_iterator_tail
= new_node
;
1009 g_img_iterator_head
.next
= new_node
;
1010 g_img_iterator_tail
= new_node
;
1016 debug("Find a file %s\n", filename
);
1022 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1024 type
= img_type_iso
;
1026 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1028 type
= img_type_wim
;
1030 #ifdef GRUB_MACHINE_EFI
1031 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1033 type
= img_type_efi
;
1036 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1038 if (len
== 18 && grub_strncmp(filename
, "ventoy_wimboot", 14) == 0)
1042 type
= img_type_img
;
1049 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1054 img
= grub_zalloc(sizeof(img_info
));
1058 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1060 for (i
= 0; i
< (int)len
; i
++)
1062 if (filename
[i
] == ' ' || filename
[i
] == '\t' || (0 == grub_isprint(filename
[i
])))
1069 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1071 img
->size
= info
->size
;
1074 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1077 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1079 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1084 if (g_ventoy_img_list
)
1086 tail
= *(node
->tail
);
1092 g_ventoy_img_list
= img
;
1095 img
->id
= g_ventoy_img_count
;
1097 if (node
&& NULL
== node
->firstiso
)
1099 node
->firstiso
= img
;
1110 *((img_info
**)(node
->tail
)) = img
;
1111 g_ventoy_img_count
++;
1113 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1114 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1117 img
->class = g_menu_class
[type
];
1119 img
->menu_prefix
= g_menu_prefix
[type
];
1121 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1128 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1130 int len
= GRUB_UINT_MAX
;
1131 const char *value
= NULL
;
1132 char name
[32] = {0};
1133 char plat
[32] = {0};
1134 char guidstr
[32] = {0};
1135 ventoy_guid guid
= VENTOY_GUID
;
1136 const char *fmt1
= NULL
;
1137 const char *fmt2
= NULL
;
1138 const char *fmt3
= NULL
;
1139 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1140 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1141 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1142 const char fmtcode
[]={
1143 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1144 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1145 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1146 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1147 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1148 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1151 grub_memset(name
, 0, sizeof(name
));
1152 puint
[0] = grub_swap_bytes32(0x56454e54);
1153 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1154 puint
[2] = grub_swap_bytes32(0x45525349);
1155 puint
[1] = grub_swap_bytes32(0x4f595f56);
1156 value
= ventoy_get_env(name
);
1158 grub_memset(name
, 0, sizeof(name
));
1159 puint
[1] = grub_swap_bytes32(0x5f544f50);
1160 puint
[0] = grub_swap_bytes32(0x56544c45);
1161 fmt1
= ventoy_get_env(name
);
1167 grub_memset(name
, 0, sizeof(name
));
1168 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1169 puint
[0] = grub_swap_bytes32(0x56544c45);
1170 fmt2
= ventoy_get_env(name
);
1172 grub_memset(name
, 0, sizeof(name
));
1173 puint
[1] = grub_swap_bytes32(0x5f434c52);
1174 puint
[0] = grub_swap_bytes32(0x56544c45);
1175 fmt3
= ventoy_get_env(name
);
1177 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1179 #if defined (GRUB_MACHINE_EFI)
1180 puint2
[0] = grub_swap_bytes32(0x55454649);
1182 puint2
[0] = grub_swap_bytes32(0x42494f53);
1185 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1186 #pragma GCC diagnostic push
1187 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1188 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1189 fmt1
? fmt1
: fmtdata
,
1190 fmt2
? fmt2
: fmtdata
+ 4,
1191 value
? value
: "", plat
, guidstr
,
1192 fmt3
? fmt3
: fmtdata
+ 6);
1193 #pragma GCC diagnostic pop
1195 grub_memset(name
, 0, sizeof(name
));
1196 puint
[0] = grub_swap_bytes32(0x76746f79);
1197 puint
[2] = grub_swap_bytes32(0x656e7365);
1198 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1199 ventoy_set_env(name
, guidstr
);
1204 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1206 img_info
*minimg
= NULL
;
1207 img_info
*img
= (img_info
*)(node
->firstiso
);
1209 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1211 if (img
->select
== 0 && (NULL
== minimg
|| grub_strcmp(img
->name
, minimg
->name
) < 0))
1226 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1228 img_iterator_node
*Minchild
= NULL
;
1229 img_iterator_node
*child
= node
->firstchild
;
1231 while (child
&& child
->parent
== node
)
1233 if (child
->select
== 0 && (NULL
== Minchild
|| grub_strcmp(child
->dir
, Minchild
->dir
) < 0))
1237 child
= child
->next
;
1242 Minchild
->select
= 1;
1248 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1251 img_info
*img
= NULL
;
1252 const char *dir_class
= NULL
;
1253 const char *dir_alias
= NULL
;
1254 img_iterator_node
*child
= NULL
;
1256 if (node
->isocnt
== 0 || node
->done
== 1)
1261 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1263 offset
= node
->parent
->dirlen
;
1266 if (node
== &g_img_iterator_head
)
1268 if (g_default_menu_mode
== 0)
1270 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1271 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1272 " echo 'return ...' \n"
1278 node
->dir
[node
->dirlen
- 1] = 0;
1279 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1282 dir_class
= "vtoydir";
1285 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1288 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1289 "submenu \"%-10s %s\" --class=\"%s\" {\n",
1290 "DIR", dir_alias
, dir_class
);
1294 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1295 "submenu \"%-10s [%s]\" --class=\"%s\" {\n",
1296 "DIR", node
->dir
+ offset
, dir_class
);
1299 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1300 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1301 " echo 'return ...' \n"
1305 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1307 ventoy_dynamic_tree_menu(child
);
1310 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1312 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1313 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1316 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1317 img
->unsupport
? "[unsupported] " : "",
1318 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1320 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1323 if (node
!= &g_img_iterator_head
)
1325 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1332 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1336 grub_device_t dev
= NULL
;
1337 img_info
*cur
= NULL
;
1338 img_info
*tail
= NULL
;
1339 img_info
*default_node
= NULL
;
1340 const char *strdata
= NULL
;
1341 char *device_name
= NULL
;
1342 const char *default_image
= NULL
;
1345 img_iterator_node
*node
= NULL
;
1346 img_iterator_node
*tmp
= NULL
;
1352 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1355 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1357 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1360 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1361 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1363 g_filt_dot_underscore_file
= 1;
1366 device_name
= grub_file_get_device_name(args
[0]);
1372 g_enum_dev
= dev
= grub_device_open(device_name
);
1378 g_enum_fs
= fs
= grub_fs_probe(dev
);
1384 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1386 debug("unsupported fs:<%s>\n", fs
->name
);
1387 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1391 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1392 if (strdata
&& strdata
[0] == '1')
1394 g_default_menu_mode
= 1;
1397 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1399 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1401 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1402 if (strdata
&& strdata
[0] == '/')
1404 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1405 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1407 g_img_iterator_head
.dir
[len
++] = '/';
1409 g_img_iterator_head
.dirlen
= len
;
1413 g_img_iterator_head
.dirlen
= 1;
1414 grub_strcpy(g_img_iterator_head
.dir
, "/");
1417 g_img_iterator_head
.tail
= &tail
;
1419 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1421 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1424 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1426 ventoy_dynamic_tree_menu(node
);
1430 node
= g_img_iterator_head
.next
;
1438 /* sort image list by image name */
1439 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1441 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1443 if (ventoy_cmp_img(cur
, tail
) > 0)
1445 ventoy_swap_img(cur
, tail
);
1450 if (g_default_menu_mode
== 1)
1452 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1453 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1454 " echo 'return ...' \n"
1458 if (g_default_menu_mode
== 0)
1460 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1463 img_len
= grub_strlen(default_image
);
1467 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1469 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1470 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1473 cur
->unsupport
? "[unsupported] " : "",
1474 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1476 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1478 if (g_default_menu_mode
== 0 && default_image
&& default_node
== NULL
)
1480 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1489 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1492 g_list_script_buf
[g_list_script_pos
] = 0;
1494 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1495 grub_env_set(args
[1], buf
);
1499 check_free(device_name
, grub_free
);
1500 check_free(dev
, grub_device_close
);
1502 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1506 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1508 img_info
*next
= NULL
;
1509 img_info
*cur
= g_ventoy_img_list
;
1522 g_ventoy_img_list
= NULL
;
1523 g_ventoy_img_count
= 0;
1525 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1528 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1531 img_info
*cur
= g_ventoy_img_list
;
1535 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1537 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1540 img_id
= grub_strtol(args
[0], NULL
, 10);
1541 if (img_id
>= g_ventoy_img_count
)
1543 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
1546 debug("Find image %ld name \n", img_id
);
1548 while (cur
&& img_id
> 0)
1556 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
1559 debug("image name is %s\n", cur
->name
);
1561 grub_env_set(args
[1], cur
->name
);
1563 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1566 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1571 const char *id
= NULL
;
1572 img_info
*cur
= g_ventoy_img_list
;
1576 if (argc
< 1 || argc
> 2)
1578 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
1581 id
= grub_env_get("chosen");
1583 pos
= grub_strstr(id
, "VID_");
1586 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
1590 img_id
= (int)grub_strtoul(id
, NULL
, 10);
1595 if (img_id
== cur
->id
)
1604 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
1607 grub_env_set(args
[0], cur
->path
);
1611 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
1612 grub_env_set(args
[1], value
);
1615 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1618 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
)
1625 device_name
= grub_file_get_device_name(filename
);
1637 pos2
= grub_strstr(pos
, ",");
1640 pos2
= grub_strstr(pos
, ")");
1648 disk
= grub_disk_open(pos
);
1651 grub_disk_read(disk
, 0, 0x180, 16, guid
);
1652 grub_disk_close(disk
);
1659 grub_free(device_name
);
1663 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
1665 eltorito_descriptor desc
;
1667 grub_memset(&desc
, 0, sizeof(desc
));
1668 grub_file_seek(file
, 17 * 2048);
1669 grub_file_read(file
, &desc
, sizeof(desc
));
1671 if (desc
.type
!= 0 || desc
.version
!= 1)
1676 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
1677 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
1685 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
1689 grub_uint8_t buf
[512];
1691 grub_file_seek(file
, sector
* 2048);
1692 grub_file_read(file
, buf
, sizeof(buf
));
1694 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
1696 debug("%s efi eltorito in Validation Entry\n", file
->name
);
1700 if (buf
[0] == 0x01 && buf
[1] == 0x00)
1705 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
1707 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
1709 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1713 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
1715 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1720 debug("%s does not contain efi eltorito\n", file
->name
);
1724 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
1727 const char *fs
= NULL
;
1728 const char *cdprompt
= NULL
;
1730 grub_uint8_t chksum
= 0;
1733 disk
= file
->device
->disk
;
1734 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
1736 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
1737 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
1738 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
1740 pos
= grub_strstr(file
->name
, "/");
1746 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
1748 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
);
1750 param
->vtoy_img_size
= file
->size
;
1752 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
1753 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
1755 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
1757 /* Windows CD/DVD prompt 0:suppress 1:reserved */
1758 param
->vtoy_reserved
[4] = 0;
1759 if (g_ventoy_chain_type
== 1) /* Windows */
1761 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
1762 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
1764 param
->vtoy_reserved
[4] = 1;
1768 fs
= ventoy_get_env("ventoy_fs_probe");
1769 if (fs
&& grub_strcmp(fs
, "udf") == 0)
1771 param
->vtoy_reserved
[3] = 1;
1774 /* calculate checksum */
1775 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
1777 chksum
+= *((grub_uint8_t
*)param
+ i
);
1779 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
1784 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
1786 grub_uint32_t i
= 0;
1787 grub_uint64_t total
= 0;
1788 ventoy_img_chunk
*chunk
= NULL
;
1790 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
1792 chunk
= chunklist
->chunk
+ i
;
1794 if (chunk
->disk_start_sector
<= start
)
1796 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
1800 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
1803 if (total
!= ((file
->size
+ 511) / 512))
1805 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
1812 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
1815 grub_uint32_t i
= 0;
1816 grub_uint32_t sector
= 0;
1817 grub_uint32_t count
= 0;
1818 grub_off_t size
= 0;
1819 grub_off_t read
= 0;
1821 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
1822 if (fs_type
== ventoy_fs_exfat
)
1824 grub_fat_get_file_chunk(start
, file
, chunklist
);
1826 else if (fs_type
== ventoy_fs_ext
)
1828 grub_ext_get_file_chunk(start
, file
, chunklist
);
1832 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
1833 file
->read_hook_data
= chunklist
;
1835 for (size
= file
->size
; size
> 0; size
-= read
)
1837 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
1838 grub_file_read(file
, NULL
, read
);
1841 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
1843 chunklist
->chunk
[i
].disk_start_sector
+= start
;
1844 chunklist
->chunk
[i
].disk_end_sector
+= start
;
1847 if (ventoy_fs_udf
== fs_type
)
1849 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
1851 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
1852 chunklist
->chunk
[i
].img_start_sector
= sector
;
1853 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
1862 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1866 grub_disk_addr_t start
;
1871 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1874 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
1877 if (g_img_chunk_list
.chunk
)
1879 grub_free(g_img_chunk_list
.chunk
);
1882 /* get image chunk data */
1883 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
1884 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1885 if (NULL
== g_img_chunk_list
.chunk
)
1887 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1890 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1891 g_img_chunk_list
.cur_chunk
= 0;
1893 start
= file
->device
->disk
->partition
->start
;
1895 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
1897 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
1898 grub_file_close(file
);
1902 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
1905 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
1906 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1909 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1914 char configfile
[128];
1915 install_template
*node
= NULL
;
1921 debug("select auto installation argc:%d\n", argc
);
1928 node
= ventoy_plugin_find_install_template(args
[0]);
1931 debug("Auto install template not found for %s\n", args
[0]);
1935 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
1937 node
->cursel
= node
->autosel
- 1;
1938 debug("Auto install template auto select %d\n", node
->autosel
);
1942 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
1948 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
1949 " echo %s\n}\n", "123");
1951 for (i
= 0; i
< node
->templatenum
; i
++)
1953 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
1955 node
->templatepath
[i
].path
);
1958 g_ventoy_menu_esc
= 1;
1959 g_ventoy_suppress_esc
= 1;
1961 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
1962 grub_script_execute_sourcecode(configfile
);
1964 g_ventoy_menu_esc
= 0;
1965 g_ventoy_suppress_esc
= 0;
1969 node
->cursel
= g_ventoy_last_entry
- 1;
1971 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1974 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1979 char configfile
[128];
1980 persistence_config
*node
;
1986 debug("select persistence argc:%d\n", argc
);
1993 node
= ventoy_plugin_find_persistent(args
[0]);
1996 debug("Persistence image not found for %s\n", args
[0]);
2000 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2002 node
->cursel
= node
->autosel
- 1;
2003 debug("Persistence image auto select %d\n", node
->autosel
);
2007 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2013 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2014 " echo %s\n}\n", "123");
2016 for (i
= 0; i
< node
->backendnum
; i
++)
2018 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2020 node
->backendpath
[i
].path
);
2024 g_ventoy_menu_esc
= 1;
2025 g_ventoy_suppress_esc
= 1;
2027 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2028 grub_script_execute_sourcecode(configfile
);
2030 g_ventoy_menu_esc
= 0;
2031 g_ventoy_suppress_esc
= 0;
2035 node
->cursel
= g_ventoy_last_entry
- 1;
2037 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2040 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2043 ventoy_img_chunk
*cur
;
2049 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2051 cur
= g_img_chunk_list
.chunk
+ i
;
2052 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2053 cur
->img_start_sector
, cur
->img_end_sector
,
2054 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2058 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2061 #ifdef GRUB_MACHINE_EFI
2062 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2070 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2073 ulong chain_len
= 0;
2074 char *chain_data
= NULL
;
2075 char *relocator_addr
= NULL
;
2076 grub_relocator_chunk_t ch
;
2077 struct grub_relocator
*relocator
= NULL
;
2078 char envbuf
[64] = { 0 };
2089 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2090 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2092 relocator
= grub_relocator_new ();
2095 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2099 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2100 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2104 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2105 grub_relocator_unload (relocator
);
2109 relocator_addr
= get_virtual_current_address(ch
);
2111 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2113 grub_relocator_unload (relocator
);
2115 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2116 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2118 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2122 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2126 ventoy_img_chunk_list chunklist
;
2131 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2134 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2137 /* get image chunk data */
2138 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2139 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2140 if (NULL
== chunklist
.chunk
)
2142 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2145 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2146 chunklist
.cur_chunk
= 0;
2148 ventoy_get_block_list(file
, &chunklist
, 0);
2150 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2152 grub_printf("########## UNSUPPORTED ###############\n");
2155 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2157 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2159 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2160 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2163 grub_printf("\n==================================\n");
2165 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2167 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2168 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2169 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2170 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2171 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2175 grub_free(chunklist
.chunk
);
2176 grub_file_close(file
);
2178 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2181 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2184 ventoy_grub_param_file_replace
*replace
= NULL
;
2192 replace
= &(g_grub_param
->file_replace
);
2193 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2195 replace
->old_name_cnt
= 0;
2196 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2198 replace
->old_name_cnt
++;
2199 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2202 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2205 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2208 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2216 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2217 grub_printf("%s", g_list_script_buf
);
2221 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2222 grub_printf("%s", g_tree_script_buf
);
2228 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2230 img_info
*cur
= g_ventoy_img_list
;
2238 grub_printf("path:<%s> id=%d\n", cur
->path
, cur
->id
);
2239 grub_printf("name:<%s>\n\n", cur
->name
);
2246 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2252 ventoy_plugin_dump_injection();
2257 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2263 ventoy_plugin_dump_auto_install();
2268 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2274 ventoy_plugin_dump_persistence();
2279 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2290 if (args
[0][0] == '0')
2292 return g_ventoy_memdisk_mode
? 0 : 1;
2294 else if (args
[0][0] == '1')
2296 return g_ventoy_iso_raw
? 0 : 1;
2298 else if (args
[0][0] == '2')
2300 return g_ventoy_iso_uefi_drv
? 0 : 1;
2306 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2308 static int configfile_mode
= 0;
2309 char memfile
[128] = {0};
2316 * args[0]: 0:normal 1:configfile
2317 * args[1]: 0:list_buf 1:tree_buf
2322 debug("Invalid argc %d\n", argc
);
2326 if (args
[0][0] == '0')
2328 if (args
[1][0] == '0')
2330 grub_script_execute_sourcecode(g_list_script_buf
);
2334 grub_script_execute_sourcecode(g_tree_script_buf
);
2339 if (configfile_mode
)
2341 debug("Now already in F3 mode %d\n", configfile_mode
);
2345 if (args
[1][0] == '0')
2347 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2348 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2352 g_ventoy_last_entry
= -1;
2353 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2354 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2357 configfile_mode
= 1;
2358 grub_script_execute_sourcecode(memfile
);
2359 configfile_mode
= 0;
2365 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2376 g_ventoy_case_insensitive
= 1;
2377 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2378 g_ventoy_case_insensitive
= 0;
2384 grub_file_close(file
);
2390 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2395 const char *isopath
= NULL
;
2397 ventoy_mbr_head mbr
;
2404 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2407 isopath
= grub_env_get("vtoy_iso_part");
2410 debug("isopath is null %p\n", isopath
);
2414 debug("isopath is %s\n", isopath
);
2416 for (id
= 0; id
< 30 && (find
== 0); id
++)
2418 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2419 if (grub_strstr(isopath
, hdname
))
2421 debug("skip %s ...\n", hdname
);
2425 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2427 disk
= grub_disk_open(hdname
);
2430 debug("%s not exist\n", hdname
);
2434 grub_memset(&mbr
, 0, sizeof(mbr
));
2435 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2437 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2439 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2440 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2443 grub_env_set(args
[0], hdname
);
2447 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2451 debug("read %s failed\n", hdname
);
2454 grub_disk_close(disk
);
2460 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2471 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2474 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2477 debug("failed to open file %s\n", args
[0]);
2481 buf
= grub_malloc(len
);
2488 grub_file_read(file
, buf
, len
- 1);
2490 ventoy_get_line(buf
);
2491 ventoy_set_env(args
[1], buf
);
2495 grub_check_free(buf
);
2496 grub_file_close(file
);
2501 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2506 ventoy_iso9660_vd pvd
;
2513 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
2516 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2519 debug("failed to open file %s\n", args
[0]);
2523 grub_file_seek(file
, 16 * 2048);
2524 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
2525 if (len
!= sizeof(pvd
))
2527 debug("failed to read pvd %d\n", len
);
2531 grub_memset(buf
, 0, sizeof(buf
));
2532 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
2533 ventoy_set_env(args
[1], buf
);
2535 grub_memset(buf
, 0, sizeof(buf
));
2536 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
2537 ventoy_set_env(args
[2], buf
);
2540 grub_file_close(file
);
2545 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2556 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
2559 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2562 debug("failed to open file %s\n", args
[0]);
2566 grub_memset(buf
, 0, sizeof(buf
));
2567 grub_file_seek(file
, 16 * 2048 + 813);
2568 len
= (int)grub_file_read(file
, buf
, 17);
2571 debug("failed to read create date %d\n", len
);
2575 ventoy_set_env(args
[1], buf
);
2578 grub_file_close(file
);
2583 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2589 ventoy_env_hook_root(1);
2594 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2600 ventoy_env_hook_root(0);
2605 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
2607 grub_uint64_t size
= 0;
2610 char fullpath
[256] = {0};
2613 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
2616 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
2619 debug("grub_file_open failed <%s>\n", fullpath
);
2625 grub_file_close(file
);
2629 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
2633 char fullpath
[256] = {0};
2636 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
2639 file
= grub_file_open(fullpath
, type
);
2642 debug("grub_file_open failed <%s>\n", fullpath
);
2649 int ventoy_is_file_exist(const char *fmt
, ...)
2654 char buf
[256] = {0};
2656 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
2660 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
2663 grub_strncpy(pos
+ len
, " ]", 2);
2665 debug("script exec %s\n", buf
);
2667 if (0 == grub_script_execute_sourcecode(buf
))
2675 int ventoy_is_dir_exist(const char *fmt
, ...)
2680 char buf
[256] = {0};
2682 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
2686 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
2689 grub_strncpy(pos
+ len
, " ]", 2);
2691 debug("script exec %s\n", buf
);
2693 if (0 == grub_script_execute_sourcecode(buf
))
2701 static int ventoy_env_init(void)
2705 grub_env_set("vtdebug_flag", "");
2707 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2708 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2710 ventoy_filt_register(0, ventoy_wrapper_open
);
2712 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
2715 g_grub_param
->grub_env_get
= grub_env_get
;
2716 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
2717 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
2718 grub_env_set("env_param", buf
);
2724 static cmd_para ventoy_cmds
[] =
2726 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
2727 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
2728 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
2729 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
2730 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
2731 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
2732 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
2733 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
2734 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
2735 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
2736 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
2737 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
2738 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
2739 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
2740 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
2741 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
2743 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
2744 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
2746 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
2747 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
2748 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
2749 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
2750 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
2751 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
2752 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
2753 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
2754 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
2755 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
2757 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
2758 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
2759 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
2760 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
2761 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
2762 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
2764 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
2765 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
2766 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
2767 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
2768 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
2769 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
2770 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
2771 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
2772 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
2773 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
2775 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
2776 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
2777 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
2778 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
2779 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
2780 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
2781 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
2783 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
2784 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
2785 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
2786 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
2789 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
2790 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
2792 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
2793 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
2794 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
2795 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
2796 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
2797 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
2798 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
2799 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
2800 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
2802 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
2803 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
2809 GRUB_MOD_INIT(ventoy
)
2812 cmd_para
*cur
= NULL
;
2816 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
2818 cur
= ventoy_cmds
+ i
;
2819 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
2820 cur
->summary
, cur
->description
, cur
->parser
);
2824 GRUB_MOD_FINI(ventoy
)
2828 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
2830 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);