1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/random.h>
49 #include <grub/ventoy.h>
50 #include "ventoy_def.h"
53 GRUB_MOD_LICENSE ("GPLv3+");
55 static grub_uint8_t g_check_mbr_data
[] = {
56 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
62 initrd_info
*g_initrd_img_list
= NULL
;
63 initrd_info
*g_initrd_img_tail
= NULL
;
64 int g_initrd_img_count
= 0;
65 int g_valid_initrd_count
= 0;
66 int g_default_menu_mode
= 0;
67 int g_filt_dot_underscore_file
= 0;
68 int g_sort_case_sensitive
= 0;
69 int g_tree_view_menu_style
= 0;
70 static grub_file_t g_old_file
;
71 static int g_ventoy_last_entry_back
;
74 char g_img_swap_tmp_buf
[1024];
75 img_info g_img_swap_tmp
;
76 img_info
*g_ventoy_img_list
= NULL
;
78 int g_ventoy_img_count
= 0;
80 grub_device_t g_enum_dev
= NULL
;
81 grub_fs_t g_enum_fs
= NULL
;
82 int g_img_max_search_level
= -1;
83 img_iterator_node g_img_iterator_head
;
84 img_iterator_node
*g_img_iterator_tail
= NULL
;
86 grub_uint8_t g_ventoy_break_level
= 0;
87 grub_uint8_t g_ventoy_debug_level
= 0;
88 grub_uint8_t g_ventoy_chain_type
= 0;
90 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
91 grub_uint32_t g_ventoy_cpio_size
= 0;
92 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
93 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
95 int g_plugin_image_list
= 0;
97 ventoy_grub_param
*g_grub_param
= NULL
;
99 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
101 ventoy_img_chunk_list g_img_chunk_list
;
103 int g_wimboot_enable
= 0;
104 ventoy_img_chunk_list g_wimiso_chunk_list
;
105 char *g_wimiso_path
= NULL
;
106 grub_uint32_t g_wimiso_size
= 0;
108 int g_vhdboot_enable
= 0;
110 grub_uint64_t g_conf_replace_offset
= 0;
111 grub_uint64_t g_svd_replace_offset
= 0;
112 conf_replace
*g_conf_replace_node
= NULL
;
113 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
114 int g_conf_replace_new_len
= 0;
115 int g_conf_replace_new_len_align
= 0;
117 int g_ventoy_disk_bios_id
= 0;
118 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
119 grub_uint64_t g_ventoy_disk_size
= 0;
120 grub_uint64_t g_ventoy_disk_part_size
[2];
122 char *g_tree_script_buf
= NULL
;
123 int g_tree_script_pos
= 0;
124 int g_tree_script_pre
= 0;
126 static char *g_list_script_buf
= NULL
;
127 static int g_list_script_pos
= 0;
129 static char *g_part_list_buf
= NULL
;
130 static int g_part_list_pos
= 0;
131 static grub_uint64_t g_part_end_max
= 0;
133 static int g_video_mode_max
= 0;
134 static int g_video_mode_num
= 0;
135 static ventoy_video_mode
*g_video_mode_list
= NULL
;
137 static int g_enumerate_time_checked
= 0;
138 static grub_uint64_t g_enumerate_start_time_ms
;
139 static grub_uint64_t g_enumerate_finish_time_ms
;
140 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
142 static char g_iso_vd_id_publisher
[130];
143 static char g_iso_vd_id_prepare
[130];
144 static char g_iso_vd_id_application
[130];
146 static int g_pager_flag
= 0;
147 static char g_old_pager
[32];
149 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
151 const char *g_menu_class
[img_type_max
] =
153 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
156 const char *g_menu_prefix
[img_type_max
] =
158 "iso", "wim", "efi", "img", "vhd", "vtoy"
161 static int g_vtoy_load_prompt
= 0;
162 static char g_vtoy_prompt_msg
[64];
164 static char g_json_case_mis_path
[32];
166 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
168 int ventoy_get_fs_type(const char *fs
)
172 return ventoy_fs_max
;
174 else if (grub_strncmp(fs
, "exfat", 5) == 0)
176 return ventoy_fs_exfat
;
178 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
180 return ventoy_fs_ntfs
;
182 else if (grub_strncmp(fs
, "ext", 3) == 0)
184 return ventoy_fs_ext
;
186 else if (grub_strncmp(fs
, "xfs", 3) == 0)
188 return ventoy_fs_xfs
;
190 else if (grub_strncmp(fs
, "udf", 3) == 0)
192 return ventoy_fs_udf
;
194 else if (grub_strncmp(fs
, "fat", 3) == 0)
196 return ventoy_fs_fat
;
199 return ventoy_fs_max
;
202 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
221 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
223 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
227 static int ventoy_control_get_flag(const char *key
)
229 const char *val
= ventoy_get_env(key
);
231 if (val
&& val
[0] == '1' && val
[1] == 0)
238 static grub_err_t
ventoy_fs_close(grub_file_t file
)
240 grub_file_close(g_old_file
);
241 grub_free(file
->data
);
249 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
255 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
260 for (i
= 0; i
< g_video_mode_num
; i
++)
262 if (g_video_mode_list
[i
].width
== info
->width
&&
263 g_video_mode_list
[i
].height
== info
->height
&&
264 g_video_mode_list
[i
].bpp
== info
->bpp
)
270 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
271 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
272 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
275 if (g_video_mode_num
== g_video_mode_max
)
277 g_video_mode_max
*= 2;
278 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
284 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
286 if (v1
->bpp
== v2
->bpp
)
288 if (v1
->width
== v2
->width
)
290 if (v1
->height
== v2
->height
)
296 return (v1
->height
< v2
->height
) ? -1 : 1;
301 return (v1
->width
< v2
->width
) ? -1 : 1;
306 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
310 static int ventoy_enum_video_mode(void)
313 grub_video_adapter_t adapter
;
314 grub_video_driver_id_t id
;
315 ventoy_video_mode mode
;
317 g_video_mode_num
= 0;
318 g_video_mode_max
= 1024;
319 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
320 if (!g_video_mode_list
)
325 #ifdef GRUB_MACHINE_PCBIOS
326 grub_dl_load ("vbe");
329 id
= grub_video_get_driver_id ();
331 FOR_VIDEO_ADAPTERS (adapter
)
333 if (!adapter
->iterate
||
334 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
335 adapter
->init() != GRUB_ERR_NONE
)))
340 adapter
->iterate(ventoy_video_hook
, NULL
);
342 if (adapter
->id
!= id
)
348 /* sort video mode */
349 for (i
= 0; i
< g_video_mode_num
; i
++)
350 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
352 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
354 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
355 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
356 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
360 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
363 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
367 static struct grub_fs vtoy_fs
=
372 .fs_read
= ventoy_fs_read
,
373 .fs_close
= ventoy_fs_close
,
383 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
389 file
->data
= grub_malloc(rawFile
->size
+ 4096);
395 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
396 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
398 g_old_file
= rawFile
;
400 file
->size
= rawFile
->size
+ len
;
401 file
->device
= rawFile
->device
;
403 file
->not_easily_seekable
= 1;
408 static int ventoy_check_decimal_var(const char *name
, long *value
)
410 const char *value_str
= NULL
;
412 value_str
= grub_env_get(name
);
413 if (NULL
== value_str
)
415 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
418 if (!ventoy_is_decimal(value_str
))
420 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
423 *value
= grub_strtol(value_str
, NULL
, 10);
425 return GRUB_ERR_NONE
;
428 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
430 grub_uint64_t sectors
;
432 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
434 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
438 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
441 return sectors
* 512;
444 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
450 grub_uint32_t offset
;
452 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
455 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
459 len
= (int)file
->size
;
461 data
= (char *)grub_malloc(file
->size
);
467 grub_file_read(file
, data
, file
->size
);
468 grub_file_close(file
);
470 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
471 grub_script_execute_sourcecode(exec
);
473 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
474 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
475 grub_file_close(file
);
477 grub_script_execute_sourcecode("loopback -d efiboot");
481 *direntoff
= offset
+ 2;
486 static int ventoy_set_check_result(int ret
)
490 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
491 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
492 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
496 grub_printf(VTOY_WARNING
"\n");
497 grub_printf(VTOY_WARNING
"\n");
498 grub_printf(VTOY_WARNING
"\n\n\n");
500 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
501 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
503 grub_printf("\n\nWill exit after 10 seconds ...... ");
511 static int ventoy_check_official_device(grub_device_t dev
)
515 grub_uint64_t offset
;
518 grub_uint8_t mbr
[512];
522 struct grub_partition
*partition
;
524 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
526 return ventoy_set_check_result(1 | 0x1000);
529 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
530 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
531 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
533 #ifndef GRUB_MACHINE_EFI
534 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
535 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
536 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
538 return ventoy_set_check_result(2 | 0x1000);
547 /* We must have partition 2 */
550 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
554 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
558 return ventoy_set_check_result(3 | 0x1000);
561 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
563 grub_file_close(file
);
564 return ventoy_set_check_result(4 | 0x1000);
567 partition
= dev
->disk
->partition
;
568 if (partition
->number
!= 0 || partition
->start
!= 2048)
570 return ventoy_set_check_result(5);
575 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
577 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
578 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
579 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
581 grub_file_close(file
);
582 return ventoy_set_check_result(6);
587 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
588 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
589 PartTbl
[1].SectorCount
!= 65536)
591 grub_file_close(file
);
592 return ventoy_set_check_result(6);
598 offset
= partition
->start
+ partition
->len
;
599 partition
= file
->device
->disk
->partition
;
600 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
602 grub_file_close(file
);
603 return ventoy_set_check_result(7);
607 grub_file_close(file
);
611 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
612 dev2
= grub_device_open(devname
);
615 return ventoy_set_check_result(8);
618 fs
= grub_fs_probe(dev2
);
621 grub_device_close(dev2
);
622 return ventoy_set_check_result(9);
625 fs
->fs_label(dev2
, &label
);
626 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
628 grub_device_close(dev2
);
629 return ventoy_set_check_result(10);
632 grub_device_close(dev2
);
636 disk
= grub_disk_open(dev
->disk
->name
);
639 return ventoy_set_check_result(11);
642 grub_memset(mbr
, 0, 512);
643 grub_disk_read(disk
, 0, 0, 512, mbr
);
644 grub_disk_close(disk
);
646 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
648 return ventoy_set_check_result(12);
651 return ventoy_set_check_result(0);
654 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
658 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
668 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
670 grub_uint64_t size
= 0;
673 char fullpath
[256] = {0};
676 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
679 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
682 debug("grub_file_open failed <%s>\n", fullpath
);
688 grub_file_close(file
);
692 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
696 char fullpath
[512] = {0};
699 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
702 file
= grub_file_open(fullpath
, type
);
705 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
712 int ventoy_is_dir_exist(const char *fmt
, ...)
719 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
723 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
726 grub_strncpy(pos
+ len
, "\" ]", 3);
728 debug("script exec %s\n", buf
);
730 if (0 == grub_script_execute_sourcecode(buf
))
738 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
741 grub_uint8_t
*outbuf
;
742 grub_uint8_t gzHdr
[10] =
744 0x1F, 0x8B, /* magic */
752 grub_memset(&s
, 0, sizeof(mz_stream
));
754 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
756 outbuf
= (grub_uint8_t
*)mem_out
;
758 mem_out_len
-= sizeof(gzHdr
) + 8;
759 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
760 outbuf
+= sizeof(gzHdr
);
762 s
.avail_in
= mem_in_len
;
765 s
.avail_out
= mem_out_len
;
768 mz_deflate(&s
, MZ_FINISH
);
772 outbuf
+= s
.total_out
;
773 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
774 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
776 return s
.total_out
+ sizeof(gzHdr
) + 8;
784 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
788 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
791 if (0 == grub_strcmp(args
[0], "on"))
794 grub_env_set("vtdebug_flag", "debug");
799 grub_env_set("vtdebug_flag", "");
802 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
805 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
809 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
811 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
812 grub_printf(" level:\r\n");
813 grub_printf(" 01/11: busybox / (+cat log)\r\n");
814 grub_printf(" 02/12: initrd / (+cat log)\r\n");
815 grub_printf(" 03/13: hook / (+cat log)\r\n");
817 grub_printf(" debug:\r\n");
818 grub_printf(" 0: debug is off\r\n");
819 grub_printf(" 1: debug is on\r\n");
821 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
824 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
826 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
828 g_ventoy_debug_level
= 1;
831 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
834 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
843 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
846 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
878 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
894 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
910 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
915 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
917 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
920 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
925 value_long
+= grub_strtol(args
[1], NULL
, 10);
927 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
928 grub_env_set(args
[0], buf
);
930 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
933 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
935 ulonglong value1
= 0;
936 ulonglong value2
= 0;
941 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
944 value1
= grub_strtoull(args
[0], NULL
, 10);
945 value2
= grub_strtoull(args
[1], NULL
, 10);
947 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
948 grub_env_set(args
[2], buf
);
950 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
953 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
968 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
971 debug("failed to open file <%s> for udf check\n", args
[0]);
975 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
977 grub_env_set(args
[1], buf
);
979 grub_file_close(file
);
985 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
993 g_wimboot_enable
= 0;
995 grub_check_free(g_wimiso_path
);
996 grub_check_free(g_wimiso_chunk_list
.chunk
);
998 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1004 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1005 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1006 if (NULL
== g_wimiso_chunk_list
.chunk
)
1008 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1011 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1012 g_wimiso_chunk_list
.cur_chunk
= 0;
1014 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1016 g_wimboot_enable
= 1;
1017 g_wimiso_path
= grub_strdup(args
[0]);
1018 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1019 grub_file_close(file
);
1024 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1034 ventoy_iso9660_override
*dirent
;
1043 totlen
= sizeof(ventoy_chain_head
);
1045 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1047 debug("failed to load efiboot template %d\n", len
);
1053 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1055 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1058 debug("failed to open file <%s>\n", args
[0]);
1062 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1067 totlen
+= ventoy_align_2k(file
->size
);
1069 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1070 dirent
->first_sector
= len
/ 2048;
1071 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1072 dirent
->size
= (grub_uint32_t
)file
->size
;
1073 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1075 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1077 #ifdef GRUB_MACHINE_EFI
1078 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1080 data
= (char *)grub_malloc(totlen
);
1083 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1085 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1086 grub_check_free(buf
);
1088 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1089 grub_file_close(file
);
1091 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1092 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1093 grub_env_set(name
, value
);
1095 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1096 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1097 grub_env_set(name
, value
);
1102 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1108 g_vtoy_load_prompt
= 0;
1109 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1111 if (argc
== 2 && args
[0][0] == '1')
1113 g_vtoy_load_prompt
= 1;
1114 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1117 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1120 int ventoy_need_prompt_load_file(void)
1122 return g_vtoy_load_prompt
;
1125 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1127 grub_uint64_t ro
= 0;
1128 grub_uint64_t div
= 0;
1129 grub_ssize_t left
= size
;
1130 char *cur
= (char *)buf
;
1132 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1135 while (left
>= VTOY_SIZE_2MB
)
1137 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1138 cur
+= VTOY_SIZE_2MB
;
1139 left
-= VTOY_SIZE_2MB
;
1141 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1142 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1148 grub_file_read(file
, cur
, left
);
1151 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1157 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1164 enum grub_file_type type
;
1175 if (grub_strcmp(args
[0], "nodecompress") == 0)
1177 type
= VENTOY_FILE_TYPE
;
1181 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1184 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1187 debug("failed to open file <%s>\n", args
[1]);
1191 #ifdef GRUB_MACHINE_EFI
1192 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1194 buf
= (char *)grub_malloc(file
->size
);
1199 grub_file_close(file
);
1203 if (g_vtoy_load_prompt
)
1205 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1209 grub_file_read(file
, buf
, file
->size
);
1212 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1213 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1214 grub_env_set(name
, value
);
1216 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1217 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1218 grub_env_set(name
, value
);
1220 grub_file_close(file
);
1226 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1244 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1247 debug("failed to open file <%s> for udf check\n", args
[0]);
1251 headlen
= sizeof(ventoy_chain_head
);
1253 #ifdef GRUB_MACHINE_EFI
1254 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1256 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1259 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1261 grub_file_read(file
, buf
+ headlen
, file
->size
);
1263 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1264 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1265 grub_env_set(name
, value
);
1267 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1268 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1269 grub_env_set(name
, value
);
1271 grub_file_close(file
);
1277 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1283 if (grub_iso9660_is_joliet())
1285 debug("This time has joliet process\n");
1294 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1303 if (args
[0][0] == '1')
1305 grub_iso9660_set_nojoliet(1);
1309 grub_iso9660_set_nojoliet(0);
1315 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1320 grub_uint8_t buf
[32];
1331 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1334 debug("failed to open file <%s> for udf check\n", args
[0]);
1338 for (i
= 16; i
< 32; i
++)
1340 grub_file_seek(file
, i
* 2048);
1341 grub_file_read(file
, buf
, sizeof(buf
));
1349 grub_file_seek(file
, i
* 2048);
1350 grub_file_read(file
, buf
, sizeof(buf
));
1352 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1355 grub_file_seek(file
, i
* 2048);
1356 grub_file_read(file
, buf
, sizeof(buf
));
1358 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1359 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1365 grub_file_close(file
);
1367 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1372 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1374 long value_long1
= 0;
1375 long value_long2
= 0;
1377 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1379 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1382 value_long1
= grub_strtol(args
[0], NULL
, 10);
1383 value_long2
= grub_strtol(args
[2], NULL
, 10);
1385 if (0 == grub_strcmp(args
[1], "eq"))
1387 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1389 else if (0 == grub_strcmp(args
[1], "ne"))
1391 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1393 else if (0 == grub_strcmp(args
[1], "gt"))
1395 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1397 else if (0 == grub_strcmp(args
[1], "lt"))
1399 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1401 else if (0 == grub_strcmp(args
[1], "ge"))
1403 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1405 else if (0 == grub_strcmp(args
[1], "le"))
1407 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1411 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1417 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1420 char buf
[128] = {0};
1424 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1427 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1428 pos
= grub_strstr(buf
, ",");
1434 grub_env_set(args
[1], buf
);
1436 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1439 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1445 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1451 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1454 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1456 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1457 if (0 == grub_script_execute_sourcecode(buf
))
1459 debug("file %s exist, ventoy_compatible YES\n", buf
);
1460 grub_env_set("ventoy_compatible", "YES");
1461 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1465 debug("file %s NOT exist\n", buf
);
1469 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1470 pos
= grub_strstr(buf
, ")");
1476 disk
= grub_disk_open(buf
);
1479 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1480 grub_disk_close(disk
);
1482 g_img_swap_tmp_buf
[703] = 0;
1483 for (i
= 318; i
< 703; i
++)
1485 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1486 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1488 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1489 grub_env_set("ventoy_compatible", "YES");
1490 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1496 debug("failed to open disk <%s>\n", buf
);
1499 grub_env_set("ventoy_compatible", "NO");
1500 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1503 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1509 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1511 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1514 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1519 if (0 == g_sort_case_sensitive
)
1521 if (grub_islower(c1
))
1523 c1
= c1
- 'a' + 'A';
1526 if (grub_islower(c2
))
1528 c2
= c2
- 'a' + 'A';
1541 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1547 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1549 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1552 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1557 if (0 == g_sort_case_sensitive
)
1559 if (grub_islower(c1
))
1561 c1
= c1
- 'a' + 'A';
1564 if (grub_islower(c2
))
1566 c2
= c2
- 'a' + 'A';
1579 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1581 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1583 grub_memcpy(img1
, img2
, sizeof(img_info
));
1584 img1
->next
= g_img_swap_tmp
.next
;
1585 img1
->prev
= g_img_swap_tmp
.prev
;
1587 g_img_swap_tmp
.next
= img2
->next
;
1588 g_img_swap_tmp
.prev
= img2
->prev
;
1589 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1592 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1596 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1604 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1606 ventoy_vlnk_part
*node
= NULL
;
1607 grub_uint32_t SelfSig
;
1608 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1610 /* skip Ventoy partition 1/2 */
1611 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1612 if (partition
->number
< 2 && SelfSig
== *pSig
)
1617 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1620 node
->disksig
= *pSig
;
1621 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1622 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1623 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1625 node
->next
= g_vlnk_part_list
;
1626 g_vlnk_part_list
= node
;
1632 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1639 disk
= grub_disk_open(name
);
1642 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1643 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1644 grub_disk_close(disk
);
1650 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1652 const char *fs
[ventoy_fs_max
+ 1] =
1654 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1659 cur
->dev
= grub_device_open(cur
->device
);
1664 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1670 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1675 char *disk
, *device
;
1676 grub_uint32_t readcrc
, calccrc
;
1677 ventoy_vlnk_part
*cur
;
1678 grub_fs_t fs
= NULL
;
1680 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1684 grub_printf("VLNK invalid guid\n");
1690 readcrc
= vlnk
->crc32
;
1692 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1693 if (readcrc
!= calccrc
)
1697 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1703 if (!g_vlnk_part_list
)
1705 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1708 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1710 if (cur
->disksig
== vlnk
->disk_signature
)
1714 if (cur
->partoffset
== vlnk
->part_offset
)
1717 device
= cur
->device
;
1719 if (cur
->probe
== 0)
1722 ventoy_vlnk_probe_fs(cur
);
1732 struct grub_file file
;
1734 grub_memset(&file
, 0, sizeof(file
));
1735 file
.device
= cur
->dev
;
1736 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1739 cur
->fs
->fs_close(&file
);
1740 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1749 grub_printf("\n==== VLNK Information ====\n"
1750 "Disk Signature: %08x\n"
1751 "Partition Offset: %llu\n"
1752 "File Path: <%s>\n\n",
1753 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1757 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1761 grub_printf("Disk Find: [ NO ]\n");
1766 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1770 grub_printf("Part Find: [ NO ]\n");
1772 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1775 grub_printf("VLNK File: <%s>\n", dst
);
1782 return (1 - filefind
);
1785 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1790 grub_file_t file
= NULL
;
1795 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1797 else if (dir
[0] == '/')
1799 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1803 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1806 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1812 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1813 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1814 grub_file_close(file
);
1816 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1818 rc
= grub_file_add_vlnk(src
, dst
);
1824 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1834 const menu_tip
*tip
;
1835 img_iterator_node
*tmp
;
1836 img_iterator_node
*new_node
;
1837 img_iterator_node
*node
= (img_iterator_node
*)data
;
1839 if (g_enumerate_time_checked
== 0)
1841 g_enumerate_finish_time_ms
= grub_get_time_ms();
1842 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1845 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1847 g_enumerate_time_checked
= 1;
1851 len
= grub_strlen(filename
);
1855 if (node
->level
+ 1 > g_img_max_search_level
)
1860 if ((len
== 1 && filename
[0] == '.') ||
1861 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1866 if (!ventoy_img_name_valid(filename
, len
))
1871 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1876 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1878 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1879 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1882 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1887 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1890 new_node
->level
= node
->level
+ 1;
1891 new_node
->plugin_list_index
= index
;
1892 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1894 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1897 debug("Directory %s ignored...\n", new_node
->dir
);
1898 grub_free(new_node
);
1902 new_node
->tail
= node
->tail
;
1904 new_node
->parent
= node
;
1905 if (!node
->firstchild
)
1907 node
->firstchild
= new_node
;
1910 if (g_img_iterator_tail
)
1912 g_img_iterator_tail
->next
= new_node
;
1913 g_img_iterator_tail
= new_node
;
1917 g_img_iterator_head
.next
= new_node
;
1918 g_img_iterator_tail
= new_node
;
1924 debug("Find a file %s\n", filename
);
1930 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1932 type
= img_type_iso
;
1934 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1936 type
= img_type_wim
;
1938 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1939 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1941 type
= img_type_vhd
;
1943 #ifdef GRUB_MACHINE_EFI
1944 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1946 type
= img_type_efi
;
1949 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1951 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1953 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1954 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1959 type
= img_type_img
;
1961 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1963 type
= img_type_vtoy
;
1965 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1967 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1969 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1970 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1979 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1984 if (g_plugin_image_list
)
1986 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1987 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1988 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1990 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1993 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1995 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2000 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2002 if (grub_file_is_vlnk_suffix(filename
, len
))
2005 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2012 img
= grub_zalloc(sizeof(img_info
));
2016 img
->plugin_list_index
= index
;
2017 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2019 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2021 img
->size
= info
->size
;
2022 if (vlnk
|| 0 == img
->size
)
2024 if (node
->dir
[0] == '/')
2026 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2030 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2034 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2036 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2041 if (g_ventoy_img_list
)
2043 tail
= *(node
->tail
);
2049 g_ventoy_img_list
= img
;
2052 img
->id
= g_ventoy_img_count
;
2054 if (node
&& NULL
== node
->firstiso
)
2056 node
->firstiso
= img
;
2067 *((img_info
**)(node
->tail
)) = img
;
2068 g_ventoy_img_count
++;
2070 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2072 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2075 img
->tip1
= tip
->tip1
;
2076 img
->tip2
= tip
->tip2
;
2079 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2082 img
->class = g_menu_class
[type
];
2084 img
->menu_prefix
= g_menu_prefix
[type
];
2086 if (img_type_iso
== type
)
2088 if (ventoy_plugin_check_memdisk(img
->path
))
2090 img
->menu_prefix
= "miso";
2094 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2101 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2103 int len
= GRUB_UINT_MAX
;
2104 const char *value
= NULL
;
2105 char name
[32] = {0};
2106 char plat
[32] = {0};
2107 char guidstr
[32] = {0};
2108 ventoy_guid guid
= VENTOY_GUID
;
2109 const char *fmt1
= NULL
;
2110 const char *fmt2
= NULL
;
2111 const char *fmt3
= NULL
;
2112 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2113 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2114 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2115 const char fmtcode
[]={
2116 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2117 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2118 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2119 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2120 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2121 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2124 grub_memset(name
, 0, sizeof(name
));
2125 puint
[0] = grub_swap_bytes32(0x56454e54);
2126 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2127 puint
[2] = grub_swap_bytes32(0x45525349);
2128 puint
[1] = grub_swap_bytes32(0x4f595f56);
2129 value
= ventoy_get_env(name
);
2131 grub_memset(name
, 0, sizeof(name
));
2132 puint
[1] = grub_swap_bytes32(0x5f544f50);
2133 puint
[0] = grub_swap_bytes32(0x56544c45);
2134 fmt1
= ventoy_get_env(name
);
2140 grub_memset(name
, 0, sizeof(name
));
2141 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2142 puint
[0] = grub_swap_bytes32(0x56544c45);
2143 fmt2
= ventoy_get_env(name
);
2145 grub_memset(name
, 0, sizeof(name
));
2146 puint
[1] = grub_swap_bytes32(0x5f434c52);
2147 puint
[0] = grub_swap_bytes32(0x56544c45);
2148 fmt3
= ventoy_get_env(name
);
2150 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2152 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2154 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2155 #pragma GCC diagnostic push
2156 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2157 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2158 fmt1
? fmt1
: fmtdata
,
2159 fmt2
? fmt2
: fmtdata
+ 4,
2160 value
? value
: "", plat
, guidstr
,
2161 fmt3
? fmt3
: fmtdata
+ 6);
2162 #pragma GCC diagnostic pop
2164 grub_memset(name
, 0, sizeof(name
));
2165 puint
[0] = grub_swap_bytes32(0x76746f79);
2166 puint
[2] = grub_swap_bytes32(0x656e7365);
2167 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2168 ventoy_set_env(name
, guidstr
);
2173 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2177 grub_uint8_t md5
[16];
2181 grub_memset(input
, 0, sizeof(input
));
2183 grub_printf("Enter password: ");
2186 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2188 grub_password_get(input
, 128);
2189 if (grub_strcmp(pwd
->text
, input
) == 0)
2194 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2196 grub_password_get(input
, 128);
2197 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2198 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2203 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2205 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2206 grub_password_get(input
+ offset
, 128);
2208 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2209 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2215 grub_printf("Invalid password!\n\n");
2222 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2224 img_info
*minimg
= NULL
;
2225 img_info
*img
= (img_info
*)(node
->firstiso
);
2227 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2229 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2244 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2246 img_iterator_node
*Minchild
= NULL
;
2247 img_iterator_node
*child
= node
->firstchild
;
2249 while (child
&& child
->parent
== node
)
2251 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2255 child
= child
->next
;
2260 Minchild
->select
= 1;
2266 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2269 img_info
*img
= NULL
;
2270 const char *dir_class
= NULL
;
2271 const char *dir_alias
= NULL
;
2272 img_iterator_node
*child
= NULL
;
2273 const menu_tip
*tip
= NULL
;
2275 if (node
->isocnt
== 0 || node
->done
== 1)
2280 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2282 offset
= node
->parent
->dirlen
;
2285 if (node
== &g_img_iterator_head
)
2287 if (g_default_menu_mode
== 0)
2289 if (g_tree_view_menu_style
== 0)
2291 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2292 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2293 " echo 'return ...' \n"
2298 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2299 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2300 " echo 'return ...' \n"
2305 g_tree_script_pre
= g_tree_script_pos
;
2309 node
->dir
[node
->dirlen
- 1] = 0;
2310 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2313 dir_class
= "vtoydir";
2316 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2318 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2321 if (g_tree_view_menu_style
== 0)
2323 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2324 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2325 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2329 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2330 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2331 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2336 dir_alias
= node
->dir
+ offset
;
2338 if (g_tree_view_menu_style
== 0)
2340 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2341 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2342 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2346 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2347 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2348 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2352 if (g_tree_view_menu_style
== 0)
2354 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2355 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2356 " echo 'return ...' \n"
2357 "}\n", "<--", node
->dir
);
2361 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2362 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2363 " echo 'return ...' \n"
2368 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2370 ventoy_dynamic_tree_menu(child
);
2373 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2375 if (g_tree_view_menu_style
== 0)
2377 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2378 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2381 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2382 img
->unsupport
? "[***********] " : "",
2383 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2385 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2389 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2390 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2393 img
->unsupport
? "[***********] " : "",
2394 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2396 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2400 if (node
!= &g_img_iterator_head
)
2402 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2409 static int ventoy_set_default_menu(void)
2415 const char *strdata
= NULL
;
2416 img_info
*cur
= NULL
;
2417 img_info
*default_node
= NULL
;
2418 const char *default_image
= NULL
;
2420 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2421 if (default_image
&& default_image
[0] == '/')
2423 img_len
= grub_strlen(default_image
);
2425 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2427 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2439 if (0 == g_default_menu_mode
)
2441 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2445 def
= grub_strdup(default_image
);
2451 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2453 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2454 if (strdata
&& strdata
[0] == '/')
2456 pos
= def
+ grub_strlen(strdata
);
2467 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2470 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2474 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2482 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2484 img_info
*next
= NULL
;
2485 img_info
*cur
= g_ventoy_img_list
;
2498 g_ventoy_img_list
= NULL
;
2499 g_ventoy_img_count
= 0;
2501 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2504 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2507 img_info
*cur
= g_ventoy_img_list
;
2511 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2513 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2516 img_id
= grub_strtol(args
[0], NULL
, 10);
2517 if (img_id
>= g_ventoy_img_count
)
2519 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2522 debug("Find image %ld name \n", img_id
);
2524 while (cur
&& img_id
> 0)
2532 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2535 debug("image name is %s\n", cur
->name
);
2537 grub_env_set(args
[1], cur
->name
);
2539 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2542 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2546 img_info
*cur
= g_ventoy_img_list
;
2552 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2555 len
= (int)grub_strlen(args
[0]);
2559 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2568 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2571 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2572 grub_env_set("chosen", id
);
2573 grub_env_export("chosen");
2575 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2578 static char g_fake_vlnk_src
[512];
2579 static char g_fake_vlnk_dst
[512];
2580 static grub_uint64_t g_fake_vlnk_size
;
2581 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2587 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2589 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2590 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2592 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2594 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2597 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2603 g_fake_vlnk_src
[0] = 0;
2604 g_fake_vlnk_dst
[0] = 0;
2605 g_fake_vlnk_size
= 0;
2606 grub_file_vtoy_vlnk(NULL
, NULL
);
2608 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2612 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2617 const char *id
= NULL
;
2618 img_info
*cur
= NULL
;
2622 if (argc
< 1 || argc
> 3)
2624 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2627 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2629 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2630 grub_env_set(args
[0], pos
);
2633 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2634 grub_env_set(args
[1], value
);
2639 for (last
= pos
; *pos
; pos
++)
2646 grub_env_set(args
[2], last
+ 1);
2652 id
= grub_env_get("chosen");
2654 pos
= grub_strstr(id
, "VID_");
2657 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2661 cur
= g_ventoy_img_list
;
2666 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2669 grub_env_set(args
[0], cur
->path
);
2673 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2674 grub_env_set(args
[1], value
);
2679 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2680 grub_env_set(args
[2], cur
->name
);
2684 g_svd_replace_offset
= 0;
2686 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2690 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2694 grub_device_t dev
= NULL
;
2695 img_info
*cur
= NULL
;
2696 img_info
*tail
= NULL
;
2697 img_info
*min
= NULL
;
2698 img_info
*head
= NULL
;
2699 const char *strdata
= NULL
;
2700 char *device_name
= NULL
;
2702 img_iterator_node
*node
= NULL
;
2703 img_iterator_node
*tmp
= NULL
;
2709 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2712 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2714 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2719 g_enumerate_time_checked
= 0;
2720 g_enumerate_start_time_ms
= grub_get_time_ms();
2722 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2723 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2725 g_filt_dot_underscore_file
= 1;
2728 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2729 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2731 g_sort_case_sensitive
= 1;
2734 device_name
= grub_file_get_device_name(args
[0]);
2740 g_enum_dev
= dev
= grub_device_open(device_name
);
2746 g_enum_fs
= fs
= grub_fs_probe(dev
);
2752 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2754 debug("unsupported fs:<%s>\n", fs
->name
);
2755 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2759 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2761 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2762 if (strdata
&& strdata
[0] == '1')
2764 g_default_menu_mode
= 1;
2767 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2769 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2771 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2772 if (strdata
&& strdata
[0] == '/')
2774 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2775 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2777 g_img_iterator_head
.dir
[len
++] = '/';
2779 g_img_iterator_head
.dirlen
= len
;
2783 g_img_iterator_head
.dirlen
= 1;
2784 grub_strcpy(g_img_iterator_head
.dir
, "/");
2787 g_img_iterator_head
.tail
= &tail
;
2789 if (g_img_max_search_level
< 0)
2791 g_img_max_search_level
= GRUB_INT_MAX
;
2792 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2793 if (strdata
&& ventoy_is_decimal(strdata
))
2795 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2799 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2800 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2801 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2802 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2803 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2804 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2806 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2808 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2811 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2812 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2814 g_tree_view_menu_style
= 1;
2817 ventoy_set_default_menu();
2819 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2821 ventoy_dynamic_tree_menu(node
);
2825 node
= g_img_iterator_head
.next
;
2833 /* sort image list by image name */
2834 while (g_ventoy_img_list
)
2836 min
= g_ventoy_img_list
;
2837 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2839 if (ventoy_cmp_img(min
, cur
) > 0)
2847 min
->prev
->next
= min
->next
;
2852 min
->next
->prev
= min
->prev
;
2855 if (min
== g_ventoy_img_list
)
2857 g_ventoy_img_list
= min
->next
;
2875 g_ventoy_img_list
= head
;
2877 if (g_default_menu_mode
== 1)
2879 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2880 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2881 " echo 'return ...' \n"
2885 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2887 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2888 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2891 cur
->unsupport
? "[***********] " : "",
2892 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2894 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2897 g_tree_script_buf
[g_tree_script_pos
] = 0;
2898 g_list_script_buf
[g_list_script_pos
] = 0;
2900 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2901 grub_env_set(args
[1], buf
);
2905 check_free(device_name
, grub_free
);
2906 check_free(dev
, grub_device_close
);
2908 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2911 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2918 device_name
= grub_file_get_device_name(filename
);
2930 pos2
= grub_strstr(pos
, ",");
2933 pos2
= grub_strstr(pos
, ")");
2941 disk
= grub_disk_open(pos
);
2944 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2945 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2946 grub_disk_close(disk
);
2953 grub_free(device_name
);
2957 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2959 eltorito_descriptor desc
;
2961 grub_memset(&desc
, 0, sizeof(desc
));
2962 grub_file_seek(file
, 17 * 2048);
2963 grub_file_read(file
, &desc
, sizeof(desc
));
2965 if (desc
.type
!= 0 || desc
.version
!= 1)
2970 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2971 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2979 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2981 grub_uint8_t buf
[512];
2983 grub_file_seek(file
, sector
* 2048);
2984 grub_file_read(file
, buf
, sizeof(buf
));
2986 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2987 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2989 return *((grub_uint32_t
*)(buf
+ 40));
2995 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2999 grub_uint8_t buf
[512];
3000 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3002 grub_file_seek(file
, sector
* 2048);
3003 grub_file_read(file
, buf
, sizeof(buf
));
3005 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3007 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3011 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3016 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3018 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3020 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3024 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3026 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3031 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3033 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3035 if (buf
[36] == parttype
[i
])
3037 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3043 debug("%s does not contain efi eltorito\n", file
->name
);
3047 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3050 const char *fs
= NULL
;
3051 const char *val
= NULL
;
3052 const char *cdprompt
= NULL
;
3054 grub_uint8_t chksum
= 0;
3057 disk
= file
->device
->disk
;
3058 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3060 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3061 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3062 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3064 pos
= grub_strstr(file
->name
, "/");
3070 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3072 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3074 param
->vtoy_img_size
= file
->size
;
3076 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3077 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3079 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3081 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3082 param
->vtoy_reserved
[4] = 0;
3083 if (g_ventoy_chain_type
== 1) /* Windows */
3085 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3086 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3088 param
->vtoy_reserved
[4] = 1;
3092 fs
= ventoy_get_env("ventoy_fs_probe");
3093 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3095 param
->vtoy_reserved
[3] = 1;
3098 param
->vtoy_reserved
[5] = 0;
3099 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3100 if (val
&& val
[0] == '1' && val
[1] == 0)
3102 param
->vtoy_reserved
[5] = 1;
3105 /* ventoy_disk_signature used for vlnk */
3106 param
->vtoy_reserved
[6] = file
->vlnk
;
3107 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3109 /* calculate checksum */
3110 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3112 chksum
+= *((grub_uint8_t
*)param
+ i
);
3114 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3119 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3121 grub_uint32_t i
= 0;
3122 grub_uint64_t total
= 0;
3123 grub_uint64_t fileblk
= 0;
3124 ventoy_img_chunk
*chunk
= NULL
;
3126 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3128 chunk
= chunklist
->chunk
+ i
;
3130 if (chunk
->disk_start_sector
<= start
)
3132 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3136 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3139 fileblk
= (file
->size
+ 511) / 512;
3141 if (total
!= fileblk
)
3143 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3144 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3146 debug("maybe img file to be processed.\n");
3156 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3160 grub_uint32_t i
= 0;
3161 grub_uint32_t sector
= 0;
3162 grub_uint32_t count
= 0;
3163 grub_off_t size
= 0;
3164 grub_off_t read
= 0;
3166 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3167 if (fs_type
== ventoy_fs_exfat
)
3169 grub_fat_get_file_chunk(start
, file
, chunklist
);
3171 else if (fs_type
== ventoy_fs_ext
)
3173 grub_ext_get_file_chunk(start
, file
, chunklist
);
3177 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3178 file
->read_hook_data
= chunklist
;
3180 for (size
= file
->size
; size
> 0; size
-= read
)
3182 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3183 grub_file_read(file
, NULL
, read
);
3186 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3188 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3189 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3192 if (ventoy_fs_udf
== fs_type
)
3194 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3196 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3197 chunklist
->chunk
[i
].img_start_sector
= sector
;
3198 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3204 len
= (int)grub_strlen(file
->name
);
3205 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3206 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3207 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3208 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3210 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3212 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3222 chunklist
->chunk
[i
].img_start_sector
= sector
;
3223 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3231 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3235 grub_disk_addr_t start
;
3240 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3243 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3246 g_conf_replace_node
= NULL
;
3247 g_conf_replace_offset
= 0;
3249 if (g_img_chunk_list
.chunk
)
3251 grub_free(g_img_chunk_list
.chunk
);
3254 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3256 grub_file_close(file
);
3257 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3260 /* get image chunk data */
3261 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3262 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3263 if (NULL
== g_img_chunk_list
.chunk
)
3265 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3268 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3269 g_img_chunk_list
.cur_chunk
= 0;
3271 start
= file
->device
->disk
->partition
->start
;
3273 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3275 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3276 grub_file_close(file
);
3280 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3283 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3284 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3285 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3288 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3290 grub_uint64_t offset
= 0;
3291 grub_uint32_t align
= 0;
3292 grub_file_t file
= NULL
;
3293 conf_replace
*node
= NULL
;
3299 debug("select conf replace argc:%d\n", argc
);
3306 node
= ventoy_plugin_find_conf_replace(args
[1]);
3309 debug("Conf replace not found for %s\n", args
[1]);
3313 debug("Find conf replace for %s\n", args
[1]);
3315 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3318 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3319 grub_file_close(file
);
3321 else if (node
->img
> 0)
3327 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3331 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3334 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3338 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3340 if (align
> vtoy_max_replace_file_size
)
3342 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3346 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3347 g_conf_replace_new_len
= (int)file
->size
;
3348 g_conf_replace_new_len_align
= align
;
3350 g_conf_replace_node
= node
;
3351 g_conf_replace_offset
= offset
+ 2;
3355 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3356 g_grub_param
->img_replace
.old_name_cnt
= 1;
3357 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3360 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3365 grub_file_close(file
);
3367 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3370 static int ventoy_is_builtin_var(const char *var
)
3374 const char *builtin_vars_full
[] =
3376 "VT_DISK_1ST_NONVTOY",
3377 "VT_DISK_1ST_NONUSB",
3381 for (i
= 0; builtin_vars_full
[i
]; i
++)
3383 if (grub_strcmp(builtin_vars_full
[i
], var
) == 0)
3389 if (grub_strncmp(var
, "VT_DISK_CLOSEST_", 16) == 0)
3394 if (*c
< '0' || *c
> '9')
3401 if (*c
== 0 && c
!= (var
+ 16))
3410 static int ventoy_var_expand(int *flag
, const char *var
, char *expand
, int len
)
3415 const char *ch
= var
;
3421 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z'))
3428 debug("Invalid variable letter <%c>\n", *ch
);
3435 debug("Invalid variable length:%d <%s>\n", n
, var
);
3439 if (ventoy_is_builtin_var(var
))
3448 grub_printf("\n=================== Parameter Expansion ===================\n\n");
3451 grub_printf("<%s>: ", var
);
3454 while (i
< (len
- 1))
3457 if ((c
== '\n') || (c
== '\r'))
3466 else if (grub_isprint(c
))
3468 if (i
+ 1 < (len
- 1))
3470 grub_printf("%c", c
);
3480 expand
[i
- 1] = ' ';
3481 grub_printf("\r<%s>: %s", var
, expand
);
3484 grub_printf("\r<%s>: %s", var
, expand
);
3496 grub_snprintf(expand
, len
, "$$%s$$", var
);
3502 static int ventoy_auto_install_var_expand(install_template
*node
)
3509 char *newbuf
= NULL
;
3510 char *curline
= NULL
;
3511 char *nextline
= NULL
;
3512 grub_uint8_t
*code
= NULL
;
3515 code
= (grub_uint8_t
*)node
->filebuf
;
3517 if (node
->filelen
>= VTOY_SIZE_1MB
)
3519 debug("auto install script too long %d\n", node
->filelen
);
3523 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3525 debug("UCS-2 encoding NOT supported\n");
3529 start
= grub_strstr(node
->filebuf
, "$$");
3532 debug("no need to expand variable, no start.\n");
3536 end
= grub_strstr(start
+ 2, "$$");
3539 debug("no need to expand variable, no end.\n");
3543 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3544 newbuf
= grub_malloc(newlen
);
3547 debug("Failed to alloc newbuf %d\n", newlen
);
3551 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3553 nextline
= ventoy_get_line(curline
);
3555 start
= grub_strstr(curline
, "$$");
3558 end
= grub_strstr(start
+ 2, "$$");
3564 VTOY_APPEND_NEWBUF(curline
);
3566 value
[sizeof(value
) - 1] = 0;
3567 ventoy_var_expand(&flag
, start
+ 2, value
, sizeof(value
) - 1);
3568 VTOY_APPEND_NEWBUF(value
);
3570 VTOY_APPEND_NEWBUF(end
+ 2);
3574 VTOY_APPEND_NEWBUF(curline
);
3577 newbuf
[pos
++] = '\n';
3580 grub_free(node
->filebuf
);
3581 node
->filebuf
= newbuf
;
3582 node
->filelen
= pos
;
3587 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3593 grub_file_t file
= NULL
;
3594 char configfile
[128];
3595 install_template
*node
= NULL
;
3601 debug("select auto installation argc:%d\n", argc
);
3608 node
= ventoy_plugin_find_install_template(args
[0]);
3611 debug("Auto install template not found for %s\n", args
[0]);
3615 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3617 defidx
= node
->autosel
;
3618 if (node
->timeout
< 0)
3620 node
->cursel
= node
->autosel
- 1;
3621 debug("Auto install template auto select %d\n", node
->autosel
);
3626 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3632 if (node
->timeout
> 0)
3634 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3637 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3638 " echo %s\n}\n", "");
3640 for (i
= 0; i
< node
->templatenum
; i
++)
3642 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3644 node
->templatepath
[i
].path
);
3647 g_ventoy_menu_esc
= 1;
3648 g_ventoy_suppress_esc
= 1;
3649 g_ventoy_suppress_esc_default
= defidx
;
3651 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3652 grub_script_execute_sourcecode(configfile
);
3654 g_ventoy_menu_esc
= 0;
3655 g_ventoy_suppress_esc
= 0;
3656 g_ventoy_suppress_esc_default
= 1;
3660 node
->cursel
= g_ventoy_last_entry
- 1;
3662 grub_check_free(node
->filebuf
);
3665 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3667 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3668 node
->templatepath
[node
->cursel
].path
);
3671 node
->filebuf
= grub_malloc(file
->size
+ 8);
3674 grub_file_read(file
, node
->filebuf
, file
->size
);
3675 grub_file_close(file
);
3677 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3678 node
->filelen
= (int)file
->size
;
3680 ventoy_auto_install_var_expand(node
);
3685 debug("Failed to open auto install script <%s%s>\n",
3686 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3690 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3693 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3699 char configfile
[128];
3700 persistence_config
*node
;
3706 debug("select persistence argc:%d\n", argc
);
3713 node
= ventoy_plugin_find_persistent(args
[0]);
3716 debug("Persistence image not found for %s\n", args
[0]);
3720 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3722 defidx
= node
->autosel
;
3723 if (node
->timeout
< 0)
3725 node
->cursel
= node
->autosel
- 1;
3726 debug("Persistence image auto select %d\n", node
->autosel
);
3731 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3737 if (node
->timeout
> 0)
3739 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3742 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3743 " echo %s\n}\n", "");
3745 for (i
= 0; i
< node
->backendnum
; i
++)
3747 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3749 node
->backendpath
[i
].path
);
3753 g_ventoy_menu_esc
= 1;
3754 g_ventoy_suppress_esc
= 1;
3755 g_ventoy_suppress_esc_default
= defidx
;
3757 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3758 grub_script_execute_sourcecode(configfile
);
3760 g_ventoy_menu_esc
= 0;
3761 g_ventoy_suppress_esc
= 0;
3762 g_ventoy_suppress_esc_default
= 1;
3766 node
->cursel
= g_ventoy_last_entry
- 1;
3768 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3771 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3774 ventoy_img_chunk
*cur
;
3780 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3782 cur
= g_img_chunk_list
.chunk
+ i
;
3783 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3784 cur
->img_start_sector
, cur
->img_end_sector
,
3785 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3789 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3792 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3796 ventoy_img_chunk_list chunklist
;
3801 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3804 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3807 /* get image chunk data */
3808 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3809 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3810 if (NULL
== chunklist
.chunk
)
3812 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3815 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3816 chunklist
.cur_chunk
= 0;
3818 ventoy_get_block_list(file
, &chunklist
, 0);
3820 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3822 grub_printf("########## UNSUPPORTED ###############\n");
3825 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3827 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3829 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3830 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3833 grub_printf("\n==================================\n");
3835 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3837 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3838 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3839 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3840 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3841 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3845 grub_free(chunklist
.chunk
);
3846 grub_file_close(file
);
3848 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3851 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3854 ventoy_grub_param_file_replace
*replace
= NULL
;
3862 replace
= &(g_grub_param
->file_replace
);
3863 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3865 replace
->old_name_cnt
= 0;
3866 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3868 replace
->old_name_cnt
++;
3869 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3872 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3875 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3878 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3881 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3887 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3888 grub_env_set(args
[0], buf
);
3891 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3894 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3902 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3903 grub_printf("%s", g_list_script_buf
);
3907 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3908 grub_printf("%s", g_tree_script_buf
);
3914 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3916 img_info
*cur
= g_ventoy_img_list
;
3924 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3925 grub_printf("name:<%s>\n\n", cur
->name
);
3932 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3938 ventoy_plugin_dump_injection();
3943 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3949 ventoy_plugin_dump_auto_install();
3954 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3960 ventoy_plugin_dump_persistence();
3965 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
3971 len1
= (int)grub_strlen(filename
);
3972 len2
= (int)grub_strlen(suffix
);
3979 for (i
= len1
- 1; i
>= 0; i
--)
3981 if (filename
[i
] == '.')
3992 if (filename
[i
- len2
- 1] != '_')
3997 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4005 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4011 if (argc
!= 1 && argc
!= 2)
4016 if (args
[0][0] == '0')
4018 if (g_ventoy_memdisk_mode
)
4023 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4030 else if (args
[0][0] == '1')
4032 return g_ventoy_iso_raw
? 0 : 1;
4034 else if (args
[0][0] == '2')
4036 return g_ventoy_iso_uefi_drv
? 0 : 1;
4038 else if (args
[0][0] == '3')
4040 if (g_ventoy_grub2_mode
)
4045 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4052 else if (args
[0][0] == '4')
4054 if (g_ventoy_wimboot_mode
)
4059 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4070 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4072 static int configfile_mode
= 0;
4073 char memfile
[128] = {0};
4080 * args[0]: 0:normal 1:configfile
4081 * args[1]: 0:list_buf 1:tree_buf
4086 debug("Invalid argc %d\n", argc
);
4092 if (args
[0][0] == '0')
4094 if (args
[1][0] == '0')
4096 grub_script_execute_sourcecode(g_list_script_buf
);
4100 grub_script_execute_sourcecode(g_tree_script_buf
);
4105 if (configfile_mode
)
4107 debug("Now already in F3 mode %d\n", configfile_mode
);
4111 if (args
[1][0] == '0')
4113 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4114 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4118 g_ventoy_last_entry
= -1;
4119 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4120 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4123 configfile_mode
= 1;
4124 grub_script_execute_sourcecode(memfile
);
4125 configfile_mode
= 0;
4131 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4142 g_ventoy_case_insensitive
= 1;
4143 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4144 g_ventoy_case_insensitive
= 0;
4150 grub_file_close(file
);
4156 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4161 const char *isopath
= NULL
;
4163 ventoy_mbr_head mbr
;
4170 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4173 isopath
= grub_env_get("vtoy_iso_part");
4176 debug("isopath is null %p\n", isopath
);
4180 debug("isopath is %s\n", isopath
);
4182 for (id
= 0; id
< 30 && (find
== 0); id
++)
4184 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4185 if (grub_strstr(isopath
, hdname
))
4187 debug("skip %s ...\n", hdname
);
4191 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4193 disk
= grub_disk_open(hdname
);
4196 debug("%s not exist\n", hdname
);
4200 grub_memset(&mbr
, 0, sizeof(mbr
));
4201 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4203 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4205 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4206 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4209 grub_env_set(args
[0], hdname
);
4213 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4217 debug("read %s failed\n", hdname
);
4220 grub_disk_close(disk
);
4226 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4237 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4240 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4243 debug("failed to open file %s\n", args
[0]);
4247 buf
= grub_malloc(len
);
4254 grub_file_read(file
, buf
, len
- 1);
4256 ventoy_get_line(buf
);
4257 ventoy_set_env(args
[1], buf
);
4261 grub_check_free(buf
);
4262 grub_file_close(file
);
4267 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4269 grub_uint64_t end_max
= 0;
4270 int *pCnt
= (int *)data
;
4275 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4276 "0 %llu linear /dev/ventoy %llu\n",
4277 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4279 end_max
= (partition
->len
+ partition
->start
) * 512;
4280 if (end_max
> g_part_end_max
)
4282 g_part_end_max
= end_max
;
4288 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4291 char *device_name
= NULL
;
4292 grub_device_t dev
= NULL
;
4297 g_part_list_pos
= 0;
4299 grub_env_unset("vtoy_img_part_file");
4306 device_name
= grub_file_get_device_name(args
[0]);
4309 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4313 dev
= grub_device_open(device_name
);
4316 debug("grub_device_open failed, %s\n", device_name
);
4320 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4322 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4323 grub_env_set("vtoy_img_part_file", buf
);
4325 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4326 grub_env_set("vtoy_img_part_cnt", buf
);
4328 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4329 grub_env_set("vtoy_img_max_part_end", buf
);
4333 check_free(device_name
, grub_free
);
4334 check_free(dev
, grub_device_close
);
4340 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4351 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4354 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4357 debug("failed to open file %s\n", args
[0]);
4361 buf
= grub_malloc(file
->size
+ 1);
4367 buf
[file
->size
] = 0;
4368 grub_file_read(file
, buf
, file
->size
);
4370 if (grub_strstr(buf
, args
[1]))
4377 grub_check_free(buf
);
4378 grub_file_close(file
);
4383 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4389 ventoy_iso9660_vd pvd
;
4396 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4399 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4402 debug("failed to open file %s\n", args
[0]);
4406 grub_file_seek(file
, 16 * 2048);
4407 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4408 if (len
!= sizeof(pvd
))
4410 debug("failed to read pvd %d\n", len
);
4414 grub_memset(buf
, 0, sizeof(buf
));
4415 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4416 ventoy_set_env(args
[1], buf
);
4418 grub_memset(buf
, 0, sizeof(buf
));
4419 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4420 ventoy_set_env(args
[2], buf
);
4424 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4425 ventoy_set_env(args
[3], buf
);
4428 grub_file_close(file
);
4433 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4444 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4447 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4450 debug("failed to open file %s\n", args
[0]);
4454 grub_memset(buf
, 0, sizeof(buf
));
4455 grub_file_seek(file
, 16 * 2048 + 813);
4456 len
= (int)grub_file_read(file
, buf
, 17);
4459 debug("failed to read create date %d\n", len
);
4463 ventoy_set_env(args
[1], buf
);
4466 grub_file_close(file
);
4471 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4477 ventoy_env_hook_root(1);
4482 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4488 ventoy_env_hook_root(0);
4493 #ifdef GRUB_MACHINE_EFI
4494 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4499 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4505 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4506 if (var
&& *var
== 1)
4514 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4523 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4528 grub_uint64_t FileSectors
= 0;
4529 ventoy_gpt_info
*gpt
= NULL
;
4530 ventoy_part_table
*pt
= NULL
;
4531 grub_uint8_t zeroguid
[16] = {0};
4536 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4539 debug("failed to open file %s\n", args
[0]);
4543 if (file
->size
% 512)
4545 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4549 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4555 FileSectors
= file
->size
/ 512;
4557 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4558 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4560 debug("This is EFI partition table\n");
4562 for (i
= 0; i
< 128; i
++)
4564 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4566 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4568 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4569 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4577 debug("This is MBR partition table\n");
4579 for (i
= 0; i
< 4; i
++)
4581 pt
= gpt
->MBR
.PartTbl
+ i
;
4582 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4584 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4585 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4586 (ulonglong
)FileSectors
);
4595 grub_file_close(file
);
4596 grub_check_free(gpt
);
4597 grub_errno
= GRUB_ERR_NONE
;
4601 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4610 for (i
= 0; i
< 500; i
++)
4612 ret
= grub_getkey_noblock();
4613 if (ret
== GRUB_TERM_NO_KEY
)
4622 grub_printf("\n\n Still have key input after clear.\n");
4630 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4637 int image_sector_size
;
4639 ventoy_chain_head
*chain
;
4640 ventoy_img_chunk
*chunk
;
4641 ventoy_os_param
*osparam
;
4642 ventoy_image_location
*location
;
4643 ventoy_image_disk_region
*region
;
4644 struct grub_acpi_table_header
*acpi
;
4653 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4655 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4661 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4663 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4665 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4669 img_chunk_num
= chain
->img_chunk_num
;
4671 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4672 datalen
= sizeof(ventoy_os_param
) + loclen
;
4674 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4675 acpi
= grub_zalloc(buflen
);
4681 /* Step1: Fill acpi table header */
4682 grub_memcpy(acpi
->signature
, "VTOY", 4);
4683 acpi
->length
= buflen
;
4685 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4686 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4688 acpi
->creator_id
[0] = 1;
4689 acpi
->creator_rev
= 1;
4691 /* Step2: Fill data */
4692 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4693 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4694 osparam
->vtoy_img_location_addr
= 0;
4695 osparam
->vtoy_img_location_len
= loclen
;
4696 osparam
->chksum
= 0;
4697 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4699 location
= (ventoy_image_location
*)(osparam
+ 1);
4700 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4701 location
->image_sector_size
= image_sector_size
;
4702 location
->disk_sector_size
= chain
->disk_sector_size
;
4703 location
->region_count
= img_chunk_num
;
4705 region
= location
->regions
;
4706 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4707 if (512 == image_sector_size
)
4709 for (i
= 0; i
< img_chunk_num
; i
++)
4711 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4712 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4713 region
->disk_start_sector
= chunk
->disk_start_sector
;
4720 for (i
= 0; i
< img_chunk_num
; i
++)
4722 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4723 region
->image_start_sector
= chunk
->img_start_sector
;
4724 region
->disk_start_sector
= chunk
->disk_start_sector
;
4730 /* Step3: Fill acpi checksum */
4732 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4734 /* load acpi table */
4735 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4736 grub_script_execute_sourcecode(cmd
);
4740 VENTOY_CMD_RETURN(0);
4743 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4749 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4750 g_ventoy_last_entry
= -1;
4755 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4761 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4766 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4768 const char *pos
= filename
+ 1;
4776 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4778 grub_strncpy((char *)data
, filename
, 128);
4789 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4792 char *device_name
= NULL
;
4793 grub_device_t dev
= NULL
;
4794 grub_fs_t fs
= NULL
;
4795 char buf
[128] = {0};
4801 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4805 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4807 device_name
= grub_file_get_device_name(args
[0]);
4810 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4814 dev
= grub_device_open(device_name
);
4817 debug("grub_device_open failed, %s\n", device_name
);
4821 fs
= grub_fs_probe(dev
);
4824 debug("grub_fs_probe failed, %s\n", device_name
);
4828 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4832 ventoy_set_env(args
[2], buf
);
4839 check_free(device_name
, grub_free
);
4840 check_free(dev
, grub_device_close
);
4845 int ventoy_load_part_table(const char *diskname
)
4852 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4853 if (!g_ventoy_part_info
)
4858 disk
= grub_disk_open(diskname
);
4861 debug("Failed to open disk %s\n", diskname
);
4865 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4867 g_ventoy_disk_bios_id
= disk
->id
;
4869 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4870 grub_disk_close(disk
);
4872 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4873 dev
= grub_device_open(name
);
4876 /* Check for official Ventoy device */
4877 ret
= ventoy_check_official_device(dev
);
4878 grub_device_close(dev
);
4886 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4887 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4892 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4899 ret
= ventoy_load_part_table(args
[0]);
4905 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4906 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4911 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4914 const char *vcfg
= NULL
;
4919 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4922 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4923 grub_env_set(args
[1], vcfg
);
4928 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4936 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4939 grub_uint8_t zeroguid
[16] = {0};
4944 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4947 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4949 if (id
>= 1 && id
<= 128)
4951 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4959 if (id
>= 1 && id
<= 4)
4961 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4971 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4974 char *device_name
= NULL
;
4975 grub_device_t dev
= NULL
;
4976 grub_fs_t fs
= NULL
;
4981 debug("get fs label for %s\n", args
[0]);
4985 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4989 device_name
= grub_file_get_device_name(args
[0]);
4992 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4996 dev
= grub_device_open(device_name
);
4999 debug("grub_device_open failed, %s\n", device_name
);
5003 fs
= grub_fs_probe(dev
);
5004 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5006 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5010 fs
->fs_label(dev
, &label
);
5013 debug("label=<%s>\n", label
);
5014 ventoy_set_env(args
[1], label
);
5022 check_free(device_name
, grub_free
);
5023 check_free(dev
, grub_device_close
);
5028 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5032 grub_snprintf((char *)data
, 256, "%s", filename
);
5039 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5041 if (info
->dir
&& filename
&& filename
[0] != '.')
5043 grub_snprintf((char *)data
, 256, "%s", filename
);
5050 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5053 char *device_name
= NULL
;
5054 grub_device_t dev
= NULL
;
5055 grub_fs_t fs
= NULL
;
5056 char name
[256] ={0};
5060 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5064 device_name
= grub_file_get_device_name(args
[0]);
5067 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5071 dev
= grub_device_open(device_name
);
5074 debug("grub_device_open failed, %s\n", device_name
);
5078 fs
= grub_fs_probe(dev
);
5081 debug("grub_fs_probe failed, %s\n", device_name
);
5085 fs
->fs_dir(dev
, args
[1], hook
, name
);
5088 ventoy_set_env(args
[2], name
);
5095 check_free(device_name
, grub_free
);
5096 check_free(dev
, grub_device_close
);
5101 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5104 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5107 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5110 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5113 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5123 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5127 for (pos
= args
[0]; *pos
; pos
++)
5141 grub_env_set(args
[1], args
[0]);
5151 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5161 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5166 len
= (int)grub_strlen(buf
);
5167 for (i
= len
; i
> 0; i
--)
5169 if (buf
[i
- 1] == '/')
5171 grub_env_set(args
[1], buf
+ i
);
5176 grub_env_set(args
[1], buf
);
5181 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5183 struct grub_video_mode_info info
;
5190 if (!g_video_mode_list
)
5192 ventoy_enum_video_mode();
5195 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5197 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5201 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5204 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5206 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5207 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5209 VENTOY_CMD_RETURN(0);
5212 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5214 struct grub_video_mode_info info
;
5221 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5223 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5227 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5230 grub_env_set(args
[0], buf
);
5232 VENTOY_CMD_RETURN(0);
5235 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5243 if (!g_video_mode_list
)
5248 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5249 if (id
< g_video_mode_num
)
5251 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5252 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5255 grub_env_set(args
[1], buf
);
5257 VENTOY_CMD_RETURN(0);
5260 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5263 grub_uint32_t loadsector
= 0;
5266 grub_uint32_t boot_catlog
= 0;
5267 grub_uint8_t buf
[512];
5273 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5277 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5280 debug("failed to open %s\n", args
[0]);
5284 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5285 if (boot_catlog
== 0)
5287 debug("No bootcatlog found\n");
5288 grub_file_close(file
);
5292 grub_memset(buf
, 0, sizeof(buf
));
5293 grub_file_seek(file
, boot_catlog
* 2048);
5294 grub_file_read(file
, buf
, sizeof(buf
));
5295 grub_file_close(file
);
5297 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5299 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5301 if (buf
[i
+ 32] == 0x88)
5303 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5304 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5310 if (loadsector
== 0)
5312 debug("No EFI eltorito info found\n");
5316 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5317 grub_env_set(args
[1], value
);
5318 VENTOY_CMD_RETURN(0);
5321 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5326 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5328 if (pfsdir
->initrd
[0])
5333 curpos
= pfsdir
->curpos
;
5334 len
= grub_strlen(filename
);
5338 if ((len
== 1 && filename
[0] == '.') ||
5339 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5344 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5347 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5348 pfsdir
->curpos
= curpos
+ printlen
;
5349 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5350 pfsdir
->curpos
= curpos
;
5351 pfsdir
->fullpath
[curpos
] = 0;
5355 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5358 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5359 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5361 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5363 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5372 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5376 char *device_name
= NULL
;
5377 grub_device_t dev
= NULL
;
5378 grub_fs_t fs
= NULL
;
5379 replace_fs_dir
*pfsdir
= NULL
;
5385 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5389 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5395 device_name
= grub_file_get_device_name(args
[0]);
5401 dev
= grub_device_open(device_name
);
5407 fs
= grub_fs_probe(dev
);
5416 pfsdir
->fullpath
[0] = '/';
5417 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5419 if (pfsdir
->initrd
[0])
5421 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5423 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5425 if (pfsdir
->initrd
[i
] == '/')
5427 pfsdir
->initrd
[i
] = '\\';
5431 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5432 grub_env_set(args
[1], pos
);
5436 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5441 grub_check_free(pfsdir
);
5442 grub_check_free(device_name
);
5443 check_free(dev
, grub_device_close
);
5445 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5448 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5450 const char *pager
= NULL
;
5456 pager
= grub_env_get("pager");
5460 grub_env_set("pager", "1");
5462 else if (pager
[0] == '1')
5468 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5470 grub_env_set("pager", "1");
5473 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5476 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5482 if (g_pager_flag
== 1)
5484 grub_env_unset("pager");
5486 else if (g_pager_flag
== 2)
5488 grub_env_set("pager", g_old_pager
);
5491 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5494 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5496 if (g_json_case_mis_path
[0])
5501 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5503 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5509 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5512 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5514 if (g_json_case_mis_path
[0])
5519 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5521 if (grub_strcasecmp(filename
, "ventoy") == 0)
5523 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5524 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5525 if (g_json_case_mis_path
[0])
5535 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5538 char *device_name
= NULL
;
5539 grub_device_t dev
= NULL
;
5540 grub_fs_t fs
= NULL
;
5541 chk_case_fs_dir fs_dir
;
5547 device_name
= grub_file_get_device_name(args
[0]);
5553 dev
= grub_device_open(device_name
);
5559 fs
= grub_fs_probe(dev
);
5565 fstype
= ventoy_get_fs_type(fs
->name
);
5566 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5571 g_json_case_mis_path
[0] = 0;
5574 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5576 if (g_json_case_mis_path
[0])
5578 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5583 grub_check_free(device_name
);
5584 check_free(dev
, grub_device_close
);
5586 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5589 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5592 grub_partition_t part
;
5593 char priority_str
[3]; /* Maximum value 15 */
5597 if (argc
< 2 || argc
> 3)
5598 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5599 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5601 /* Open the disk if it exists */
5602 disk
= grub_disk_open (args
[0]);
5605 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5609 part
= grub_partition_probe (disk
, args
[1]);
5612 grub_disk_close (disk
);
5613 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5614 "No such partition");
5617 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5619 grub_disk_close (disk
);
5620 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5621 "Not a GPT partition");
5624 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5625 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5629 grub_env_set (args
[2], priority_str
);
5630 grub_env_export (args
[2]);
5634 grub_printf ("Priority is %s\n", priority_str
);
5637 grub_disk_close (disk
);
5638 return GRUB_ERR_NONE
;
5642 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5646 grub_file_t file
= NULL
;
5647 grub_uint32_t loadrba
= 0;
5648 grub_uint32_t boot_catlog
= 0;
5649 grub_uint8_t sector
[512];
5650 boot_info_table
*info
= NULL
;
5655 /* This also trigger a iso9660 fs parse */
5656 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5661 joliet
= grub_iso9660_is_joliet();
5667 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5670 debug("failed to open %s\n", args
[0]);
5674 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5675 if (boot_catlog
== 0)
5677 debug("no bootcatlog found %u\n", boot_catlog
);
5681 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5684 debug("no bios eltorito rba found %u\n", loadrba
);
5688 grub_file_seek(file
, loadrba
* 2048);
5689 grub_file_read(file
, sector
, 512);
5691 info
= (boot_info_table
*)sector
;
5692 if (info
->bi_data0
== 0x7c6ceafa &&
5693 info
->bi_data1
== 0x90900000 &&
5694 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5695 info
->bi_BootFileLocation
== loadrba
)
5697 debug("bootloader is syslinux, %u.\n", loadrba
);
5703 grub_file_close(file
);
5704 grub_errno
= GRUB_ERR_NONE
;
5708 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5711 ventoy_vlnk_part
*node
;
5717 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5719 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5720 ++n
, node
->device
, node
->disksig
,
5721 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5727 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5735 len
= (int)grub_strlen(args
[0]);
5736 if (grub_file_is_vlnk_suffix(args
[0], len
))
5745 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5748 const char *name
= NULL
;
5754 grub_env_unset(args
[1]);
5755 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5758 debug("VLNK SRC: <%s>\n", args
[0]);
5759 debug("VLNK DST: <%s>\n", name
);
5760 grub_env_set(args
[1], name
);
5768 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5772 grub_file_t file
= NULL
;
5783 len
= (int)grub_strlen(args
[0]);
5784 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5786 grub_printf("Invalid vlnk suffix\n");
5790 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5793 grub_printf("Failed to open %s\n", args
[0]);
5797 if (file
->size
!= 32768)
5799 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5803 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5804 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5806 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5811 check_free(file
, grub_file_close
);
5812 grub_errno
= GRUB_ERR_NONE
;
5816 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5822 g_iso_vd_id_publisher
[0] = 0;
5823 g_iso_vd_id_prepare
[0] = 0;
5824 g_iso_vd_id_application
[0] = 0;
5829 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5833 grub_file_t file
= NULL
;
5838 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5841 grub_printf("Failed to open %s\n", args
[0]);
5845 grub_file_seek(file
, 16 * 2048 + offset
);
5846 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5849 grub_file_seek(file
, 16 * 2048 + offset
);
5850 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5853 grub_file_seek(file
, 16 * 2048 + offset
);
5854 grub_file_read(file
, g_iso_vd_id_application
, 128);
5858 check_free(file
, grub_file_close
);
5859 grub_errno
= GRUB_ERR_NONE
;
5863 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5866 char *id
= g_iso_vd_id_publisher
;
5871 if (args
[0][0] == '1')
5873 id
= g_iso_vd_id_prepare
;
5875 else if (args
[0][0] == '2')
5877 id
= g_iso_vd_id_application
;
5880 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5885 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5890 grub_errno
= GRUB_ERR_NONE
;
5894 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5899 g_ventoy_fn_mutex
= 0;
5900 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5902 g_ventoy_fn_mutex
= 1;
5905 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5908 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5910 grub_uint64_t total
;
5911 grub_uint64_t org_required
;
5912 grub_uint64_t new_required
;
5918 #ifdef GRUB_MACHINE_EFI
5919 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
5920 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
5921 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
5922 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
5927 grub_printf("Non EFI mode!\n");
5932 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5935 int ventoy_env_init(void)
5939 grub_env_set("vtdebug_flag", "");
5941 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5942 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5943 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5944 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5946 ventoy_filt_register(0, ventoy_wrapper_open
);
5948 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5951 g_grub_param
->grub_env_get
= grub_env_get
;
5952 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5953 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5954 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5955 grub_env_set("env_param", buf
);
5956 grub_env_set("ventoy_env_param", buf
);
5958 grub_env_export("env_param");
5959 grub_env_export("ventoy_env_param");
5962 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5963 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5965 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5966 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5968 grub_env_export("vtoy_winpeshl_ini_addr");
5969 grub_env_export("vtoy_winpeshl_ini_size");
5971 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5972 grub_env_set("vtoy_chain_file_size", buf
);
5973 grub_env_export("vtoy_chain_file_size");
5975 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5976 grub_env_set("vtoy_chain_file_read", buf
);
5977 grub_env_export("vtoy_chain_file_read");
5984 static cmd_para ventoy_cmds
[] =
5986 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
5987 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
5988 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5989 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5990 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5991 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5992 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5993 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5994 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5995 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5996 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5997 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5998 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5999 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6000 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6001 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6002 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6003 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6004 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6005 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6006 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6007 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6008 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6009 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6010 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6011 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6012 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6014 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6015 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6016 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6017 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6018 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6019 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6020 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6022 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6023 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6024 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6025 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6026 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6027 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6028 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6029 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6030 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6031 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6034 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6035 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6036 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6037 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6038 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6039 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6040 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6041 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6042 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6043 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6044 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6046 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6047 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6048 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6049 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6050 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6051 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6052 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6054 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6055 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6056 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6057 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6058 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6059 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6060 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6061 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6062 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6063 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6065 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6066 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6067 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6068 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6069 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6070 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6071 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6072 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6073 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6075 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6076 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6077 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6078 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6081 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6082 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6083 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6085 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6086 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6087 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6090 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6091 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6092 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6093 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6094 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6095 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6096 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6097 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6098 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6099 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6100 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6101 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6102 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6103 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6105 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6106 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6107 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6108 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6109 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6110 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6111 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6112 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6113 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6114 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6115 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6116 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6118 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6119 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6120 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6121 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6122 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6123 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6124 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6125 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6126 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6127 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6128 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6129 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6130 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6131 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6132 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6133 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6134 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6135 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6136 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6139 int ventoy_register_all_cmd(void)
6142 cmd_para
*cur
= NULL
;
6144 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6146 cur
= ventoy_cmds
+ i
;
6147 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6148 cur
->summary
, cur
->description
, cur
->parser
);
6154 int ventoy_unregister_all_cmd(void)
6158 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6160 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);