1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 static grub_uint8_t g_check_mbr_data
[] = {
55 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 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 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
61 initrd_info
*g_initrd_img_list
= NULL
;
62 initrd_info
*g_initrd_img_tail
= NULL
;
63 int g_initrd_img_count
= 0;
64 int g_valid_initrd_count
= 0;
65 int g_default_menu_mode
= 0;
66 int g_filt_dot_underscore_file
= 0;
67 int g_sort_case_sensitive
= 0;
68 int g_tree_view_menu_style
= 0;
69 static grub_file_t g_old_file
;
70 static int g_ventoy_last_entry_back
;
73 char g_img_swap_tmp_buf
[1024];
74 img_info g_img_swap_tmp
;
75 img_info
*g_ventoy_img_list
= NULL
;
77 int g_ventoy_img_count
= 0;
79 grub_device_t g_enum_dev
= NULL
;
80 grub_fs_t g_enum_fs
= NULL
;
81 int g_img_max_search_level
= -1;
82 img_iterator_node g_img_iterator_head
;
83 img_iterator_node
*g_img_iterator_tail
= NULL
;
85 grub_uint8_t g_ventoy_break_level
= 0;
86 grub_uint8_t g_ventoy_debug_level
= 0;
87 grub_uint8_t g_ventoy_chain_type
= 0;
89 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
90 grub_uint32_t g_ventoy_cpio_size
= 0;
91 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
92 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
94 int g_plugin_image_list
= 0;
96 ventoy_grub_param
*g_grub_param
= NULL
;
98 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
100 ventoy_img_chunk_list g_img_chunk_list
;
102 int g_wimboot_enable
= 0;
103 ventoy_img_chunk_list g_wimiso_chunk_list
;
104 char *g_wimiso_path
= NULL
;
105 grub_uint32_t g_wimiso_size
= 0;
107 int g_vhdboot_enable
= 0;
109 grub_uint64_t g_conf_replace_offset
= 0;
110 grub_uint64_t g_svd_replace_offset
= 0;
111 conf_replace
*g_conf_replace_node
= NULL
;
112 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
113 int g_conf_replace_new_len
= 0;
114 int g_conf_replace_new_len_align
= 0;
116 int g_ventoy_disk_bios_id
= 0;
117 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
118 grub_uint64_t g_ventoy_disk_size
= 0;
119 grub_uint64_t g_ventoy_disk_part_size
[2];
121 char *g_tree_script_buf
= NULL
;
122 int g_tree_script_pos
= 0;
123 int g_tree_script_pre
= 0;
125 static char *g_list_script_buf
= NULL
;
126 static int g_list_script_pos
= 0;
128 static char *g_part_list_buf
= NULL
;
129 static int g_part_list_pos
= 0;
130 static grub_uint64_t g_part_end_max
= 0;
132 static int g_video_mode_max
= 0;
133 static int g_video_mode_num
= 0;
134 static ventoy_video_mode
*g_video_mode_list
= NULL
;
136 static int g_enumerate_time_checked
= 0;
137 static grub_uint64_t g_enumerate_start_time_ms
;
138 static grub_uint64_t g_enumerate_finish_time_ms
;
139 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
141 static char g_iso_vd_id_publisher
[130];
142 static char g_iso_vd_id_prepare
[130];
143 static char g_iso_vd_id_application
[130];
145 static int g_pager_flag
= 0;
146 static char g_old_pager
[32];
148 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
150 const char *g_menu_class
[img_type_max
] =
152 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
155 const char *g_menu_prefix
[img_type_max
] =
157 "iso", "wim", "efi", "img", "vhd", "vtoy"
160 static int g_vtoy_load_prompt
= 0;
161 static char g_vtoy_prompt_msg
[64];
163 static char g_json_case_mis_path
[32];
165 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
167 int ventoy_get_fs_type(const char *fs
)
171 return ventoy_fs_max
;
173 else if (grub_strncmp(fs
, "exfat", 5) == 0)
175 return ventoy_fs_exfat
;
177 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
179 return ventoy_fs_ntfs
;
181 else if (grub_strncmp(fs
, "ext", 3) == 0)
183 return ventoy_fs_ext
;
185 else if (grub_strncmp(fs
, "xfs", 3) == 0)
187 return ventoy_fs_xfs
;
189 else if (grub_strncmp(fs
, "udf", 3) == 0)
191 return ventoy_fs_udf
;
193 else if (grub_strncmp(fs
, "fat", 3) == 0)
195 return ventoy_fs_fat
;
198 return ventoy_fs_max
;
201 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
220 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
222 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
226 static int ventoy_control_get_flag(const char *key
)
228 const char *val
= ventoy_get_env(key
);
230 if (val
&& val
[0] == '1' && val
[1] == 0)
237 static grub_err_t
ventoy_fs_close(grub_file_t file
)
239 grub_file_close(g_old_file
);
240 grub_free(file
->data
);
248 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
254 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
259 for (i
= 0; i
< g_video_mode_num
; i
++)
261 if (g_video_mode_list
[i
].width
== info
->width
&&
262 g_video_mode_list
[i
].height
== info
->height
&&
263 g_video_mode_list
[i
].bpp
== info
->bpp
)
269 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
270 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
271 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
274 if (g_video_mode_num
== g_video_mode_max
)
276 g_video_mode_max
*= 2;
277 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
283 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
285 if (v1
->bpp
== v2
->bpp
)
287 if (v1
->width
== v2
->width
)
289 if (v1
->height
== v2
->height
)
295 return (v1
->height
< v2
->height
) ? -1 : 1;
300 return (v1
->width
< v2
->width
) ? -1 : 1;
305 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
309 static int ventoy_enum_video_mode(void)
312 grub_video_adapter_t adapter
;
313 grub_video_driver_id_t id
;
314 ventoy_video_mode mode
;
316 g_video_mode_num
= 0;
317 g_video_mode_max
= 1024;
318 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
319 if (!g_video_mode_list
)
324 #ifdef GRUB_MACHINE_PCBIOS
325 grub_dl_load ("vbe");
328 id
= grub_video_get_driver_id ();
330 FOR_VIDEO_ADAPTERS (adapter
)
332 if (!adapter
->iterate
||
333 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
334 adapter
->init() != GRUB_ERR_NONE
)))
339 adapter
->iterate(ventoy_video_hook
, NULL
);
341 if (adapter
->id
!= id
)
347 /* sort video mode */
348 for (i
= 0; i
< g_video_mode_num
; i
++)
349 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
351 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
353 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
354 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
355 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
359 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
362 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
366 static struct grub_fs vtoy_fs
=
371 .fs_read
= ventoy_fs_read
,
372 .fs_close
= ventoy_fs_close
,
382 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
388 file
->data
= grub_malloc(rawFile
->size
+ 4096);
394 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
395 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
397 g_old_file
= rawFile
;
399 file
->size
= rawFile
->size
+ len
;
400 file
->device
= rawFile
->device
;
402 file
->not_easily_seekable
= 1;
407 static int ventoy_check_decimal_var(const char *name
, long *value
)
409 const char *value_str
= NULL
;
411 value_str
= grub_env_get(name
);
412 if (NULL
== value_str
)
414 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
417 if (!ventoy_is_decimal(value_str
))
419 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
422 *value
= grub_strtol(value_str
, NULL
, 10);
424 return GRUB_ERR_NONE
;
427 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
429 grub_uint64_t sectors
;
431 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
433 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
437 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
440 return sectors
* 512;
443 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
449 grub_uint32_t offset
;
451 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
454 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
458 len
= (int)file
->size
;
460 data
= (char *)grub_malloc(file
->size
);
466 grub_file_read(file
, data
, file
->size
);
467 grub_file_close(file
);
469 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
470 grub_script_execute_sourcecode(exec
);
472 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
473 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
474 grub_file_close(file
);
476 grub_script_execute_sourcecode("loopback -d efiboot");
480 *direntoff
= offset
+ 2;
485 static int ventoy_set_check_result(int ret
)
489 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
490 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
491 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
495 grub_printf(VTOY_WARNING
"\n");
496 grub_printf(VTOY_WARNING
"\n");
497 grub_printf(VTOY_WARNING
"\n\n\n");
499 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
500 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
502 grub_printf("\n\nWill exit after 10 seconds ...... ");
510 static int ventoy_check_official_device(grub_device_t dev
)
514 grub_uint64_t offset
;
517 grub_uint8_t mbr
[512];
521 struct grub_partition
*partition
;
523 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
525 return ventoy_set_check_result(1 | 0x1000);
528 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
529 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
530 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
532 #ifndef GRUB_MACHINE_EFI
533 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
534 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
535 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
537 return ventoy_set_check_result(2 | 0x1000);
546 /* We must have partition 2 */
549 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
553 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
557 return ventoy_set_check_result(3 | 0x1000);
560 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
562 grub_file_close(file
);
563 return ventoy_set_check_result(4 | 0x1000);
566 partition
= dev
->disk
->partition
;
567 if (partition
->number
!= 0 || partition
->start
!= 2048)
569 return ventoy_set_check_result(5);
574 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
576 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
577 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
578 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
580 grub_file_close(file
);
581 return ventoy_set_check_result(6);
586 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
587 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
588 PartTbl
[1].SectorCount
!= 65536)
590 grub_file_close(file
);
591 return ventoy_set_check_result(6);
597 offset
= partition
->start
+ partition
->len
;
598 partition
= file
->device
->disk
->partition
;
599 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
601 grub_file_close(file
);
602 return ventoy_set_check_result(7);
606 grub_file_close(file
);
610 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
611 dev2
= grub_device_open(devname
);
614 return ventoy_set_check_result(8);
617 fs
= grub_fs_probe(dev2
);
620 grub_device_close(dev2
);
621 return ventoy_set_check_result(9);
624 fs
->fs_label(dev2
, &label
);
625 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
627 grub_device_close(dev2
);
628 return ventoy_set_check_result(10);
631 grub_device_close(dev2
);
635 disk
= grub_disk_open(dev
->disk
->name
);
638 return ventoy_set_check_result(11);
641 grub_memset(mbr
, 0, 512);
642 grub_disk_read(disk
, 0, 0, 512, mbr
);
643 grub_disk_close(disk
);
645 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
647 return ventoy_set_check_result(12);
650 return ventoy_set_check_result(0);
653 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
657 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
667 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
669 grub_uint64_t size
= 0;
672 char fullpath
[256] = {0};
675 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
678 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
681 debug("grub_file_open failed <%s>\n", fullpath
);
687 grub_file_close(file
);
691 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
695 char fullpath
[512] = {0};
698 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
701 file
= grub_file_open(fullpath
, type
);
704 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
711 int ventoy_is_dir_exist(const char *fmt
, ...)
718 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
722 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
725 grub_strncpy(pos
+ len
, "\" ]", 3);
727 debug("script exec %s\n", buf
);
729 if (0 == grub_script_execute_sourcecode(buf
))
737 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
740 grub_uint8_t
*outbuf
;
741 grub_uint8_t gzHdr
[10] =
743 0x1F, 0x8B, /* magic */
751 grub_memset(&s
, 0, sizeof(mz_stream
));
753 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
755 outbuf
= (grub_uint8_t
*)mem_out
;
757 mem_out_len
-= sizeof(gzHdr
) + 8;
758 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
759 outbuf
+= sizeof(gzHdr
);
761 s
.avail_in
= mem_in_len
;
764 s
.avail_out
= mem_out_len
;
767 mz_deflate(&s
, MZ_FINISH
);
771 outbuf
+= s
.total_out
;
772 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
773 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
775 return s
.total_out
+ sizeof(gzHdr
) + 8;
783 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
787 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
790 if (0 == grub_strcmp(args
[0], "on"))
793 grub_env_set("vtdebug_flag", "debug");
798 grub_env_set("vtdebug_flag", "");
801 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
804 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
808 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
810 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
811 grub_printf(" level:\r\n");
812 grub_printf(" 01/11: busybox / (+cat log)\r\n");
813 grub_printf(" 02/12: initrd / (+cat log)\r\n");
814 grub_printf(" 03/13: hook / (+cat log)\r\n");
816 grub_printf(" debug:\r\n");
817 grub_printf(" 0: debug is off\r\n");
818 grub_printf(" 1: debug is on\r\n");
820 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
823 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
825 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
827 g_ventoy_debug_level
= 1;
830 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
833 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
842 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
845 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
877 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
893 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
909 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
914 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
916 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
919 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
924 value_long
+= grub_strtol(args
[1], NULL
, 10);
926 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
927 grub_env_set(args
[0], buf
);
929 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
932 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
934 ulonglong value1
= 0;
935 ulonglong value2
= 0;
940 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
943 value1
= grub_strtoull(args
[0], NULL
, 10);
944 value2
= grub_strtoull(args
[1], NULL
, 10);
946 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
947 grub_env_set(args
[2], buf
);
949 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
952 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
967 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
970 debug("failed to open file <%s> for udf check\n", args
[0]);
974 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
976 grub_env_set(args
[1], buf
);
978 grub_file_close(file
);
984 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
992 g_wimboot_enable
= 0;
994 grub_check_free(g_wimiso_path
);
995 grub_check_free(g_wimiso_chunk_list
.chunk
);
997 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1003 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1004 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1005 if (NULL
== g_wimiso_chunk_list
.chunk
)
1007 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1010 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1011 g_wimiso_chunk_list
.cur_chunk
= 0;
1013 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1015 g_wimboot_enable
= 1;
1016 g_wimiso_path
= grub_strdup(args
[0]);
1017 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1018 grub_file_close(file
);
1023 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1033 ventoy_iso9660_override
*dirent
;
1042 totlen
= sizeof(ventoy_chain_head
);
1044 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1046 debug("failed to load efiboot template %d\n", len
);
1052 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1054 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1057 debug("failed to open file <%s>\n", args
[0]);
1061 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1066 totlen
+= ventoy_align_2k(file
->size
);
1068 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1069 dirent
->first_sector
= len
/ 2048;
1070 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1071 dirent
->size
= (grub_uint32_t
)file
->size
;
1072 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1074 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1076 #ifdef GRUB_MACHINE_EFI
1077 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1079 data
= (char *)grub_malloc(totlen
);
1082 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1084 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1085 grub_check_free(buf
);
1087 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1088 grub_file_close(file
);
1090 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1091 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1092 grub_env_set(name
, value
);
1094 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1095 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1096 grub_env_set(name
, value
);
1101 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1107 g_vtoy_load_prompt
= 0;
1108 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1110 if (argc
== 2 && args
[0][0] == '1')
1112 g_vtoy_load_prompt
= 1;
1113 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1116 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1119 int ventoy_need_prompt_load_file(void)
1121 return g_vtoy_load_prompt
;
1124 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1126 grub_uint64_t ro
= 0;
1127 grub_uint64_t div
= 0;
1128 grub_ssize_t left
= size
;
1129 char *cur
= (char *)buf
;
1131 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1134 while (left
>= VTOY_SIZE_2MB
)
1136 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1137 cur
+= VTOY_SIZE_2MB
;
1138 left
-= VTOY_SIZE_2MB
;
1140 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1141 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1147 grub_file_read(file
, cur
, left
);
1150 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1156 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1163 enum grub_file_type type
;
1174 if (grub_strcmp(args
[0], "nodecompress") == 0)
1176 type
= VENTOY_FILE_TYPE
;
1180 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1183 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1186 debug("failed to open file <%s>\n", args
[1]);
1190 #ifdef GRUB_MACHINE_EFI
1191 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1193 buf
= (char *)grub_malloc(file
->size
);
1198 grub_file_close(file
);
1202 if (g_vtoy_load_prompt
)
1204 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1208 grub_file_read(file
, buf
, file
->size
);
1211 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1212 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1213 grub_env_set(name
, value
);
1215 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1216 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1217 grub_env_set(name
, value
);
1219 grub_file_close(file
);
1225 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1243 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1246 debug("failed to open file <%s> for udf check\n", args
[0]);
1250 headlen
= sizeof(ventoy_chain_head
);
1252 #ifdef GRUB_MACHINE_EFI
1253 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1255 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1258 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1260 grub_file_read(file
, buf
+ headlen
, file
->size
);
1262 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1263 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1264 grub_env_set(name
, value
);
1266 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1267 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1268 grub_env_set(name
, value
);
1270 grub_file_close(file
);
1276 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1282 if (grub_iso9660_is_joliet())
1284 debug("This time has joliet process\n");
1293 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1302 if (args
[0][0] == '1')
1304 grub_iso9660_set_nojoliet(1);
1308 grub_iso9660_set_nojoliet(0);
1314 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1319 grub_uint8_t buf
[32];
1330 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1333 debug("failed to open file <%s> for udf check\n", args
[0]);
1337 for (i
= 16; i
< 32; i
++)
1339 grub_file_seek(file
, i
* 2048);
1340 grub_file_read(file
, buf
, sizeof(buf
));
1348 grub_file_seek(file
, i
* 2048);
1349 grub_file_read(file
, buf
, sizeof(buf
));
1351 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1354 grub_file_seek(file
, i
* 2048);
1355 grub_file_read(file
, buf
, sizeof(buf
));
1357 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1358 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1364 grub_file_close(file
);
1366 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1371 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1373 long value_long1
= 0;
1374 long value_long2
= 0;
1376 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1378 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1381 value_long1
= grub_strtol(args
[0], NULL
, 10);
1382 value_long2
= grub_strtol(args
[2], NULL
, 10);
1384 if (0 == grub_strcmp(args
[1], "eq"))
1386 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1388 else if (0 == grub_strcmp(args
[1], "ne"))
1390 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1392 else if (0 == grub_strcmp(args
[1], "gt"))
1394 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1396 else if (0 == grub_strcmp(args
[1], "lt"))
1398 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1400 else if (0 == grub_strcmp(args
[1], "ge"))
1402 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1404 else if (0 == grub_strcmp(args
[1], "le"))
1406 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1410 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1416 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1419 char buf
[128] = {0};
1423 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1426 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1427 pos
= grub_strstr(buf
, ",");
1433 grub_env_set(args
[1], buf
);
1435 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1438 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1444 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1450 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1453 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1455 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1456 if (0 == grub_script_execute_sourcecode(buf
))
1458 debug("file %s exist, ventoy_compatible YES\n", buf
);
1459 grub_env_set("ventoy_compatible", "YES");
1460 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1464 debug("file %s NOT exist\n", buf
);
1468 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1469 pos
= grub_strstr(buf
, ")");
1475 disk
= grub_disk_open(buf
);
1478 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1479 grub_disk_close(disk
);
1481 g_img_swap_tmp_buf
[703] = 0;
1482 for (i
= 318; i
< 703; i
++)
1484 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1485 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1487 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1488 grub_env_set("ventoy_compatible", "YES");
1489 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1495 debug("failed to open disk <%s>\n", buf
);
1498 grub_env_set("ventoy_compatible", "NO");
1499 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1502 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1508 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1510 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1513 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1518 if (0 == g_sort_case_sensitive
)
1520 if (grub_islower(c1
))
1522 c1
= c1
- 'a' + 'A';
1525 if (grub_islower(c2
))
1527 c2
= c2
- 'a' + 'A';
1540 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1546 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1548 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1551 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1556 if (0 == g_sort_case_sensitive
)
1558 if (grub_islower(c1
))
1560 c1
= c1
- 'a' + 'A';
1563 if (grub_islower(c2
))
1565 c2
= c2
- 'a' + 'A';
1578 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1580 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1582 grub_memcpy(img1
, img2
, sizeof(img_info
));
1583 img1
->next
= g_img_swap_tmp
.next
;
1584 img1
->prev
= g_img_swap_tmp
.prev
;
1586 g_img_swap_tmp
.next
= img2
->next
;
1587 g_img_swap_tmp
.prev
= img2
->prev
;
1588 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1591 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1595 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1603 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1605 ventoy_vlnk_part
*node
= NULL
;
1606 grub_uint32_t SelfSig
;
1607 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1609 /* skip Ventoy partition 1/2 */
1610 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1611 if (partition
->number
< 2 && SelfSig
== *pSig
)
1616 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1619 node
->disksig
= *pSig
;
1620 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1621 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1622 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1624 node
->next
= g_vlnk_part_list
;
1625 g_vlnk_part_list
= node
;
1631 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1638 disk
= grub_disk_open(name
);
1641 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1642 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1643 grub_disk_close(disk
);
1649 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1651 const char *fs
[ventoy_fs_max
+ 1] =
1653 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1658 cur
->dev
= grub_device_open(cur
->device
);
1663 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1669 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1674 char *disk
, *device
;
1675 grub_uint32_t readcrc
, calccrc
;
1676 ventoy_vlnk_part
*cur
;
1677 grub_fs_t fs
= NULL
;
1679 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1683 grub_printf("VLNK invalid guid\n");
1689 readcrc
= vlnk
->crc32
;
1691 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1692 if (readcrc
!= calccrc
)
1696 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1702 if (!g_vlnk_part_list
)
1704 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1707 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1709 if (cur
->disksig
== vlnk
->disk_signature
)
1713 if (cur
->partoffset
== vlnk
->part_offset
)
1716 device
= cur
->device
;
1718 if (cur
->probe
== 0)
1721 ventoy_vlnk_probe_fs(cur
);
1731 struct grub_file file
;
1733 grub_memset(&file
, 0, sizeof(file
));
1734 file
.device
= cur
->dev
;
1735 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1738 cur
->fs
->fs_close(&file
);
1739 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1748 grub_printf("\n==== VLNK Information ====\n"
1749 "Disk Signature: %08x\n"
1750 "Partition Offset: %llu\n"
1751 "File Path: <%s>\n\n",
1752 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1756 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1760 grub_printf("Disk Find: [ NO ]\n");
1765 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1769 grub_printf("Part Find: [ NO ]\n");
1771 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1774 grub_printf("VLNK File: <%s>\n", dst
);
1781 return (1 - filefind
);
1784 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1789 grub_file_t file
= NULL
;
1794 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1796 else if (dir
[0] == '/')
1798 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1802 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1805 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1811 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1812 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1813 grub_file_close(file
);
1815 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1817 rc
= grub_file_add_vlnk(src
, dst
);
1823 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1833 const menu_tip
*tip
;
1834 img_iterator_node
*tmp
;
1835 img_iterator_node
*new_node
;
1836 img_iterator_node
*node
= (img_iterator_node
*)data
;
1838 if (g_enumerate_time_checked
== 0)
1840 g_enumerate_finish_time_ms
= grub_get_time_ms();
1841 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1844 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1846 g_enumerate_time_checked
= 1;
1850 len
= grub_strlen(filename
);
1854 if (node
->level
+ 1 > g_img_max_search_level
)
1859 if ((len
== 1 && filename
[0] == '.') ||
1860 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1865 if (!ventoy_img_name_valid(filename
, len
))
1870 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1875 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1877 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1878 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1881 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1886 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1889 new_node
->level
= node
->level
+ 1;
1890 new_node
->plugin_list_index
= index
;
1891 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1893 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1896 debug("Directory %s ignored...\n", new_node
->dir
);
1897 grub_free(new_node
);
1901 new_node
->tail
= node
->tail
;
1903 new_node
->parent
= node
;
1904 if (!node
->firstchild
)
1906 node
->firstchild
= new_node
;
1909 if (g_img_iterator_tail
)
1911 g_img_iterator_tail
->next
= new_node
;
1912 g_img_iterator_tail
= new_node
;
1916 g_img_iterator_head
.next
= new_node
;
1917 g_img_iterator_tail
= new_node
;
1923 debug("Find a file %s\n", filename
);
1929 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1931 type
= img_type_iso
;
1933 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1935 type
= img_type_wim
;
1937 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1938 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1940 type
= img_type_vhd
;
1942 #ifdef GRUB_MACHINE_EFI
1943 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1945 type
= img_type_efi
;
1948 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1950 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1952 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1953 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1958 type
= img_type_img
;
1960 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1962 type
= img_type_vtoy
;
1964 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1966 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1968 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1969 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1978 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1983 if (g_plugin_image_list
)
1985 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1986 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1987 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1989 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1992 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1994 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1999 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2001 if (grub_file_is_vlnk_suffix(filename
, len
))
2004 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2011 img
= grub_zalloc(sizeof(img_info
));
2015 img
->plugin_list_index
= index
;
2016 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2018 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2020 img
->size
= info
->size
;
2021 if (vlnk
|| 0 == img
->size
)
2023 if (node
->dir
[0] == '/')
2025 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2029 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2033 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2035 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2040 if (g_ventoy_img_list
)
2042 tail
= *(node
->tail
);
2048 g_ventoy_img_list
= img
;
2051 img
->id
= g_ventoy_img_count
;
2053 if (node
&& NULL
== node
->firstiso
)
2055 node
->firstiso
= img
;
2066 *((img_info
**)(node
->tail
)) = img
;
2067 g_ventoy_img_count
++;
2069 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2071 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2074 img
->tip1
= tip
->tip1
;
2075 img
->tip2
= tip
->tip2
;
2078 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2081 img
->class = g_menu_class
[type
];
2083 img
->menu_prefix
= g_menu_prefix
[type
];
2085 if (img_type_iso
== type
)
2087 if (ventoy_plugin_check_memdisk(img
->path
))
2089 img
->menu_prefix
= "miso";
2093 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2100 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2102 int len
= GRUB_UINT_MAX
;
2103 const char *value
= NULL
;
2104 char name
[32] = {0};
2105 char plat
[32] = {0};
2106 char guidstr
[32] = {0};
2107 ventoy_guid guid
= VENTOY_GUID
;
2108 const char *fmt1
= NULL
;
2109 const char *fmt2
= NULL
;
2110 const char *fmt3
= NULL
;
2111 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2112 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2113 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2114 const char fmtcode
[]={
2115 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2116 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2117 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2118 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2119 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2120 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2123 grub_memset(name
, 0, sizeof(name
));
2124 puint
[0] = grub_swap_bytes32(0x56454e54);
2125 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2126 puint
[2] = grub_swap_bytes32(0x45525349);
2127 puint
[1] = grub_swap_bytes32(0x4f595f56);
2128 value
= ventoy_get_env(name
);
2130 grub_memset(name
, 0, sizeof(name
));
2131 puint
[1] = grub_swap_bytes32(0x5f544f50);
2132 puint
[0] = grub_swap_bytes32(0x56544c45);
2133 fmt1
= ventoy_get_env(name
);
2139 grub_memset(name
, 0, sizeof(name
));
2140 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2141 puint
[0] = grub_swap_bytes32(0x56544c45);
2142 fmt2
= ventoy_get_env(name
);
2144 grub_memset(name
, 0, sizeof(name
));
2145 puint
[1] = grub_swap_bytes32(0x5f434c52);
2146 puint
[0] = grub_swap_bytes32(0x56544c45);
2147 fmt3
= ventoy_get_env(name
);
2149 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2151 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2153 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2154 #pragma GCC diagnostic push
2155 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2156 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2157 fmt1
? fmt1
: fmtdata
,
2158 fmt2
? fmt2
: fmtdata
+ 4,
2159 value
? value
: "", plat
, guidstr
,
2160 fmt3
? fmt3
: fmtdata
+ 6);
2161 #pragma GCC diagnostic pop
2163 grub_memset(name
, 0, sizeof(name
));
2164 puint
[0] = grub_swap_bytes32(0x76746f79);
2165 puint
[2] = grub_swap_bytes32(0x656e7365);
2166 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2167 ventoy_set_env(name
, guidstr
);
2172 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2176 grub_uint8_t md5
[16];
2180 grub_memset(input
, 0, sizeof(input
));
2182 grub_printf("Enter password: ");
2185 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2187 grub_password_get(input
, 128);
2188 if (grub_strcmp(pwd
->text
, input
) == 0)
2193 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2195 grub_password_get(input
, 128);
2196 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2197 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2202 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2204 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2205 grub_password_get(input
+ offset
, 128);
2207 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2208 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2214 grub_printf("Invalid password!\n\n");
2221 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2223 img_info
*minimg
= NULL
;
2224 img_info
*img
= (img_info
*)(node
->firstiso
);
2226 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2228 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2243 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2245 img_iterator_node
*Minchild
= NULL
;
2246 img_iterator_node
*child
= node
->firstchild
;
2248 while (child
&& child
->parent
== node
)
2250 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2254 child
= child
->next
;
2259 Minchild
->select
= 1;
2265 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2268 img_info
*img
= NULL
;
2269 const char *dir_class
= NULL
;
2270 const char *dir_alias
= NULL
;
2271 img_iterator_node
*child
= NULL
;
2272 const menu_tip
*tip
= NULL
;
2274 if (node
->isocnt
== 0 || node
->done
== 1)
2279 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2281 offset
= node
->parent
->dirlen
;
2284 if (node
== &g_img_iterator_head
)
2286 if (g_default_menu_mode
== 0)
2288 if (g_tree_view_menu_style
== 0)
2290 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2291 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2292 " echo 'return ...' \n"
2297 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2298 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2299 " echo 'return ...' \n"
2304 g_tree_script_pre
= g_tree_script_pos
;
2308 node
->dir
[node
->dirlen
- 1] = 0;
2309 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2312 dir_class
= "vtoydir";
2315 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2317 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2320 if (g_tree_view_menu_style
== 0)
2322 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2323 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2324 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2328 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2329 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2330 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2335 dir_alias
= node
->dir
+ offset
;
2337 if (g_tree_view_menu_style
== 0)
2339 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2340 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2341 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2345 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2346 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2347 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2351 if (g_tree_view_menu_style
== 0)
2353 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2354 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2355 " echo 'return ...' \n"
2356 "}\n", "<--", node
->dir
);
2360 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2361 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2362 " echo 'return ...' \n"
2367 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2369 ventoy_dynamic_tree_menu(child
);
2372 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2374 if (g_tree_view_menu_style
== 0)
2376 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2377 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2380 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2381 img
->unsupport
? "[***********] " : "",
2382 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2384 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2388 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2389 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2392 img
->unsupport
? "[***********] " : "",
2393 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2395 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2399 if (node
!= &g_img_iterator_head
)
2401 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2408 static int ventoy_set_default_menu(void)
2414 const char *strdata
= NULL
;
2415 img_info
*cur
= NULL
;
2416 img_info
*default_node
= NULL
;
2417 const char *default_image
= NULL
;
2419 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2420 if (default_image
&& default_image
[0] == '/')
2422 img_len
= grub_strlen(default_image
);
2424 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2426 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2438 if (0 == g_default_menu_mode
)
2440 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2444 def
= grub_strdup(default_image
);
2450 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2452 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2453 if (strdata
&& strdata
[0] == '/')
2455 pos
= def
+ grub_strlen(strdata
);
2466 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2469 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2473 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2481 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2483 img_info
*next
= NULL
;
2484 img_info
*cur
= g_ventoy_img_list
;
2497 g_ventoy_img_list
= NULL
;
2498 g_ventoy_img_count
= 0;
2500 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2503 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2506 img_info
*cur
= g_ventoy_img_list
;
2510 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2512 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2515 img_id
= grub_strtol(args
[0], NULL
, 10);
2516 if (img_id
>= g_ventoy_img_count
)
2518 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2521 debug("Find image %ld name \n", img_id
);
2523 while (cur
&& img_id
> 0)
2531 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2534 debug("image name is %s\n", cur
->name
);
2536 grub_env_set(args
[1], cur
->name
);
2538 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2541 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2545 img_info
*cur
= g_ventoy_img_list
;
2551 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2554 len
= (int)grub_strlen(args
[0]);
2558 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2567 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2570 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2571 grub_env_set("chosen", id
);
2572 grub_env_export("chosen");
2574 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2577 static char g_fake_vlnk_src
[512];
2578 static char g_fake_vlnk_dst
[512];
2579 static grub_uint64_t g_fake_vlnk_size
;
2580 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2586 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2588 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2589 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2591 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2593 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2596 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2602 g_fake_vlnk_src
[0] = 0;
2603 g_fake_vlnk_dst
[0] = 0;
2604 g_fake_vlnk_size
= 0;
2605 grub_file_vtoy_vlnk(NULL
, NULL
);
2607 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2611 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2616 const char *id
= NULL
;
2617 img_info
*cur
= NULL
;
2621 if (argc
< 1 || argc
> 3)
2623 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2626 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2628 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2629 grub_env_set(args
[0], pos
);
2632 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2633 grub_env_set(args
[1], value
);
2638 for (last
= pos
; *pos
; pos
++)
2645 grub_env_set(args
[2], last
+ 1);
2651 id
= grub_env_get("chosen");
2653 pos
= grub_strstr(id
, "VID_");
2656 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2660 cur
= g_ventoy_img_list
;
2665 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2668 grub_env_set(args
[0], cur
->path
);
2672 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2673 grub_env_set(args
[1], value
);
2678 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2679 grub_env_set(args
[2], cur
->name
);
2683 g_svd_replace_offset
= 0;
2685 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2689 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2693 grub_device_t dev
= NULL
;
2694 img_info
*cur
= NULL
;
2695 img_info
*tail
= NULL
;
2696 img_info
*min
= NULL
;
2697 img_info
*head
= NULL
;
2698 const char *strdata
= NULL
;
2699 char *device_name
= NULL
;
2701 img_iterator_node
*node
= NULL
;
2702 img_iterator_node
*tmp
= NULL
;
2708 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2711 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2713 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2718 g_enumerate_time_checked
= 0;
2719 g_enumerate_start_time_ms
= grub_get_time_ms();
2721 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2722 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2724 g_filt_dot_underscore_file
= 1;
2727 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2728 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2730 g_sort_case_sensitive
= 1;
2733 device_name
= grub_file_get_device_name(args
[0]);
2739 g_enum_dev
= dev
= grub_device_open(device_name
);
2745 g_enum_fs
= fs
= grub_fs_probe(dev
);
2751 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2753 debug("unsupported fs:<%s>\n", fs
->name
);
2754 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2758 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2760 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2761 if (strdata
&& strdata
[0] == '1')
2763 g_default_menu_mode
= 1;
2766 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2768 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2770 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2771 if (strdata
&& strdata
[0] == '/')
2773 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2774 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2776 g_img_iterator_head
.dir
[len
++] = '/';
2778 g_img_iterator_head
.dirlen
= len
;
2782 g_img_iterator_head
.dirlen
= 1;
2783 grub_strcpy(g_img_iterator_head
.dir
, "/");
2786 g_img_iterator_head
.tail
= &tail
;
2788 if (g_img_max_search_level
< 0)
2790 g_img_max_search_level
= GRUB_INT_MAX
;
2791 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2792 if (strdata
&& ventoy_is_decimal(strdata
))
2794 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2798 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2799 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2800 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2801 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2802 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2803 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2805 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2807 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2810 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2811 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2813 g_tree_view_menu_style
= 1;
2816 ventoy_set_default_menu();
2818 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2820 ventoy_dynamic_tree_menu(node
);
2824 node
= g_img_iterator_head
.next
;
2832 /* sort image list by image name */
2833 while (g_ventoy_img_list
)
2835 min
= g_ventoy_img_list
;
2836 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2838 if (ventoy_cmp_img(min
, cur
) > 0)
2846 min
->prev
->next
= min
->next
;
2851 min
->next
->prev
= min
->prev
;
2854 if (min
== g_ventoy_img_list
)
2856 g_ventoy_img_list
= min
->next
;
2874 g_ventoy_img_list
= head
;
2876 if (g_default_menu_mode
== 1)
2878 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2879 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2880 " echo 'return ...' \n"
2884 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2886 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2887 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2890 cur
->unsupport
? "[***********] " : "",
2891 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2893 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2896 g_tree_script_buf
[g_tree_script_pos
] = 0;
2897 g_list_script_buf
[g_list_script_pos
] = 0;
2899 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2900 grub_env_set(args
[1], buf
);
2904 check_free(device_name
, grub_free
);
2905 check_free(dev
, grub_device_close
);
2907 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2910 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2917 device_name
= grub_file_get_device_name(filename
);
2929 pos2
= grub_strstr(pos
, ",");
2932 pos2
= grub_strstr(pos
, ")");
2940 disk
= grub_disk_open(pos
);
2943 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2944 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2945 grub_disk_close(disk
);
2952 grub_free(device_name
);
2956 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2958 eltorito_descriptor desc
;
2960 grub_memset(&desc
, 0, sizeof(desc
));
2961 grub_file_seek(file
, 17 * 2048);
2962 grub_file_read(file
, &desc
, sizeof(desc
));
2964 if (desc
.type
!= 0 || desc
.version
!= 1)
2969 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2970 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2978 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2980 grub_uint8_t buf
[512];
2982 grub_file_seek(file
, sector
* 2048);
2983 grub_file_read(file
, buf
, sizeof(buf
));
2985 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2986 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2988 return *((grub_uint32_t
*)(buf
+ 40));
2994 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2998 grub_uint8_t buf
[512];
2999 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3001 grub_file_seek(file
, sector
* 2048);
3002 grub_file_read(file
, buf
, sizeof(buf
));
3004 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3006 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3010 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3015 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3017 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3019 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3023 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3025 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3030 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3032 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3034 if (buf
[36] == parttype
[i
])
3036 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3042 debug("%s does not contain efi eltorito\n", file
->name
);
3046 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3049 const char *fs
= NULL
;
3050 const char *val
= NULL
;
3051 const char *cdprompt
= NULL
;
3053 grub_uint8_t chksum
= 0;
3056 disk
= file
->device
->disk
;
3057 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3059 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3060 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3061 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3063 pos
= grub_strstr(file
->name
, "/");
3069 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3071 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3073 param
->vtoy_img_size
= file
->size
;
3075 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3076 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3078 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3080 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3081 param
->vtoy_reserved
[4] = 0;
3082 if (g_ventoy_chain_type
== 1) /* Windows */
3084 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3085 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3087 param
->vtoy_reserved
[4] = 1;
3091 fs
= ventoy_get_env("ventoy_fs_probe");
3092 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3094 param
->vtoy_reserved
[3] = 1;
3097 param
->vtoy_reserved
[5] = 0;
3098 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3099 if (val
&& val
[0] == '1' && val
[1] == 0)
3101 param
->vtoy_reserved
[5] = 1;
3104 /* ventoy_disk_signature used for vlnk */
3105 param
->vtoy_reserved
[6] = file
->vlnk
;
3106 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3108 /* calculate checksum */
3109 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3111 chksum
+= *((grub_uint8_t
*)param
+ i
);
3113 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3118 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3120 grub_uint32_t i
= 0;
3121 grub_uint64_t total
= 0;
3122 grub_uint64_t fileblk
= 0;
3123 ventoy_img_chunk
*chunk
= NULL
;
3125 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3127 chunk
= chunklist
->chunk
+ i
;
3129 if (chunk
->disk_start_sector
<= start
)
3131 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3135 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3138 fileblk
= (file
->size
+ 511) / 512;
3140 if (total
!= fileblk
)
3142 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3143 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3145 debug("maybe img file to be processed.\n");
3155 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3159 grub_uint32_t i
= 0;
3160 grub_uint32_t sector
= 0;
3161 grub_uint32_t count
= 0;
3162 grub_off_t size
= 0;
3163 grub_off_t read
= 0;
3165 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3166 if (fs_type
== ventoy_fs_exfat
)
3168 grub_fat_get_file_chunk(start
, file
, chunklist
);
3170 else if (fs_type
== ventoy_fs_ext
)
3172 grub_ext_get_file_chunk(start
, file
, chunklist
);
3176 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3177 file
->read_hook_data
= chunklist
;
3179 for (size
= file
->size
; size
> 0; size
-= read
)
3181 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3182 grub_file_read(file
, NULL
, read
);
3185 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3187 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3188 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3191 if (ventoy_fs_udf
== fs_type
)
3193 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3195 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3196 chunklist
->chunk
[i
].img_start_sector
= sector
;
3197 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3203 len
= (int)grub_strlen(file
->name
);
3204 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3205 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3206 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3207 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3209 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3211 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3221 chunklist
->chunk
[i
].img_start_sector
= sector
;
3222 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3230 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3234 grub_disk_addr_t start
;
3239 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3242 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3245 g_conf_replace_node
= NULL
;
3246 g_conf_replace_offset
= 0;
3248 if (g_img_chunk_list
.chunk
)
3250 grub_free(g_img_chunk_list
.chunk
);
3253 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3255 grub_file_close(file
);
3256 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3259 /* get image chunk data */
3260 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3261 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3262 if (NULL
== g_img_chunk_list
.chunk
)
3264 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3267 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3268 g_img_chunk_list
.cur_chunk
= 0;
3270 start
= file
->device
->disk
->partition
->start
;
3272 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3274 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3275 grub_file_close(file
);
3279 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3282 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3283 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3284 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3287 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3289 grub_uint64_t offset
= 0;
3290 grub_uint32_t align
= 0;
3291 grub_file_t file
= NULL
;
3292 conf_replace
*node
= NULL
;
3298 debug("select conf replace argc:%d\n", argc
);
3305 node
= ventoy_plugin_find_conf_replace(args
[1]);
3308 debug("Conf replace not found for %s\n", args
[1]);
3312 debug("Find conf replace for %s\n", args
[1]);
3314 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3317 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3318 grub_file_close(file
);
3320 else if (node
->img
> 0)
3326 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3330 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3333 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3337 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3339 if (align
> vtoy_max_replace_file_size
)
3341 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3345 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3346 g_conf_replace_new_len
= (int)file
->size
;
3347 g_conf_replace_new_len_align
= align
;
3349 g_conf_replace_node
= node
;
3350 g_conf_replace_offset
= offset
+ 2;
3354 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3355 g_grub_param
->img_replace
.old_name_cnt
= 1;
3356 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3359 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3364 grub_file_close(file
);
3366 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3369 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3375 char configfile
[128];
3376 install_template
*node
= NULL
;
3382 debug("select auto installation argc:%d\n", argc
);
3389 node
= ventoy_plugin_find_install_template(args
[0]);
3392 debug("Auto install template not found for %s\n", args
[0]);
3396 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3398 defidx
= node
->autosel
;
3399 if (node
->timeout
< 0)
3401 node
->cursel
= node
->autosel
- 1;
3402 debug("Auto install template auto select %d\n", node
->autosel
);
3407 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3413 if (node
->timeout
> 0)
3415 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3418 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3419 " echo %s\n}\n", "");
3421 for (i
= 0; i
< node
->templatenum
; i
++)
3423 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3425 node
->templatepath
[i
].path
);
3428 g_ventoy_menu_esc
= 1;
3429 g_ventoy_suppress_esc
= 1;
3430 g_ventoy_suppress_esc_default
= defidx
;
3432 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3433 grub_script_execute_sourcecode(configfile
);
3435 g_ventoy_menu_esc
= 0;
3436 g_ventoy_suppress_esc
= 0;
3437 g_ventoy_suppress_esc_default
= 1;
3441 node
->cursel
= g_ventoy_last_entry
- 1;
3443 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3446 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3452 char configfile
[128];
3453 persistence_config
*node
;
3459 debug("select persistence argc:%d\n", argc
);
3466 node
= ventoy_plugin_find_persistent(args
[0]);
3469 debug("Persistence image not found for %s\n", args
[0]);
3473 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3475 defidx
= node
->autosel
;
3476 if (node
->timeout
< 0)
3478 node
->cursel
= node
->autosel
- 1;
3479 debug("Persistence image auto select %d\n", node
->autosel
);
3484 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3490 if (node
->timeout
> 0)
3492 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3495 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3496 " echo %s\n}\n", "");
3498 for (i
= 0; i
< node
->backendnum
; i
++)
3500 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3502 node
->backendpath
[i
].path
);
3506 g_ventoy_menu_esc
= 1;
3507 g_ventoy_suppress_esc
= 1;
3508 g_ventoy_suppress_esc_default
= defidx
;
3510 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3511 grub_script_execute_sourcecode(configfile
);
3513 g_ventoy_menu_esc
= 0;
3514 g_ventoy_suppress_esc
= 0;
3515 g_ventoy_suppress_esc_default
= 1;
3519 node
->cursel
= g_ventoy_last_entry
- 1;
3521 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3524 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3527 ventoy_img_chunk
*cur
;
3533 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3535 cur
= g_img_chunk_list
.chunk
+ i
;
3536 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3537 cur
->img_start_sector
, cur
->img_end_sector
,
3538 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3542 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3545 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3549 ventoy_img_chunk_list chunklist
;
3554 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3557 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3560 /* get image chunk data */
3561 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3562 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3563 if (NULL
== chunklist
.chunk
)
3565 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3568 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3569 chunklist
.cur_chunk
= 0;
3571 ventoy_get_block_list(file
, &chunklist
, 0);
3573 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3575 grub_printf("########## UNSUPPORTED ###############\n");
3578 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3580 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3582 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3583 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3586 grub_printf("\n==================================\n");
3588 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3590 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3591 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3592 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3593 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3594 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3598 grub_free(chunklist
.chunk
);
3599 grub_file_close(file
);
3601 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3604 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3607 ventoy_grub_param_file_replace
*replace
= NULL
;
3615 replace
= &(g_grub_param
->file_replace
);
3616 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3618 replace
->old_name_cnt
= 0;
3619 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3621 replace
->old_name_cnt
++;
3622 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3625 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3628 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3631 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3634 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3640 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3641 grub_env_set(args
[0], buf
);
3644 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3647 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3655 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3656 grub_printf("%s", g_list_script_buf
);
3660 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3661 grub_printf("%s", g_tree_script_buf
);
3667 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3669 img_info
*cur
= g_ventoy_img_list
;
3677 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3678 grub_printf("name:<%s>\n\n", cur
->name
);
3685 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3691 ventoy_plugin_dump_injection();
3696 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3702 ventoy_plugin_dump_auto_install();
3707 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3713 ventoy_plugin_dump_persistence();
3718 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
3724 len1
= (int)grub_strlen(filename
);
3725 len2
= (int)grub_strlen(suffix
);
3732 for (i
= len1
- 1; i
>= 0; i
--)
3734 if (filename
[i
] == '.')
3745 if (filename
[i
- len2
- 1] != '_')
3750 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
3758 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3764 if (argc
!= 1 && argc
!= 2)
3769 if (args
[0][0] == '0')
3771 if (g_ventoy_memdisk_mode
)
3776 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
3783 else if (args
[0][0] == '1')
3785 return g_ventoy_iso_raw
? 0 : 1;
3787 else if (args
[0][0] == '2')
3789 return g_ventoy_iso_uefi_drv
? 0 : 1;
3791 else if (args
[0][0] == '3')
3793 if (g_ventoy_grub2_mode
)
3798 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
3805 else if (args
[0][0] == '4')
3807 if (g_ventoy_wimboot_mode
)
3812 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
3823 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3825 static int configfile_mode
= 0;
3826 char memfile
[128] = {0};
3833 * args[0]: 0:normal 1:configfile
3834 * args[1]: 0:list_buf 1:tree_buf
3839 debug("Invalid argc %d\n", argc
);
3845 if (args
[0][0] == '0')
3847 if (args
[1][0] == '0')
3849 grub_script_execute_sourcecode(g_list_script_buf
);
3853 grub_script_execute_sourcecode(g_tree_script_buf
);
3858 if (configfile_mode
)
3860 debug("Now already in F3 mode %d\n", configfile_mode
);
3864 if (args
[1][0] == '0')
3866 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3867 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3871 g_ventoy_last_entry
= -1;
3872 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3873 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3876 configfile_mode
= 1;
3877 grub_script_execute_sourcecode(memfile
);
3878 configfile_mode
= 0;
3884 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3895 g_ventoy_case_insensitive
= 1;
3896 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3897 g_ventoy_case_insensitive
= 0;
3903 grub_file_close(file
);
3909 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3914 const char *isopath
= NULL
;
3916 ventoy_mbr_head mbr
;
3923 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3926 isopath
= grub_env_get("vtoy_iso_part");
3929 debug("isopath is null %p\n", isopath
);
3933 debug("isopath is %s\n", isopath
);
3935 for (id
= 0; id
< 30 && (find
== 0); id
++)
3937 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3938 if (grub_strstr(isopath
, hdname
))
3940 debug("skip %s ...\n", hdname
);
3944 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3946 disk
= grub_disk_open(hdname
);
3949 debug("%s not exist\n", hdname
);
3953 grub_memset(&mbr
, 0, sizeof(mbr
));
3954 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3956 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3958 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3959 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3962 grub_env_set(args
[0], hdname
);
3966 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3970 debug("read %s failed\n", hdname
);
3973 grub_disk_close(disk
);
3979 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3990 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3993 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3996 debug("failed to open file %s\n", args
[0]);
4000 buf
= grub_malloc(len
);
4007 grub_file_read(file
, buf
, len
- 1);
4009 ventoy_get_line(buf
);
4010 ventoy_set_env(args
[1], buf
);
4014 grub_check_free(buf
);
4015 grub_file_close(file
);
4020 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4022 grub_uint64_t end_max
= 0;
4023 int *pCnt
= (int *)data
;
4028 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4029 "0 %llu linear /dev/ventoy %llu\n",
4030 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4032 end_max
= (partition
->len
+ partition
->start
) * 512;
4033 if (end_max
> g_part_end_max
)
4035 g_part_end_max
= end_max
;
4041 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4044 char *device_name
= NULL
;
4045 grub_device_t dev
= NULL
;
4050 g_part_list_pos
= 0;
4052 grub_env_unset("vtoy_img_part_file");
4059 device_name
= grub_file_get_device_name(args
[0]);
4062 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4066 dev
= grub_device_open(device_name
);
4069 debug("grub_device_open failed, %s\n", device_name
);
4073 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4075 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4076 grub_env_set("vtoy_img_part_file", buf
);
4078 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4079 grub_env_set("vtoy_img_part_cnt", buf
);
4081 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4082 grub_env_set("vtoy_img_max_part_end", buf
);
4086 check_free(device_name
, grub_free
);
4087 check_free(dev
, grub_device_close
);
4093 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4104 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4107 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4110 debug("failed to open file %s\n", args
[0]);
4114 buf
= grub_malloc(file
->size
+ 1);
4120 buf
[file
->size
] = 0;
4121 grub_file_read(file
, buf
, file
->size
);
4123 if (grub_strstr(buf
, args
[1]))
4130 grub_check_free(buf
);
4131 grub_file_close(file
);
4136 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4142 ventoy_iso9660_vd pvd
;
4149 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4152 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4155 debug("failed to open file %s\n", args
[0]);
4159 grub_file_seek(file
, 16 * 2048);
4160 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4161 if (len
!= sizeof(pvd
))
4163 debug("failed to read pvd %d\n", len
);
4167 grub_memset(buf
, 0, sizeof(buf
));
4168 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4169 ventoy_set_env(args
[1], buf
);
4171 grub_memset(buf
, 0, sizeof(buf
));
4172 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4173 ventoy_set_env(args
[2], buf
);
4177 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4178 ventoy_set_env(args
[3], buf
);
4181 grub_file_close(file
);
4186 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4197 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4200 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4203 debug("failed to open file %s\n", args
[0]);
4207 grub_memset(buf
, 0, sizeof(buf
));
4208 grub_file_seek(file
, 16 * 2048 + 813);
4209 len
= (int)grub_file_read(file
, buf
, 17);
4212 debug("failed to read create date %d\n", len
);
4216 ventoy_set_env(args
[1], buf
);
4219 grub_file_close(file
);
4224 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4230 ventoy_env_hook_root(1);
4235 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4241 ventoy_env_hook_root(0);
4246 #ifdef GRUB_MACHINE_EFI
4247 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4252 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4258 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4259 if (var
&& *var
== 1)
4267 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4276 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4281 grub_uint64_t FileSectors
= 0;
4282 ventoy_gpt_info
*gpt
= NULL
;
4283 ventoy_part_table
*pt
= NULL
;
4284 grub_uint8_t zeroguid
[16] = {0};
4289 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4292 debug("failed to open file %s\n", args
[0]);
4296 if (file
->size
% 512)
4298 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4302 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4308 FileSectors
= file
->size
/ 512;
4310 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4311 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4313 debug("This is EFI partition table\n");
4315 for (i
= 0; i
< 128; i
++)
4317 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4319 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4321 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4322 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4330 debug("This is MBR partition table\n");
4332 for (i
= 0; i
< 4; i
++)
4334 pt
= gpt
->MBR
.PartTbl
+ i
;
4335 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4337 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4338 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4339 (ulonglong
)FileSectors
);
4348 grub_file_close(file
);
4349 grub_check_free(gpt
);
4350 grub_errno
= GRUB_ERR_NONE
;
4354 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4363 for (i
= 0; i
< 500; i
++)
4365 ret
= grub_getkey_noblock();
4366 if (ret
== GRUB_TERM_NO_KEY
)
4375 grub_printf("\n\n Still have key input after clear.\n");
4383 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4390 int image_sector_size
;
4392 ventoy_chain_head
*chain
;
4393 ventoy_img_chunk
*chunk
;
4394 ventoy_os_param
*osparam
;
4395 ventoy_image_location
*location
;
4396 ventoy_image_disk_region
*region
;
4397 struct grub_acpi_table_header
*acpi
;
4406 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4408 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4414 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4416 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4418 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4422 img_chunk_num
= chain
->img_chunk_num
;
4424 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4425 datalen
= sizeof(ventoy_os_param
) + loclen
;
4427 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4428 acpi
= grub_zalloc(buflen
);
4434 /* Step1: Fill acpi table header */
4435 grub_memcpy(acpi
->signature
, "VTOY", 4);
4436 acpi
->length
= buflen
;
4438 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4439 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4441 acpi
->creator_id
[0] = 1;
4442 acpi
->creator_rev
= 1;
4444 /* Step2: Fill data */
4445 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4446 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4447 osparam
->vtoy_img_location_addr
= 0;
4448 osparam
->vtoy_img_location_len
= loclen
;
4449 osparam
->chksum
= 0;
4450 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4452 location
= (ventoy_image_location
*)(osparam
+ 1);
4453 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4454 location
->image_sector_size
= image_sector_size
;
4455 location
->disk_sector_size
= chain
->disk_sector_size
;
4456 location
->region_count
= img_chunk_num
;
4458 region
= location
->regions
;
4459 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4460 if (512 == image_sector_size
)
4462 for (i
= 0; i
< img_chunk_num
; i
++)
4464 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4465 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4466 region
->disk_start_sector
= chunk
->disk_start_sector
;
4473 for (i
= 0; i
< img_chunk_num
; i
++)
4475 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4476 region
->image_start_sector
= chunk
->img_start_sector
;
4477 region
->disk_start_sector
= chunk
->disk_start_sector
;
4483 /* Step3: Fill acpi checksum */
4485 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4487 /* load acpi table */
4488 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4489 grub_script_execute_sourcecode(cmd
);
4493 VENTOY_CMD_RETURN(0);
4496 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4502 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4503 g_ventoy_last_entry
= -1;
4508 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4514 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4519 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4521 const char *pos
= filename
+ 1;
4529 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4531 grub_strncpy((char *)data
, filename
, 128);
4542 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4545 char *device_name
= NULL
;
4546 grub_device_t dev
= NULL
;
4547 grub_fs_t fs
= NULL
;
4548 char buf
[128] = {0};
4554 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4558 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4560 device_name
= grub_file_get_device_name(args
[0]);
4563 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4567 dev
= grub_device_open(device_name
);
4570 debug("grub_device_open failed, %s\n", device_name
);
4574 fs
= grub_fs_probe(dev
);
4577 debug("grub_fs_probe failed, %s\n", device_name
);
4581 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4585 ventoy_set_env(args
[2], buf
);
4592 check_free(device_name
, grub_free
);
4593 check_free(dev
, grub_device_close
);
4598 int ventoy_load_part_table(const char *diskname
)
4605 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4606 if (!g_ventoy_part_info
)
4611 disk
= grub_disk_open(diskname
);
4614 debug("Failed to open disk %s\n", diskname
);
4618 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4620 g_ventoy_disk_bios_id
= disk
->id
;
4622 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4623 grub_disk_close(disk
);
4625 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4626 dev
= grub_device_open(name
);
4629 /* Check for official Ventoy device */
4630 ret
= ventoy_check_official_device(dev
);
4631 grub_device_close(dev
);
4639 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4640 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4645 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4652 ret
= ventoy_load_part_table(args
[0]);
4658 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4659 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4664 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4667 const char *vcfg
= NULL
;
4672 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4675 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4676 grub_env_set(args
[1], vcfg
);
4681 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4689 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4692 grub_uint8_t zeroguid
[16] = {0};
4697 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4700 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4702 if (id
>= 1 && id
<= 128)
4704 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4712 if (id
>= 1 && id
<= 4)
4714 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4724 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4727 char *device_name
= NULL
;
4728 grub_device_t dev
= NULL
;
4729 grub_fs_t fs
= NULL
;
4734 debug("get fs label for %s\n", args
[0]);
4738 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4742 device_name
= grub_file_get_device_name(args
[0]);
4745 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4749 dev
= grub_device_open(device_name
);
4752 debug("grub_device_open failed, %s\n", device_name
);
4756 fs
= grub_fs_probe(dev
);
4757 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4759 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4763 fs
->fs_label(dev
, &label
);
4766 debug("label=<%s>\n", label
);
4767 ventoy_set_env(args
[1], label
);
4775 check_free(device_name
, grub_free
);
4776 check_free(dev
, grub_device_close
);
4781 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4785 grub_snprintf((char *)data
, 256, "%s", filename
);
4792 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4794 if (info
->dir
&& filename
&& filename
[0] != '.')
4796 grub_snprintf((char *)data
, 256, "%s", filename
);
4803 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4806 char *device_name
= NULL
;
4807 grub_device_t dev
= NULL
;
4808 grub_fs_t fs
= NULL
;
4809 char name
[256] ={0};
4813 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4817 device_name
= grub_file_get_device_name(args
[0]);
4820 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4824 dev
= grub_device_open(device_name
);
4827 debug("grub_device_open failed, %s\n", device_name
);
4831 fs
= grub_fs_probe(dev
);
4834 debug("grub_fs_probe failed, %s\n", device_name
);
4838 fs
->fs_dir(dev
, args
[1], hook
, name
);
4841 ventoy_set_env(args
[2], name
);
4848 check_free(device_name
, grub_free
);
4849 check_free(dev
, grub_device_close
);
4854 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4857 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4860 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4863 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4866 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4876 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4880 for (pos
= args
[0]; *pos
; pos
++)
4894 grub_env_set(args
[1], args
[0]);
4904 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4914 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4919 len
= (int)grub_strlen(buf
);
4920 for (i
= len
; i
> 0; i
--)
4922 if (buf
[i
- 1] == '/')
4924 grub_env_set(args
[1], buf
+ i
);
4929 grub_env_set(args
[1], buf
);
4934 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4936 struct grub_video_mode_info info
;
4943 if (!g_video_mode_list
)
4945 ventoy_enum_video_mode();
4948 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4950 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4954 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4957 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4959 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4960 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4962 VENTOY_CMD_RETURN(0);
4965 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4967 struct grub_video_mode_info info
;
4974 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4976 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4980 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4983 grub_env_set(args
[0], buf
);
4985 VENTOY_CMD_RETURN(0);
4988 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4996 if (!g_video_mode_list
)
5001 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5002 if (id
< g_video_mode_num
)
5004 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5005 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5008 grub_env_set(args
[1], buf
);
5010 VENTOY_CMD_RETURN(0);
5013 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5016 grub_uint32_t loadsector
= 0;
5019 grub_uint32_t boot_catlog
= 0;
5020 grub_uint8_t buf
[512];
5026 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5030 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5033 debug("failed to open %s\n", args
[0]);
5037 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5038 if (boot_catlog
== 0)
5040 debug("No bootcatlog found\n");
5041 grub_file_close(file
);
5045 grub_memset(buf
, 0, sizeof(buf
));
5046 grub_file_seek(file
, boot_catlog
* 2048);
5047 grub_file_read(file
, buf
, sizeof(buf
));
5048 grub_file_close(file
);
5050 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5052 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5054 if (buf
[i
+ 32] == 0x88)
5056 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5057 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5063 if (loadsector
== 0)
5065 debug("No EFI eltorito info found\n");
5069 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5070 grub_env_set(args
[1], value
);
5071 VENTOY_CMD_RETURN(0);
5074 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5079 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5081 if (pfsdir
->initrd
[0])
5086 curpos
= pfsdir
->curpos
;
5087 len
= grub_strlen(filename
);
5091 if ((len
== 1 && filename
[0] == '.') ||
5092 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5097 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5100 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5101 pfsdir
->curpos
= curpos
+ printlen
;
5102 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5103 pfsdir
->curpos
= curpos
;
5104 pfsdir
->fullpath
[curpos
] = 0;
5108 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5111 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5112 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5114 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5116 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5125 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5129 char *device_name
= NULL
;
5130 grub_device_t dev
= NULL
;
5131 grub_fs_t fs
= NULL
;
5132 replace_fs_dir
*pfsdir
= NULL
;
5138 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5142 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5148 device_name
= grub_file_get_device_name(args
[0]);
5154 dev
= grub_device_open(device_name
);
5160 fs
= grub_fs_probe(dev
);
5169 pfsdir
->fullpath
[0] = '/';
5170 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5172 if (pfsdir
->initrd
[0])
5174 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5176 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5178 if (pfsdir
->initrd
[i
] == '/')
5180 pfsdir
->initrd
[i
] = '\\';
5184 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5185 grub_env_set(args
[1], pos
);
5189 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5194 grub_check_free(pfsdir
);
5195 grub_check_free(device_name
);
5196 check_free(dev
, grub_device_close
);
5198 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5201 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5203 const char *pager
= NULL
;
5209 pager
= grub_env_get("pager");
5213 grub_env_set("pager", "1");
5215 else if (pager
[0] == '1')
5221 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5223 grub_env_set("pager", "1");
5226 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5229 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5235 if (g_pager_flag
== 1)
5237 grub_env_unset("pager");
5239 else if (g_pager_flag
== 2)
5241 grub_env_set("pager", g_old_pager
);
5244 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5247 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5249 if (g_json_case_mis_path
[0])
5254 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5256 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5262 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5265 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5267 if (g_json_case_mis_path
[0])
5272 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5274 if (grub_strcasecmp(filename
, "ventoy") == 0)
5276 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5277 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5278 if (g_json_case_mis_path
[0])
5288 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5291 char *device_name
= NULL
;
5292 grub_device_t dev
= NULL
;
5293 grub_fs_t fs
= NULL
;
5294 chk_case_fs_dir fs_dir
;
5300 device_name
= grub_file_get_device_name(args
[0]);
5306 dev
= grub_device_open(device_name
);
5312 fs
= grub_fs_probe(dev
);
5318 fstype
= ventoy_get_fs_type(fs
->name
);
5319 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5324 g_json_case_mis_path
[0] = 0;
5327 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5329 if (g_json_case_mis_path
[0])
5331 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5336 grub_check_free(device_name
);
5337 check_free(dev
, grub_device_close
);
5339 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5342 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5345 grub_partition_t part
;
5346 char priority_str
[3]; /* Maximum value 15 */
5350 if (argc
< 2 || argc
> 3)
5351 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5352 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5354 /* Open the disk if it exists */
5355 disk
= grub_disk_open (args
[0]);
5358 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5362 part
= grub_partition_probe (disk
, args
[1]);
5365 grub_disk_close (disk
);
5366 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5367 "No such partition");
5370 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5372 grub_disk_close (disk
);
5373 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5374 "Not a GPT partition");
5377 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5378 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5382 grub_env_set (args
[2], priority_str
);
5383 grub_env_export (args
[2]);
5387 grub_printf ("Priority is %s\n", priority_str
);
5390 grub_disk_close (disk
);
5391 return GRUB_ERR_NONE
;
5395 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5399 grub_file_t file
= NULL
;
5400 grub_uint32_t loadrba
= 0;
5401 grub_uint32_t boot_catlog
= 0;
5402 grub_uint8_t sector
[512];
5403 boot_info_table
*info
= NULL
;
5408 /* This also trigger a iso9660 fs parse */
5409 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5414 joliet
= grub_iso9660_is_joliet();
5420 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5423 debug("failed to open %s\n", args
[0]);
5427 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5428 if (boot_catlog
== 0)
5430 debug("no bootcatlog found %u\n", boot_catlog
);
5434 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5437 debug("no bios eltorito rba found %u\n", loadrba
);
5441 grub_file_seek(file
, loadrba
* 2048);
5442 grub_file_read(file
, sector
, 512);
5444 info
= (boot_info_table
*)sector
;
5445 if (info
->bi_data0
== 0x7c6ceafa &&
5446 info
->bi_data1
== 0x90900000 &&
5447 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5448 info
->bi_BootFileLocation
== loadrba
)
5450 debug("bootloader is syslinux, %u.\n", loadrba
);
5456 grub_file_close(file
);
5457 grub_errno
= GRUB_ERR_NONE
;
5461 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5464 ventoy_vlnk_part
*node
;
5470 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5472 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5473 ++n
, node
->device
, node
->disksig
,
5474 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5480 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5488 len
= (int)grub_strlen(args
[0]);
5489 if (grub_file_is_vlnk_suffix(args
[0], len
))
5498 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5501 const char *name
= NULL
;
5507 grub_env_unset(args
[1]);
5508 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5511 debug("VLNK SRC: <%s>\n", args
[0]);
5512 debug("VLNK DST: <%s>\n", name
);
5513 grub_env_set(args
[1], name
);
5521 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5525 grub_file_t file
= NULL
;
5536 len
= (int)grub_strlen(args
[0]);
5537 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5539 grub_printf("Invalid vlnk suffix\n");
5543 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5546 grub_printf("Failed to open %s\n", args
[0]);
5550 if (file
->size
!= 32768)
5552 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5556 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5557 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5559 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5564 check_free(file
, grub_file_close
);
5565 grub_errno
= GRUB_ERR_NONE
;
5569 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5575 g_iso_vd_id_publisher
[0] = 0;
5576 g_iso_vd_id_prepare
[0] = 0;
5577 g_iso_vd_id_application
[0] = 0;
5582 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5586 grub_file_t file
= NULL
;
5591 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5594 grub_printf("Failed to open %s\n", args
[0]);
5598 grub_file_seek(file
, 16 * 2048 + offset
);
5599 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5602 grub_file_seek(file
, 16 * 2048 + offset
);
5603 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5606 grub_file_seek(file
, 16 * 2048 + offset
);
5607 grub_file_read(file
, g_iso_vd_id_application
, 128);
5611 check_free(file
, grub_file_close
);
5612 grub_errno
= GRUB_ERR_NONE
;
5616 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5619 char *id
= g_iso_vd_id_publisher
;
5624 if (args
[0][0] == '1')
5626 id
= g_iso_vd_id_prepare
;
5628 else if (args
[0][0] == '2')
5630 id
= g_iso_vd_id_application
;
5633 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5638 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5643 grub_errno
= GRUB_ERR_NONE
;
5647 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5652 g_ventoy_fn_mutex
= 0;
5653 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5655 g_ventoy_fn_mutex
= 1;
5658 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5661 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5663 grub_uint64_t total
;
5664 grub_uint64_t org_required
;
5665 grub_uint64_t new_required
;
5671 #ifdef GRUB_MACHINE_EFI
5672 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
5673 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
5674 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
5675 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
5680 grub_printf("Non EFI mode!\n");
5685 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5688 int ventoy_env_init(void)
5692 grub_env_set("vtdebug_flag", "");
5694 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5695 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5696 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5697 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5699 ventoy_filt_register(0, ventoy_wrapper_open
);
5701 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5704 g_grub_param
->grub_env_get
= grub_env_get
;
5705 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5706 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5707 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5708 grub_env_set("env_param", buf
);
5709 grub_env_set("ventoy_env_param", buf
);
5711 grub_env_export("env_param");
5712 grub_env_export("ventoy_env_param");
5715 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5716 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5718 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5719 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5721 grub_env_export("vtoy_winpeshl_ini_addr");
5722 grub_env_export("vtoy_winpeshl_ini_size");
5724 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5725 grub_env_set("vtoy_chain_file_size", buf
);
5726 grub_env_export("vtoy_chain_file_size");
5728 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5729 grub_env_set("vtoy_chain_file_read", buf
);
5730 grub_env_export("vtoy_chain_file_read");
5737 static cmd_para ventoy_cmds
[] =
5739 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
5740 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
5741 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5742 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5743 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5744 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5745 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5746 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5747 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5748 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5749 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5750 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5751 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5752 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5753 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5754 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5755 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5756 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5757 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5758 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5759 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5760 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5761 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5762 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5763 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5764 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5765 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5767 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5768 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5769 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5770 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5771 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5772 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5773 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5775 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5776 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5777 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5778 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5779 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5780 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5781 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5782 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5783 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5784 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5787 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5788 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5789 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5790 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5791 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5792 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5793 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5794 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5795 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5796 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5797 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5799 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5800 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5801 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5802 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5803 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5804 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5805 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5807 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5808 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5809 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5810 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5811 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5812 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5813 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5814 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5815 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5816 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5818 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5819 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5820 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5821 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5822 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5823 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5824 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5825 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5826 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5828 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5829 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5830 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5831 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5834 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5835 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5836 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5838 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5839 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5840 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5843 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5844 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5845 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5846 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5847 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5848 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5849 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
5850 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5851 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
5852 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5853 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5854 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5855 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5856 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5858 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5859 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5860 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5861 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5862 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5863 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5864 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5865 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5866 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5867 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5868 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5869 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5871 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5872 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5873 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5874 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5875 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5876 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5877 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5878 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5879 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
5880 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
5881 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
5882 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
5883 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
5884 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
5885 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
5886 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
5887 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
5888 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
5889 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
5892 int ventoy_register_all_cmd(void)
5895 cmd_para
*cur
= NULL
;
5897 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5899 cur
= ventoy_cmds
+ i
;
5900 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5901 cur
->summary
, cur
->description
, cur
->parser
);
5907 int ventoy_unregister_all_cmd(void)
5911 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5913 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);