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
;
57 static int g_ventoy_last_entry_back
;
60 char g_img_swap_tmp_buf
[1024];
61 img_info g_img_swap_tmp
;
62 img_info
*g_ventoy_img_list
= NULL
;
64 int g_ventoy_img_count
= 0;
66 grub_device_t g_enum_dev
= NULL
;
67 grub_fs_t g_enum_fs
= NULL
;
68 img_iterator_node g_img_iterator_head
;
69 img_iterator_node
*g_img_iterator_tail
= NULL
;
71 grub_uint8_t g_ventoy_break_level
= 0;
72 grub_uint8_t g_ventoy_debug_level
= 0;
73 grub_uint8_t g_ventoy_chain_type
= 0;
75 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
76 grub_uint32_t g_ventoy_cpio_size
= 0;
77 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
78 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
80 ventoy_grub_param
*g_grub_param
= NULL
;
82 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
84 ventoy_img_chunk_list g_img_chunk_list
;
86 int g_wimboot_enable
= 0;
87 ventoy_img_chunk_list g_wimiso_chunk_list
;
88 char *g_wimiso_path
= NULL
;
90 static char *g_tree_script_buf
= NULL
;
91 static int g_tree_script_pos
= 0;
93 static char *g_list_script_buf
= NULL
;
94 static int g_list_script_pos
= 0;
96 static char *g_part_list_buf
= NULL
;
97 static int g_part_list_pos
= 0;
99 static const char *g_menu_class
[] =
101 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg"
104 static const char *g_menu_prefix
[] =
106 "iso", "wim", "efi", "img"
109 void ventoy_debug(const char *fmt
, ...)
113 va_start (args
, fmt
);
114 grub_vprintf (fmt
, args
);
118 int ventoy_is_efi_os(void)
122 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
128 static int ventoy_get_fs_type(const char *fs
)
132 return ventoy_fs_max
;
134 else if (grub_strncmp(fs
, "exfat", 5) == 0)
136 return ventoy_fs_exfat
;
138 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
140 return ventoy_fs_ntfs
;
142 else if (grub_strncmp(fs
, "ext", 3) == 0)
144 return ventoy_fs_ext
;
146 else if (grub_strncmp(fs
, "xfs", 3) == 0)
148 return ventoy_fs_xfs
;
150 else if (grub_strncmp(fs
, "udf", 3) == 0)
152 return ventoy_fs_udf
;
154 else if (grub_strncmp(fs
, "fat", 3) == 0)
156 return ventoy_fs_fat
;
159 return ventoy_fs_max
;
162 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
181 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
183 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
187 static grub_err_t
ventoy_fs_close(grub_file_t file
)
189 grub_file_close(g_old_file
);
190 grub_free(file
->data
);
198 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
202 static struct grub_fs vtoy_fs
=
207 .fs_read
= ventoy_fs_read
,
208 .fs_close
= ventoy_fs_close
,
218 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
224 file
->data
= grub_malloc(rawFile
->size
+ 4096);
230 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
231 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
233 g_old_file
= rawFile
;
235 file
->size
= rawFile
->size
+ len
;
236 file
->device
= rawFile
->device
;
238 file
->not_easily_seekable
= 1;
243 static int ventoy_check_decimal_var(const char *name
, long *value
)
245 const char *value_str
= NULL
;
247 value_str
= grub_env_get(name
);
248 if (NULL
== value_str
)
250 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
253 if (!ventoy_is_decimal(value_str
))
255 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
258 *value
= grub_strtol(value_str
, NULL
, 10);
260 return GRUB_ERR_NONE
;
263 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
267 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
270 if (0 == grub_strcmp(args
[0], "on"))
273 grub_env_set("vtdebug_flag", "debug");
278 grub_env_set("vtdebug_flag", "");
281 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
284 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
288 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
290 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
291 grub_printf(" level:\r\n");
292 grub_printf(" 01/11: busybox / (+cat log)\r\n");
293 grub_printf(" 02/12: initrd / (+cat log)\r\n");
294 grub_printf(" 03/13: hook / (+cat log)\r\n");
296 grub_printf(" debug:\r\n");
297 grub_printf(" 0: debug is on\r\n");
298 grub_printf(" 1: debug is off\r\n");
300 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
303 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
305 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
307 g_ventoy_debug_level
= 1;
310 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
313 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
322 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
325 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
357 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
362 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
364 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
367 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
372 value_long
+= grub_strtol(args
[1], NULL
, 10);
374 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
375 grub_env_set(args
[0], buf
);
377 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
380 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
395 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
398 debug("failed to open file <%s> for udf check\n", args
[0]);
402 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
404 grub_env_set(args
[1], buf
);
406 grub_file_close(file
);
412 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
420 g_wimboot_enable
= 0;
421 grub_check_free(g_wimiso_path
);
422 grub_check_free(g_wimiso_chunk_list
.chunk
);
424 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
430 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
431 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
432 if (NULL
== g_wimiso_chunk_list
.chunk
)
434 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
437 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
438 g_wimiso_chunk_list
.cur_chunk
= 0;
440 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
442 g_wimboot_enable
= 1;
443 g_wimiso_path
= grub_strdup(args
[0]);
445 grub_file_close(file
);
450 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
456 grub_uint32_t offset
;
458 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
461 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
465 len
= (int)file
->size
;
467 data
= (char *)grub_malloc(file
->size
);
473 grub_file_read(file
, data
, file
->size
);
474 grub_file_close(file
);
476 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
477 grub_script_execute_sourcecode(exec
);
479 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
480 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
481 grub_file_close(file
);
483 grub_script_execute_sourcecode("loopback -d efiboot");
487 *direntoff
= offset
+ 2;
492 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
502 ventoy_iso9660_override
*dirent
;
511 totlen
= sizeof(ventoy_chain_head
);
513 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
515 debug("failed to load efiboot template %d\n", len
);
521 debug("efiboot template len:%d offset:%d\n", len
, offset
);
523 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
526 debug("failed to open file <%s>\n", args
[0]);
530 totlen
+= ventoy_align_2k(file
->size
);
532 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
533 dirent
->first_sector
= len
/ 2048;
534 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
535 dirent
->size
= (grub_uint32_t
)file
->size
;
536 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
538 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
540 #ifdef GRUB_MACHINE_EFI
541 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
543 data
= (char *)grub_malloc(totlen
);
546 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
548 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
549 grub_check_free(buf
);
551 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
552 grub_file_close(file
);
554 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
555 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
556 grub_env_set(name
, value
);
558 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
559 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
560 grub_env_set(name
, value
);
565 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
582 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
585 debug("failed to open file <%s>\n", args
[0]);
589 #ifdef GRUB_MACHINE_EFI
590 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
592 buf
= (char *)grub_malloc(file
->size
);
595 grub_file_read(file
, buf
, file
->size
);
597 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
598 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
599 grub_env_set(name
, value
);
601 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
602 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
603 grub_env_set(name
, value
);
605 grub_file_close(file
);
611 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
629 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
632 debug("failed to open file <%s> for udf check\n", args
[0]);
636 headlen
= sizeof(ventoy_chain_head
);
638 #ifdef GRUB_MACHINE_EFI
639 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
641 buf
= (char *)grub_malloc(headlen
+ file
->size
);
644 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
646 grub_file_read(file
, buf
+ headlen
, file
->size
);
648 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
649 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
650 grub_env_set(name
, value
);
652 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
653 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
654 grub_env_set(name
, value
);
656 grub_file_close(file
);
662 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
671 if (args
[0][0] == '1')
673 grub_iso9660_set_nojoliet(1);
677 grub_iso9660_set_nojoliet(0);
683 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
688 grub_uint8_t buf
[32];
699 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
702 debug("failed to open file <%s> for udf check\n", args
[0]);
706 for (i
= 16; i
< 32; i
++)
708 grub_file_seek(file
, i
* 2048);
709 grub_file_read(file
, buf
, sizeof(buf
));
717 grub_file_seek(file
, i
* 2048);
718 grub_file_read(file
, buf
, sizeof(buf
));
720 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
723 grub_file_seek(file
, i
* 2048);
724 grub_file_read(file
, buf
, sizeof(buf
));
726 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
727 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
733 grub_file_close(file
);
735 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
740 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
742 long value_long1
= 0;
743 long value_long2
= 0;
745 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
747 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
750 value_long1
= grub_strtol(args
[0], NULL
, 10);
751 value_long2
= grub_strtol(args
[2], NULL
, 10);
753 if (0 == grub_strcmp(args
[1], "eq"))
755 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
757 else if (0 == grub_strcmp(args
[1], "ne"))
759 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
761 else if (0 == grub_strcmp(args
[1], "gt"))
763 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
765 else if (0 == grub_strcmp(args
[1], "lt"))
767 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
769 else if (0 == grub_strcmp(args
[1], "ge"))
771 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
773 else if (0 == grub_strcmp(args
[1], "le"))
775 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
779 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
785 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
792 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
795 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
796 pos
= grub_strstr(buf
, ",");
802 grub_env_set(args
[1], buf
);
804 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
807 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
813 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
819 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
822 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
824 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
825 if (0 == grub_script_execute_sourcecode(buf
))
827 debug("file %s exist, ventoy_compatible YES\n", buf
);
828 grub_env_set("ventoy_compatible", "YES");
829 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
833 debug("file %s NOT exist\n", buf
);
837 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
838 pos
= grub_strstr(buf
, ")");
844 disk
= grub_disk_open(buf
);
847 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
848 grub_disk_close(disk
);
850 g_img_swap_tmp_buf
[703] = 0;
851 for (i
= 319; i
< 703; i
++)
853 if (g_img_swap_tmp_buf
[i
] == 'V' &&
854 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
856 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
857 grub_env_set("ventoy_compatible", "YES");
858 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
864 debug("failed to open disk <%s>\n", buf
);
867 grub_env_set("ventoy_compatible", "NO");
868 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
871 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
877 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
882 if (grub_islower(c1
))
887 if (grub_islower(c2
))
901 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
903 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
905 grub_memcpy(img1
, img2
, sizeof(img_info
));
906 img1
->next
= g_img_swap_tmp
.next
;
907 img1
->prev
= g_img_swap_tmp
.prev
;
909 g_img_swap_tmp
.next
= img2
->next
;
910 g_img_swap_tmp
.prev
= img2
->prev
;
911 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
914 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
918 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
923 for (i
= 0; i
< namelen
; i
++)
925 if (filename
[i
] == ' ' || filename
[i
] == '\t')
930 if ((grub_uint8_t
)(filename
[i
]) >= 127)
939 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
943 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
953 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
961 img_iterator_node
*tmp
;
962 img_iterator_node
*new_node
;
963 img_iterator_node
*node
= (img_iterator_node
*)data
;
965 len
= grub_strlen(filename
);
969 if ((len
== 1 && filename
[0] == '.') ||
970 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
975 if (!ventoy_img_name_valid(filename
, len
))
980 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
985 new_node
= grub_zalloc(sizeof(img_iterator_node
));
988 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
990 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
993 debug("Directory %s ignored...\n", new_node
->dir
);
998 new_node
->tail
= node
->tail
;
1000 new_node
->parent
= node
;
1001 if (!node
->firstchild
)
1003 node
->firstchild
= new_node
;
1006 if (g_img_iterator_tail
)
1008 g_img_iterator_tail
->next
= new_node
;
1009 g_img_iterator_tail
= new_node
;
1013 g_img_iterator_head
.next
= new_node
;
1014 g_img_iterator_tail
= new_node
;
1020 debug("Find a file %s\n", filename
);
1026 if (0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1028 type
= img_type_iso
;
1030 else if (g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1032 type
= img_type_wim
;
1034 #ifdef GRUB_MACHINE_EFI
1035 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1037 type
= img_type_efi
;
1040 else if (0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1042 if (len
== 18 && grub_strncmp(filename
, "ventoy_wimboot", 14) == 0)
1046 type
= img_type_img
;
1053 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1058 img
= grub_zalloc(sizeof(img_info
));
1062 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1064 for (i
= 0; i
< (int)len
; i
++)
1066 if (filename
[i
] == ' ' || filename
[i
] == '\t' || (0 == grub_isprint(filename
[i
])))
1073 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1075 img
->size
= info
->size
;
1078 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1081 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1083 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1088 if (g_ventoy_img_list
)
1090 tail
= *(node
->tail
);
1096 g_ventoy_img_list
= img
;
1099 img
->id
= g_ventoy_img_count
;
1101 if (node
&& NULL
== node
->firstiso
)
1103 node
->firstiso
= img
;
1114 *((img_info
**)(node
->tail
)) = img
;
1115 g_ventoy_img_count
++;
1117 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1118 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
);
1121 img
->class = g_menu_class
[type
];
1123 img
->menu_prefix
= g_menu_prefix
[type
];
1125 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1132 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1134 int len
= GRUB_UINT_MAX
;
1135 const char *value
= NULL
;
1136 char name
[32] = {0};
1137 char plat
[32] = {0};
1138 char guidstr
[32] = {0};
1139 ventoy_guid guid
= VENTOY_GUID
;
1140 const char *fmt1
= NULL
;
1141 const char *fmt2
= NULL
;
1142 const char *fmt3
= NULL
;
1143 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1144 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1145 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1146 const char fmtcode
[]={
1147 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1148 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1149 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1150 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1151 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1152 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1155 grub_memset(name
, 0, sizeof(name
));
1156 puint
[0] = grub_swap_bytes32(0x56454e54);
1157 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1158 puint
[2] = grub_swap_bytes32(0x45525349);
1159 puint
[1] = grub_swap_bytes32(0x4f595f56);
1160 value
= ventoy_get_env(name
);
1162 grub_memset(name
, 0, sizeof(name
));
1163 puint
[1] = grub_swap_bytes32(0x5f544f50);
1164 puint
[0] = grub_swap_bytes32(0x56544c45);
1165 fmt1
= ventoy_get_env(name
);
1171 grub_memset(name
, 0, sizeof(name
));
1172 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1173 puint
[0] = grub_swap_bytes32(0x56544c45);
1174 fmt2
= ventoy_get_env(name
);
1176 grub_memset(name
, 0, sizeof(name
));
1177 puint
[1] = grub_swap_bytes32(0x5f434c52);
1178 puint
[0] = grub_swap_bytes32(0x56544c45);
1179 fmt3
= ventoy_get_env(name
);
1181 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1183 #if defined (GRUB_MACHINE_EFI)
1184 puint2
[0] = grub_swap_bytes32(0x55454649);
1186 puint2
[0] = grub_swap_bytes32(0x42494f53);
1189 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1190 #pragma GCC diagnostic push
1191 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1192 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1193 fmt1
? fmt1
: fmtdata
,
1194 fmt2
? fmt2
: fmtdata
+ 4,
1195 value
? value
: "", plat
, guidstr
,
1196 fmt3
? fmt3
: fmtdata
+ 6);
1197 #pragma GCC diagnostic pop
1199 grub_memset(name
, 0, sizeof(name
));
1200 puint
[0] = grub_swap_bytes32(0x76746f79);
1201 puint
[2] = grub_swap_bytes32(0x656e7365);
1202 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1203 ventoy_set_env(name
, guidstr
);
1208 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1210 img_info
*minimg
= NULL
;
1211 img_info
*img
= (img_info
*)(node
->firstiso
);
1213 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1215 if (img
->select
== 0 && (NULL
== minimg
|| grub_strcmp(img
->name
, minimg
->name
) < 0))
1230 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1232 img_iterator_node
*Minchild
= NULL
;
1233 img_iterator_node
*child
= node
->firstchild
;
1235 while (child
&& child
->parent
== node
)
1237 if (child
->select
== 0 && (NULL
== Minchild
|| grub_strcmp(child
->dir
, Minchild
->dir
) < 0))
1241 child
= child
->next
;
1246 Minchild
->select
= 1;
1252 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1255 img_info
*img
= NULL
;
1256 const char *dir_class
= NULL
;
1257 const char *dir_alias
= NULL
;
1258 img_iterator_node
*child
= NULL
;
1260 if (node
->isocnt
== 0 || node
->done
== 1)
1265 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1267 offset
= node
->parent
->dirlen
;
1270 if (node
== &g_img_iterator_head
)
1272 if (g_default_menu_mode
== 0)
1274 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1275 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1276 " echo 'return ...' \n"
1282 node
->dir
[node
->dirlen
- 1] = 0;
1283 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
);
1286 dir_class
= "vtoydir";
1289 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
1292 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1293 "submenu \"%-10s %s\" --class=\"%s\" {\n",
1294 "DIR", dir_alias
, dir_class
);
1298 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1299 "submenu \"%-10s [%s]\" --class=\"%s\" {\n",
1300 "DIR", node
->dir
+ offset
, dir_class
);
1303 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1304 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1305 " echo 'return ...' \n"
1309 while ((child
= ventoy_get_min_child(node
)) != NULL
)
1311 ventoy_dynamic_tree_menu(child
);
1314 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
1316 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1317 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1320 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
1321 img
->unsupport
? "[unsupported] " : "",
1322 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
1324 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1327 if (node
!= &g_img_iterator_head
)
1329 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
1336 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1340 grub_device_t dev
= NULL
;
1341 img_info
*cur
= NULL
;
1342 img_info
*tail
= NULL
;
1343 img_info
*default_node
= NULL
;
1344 const char *strdata
= NULL
;
1345 char *device_name
= NULL
;
1346 const char *default_image
= NULL
;
1349 img_iterator_node
*node
= NULL
;
1350 img_iterator_node
*tmp
= NULL
;
1356 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
1359 if (g_ventoy_img_list
|| g_ventoy_img_count
)
1361 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
1364 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1365 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
1367 g_filt_dot_underscore_file
= 1;
1370 device_name
= grub_file_get_device_name(args
[0]);
1376 g_enum_dev
= dev
= grub_device_open(device_name
);
1382 g_enum_fs
= fs
= grub_fs_probe(dev
);
1388 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
1390 debug("unsupported fs:<%s>\n", fs
->name
);
1391 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1395 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1396 if (strdata
&& strdata
[0] == '1')
1398 g_default_menu_mode
= 1;
1401 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1403 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
1405 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1406 if (strdata
&& strdata
[0] == '/')
1408 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
1409 if (g_img_iterator_head
.dir
[len
- 1] != '/')
1411 g_img_iterator_head
.dir
[len
++] = '/';
1413 g_img_iterator_head
.dirlen
= len
;
1417 g_img_iterator_head
.dirlen
= 1;
1418 grub_strcpy(g_img_iterator_head
.dir
, "/");
1421 g_img_iterator_head
.tail
= &tail
;
1423 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1425 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1428 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1430 ventoy_dynamic_tree_menu(node
);
1434 node
= g_img_iterator_head
.next
;
1442 /* sort image list by image name */
1443 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1445 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1447 if (ventoy_cmp_img(cur
, tail
) > 0)
1449 ventoy_swap_img(cur
, tail
);
1454 if (g_default_menu_mode
== 1)
1456 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1457 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
1458 " echo 'return ...' \n"
1462 if (g_default_menu_mode
== 0)
1464 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
1467 img_len
= grub_strlen(default_image
);
1471 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1473 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
1474 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1477 cur
->unsupport
? "[unsupported] " : "",
1478 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
1480 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
1482 if (g_default_menu_mode
== 0 && default_image
&& default_node
== NULL
)
1484 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
1493 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
1496 g_list_script_buf
[g_list_script_pos
] = 0;
1498 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1499 grub_env_set(args
[1], buf
);
1503 check_free(device_name
, grub_free
);
1504 check_free(dev
, grub_device_close
);
1506 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1510 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1512 img_info
*next
= NULL
;
1513 img_info
*cur
= g_ventoy_img_list
;
1526 g_ventoy_img_list
= NULL
;
1527 g_ventoy_img_count
= 0;
1529 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1532 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1535 img_info
*cur
= g_ventoy_img_list
;
1539 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1541 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1544 img_id
= grub_strtol(args
[0], NULL
, 10);
1545 if (img_id
>= g_ventoy_img_count
)
1547 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
1550 debug("Find image %ld name \n", img_id
);
1552 while (cur
&& img_id
> 0)
1560 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
1563 debug("image name is %s\n", cur
->name
);
1565 grub_env_set(args
[1], cur
->name
);
1567 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1570 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1575 const char *id
= NULL
;
1576 img_info
*cur
= g_ventoy_img_list
;
1580 if (argc
< 1 || argc
> 2)
1582 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
1585 id
= grub_env_get("chosen");
1587 pos
= grub_strstr(id
, "VID_");
1590 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
1594 img_id
= (int)grub_strtoul(id
, NULL
, 10);
1599 if (img_id
== cur
->id
)
1608 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
1611 grub_env_set(args
[0], cur
->path
);
1615 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
1616 grub_env_set(args
[1], value
);
1619 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1622 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
)
1629 device_name
= grub_file_get_device_name(filename
);
1641 pos2
= grub_strstr(pos
, ",");
1644 pos2
= grub_strstr(pos
, ")");
1652 disk
= grub_disk_open(pos
);
1655 grub_disk_read(disk
, 0, 0x180, 16, guid
);
1656 grub_disk_close(disk
);
1663 grub_free(device_name
);
1667 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
1669 eltorito_descriptor desc
;
1671 grub_memset(&desc
, 0, sizeof(desc
));
1672 grub_file_seek(file
, 17 * 2048);
1673 grub_file_read(file
, &desc
, sizeof(desc
));
1675 if (desc
.type
!= 0 || desc
.version
!= 1)
1680 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
1681 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
1689 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
1693 grub_uint8_t buf
[512];
1695 grub_file_seek(file
, sector
* 2048);
1696 grub_file_read(file
, buf
, sizeof(buf
));
1698 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
1700 debug("%s efi eltorito in Validation Entry\n", file
->name
);
1704 if (buf
[0] == 0x01 && buf
[1] == 0x00)
1709 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
1711 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
1713 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1717 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
1719 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1724 debug("%s does not contain efi eltorito\n", file
->name
);
1728 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
1731 const char *fs
= NULL
;
1732 const char *cdprompt
= NULL
;
1734 grub_uint8_t chksum
= 0;
1737 disk
= file
->device
->disk
;
1738 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
1740 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
1741 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
1742 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
1744 pos
= grub_strstr(file
->name
, "/");
1750 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
1752 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
);
1754 param
->vtoy_img_size
= file
->size
;
1756 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
1757 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
1759 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
1761 /* Windows CD/DVD prompt 0:suppress 1:reserved */
1762 param
->vtoy_reserved
[4] = 0;
1763 if (g_ventoy_chain_type
== 1) /* Windows */
1765 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
1766 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
1768 param
->vtoy_reserved
[4] = 1;
1772 fs
= ventoy_get_env("ventoy_fs_probe");
1773 if (fs
&& grub_strcmp(fs
, "udf") == 0)
1775 param
->vtoy_reserved
[3] = 1;
1778 /* calculate checksum */
1779 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
1781 chksum
+= *((grub_uint8_t
*)param
+ i
);
1783 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
1788 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
1790 grub_uint32_t i
= 0;
1791 grub_uint64_t total
= 0;
1792 ventoy_img_chunk
*chunk
= NULL
;
1794 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
1796 chunk
= chunklist
->chunk
+ i
;
1798 if (chunk
->disk_start_sector
<= start
)
1800 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
1804 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
1807 if (total
!= ((file
->size
+ 511) / 512))
1809 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)((file
->size
+ 511) / 512));
1816 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
1820 grub_uint32_t i
= 0;
1821 grub_uint32_t sector
= 0;
1822 grub_uint32_t count
= 0;
1823 grub_off_t size
= 0;
1824 grub_off_t read
= 0;
1826 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
1827 if (fs_type
== ventoy_fs_exfat
)
1829 grub_fat_get_file_chunk(start
, file
, chunklist
);
1831 else if (fs_type
== ventoy_fs_ext
)
1833 grub_ext_get_file_chunk(start
, file
, chunklist
);
1837 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
1838 file
->read_hook_data
= chunklist
;
1840 for (size
= file
->size
; size
> 0; size
-= read
)
1842 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
1843 grub_file_read(file
, NULL
, read
);
1846 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
1848 chunklist
->chunk
[i
].disk_start_sector
+= start
;
1849 chunklist
->chunk
[i
].disk_end_sector
+= start
;
1852 if (ventoy_fs_udf
== fs_type
)
1854 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
1856 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
1857 chunklist
->chunk
[i
].img_start_sector
= sector
;
1858 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
1864 len
= (int)grub_strlen(file
->name
);
1865 if (grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0)
1867 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
1869 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
1879 chunklist
->chunk
[i
].img_start_sector
= sector
;
1880 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
1888 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1892 grub_disk_addr_t start
;
1897 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1900 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
1903 if (g_img_chunk_list
.chunk
)
1905 grub_free(g_img_chunk_list
.chunk
);
1908 /* get image chunk data */
1909 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
1910 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1911 if (NULL
== g_img_chunk_list
.chunk
)
1913 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1916 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1917 g_img_chunk_list
.cur_chunk
= 0;
1919 start
= file
->device
->disk
->partition
->start
;
1921 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
1923 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
1924 grub_file_close(file
);
1928 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
1931 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
1932 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1935 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1940 char configfile
[128];
1941 install_template
*node
= NULL
;
1947 debug("select auto installation argc:%d\n", argc
);
1954 node
= ventoy_plugin_find_install_template(args
[0]);
1957 debug("Auto install template not found for %s\n", args
[0]);
1961 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
1963 node
->cursel
= node
->autosel
- 1;
1964 debug("Auto install template auto select %d\n", node
->autosel
);
1968 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
1974 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
1975 " echo %s\n}\n", "123");
1977 for (i
= 0; i
< node
->templatenum
; i
++)
1979 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
1981 node
->templatepath
[i
].path
);
1984 g_ventoy_menu_esc
= 1;
1985 g_ventoy_suppress_esc
= 1;
1987 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
1988 grub_script_execute_sourcecode(configfile
);
1990 g_ventoy_menu_esc
= 0;
1991 g_ventoy_suppress_esc
= 0;
1995 node
->cursel
= g_ventoy_last_entry
- 1;
1997 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2000 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2005 char configfile
[128];
2006 persistence_config
*node
;
2012 debug("select persistence argc:%d\n", argc
);
2019 node
= ventoy_plugin_find_persistent(args
[0]);
2022 debug("Persistence image not found for %s\n", args
[0]);
2026 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
2028 node
->cursel
= node
->autosel
- 1;
2029 debug("Persistence image auto select %d\n", node
->autosel
);
2033 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2039 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
2040 " echo %s\n}\n", "123");
2042 for (i
= 0; i
< node
->backendnum
; i
++)
2044 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2046 node
->backendpath
[i
].path
);
2050 g_ventoy_menu_esc
= 1;
2051 g_ventoy_suppress_esc
= 1;
2053 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2054 grub_script_execute_sourcecode(configfile
);
2056 g_ventoy_menu_esc
= 0;
2057 g_ventoy_suppress_esc
= 0;
2061 node
->cursel
= g_ventoy_last_entry
- 1;
2063 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2066 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2069 ventoy_img_chunk
*cur
;
2075 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
2077 cur
= g_img_chunk_list
.chunk
+ i
;
2078 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2079 cur
->img_start_sector
, cur
->img_end_sector
,
2080 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
2084 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2087 #ifdef GRUB_MACHINE_EFI
2088 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2096 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2099 ulong chain_len
= 0;
2100 char *chain_data
= NULL
;
2101 char *relocator_addr
= NULL
;
2102 grub_relocator_chunk_t ch
;
2103 struct grub_relocator
*relocator
= NULL
;
2104 char envbuf
[64] = { 0 };
2115 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
2116 chain_len
= grub_strtoul(args
[1], NULL
, 10);
2118 relocator
= grub_relocator_new ();
2121 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
2125 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
2126 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
2130 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
2131 grub_relocator_unload (relocator
);
2135 relocator_addr
= get_virtual_current_address(ch
);
2137 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
2139 grub_relocator_unload (relocator
);
2141 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
2142 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
2144 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2148 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2152 ventoy_img_chunk_list chunklist
;
2157 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2160 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2163 /* get image chunk data */
2164 grub_memset(&chunklist
, 0, sizeof(chunklist
));
2165 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2166 if (NULL
== chunklist
.chunk
)
2168 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2171 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
2172 chunklist
.cur_chunk
= 0;
2174 ventoy_get_block_list(file
, &chunklist
, 0);
2176 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
2178 grub_printf("########## UNSUPPORTED ###############\n");
2181 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
2183 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2185 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2186 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
2189 grub_printf("\n==================================\n");
2191 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
2193 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
2194 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
2195 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
2196 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
2197 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
2201 grub_free(chunklist
.chunk
);
2202 grub_file_close(file
);
2204 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2207 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2210 ventoy_grub_param_file_replace
*replace
= NULL
;
2218 replace
= &(g_grub_param
->file_replace
);
2219 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
2221 replace
->old_name_cnt
= 0;
2222 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
2224 replace
->old_name_cnt
++;
2225 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
2228 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
2231 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2234 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2242 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2243 grub_printf("%s", g_list_script_buf
);
2247 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
2248 grub_printf("%s", g_tree_script_buf
);
2254 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2256 img_info
*cur
= g_ventoy_img_list
;
2264 grub_printf("path:<%s> id=%d\n", cur
->path
, cur
->id
);
2265 grub_printf("name:<%s>\n\n", cur
->name
);
2272 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2278 ventoy_plugin_dump_injection();
2283 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2289 ventoy_plugin_dump_auto_install();
2294 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2300 ventoy_plugin_dump_persistence();
2305 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2316 if (args
[0][0] == '0')
2318 return g_ventoy_memdisk_mode
? 0 : 1;
2320 else if (args
[0][0] == '1')
2322 return g_ventoy_iso_raw
? 0 : 1;
2324 else if (args
[0][0] == '2')
2326 return g_ventoy_iso_uefi_drv
? 0 : 1;
2332 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2334 static int configfile_mode
= 0;
2335 char memfile
[128] = {0};
2342 * args[0]: 0:normal 1:configfile
2343 * args[1]: 0:list_buf 1:tree_buf
2348 debug("Invalid argc %d\n", argc
);
2352 if (args
[0][0] == '0')
2354 if (args
[1][0] == '0')
2356 grub_script_execute_sourcecode(g_list_script_buf
);
2360 grub_script_execute_sourcecode(g_tree_script_buf
);
2365 if (configfile_mode
)
2367 debug("Now already in F3 mode %d\n", configfile_mode
);
2371 if (args
[1][0] == '0')
2373 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2374 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
2378 g_ventoy_last_entry
= -1;
2379 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
2380 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
2383 configfile_mode
= 1;
2384 grub_script_execute_sourcecode(memfile
);
2385 configfile_mode
= 0;
2391 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2402 g_ventoy_case_insensitive
= 1;
2403 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
2404 g_ventoy_case_insensitive
= 0;
2410 grub_file_close(file
);
2416 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2421 const char *isopath
= NULL
;
2423 ventoy_mbr_head mbr
;
2430 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
2433 isopath
= grub_env_get("vtoy_iso_part");
2436 debug("isopath is null %p\n", isopath
);
2440 debug("isopath is %s\n", isopath
);
2442 for (id
= 0; id
< 30 && (find
== 0); id
++)
2444 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
2445 if (grub_strstr(isopath
, hdname
))
2447 debug("skip %s ...\n", hdname
);
2451 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
2453 disk
= grub_disk_open(hdname
);
2456 debug("%s not exist\n", hdname
);
2460 grub_memset(&mbr
, 0, sizeof(mbr
));
2461 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
2463 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
2465 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
2466 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
2469 grub_env_set(args
[0], hdname
);
2473 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
2477 debug("read %s failed\n", hdname
);
2480 grub_disk_close(disk
);
2486 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2497 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
2500 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2503 debug("failed to open file %s\n", args
[0]);
2507 buf
= grub_malloc(len
);
2514 grub_file_read(file
, buf
, len
- 1);
2516 ventoy_get_line(buf
);
2517 ventoy_set_env(args
[1], buf
);
2521 grub_check_free(buf
);
2522 grub_file_close(file
);
2527 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
2532 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
2533 "0 %llu linear /dev/ventoy %llu\n",
2534 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
2539 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2541 char *device_name
= NULL
;
2542 grub_device_t dev
= NULL
;
2547 g_part_list_pos
= 0;
2548 grub_env_unset("vtoy_img_part_file");
2555 device_name
= grub_file_get_device_name(args
[0]);
2558 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
2562 dev
= grub_device_open(device_name
);
2565 debug("grub_device_open failed, %s\n", device_name
);
2569 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
2571 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
2572 grub_env_set("vtoy_img_part_file", buf
);
2576 check_free(device_name
, grub_free
);
2577 check_free(dev
, grub_device_close
);
2583 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2594 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
2597 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2600 debug("failed to open file %s\n", args
[0]);
2604 buf
= grub_malloc(file
->size
+ 1);
2610 buf
[file
->size
] = 0;
2611 grub_file_read(file
, buf
, file
->size
);
2613 if (grub_strstr(buf
, args
[1]))
2620 grub_check_free(buf
);
2621 grub_file_close(file
);
2626 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2631 ventoy_iso9660_vd pvd
;
2638 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid \n", cmd_raw_name
);
2641 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2644 debug("failed to open file %s\n", args
[0]);
2648 grub_file_seek(file
, 16 * 2048);
2649 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
2650 if (len
!= sizeof(pvd
))
2652 debug("failed to read pvd %d\n", len
);
2656 grub_memset(buf
, 0, sizeof(buf
));
2657 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
2658 ventoy_set_env(args
[1], buf
);
2660 grub_memset(buf
, 0, sizeof(buf
));
2661 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
2662 ventoy_set_env(args
[2], buf
);
2665 grub_file_close(file
);
2670 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2681 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
2684 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2687 debug("failed to open file %s\n", args
[0]);
2691 grub_memset(buf
, 0, sizeof(buf
));
2692 grub_file_seek(file
, 16 * 2048 + 813);
2693 len
= (int)grub_file_read(file
, buf
, 17);
2696 debug("failed to read create date %d\n", len
);
2700 ventoy_set_env(args
[1], buf
);
2703 grub_file_close(file
);
2708 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2714 ventoy_env_hook_root(1);
2719 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2725 ventoy_env_hook_root(0);
2730 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2736 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
2737 g_ventoy_last_entry
= -1;
2742 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2748 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
2753 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
2755 const char *pos
= filename
+ 1;
2763 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
2765 grub_strncpy((char *)data
, filename
, 128);
2776 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2779 char *device_name
= NULL
;
2780 grub_device_t dev
= NULL
;
2781 grub_fs_t fs
= NULL
;
2782 char buf
[128] = {0};
2788 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
2792 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
2794 device_name
= grub_file_get_device_name(args
[0]);
2797 debug("grub_file_get_device_name failed, %s\n", args
[0]);
2801 dev
= grub_device_open(device_name
);
2804 debug("grub_device_open failed, %s\n", device_name
);
2808 fs
= grub_fs_probe(dev
);
2811 debug("grub_fs_probe failed, %s\n", device_name
);
2815 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
2819 ventoy_set_env(args
[2], buf
);
2826 check_free(device_name
, grub_free
);
2827 check_free(dev
, grub_device_close
);
2832 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2835 char *device_name
= NULL
;
2836 grub_device_t dev
= NULL
;
2837 grub_fs_t fs
= NULL
;
2844 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
2848 device_name
= grub_file_get_device_name(args
[0]);
2851 debug("grub_file_get_device_name failed, %s\n", args
[0]);
2855 dev
= grub_device_open(device_name
);
2858 debug("grub_device_open failed, %s\n", device_name
);
2862 fs
= grub_fs_probe(dev
);
2865 debug("grub_fs_probe failed, %s\n", device_name
);
2869 fs
->fs_label(dev
, &label
);
2872 ventoy_set_env(args
[1], label
);
2880 check_free(device_name
, grub_free
);
2881 check_free(dev
, grub_device_close
);
2886 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
2888 grub_uint64_t size
= 0;
2891 char fullpath
[256] = {0};
2894 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
2897 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
2900 debug("grub_file_open failed <%s>\n", fullpath
);
2906 grub_file_close(file
);
2910 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
2914 char fullpath
[256] = {0};
2917 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
2920 file
= grub_file_open(fullpath
, type
);
2923 debug("grub_file_open failed <%s>\n", fullpath
);
2930 int ventoy_is_file_exist(const char *fmt
, ...)
2935 char buf
[256] = {0};
2937 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
2941 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
2944 grub_strncpy(pos
+ len
, " ]", 2);
2946 debug("script exec %s\n", buf
);
2948 if (0 == grub_script_execute_sourcecode(buf
))
2956 int ventoy_is_dir_exist(const char *fmt
, ...)
2961 char buf
[256] = {0};
2963 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d ");
2967 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
2970 grub_strncpy(pos
+ len
, " ]", 2);
2972 debug("script exec %s\n", buf
);
2974 if (0 == grub_script_execute_sourcecode(buf
))
2982 static int ventoy_env_init(void)
2986 grub_env_set("vtdebug_flag", "");
2988 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
2989 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2990 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2992 ventoy_filt_register(0, ventoy_wrapper_open
);
2994 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
2997 g_grub_param
->grub_env_get
= grub_env_get
;
2998 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
2999 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
3000 grub_env_set("env_param", buf
);
3006 static cmd_para ventoy_cmds
[] =
3008 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
3009 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
3010 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
3011 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3012 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
3013 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
3014 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
3015 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
3016 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
3017 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
3018 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
3019 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
3020 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
3021 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
3022 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
3023 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
3025 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
3026 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
3027 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
3028 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
3029 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
3030 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
3032 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
3033 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
3034 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
3035 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
3036 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
3037 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
3038 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
3039 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
3040 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
3041 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
3043 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
3044 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
3045 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
3046 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
3047 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
3048 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
3050 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3051 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
3052 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
3053 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
3054 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
3055 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
3056 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
3057 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
3058 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
3059 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
3061 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
3062 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
3063 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
3064 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
3065 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
3066 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
3067 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
3069 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
3070 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
3071 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
3072 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
3075 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
3076 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
3078 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
3079 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
3080 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
3083 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
3084 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
3085 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
3086 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
3087 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
3088 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
3089 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
3090 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
3092 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
3093 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
3099 GRUB_MOD_INIT(ventoy
)
3102 cmd_para
*cur
= NULL
;
3106 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3108 cur
= ventoy_cmds
+ i
;
3109 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
3110 cur
->summary
, cur
->description
, cur
->parser
);
3114 GRUB_MOD_FINI(ventoy
)
3118 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
3120 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);