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
)
2615 const char *id
= NULL
;
2616 img_info
*cur
= NULL
;
2620 if (argc
< 1 || argc
> 2)
2622 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2625 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2627 grub_env_set(args
[0], grub_strchr(g_fake_vlnk_src
, '/'));
2630 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2631 grub_env_set(args
[1], value
);
2637 id
= grub_env_get("chosen");
2639 pos
= grub_strstr(id
, "VID_");
2642 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2646 cur
= g_ventoy_img_list
;
2651 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2654 grub_env_set(args
[0], cur
->path
);
2658 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2659 grub_env_set(args
[1], value
);
2663 g_svd_replace_offset
= 0;
2665 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2669 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2673 grub_device_t dev
= NULL
;
2674 img_info
*cur
= NULL
;
2675 img_info
*tail
= NULL
;
2676 img_info
*min
= NULL
;
2677 img_info
*head
= NULL
;
2678 const char *strdata
= NULL
;
2679 char *device_name
= NULL
;
2681 img_iterator_node
*node
= NULL
;
2682 img_iterator_node
*tmp
= NULL
;
2688 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2691 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2693 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2698 g_enumerate_time_checked
= 0;
2699 g_enumerate_start_time_ms
= grub_get_time_ms();
2701 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2702 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2704 g_filt_dot_underscore_file
= 1;
2707 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2708 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2710 g_sort_case_sensitive
= 1;
2713 device_name
= grub_file_get_device_name(args
[0]);
2719 g_enum_dev
= dev
= grub_device_open(device_name
);
2725 g_enum_fs
= fs
= grub_fs_probe(dev
);
2731 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2733 debug("unsupported fs:<%s>\n", fs
->name
);
2734 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2738 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2740 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2741 if (strdata
&& strdata
[0] == '1')
2743 g_default_menu_mode
= 1;
2746 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2748 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2750 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2751 if (strdata
&& strdata
[0] == '/')
2753 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2754 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2756 g_img_iterator_head
.dir
[len
++] = '/';
2758 g_img_iterator_head
.dirlen
= len
;
2762 g_img_iterator_head
.dirlen
= 1;
2763 grub_strcpy(g_img_iterator_head
.dir
, "/");
2766 g_img_iterator_head
.tail
= &tail
;
2768 if (g_img_max_search_level
< 0)
2770 g_img_max_search_level
= GRUB_INT_MAX
;
2771 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2772 if (strdata
&& ventoy_is_decimal(strdata
))
2774 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2778 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2779 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2780 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2781 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2782 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2783 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2785 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2787 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2790 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2791 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2793 g_tree_view_menu_style
= 1;
2796 ventoy_set_default_menu();
2798 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2800 ventoy_dynamic_tree_menu(node
);
2804 node
= g_img_iterator_head
.next
;
2812 /* sort image list by image name */
2813 while (g_ventoy_img_list
)
2815 min
= g_ventoy_img_list
;
2816 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2818 if (ventoy_cmp_img(min
, cur
) > 0)
2826 min
->prev
->next
= min
->next
;
2831 min
->next
->prev
= min
->prev
;
2834 if (min
== g_ventoy_img_list
)
2836 g_ventoy_img_list
= min
->next
;
2854 g_ventoy_img_list
= head
;
2856 if (g_default_menu_mode
== 1)
2858 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2859 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2860 " echo 'return ...' \n"
2864 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2866 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2867 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2870 cur
->unsupport
? "[***********] " : "",
2871 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2873 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2876 g_tree_script_buf
[g_tree_script_pos
] = 0;
2877 g_list_script_buf
[g_list_script_pos
] = 0;
2879 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2880 grub_env_set(args
[1], buf
);
2884 check_free(device_name
, grub_free
);
2885 check_free(dev
, grub_device_close
);
2887 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2890 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2897 device_name
= grub_file_get_device_name(filename
);
2909 pos2
= grub_strstr(pos
, ",");
2912 pos2
= grub_strstr(pos
, ")");
2920 disk
= grub_disk_open(pos
);
2923 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2924 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2925 grub_disk_close(disk
);
2932 grub_free(device_name
);
2936 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2938 eltorito_descriptor desc
;
2940 grub_memset(&desc
, 0, sizeof(desc
));
2941 grub_file_seek(file
, 17 * 2048);
2942 grub_file_read(file
, &desc
, sizeof(desc
));
2944 if (desc
.type
!= 0 || desc
.version
!= 1)
2949 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2950 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2958 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2960 grub_uint8_t buf
[512];
2962 grub_file_seek(file
, sector
* 2048);
2963 grub_file_read(file
, buf
, sizeof(buf
));
2965 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2966 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2968 return *((grub_uint32_t
*)(buf
+ 40));
2974 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2978 grub_uint8_t buf
[512];
2979 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2981 grub_file_seek(file
, sector
* 2048);
2982 grub_file_read(file
, buf
, sizeof(buf
));
2984 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2986 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2990 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2995 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2997 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2999 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3003 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3005 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3010 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3012 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3014 if (buf
[36] == parttype
[i
])
3016 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3022 debug("%s does not contain efi eltorito\n", file
->name
);
3026 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3029 const char *fs
= NULL
;
3030 const char *val
= NULL
;
3031 const char *cdprompt
= NULL
;
3033 grub_uint8_t chksum
= 0;
3036 disk
= file
->device
->disk
;
3037 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3039 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3040 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3041 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3043 pos
= grub_strstr(file
->name
, "/");
3049 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3051 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3053 param
->vtoy_img_size
= file
->size
;
3055 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3056 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3058 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3060 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3061 param
->vtoy_reserved
[4] = 0;
3062 if (g_ventoy_chain_type
== 1) /* Windows */
3064 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3065 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3067 param
->vtoy_reserved
[4] = 1;
3071 fs
= ventoy_get_env("ventoy_fs_probe");
3072 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3074 param
->vtoy_reserved
[3] = 1;
3077 param
->vtoy_reserved
[5] = 0;
3078 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3079 if (val
&& val
[0] == '1' && val
[1] == 0)
3081 param
->vtoy_reserved
[5] = 1;
3084 /* ventoy_disk_signature used for vlnk */
3085 param
->vtoy_reserved
[6] = file
->vlnk
;
3086 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3088 /* calculate checksum */
3089 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3091 chksum
+= *((grub_uint8_t
*)param
+ i
);
3093 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3098 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3100 grub_uint32_t i
= 0;
3101 grub_uint64_t total
= 0;
3102 grub_uint64_t fileblk
= 0;
3103 ventoy_img_chunk
*chunk
= NULL
;
3105 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3107 chunk
= chunklist
->chunk
+ i
;
3109 if (chunk
->disk_start_sector
<= start
)
3111 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3115 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3118 fileblk
= (file
->size
+ 511) / 512;
3120 if (total
!= fileblk
)
3122 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3123 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3125 debug("maybe img file to be processed.\n");
3135 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3139 grub_uint32_t i
= 0;
3140 grub_uint32_t sector
= 0;
3141 grub_uint32_t count
= 0;
3142 grub_off_t size
= 0;
3143 grub_off_t read
= 0;
3145 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3146 if (fs_type
== ventoy_fs_exfat
)
3148 grub_fat_get_file_chunk(start
, file
, chunklist
);
3150 else if (fs_type
== ventoy_fs_ext
)
3152 grub_ext_get_file_chunk(start
, file
, chunklist
);
3156 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3157 file
->read_hook_data
= chunklist
;
3159 for (size
= file
->size
; size
> 0; size
-= read
)
3161 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3162 grub_file_read(file
, NULL
, read
);
3165 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3167 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3168 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3171 if (ventoy_fs_udf
== fs_type
)
3173 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3175 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3176 chunklist
->chunk
[i
].img_start_sector
= sector
;
3177 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3183 len
= (int)grub_strlen(file
->name
);
3184 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3185 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3186 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3187 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3189 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3191 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3201 chunklist
->chunk
[i
].img_start_sector
= sector
;
3202 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3210 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3214 grub_disk_addr_t start
;
3219 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3222 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3225 g_conf_replace_node
= NULL
;
3226 g_conf_replace_offset
= 0;
3228 if (g_img_chunk_list
.chunk
)
3230 grub_free(g_img_chunk_list
.chunk
);
3233 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3235 grub_file_close(file
);
3236 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3239 /* get image chunk data */
3240 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3241 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3242 if (NULL
== g_img_chunk_list
.chunk
)
3244 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3247 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3248 g_img_chunk_list
.cur_chunk
= 0;
3250 start
= file
->device
->disk
->partition
->start
;
3252 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3254 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3255 grub_file_close(file
);
3259 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3262 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3263 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3264 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3267 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3269 grub_uint64_t offset
= 0;
3270 grub_uint32_t align
= 0;
3271 grub_file_t file
= NULL
;
3272 conf_replace
*node
= NULL
;
3278 debug("select conf replace argc:%d\n", argc
);
3285 node
= ventoy_plugin_find_conf_replace(args
[1]);
3288 debug("Conf replace not found for %s\n", args
[1]);
3292 debug("Find conf replace for %s\n", args
[1]);
3294 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3297 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3298 grub_file_close(file
);
3300 else if (node
->img
> 0)
3306 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3310 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3313 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3317 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3319 if (align
> vtoy_max_replace_file_size
)
3321 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3325 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3326 g_conf_replace_new_len
= (int)file
->size
;
3327 g_conf_replace_new_len_align
= align
;
3329 g_conf_replace_node
= node
;
3330 g_conf_replace_offset
= offset
+ 2;
3334 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3335 g_grub_param
->img_replace
.old_name_cnt
= 1;
3336 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3339 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3344 grub_file_close(file
);
3346 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3349 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3355 char configfile
[128];
3356 install_template
*node
= NULL
;
3362 debug("select auto installation argc:%d\n", argc
);
3369 node
= ventoy_plugin_find_install_template(args
[0]);
3372 debug("Auto install template not found for %s\n", args
[0]);
3376 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3378 defidx
= node
->autosel
;
3379 if (node
->timeout
< 0)
3381 node
->cursel
= node
->autosel
- 1;
3382 debug("Auto install template auto select %d\n", node
->autosel
);
3387 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3393 if (node
->timeout
> 0)
3395 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3398 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3399 " echo %s\n}\n", "");
3401 for (i
= 0; i
< node
->templatenum
; i
++)
3403 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3405 node
->templatepath
[i
].path
);
3408 g_ventoy_menu_esc
= 1;
3409 g_ventoy_suppress_esc
= 1;
3410 g_ventoy_suppress_esc_default
= defidx
;
3412 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3413 grub_script_execute_sourcecode(configfile
);
3415 g_ventoy_menu_esc
= 0;
3416 g_ventoy_suppress_esc
= 0;
3417 g_ventoy_suppress_esc_default
= 1;
3421 node
->cursel
= g_ventoy_last_entry
- 1;
3423 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3426 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3432 char configfile
[128];
3433 persistence_config
*node
;
3439 debug("select persistence argc:%d\n", argc
);
3446 node
= ventoy_plugin_find_persistent(args
[0]);
3449 debug("Persistence image not found for %s\n", args
[0]);
3453 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3455 defidx
= node
->autosel
;
3456 if (node
->timeout
< 0)
3458 node
->cursel
= node
->autosel
- 1;
3459 debug("Persistence image auto select %d\n", node
->autosel
);
3464 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3470 if (node
->timeout
> 0)
3472 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3475 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3476 " echo %s\n}\n", "");
3478 for (i
= 0; i
< node
->backendnum
; i
++)
3480 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3482 node
->backendpath
[i
].path
);
3486 g_ventoy_menu_esc
= 1;
3487 g_ventoy_suppress_esc
= 1;
3488 g_ventoy_suppress_esc_default
= defidx
;
3490 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3491 grub_script_execute_sourcecode(configfile
);
3493 g_ventoy_menu_esc
= 0;
3494 g_ventoy_suppress_esc
= 0;
3495 g_ventoy_suppress_esc_default
= 1;
3499 node
->cursel
= g_ventoy_last_entry
- 1;
3501 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3504 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3507 ventoy_img_chunk
*cur
;
3513 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3515 cur
= g_img_chunk_list
.chunk
+ i
;
3516 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3517 cur
->img_start_sector
, cur
->img_end_sector
,
3518 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3522 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3525 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3529 ventoy_img_chunk_list chunklist
;
3534 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3537 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3540 /* get image chunk data */
3541 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3542 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3543 if (NULL
== chunklist
.chunk
)
3545 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3548 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3549 chunklist
.cur_chunk
= 0;
3551 ventoy_get_block_list(file
, &chunklist
, 0);
3553 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3555 grub_printf("########## UNSUPPORTED ###############\n");
3558 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3560 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3562 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3563 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3566 grub_printf("\n==================================\n");
3568 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3570 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3571 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3572 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3573 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3574 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3578 grub_free(chunklist
.chunk
);
3579 grub_file_close(file
);
3581 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3584 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3587 ventoy_grub_param_file_replace
*replace
= NULL
;
3595 replace
= &(g_grub_param
->file_replace
);
3596 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3598 replace
->old_name_cnt
= 0;
3599 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3601 replace
->old_name_cnt
++;
3602 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3605 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3608 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3611 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3614 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3620 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3621 grub_env_set(args
[0], buf
);
3624 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3627 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3635 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3636 grub_printf("%s", g_list_script_buf
);
3640 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3641 grub_printf("%s", g_tree_script_buf
);
3647 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3649 img_info
*cur
= g_ventoy_img_list
;
3657 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3658 grub_printf("name:<%s>\n\n", cur
->name
);
3665 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3671 ventoy_plugin_dump_injection();
3676 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3682 ventoy_plugin_dump_auto_install();
3687 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3693 ventoy_plugin_dump_persistence();
3698 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3709 if (args
[0][0] == '0')
3711 return g_ventoy_memdisk_mode
? 0 : 1;
3713 else if (args
[0][0] == '1')
3715 return g_ventoy_iso_raw
? 0 : 1;
3717 else if (args
[0][0] == '2')
3719 return g_ventoy_iso_uefi_drv
? 0 : 1;
3721 else if (args
[0][0] == '3')
3723 return g_ventoy_grub2_mode
? 0 : 1;
3725 else if (args
[0][0] == '4')
3727 return g_ventoy_wimboot_mode
? 0 : 1;
3733 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3735 static int configfile_mode
= 0;
3736 char memfile
[128] = {0};
3743 * args[0]: 0:normal 1:configfile
3744 * args[1]: 0:list_buf 1:tree_buf
3749 debug("Invalid argc %d\n", argc
);
3755 if (args
[0][0] == '0')
3757 if (args
[1][0] == '0')
3759 grub_script_execute_sourcecode(g_list_script_buf
);
3763 grub_script_execute_sourcecode(g_tree_script_buf
);
3768 if (configfile_mode
)
3770 debug("Now already in F3 mode %d\n", configfile_mode
);
3774 if (args
[1][0] == '0')
3776 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3777 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3781 g_ventoy_last_entry
= -1;
3782 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3783 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3786 configfile_mode
= 1;
3787 grub_script_execute_sourcecode(memfile
);
3788 configfile_mode
= 0;
3794 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3805 g_ventoy_case_insensitive
= 1;
3806 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3807 g_ventoy_case_insensitive
= 0;
3813 grub_file_close(file
);
3819 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3824 const char *isopath
= NULL
;
3826 ventoy_mbr_head mbr
;
3833 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3836 isopath
= grub_env_get("vtoy_iso_part");
3839 debug("isopath is null %p\n", isopath
);
3843 debug("isopath is %s\n", isopath
);
3845 for (id
= 0; id
< 30 && (find
== 0); id
++)
3847 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3848 if (grub_strstr(isopath
, hdname
))
3850 debug("skip %s ...\n", hdname
);
3854 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3856 disk
= grub_disk_open(hdname
);
3859 debug("%s not exist\n", hdname
);
3863 grub_memset(&mbr
, 0, sizeof(mbr
));
3864 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3866 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3868 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3869 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3872 grub_env_set(args
[0], hdname
);
3876 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3880 debug("read %s failed\n", hdname
);
3883 grub_disk_close(disk
);
3889 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3900 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3903 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3906 debug("failed to open file %s\n", args
[0]);
3910 buf
= grub_malloc(len
);
3917 grub_file_read(file
, buf
, len
- 1);
3919 ventoy_get_line(buf
);
3920 ventoy_set_env(args
[1], buf
);
3924 grub_check_free(buf
);
3925 grub_file_close(file
);
3930 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3932 grub_uint64_t end_max
= 0;
3933 int *pCnt
= (int *)data
;
3938 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3939 "0 %llu linear /dev/ventoy %llu\n",
3940 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3942 end_max
= (partition
->len
+ partition
->start
) * 512;
3943 if (end_max
> g_part_end_max
)
3945 g_part_end_max
= end_max
;
3951 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3954 char *device_name
= NULL
;
3955 grub_device_t dev
= NULL
;
3960 g_part_list_pos
= 0;
3962 grub_env_unset("vtoy_img_part_file");
3969 device_name
= grub_file_get_device_name(args
[0]);
3972 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3976 dev
= grub_device_open(device_name
);
3979 debug("grub_device_open failed, %s\n", device_name
);
3983 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3985 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3986 grub_env_set("vtoy_img_part_file", buf
);
3988 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3989 grub_env_set("vtoy_img_part_cnt", buf
);
3991 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
3992 grub_env_set("vtoy_img_max_part_end", buf
);
3996 check_free(device_name
, grub_free
);
3997 check_free(dev
, grub_device_close
);
4003 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4014 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4017 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4020 debug("failed to open file %s\n", args
[0]);
4024 buf
= grub_malloc(file
->size
+ 1);
4030 buf
[file
->size
] = 0;
4031 grub_file_read(file
, buf
, file
->size
);
4033 if (grub_strstr(buf
, args
[1]))
4040 grub_check_free(buf
);
4041 grub_file_close(file
);
4046 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4052 ventoy_iso9660_vd pvd
;
4059 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4062 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4065 debug("failed to open file %s\n", args
[0]);
4069 grub_file_seek(file
, 16 * 2048);
4070 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4071 if (len
!= sizeof(pvd
))
4073 debug("failed to read pvd %d\n", len
);
4077 grub_memset(buf
, 0, sizeof(buf
));
4078 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4079 ventoy_set_env(args
[1], buf
);
4081 grub_memset(buf
, 0, sizeof(buf
));
4082 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4083 ventoy_set_env(args
[2], buf
);
4087 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4088 ventoy_set_env(args
[3], buf
);
4091 grub_file_close(file
);
4096 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4107 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4110 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4113 debug("failed to open file %s\n", args
[0]);
4117 grub_memset(buf
, 0, sizeof(buf
));
4118 grub_file_seek(file
, 16 * 2048 + 813);
4119 len
= (int)grub_file_read(file
, buf
, 17);
4122 debug("failed to read create date %d\n", len
);
4126 ventoy_set_env(args
[1], buf
);
4129 grub_file_close(file
);
4134 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4140 ventoy_env_hook_root(1);
4145 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4151 ventoy_env_hook_root(0);
4156 #ifdef GRUB_MACHINE_EFI
4157 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4162 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4168 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4169 if (var
&& *var
== 1)
4177 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4186 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4191 grub_uint64_t FileSectors
= 0;
4192 ventoy_gpt_info
*gpt
= NULL
;
4193 ventoy_part_table
*pt
= NULL
;
4194 grub_uint8_t zeroguid
[16] = {0};
4199 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4202 debug("failed to open file %s\n", args
[0]);
4206 if (file
->size
% 512)
4208 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4212 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4218 FileSectors
= file
->size
/ 512;
4220 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4221 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4223 debug("This is EFI partition table\n");
4225 for (i
= 0; i
< 128; i
++)
4227 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4229 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4231 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4232 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4240 debug("This is MBR partition table\n");
4242 for (i
= 0; i
< 4; i
++)
4244 pt
= gpt
->MBR
.PartTbl
+ i
;
4245 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4247 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4248 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4249 (ulonglong
)FileSectors
);
4258 grub_file_close(file
);
4259 grub_check_free(gpt
);
4260 grub_errno
= GRUB_ERR_NONE
;
4264 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4273 for (i
= 0; i
< 500; i
++)
4275 ret
= grub_getkey_noblock();
4276 if (ret
== GRUB_TERM_NO_KEY
)
4285 grub_printf("\n\n Still have key input after clear.\n");
4293 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4300 int image_sector_size
;
4302 ventoy_chain_head
*chain
;
4303 ventoy_img_chunk
*chunk
;
4304 ventoy_os_param
*osparam
;
4305 ventoy_image_location
*location
;
4306 ventoy_image_disk_region
*region
;
4307 struct grub_acpi_table_header
*acpi
;
4316 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4318 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4324 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4326 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4328 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4332 img_chunk_num
= chain
->img_chunk_num
;
4334 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4335 datalen
= sizeof(ventoy_os_param
) + loclen
;
4337 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4338 acpi
= grub_zalloc(buflen
);
4344 /* Step1: Fill acpi table header */
4345 grub_memcpy(acpi
->signature
, "VTOY", 4);
4346 acpi
->length
= buflen
;
4348 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4349 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4351 acpi
->creator_id
[0] = 1;
4352 acpi
->creator_rev
= 1;
4354 /* Step2: Fill data */
4355 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4356 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4357 osparam
->vtoy_img_location_addr
= 0;
4358 osparam
->vtoy_img_location_len
= loclen
;
4359 osparam
->chksum
= 0;
4360 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4362 location
= (ventoy_image_location
*)(osparam
+ 1);
4363 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4364 location
->image_sector_size
= image_sector_size
;
4365 location
->disk_sector_size
= chain
->disk_sector_size
;
4366 location
->region_count
= img_chunk_num
;
4368 region
= location
->regions
;
4369 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4370 if (512 == image_sector_size
)
4372 for (i
= 0; i
< img_chunk_num
; i
++)
4374 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4375 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4376 region
->disk_start_sector
= chunk
->disk_start_sector
;
4383 for (i
= 0; i
< img_chunk_num
; i
++)
4385 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4386 region
->image_start_sector
= chunk
->img_start_sector
;
4387 region
->disk_start_sector
= chunk
->disk_start_sector
;
4393 /* Step3: Fill acpi checksum */
4395 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4397 /* load acpi table */
4398 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4399 grub_script_execute_sourcecode(cmd
);
4403 VENTOY_CMD_RETURN(0);
4406 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4412 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4413 g_ventoy_last_entry
= -1;
4418 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4424 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4429 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4431 const char *pos
= filename
+ 1;
4439 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4441 grub_strncpy((char *)data
, filename
, 128);
4452 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4455 char *device_name
= NULL
;
4456 grub_device_t dev
= NULL
;
4457 grub_fs_t fs
= NULL
;
4458 char buf
[128] = {0};
4464 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4468 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4470 device_name
= grub_file_get_device_name(args
[0]);
4473 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4477 dev
= grub_device_open(device_name
);
4480 debug("grub_device_open failed, %s\n", device_name
);
4484 fs
= grub_fs_probe(dev
);
4487 debug("grub_fs_probe failed, %s\n", device_name
);
4491 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4495 ventoy_set_env(args
[2], buf
);
4502 check_free(device_name
, grub_free
);
4503 check_free(dev
, grub_device_close
);
4508 int ventoy_load_part_table(const char *diskname
)
4515 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4516 if (!g_ventoy_part_info
)
4521 disk
= grub_disk_open(diskname
);
4524 debug("Failed to open disk %s\n", diskname
);
4528 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4530 g_ventoy_disk_bios_id
= disk
->id
;
4532 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4533 grub_disk_close(disk
);
4535 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4536 dev
= grub_device_open(name
);
4539 /* Check for official Ventoy device */
4540 ret
= ventoy_check_official_device(dev
);
4541 grub_device_close(dev
);
4549 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4550 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4555 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4562 ret
= ventoy_load_part_table(args
[0]);
4568 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4569 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4574 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4577 const char *vcfg
= NULL
;
4582 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4585 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4586 grub_env_set(args
[1], vcfg
);
4591 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4599 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4602 grub_uint8_t zeroguid
[16] = {0};
4607 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4610 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4612 if (id
>= 1 && id
<= 128)
4614 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4622 if (id
>= 1 && id
<= 4)
4624 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4634 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4637 char *device_name
= NULL
;
4638 grub_device_t dev
= NULL
;
4639 grub_fs_t fs
= NULL
;
4644 debug("get fs label for %s\n", args
[0]);
4648 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4652 device_name
= grub_file_get_device_name(args
[0]);
4655 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4659 dev
= grub_device_open(device_name
);
4662 debug("grub_device_open failed, %s\n", device_name
);
4666 fs
= grub_fs_probe(dev
);
4667 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4669 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4673 fs
->fs_label(dev
, &label
);
4676 debug("label=<%s>\n", label
);
4677 ventoy_set_env(args
[1], label
);
4685 check_free(device_name
, grub_free
);
4686 check_free(dev
, grub_device_close
);
4691 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4695 grub_snprintf((char *)data
, 256, "%s", filename
);
4702 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4704 if (info
->dir
&& filename
&& filename
[0] != '.')
4706 grub_snprintf((char *)data
, 256, "%s", filename
);
4713 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4716 char *device_name
= NULL
;
4717 grub_device_t dev
= NULL
;
4718 grub_fs_t fs
= NULL
;
4719 char name
[256] ={0};
4723 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4727 device_name
= grub_file_get_device_name(args
[0]);
4730 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4734 dev
= grub_device_open(device_name
);
4737 debug("grub_device_open failed, %s\n", device_name
);
4741 fs
= grub_fs_probe(dev
);
4744 debug("grub_fs_probe failed, %s\n", device_name
);
4748 fs
->fs_dir(dev
, args
[1], hook
, name
);
4751 ventoy_set_env(args
[2], name
);
4758 check_free(device_name
, grub_free
);
4759 check_free(dev
, grub_device_close
);
4764 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4767 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4770 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4773 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4776 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4786 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4790 for (pos
= args
[0]; *pos
; pos
++)
4804 grub_env_set(args
[1], args
[0]);
4814 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4824 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4829 len
= (int)grub_strlen(buf
);
4830 for (i
= len
; i
> 0; i
--)
4832 if (buf
[i
- 1] == '/')
4834 grub_env_set(args
[1], buf
+ i
);
4839 grub_env_set(args
[1], buf
);
4844 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4846 struct grub_video_mode_info info
;
4853 if (!g_video_mode_list
)
4855 ventoy_enum_video_mode();
4858 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4860 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4864 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4867 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4869 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4870 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4872 VENTOY_CMD_RETURN(0);
4875 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4877 struct grub_video_mode_info info
;
4884 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4886 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4890 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4893 grub_env_set(args
[0], buf
);
4895 VENTOY_CMD_RETURN(0);
4898 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4906 if (!g_video_mode_list
)
4911 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4912 if (id
< g_video_mode_num
)
4914 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4915 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4918 grub_env_set(args
[1], buf
);
4920 VENTOY_CMD_RETURN(0);
4923 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4926 grub_uint32_t loadsector
= 0;
4929 grub_uint32_t boot_catlog
= 0;
4930 grub_uint8_t buf
[512];
4936 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4940 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4943 debug("failed to open %s\n", args
[0]);
4947 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4948 if (boot_catlog
== 0)
4950 debug("No bootcatlog found\n");
4951 grub_file_close(file
);
4955 grub_memset(buf
, 0, sizeof(buf
));
4956 grub_file_seek(file
, boot_catlog
* 2048);
4957 grub_file_read(file
, buf
, sizeof(buf
));
4958 grub_file_close(file
);
4960 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4962 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4964 if (buf
[i
+ 32] == 0x88)
4966 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4967 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4973 if (loadsector
== 0)
4975 debug("No EFI eltorito info found\n");
4979 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4980 grub_env_set(args
[1], value
);
4981 VENTOY_CMD_RETURN(0);
4984 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4989 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4991 if (pfsdir
->initrd
[0])
4996 curpos
= pfsdir
->curpos
;
4997 len
= grub_strlen(filename
);
5001 if ((len
== 1 && filename
[0] == '.') ||
5002 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5007 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5010 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5011 pfsdir
->curpos
= curpos
+ printlen
;
5012 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5013 pfsdir
->curpos
= curpos
;
5014 pfsdir
->fullpath
[curpos
] = 0;
5018 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5021 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5022 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5024 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5026 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5035 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5039 char *device_name
= NULL
;
5040 grub_device_t dev
= NULL
;
5041 grub_fs_t fs
= NULL
;
5042 replace_fs_dir
*pfsdir
= NULL
;
5048 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5052 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5058 device_name
= grub_file_get_device_name(args
[0]);
5064 dev
= grub_device_open(device_name
);
5070 fs
= grub_fs_probe(dev
);
5079 pfsdir
->fullpath
[0] = '/';
5080 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5082 if (pfsdir
->initrd
[0])
5084 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5086 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5088 if (pfsdir
->initrd
[i
] == '/')
5090 pfsdir
->initrd
[i
] = '\\';
5094 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5095 grub_env_set(args
[1], pos
);
5099 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5104 grub_check_free(pfsdir
);
5105 grub_check_free(device_name
);
5106 check_free(dev
, grub_device_close
);
5108 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5111 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5113 const char *pager
= NULL
;
5119 pager
= grub_env_get("pager");
5123 grub_env_set("pager", "1");
5125 else if (pager
[0] == '1')
5131 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5133 grub_env_set("pager", "1");
5136 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5139 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5145 if (g_pager_flag
== 1)
5147 grub_env_unset("pager");
5149 else if (g_pager_flag
== 2)
5151 grub_env_set("pager", g_old_pager
);
5154 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5157 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5159 if (g_json_case_mis_path
[0])
5164 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5166 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5172 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5175 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5177 if (g_json_case_mis_path
[0])
5182 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5184 if (grub_strcasecmp(filename
, "ventoy") == 0)
5186 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5187 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5188 if (g_json_case_mis_path
[0])
5198 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5201 char *device_name
= NULL
;
5202 grub_device_t dev
= NULL
;
5203 grub_fs_t fs
= NULL
;
5204 chk_case_fs_dir fs_dir
;
5210 device_name
= grub_file_get_device_name(args
[0]);
5216 dev
= grub_device_open(device_name
);
5222 fs
= grub_fs_probe(dev
);
5228 fstype
= ventoy_get_fs_type(fs
->name
);
5229 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5234 g_json_case_mis_path
[0] = 0;
5237 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5239 if (g_json_case_mis_path
[0])
5241 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5246 grub_check_free(device_name
);
5247 check_free(dev
, grub_device_close
);
5249 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5252 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5255 grub_partition_t part
;
5256 char priority_str
[3]; /* Maximum value 15 */
5260 if (argc
< 2 || argc
> 3)
5261 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5262 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5264 /* Open the disk if it exists */
5265 disk
= grub_disk_open (args
[0]);
5268 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5272 part
= grub_partition_probe (disk
, args
[1]);
5275 grub_disk_close (disk
);
5276 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5277 "No such partition");
5280 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5282 grub_disk_close (disk
);
5283 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5284 "Not a GPT partition");
5287 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5288 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5292 grub_env_set (args
[2], priority_str
);
5293 grub_env_export (args
[2]);
5297 grub_printf ("Priority is %s\n", priority_str
);
5300 grub_disk_close (disk
);
5301 return GRUB_ERR_NONE
;
5305 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5309 grub_file_t file
= NULL
;
5310 grub_uint32_t loadrba
= 0;
5311 grub_uint32_t boot_catlog
= 0;
5312 grub_uint8_t sector
[512];
5313 boot_info_table
*info
= NULL
;
5318 /* This also trigger a iso9660 fs parse */
5319 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5324 joliet
= grub_iso9660_is_joliet();
5330 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5333 debug("failed to open %s\n", args
[0]);
5337 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5338 if (boot_catlog
== 0)
5340 debug("no bootcatlog found %u\n", boot_catlog
);
5344 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5347 debug("no bios eltorito rba found %u\n", loadrba
);
5351 grub_file_seek(file
, loadrba
* 2048);
5352 grub_file_read(file
, sector
, 512);
5354 info
= (boot_info_table
*)sector
;
5355 if (info
->bi_data0
== 0x7c6ceafa &&
5356 info
->bi_data1
== 0x90900000 &&
5357 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5358 info
->bi_BootFileLocation
== loadrba
)
5360 debug("bootloader is syslinux, %u.\n", loadrba
);
5366 grub_file_close(file
);
5367 grub_errno
= GRUB_ERR_NONE
;
5371 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5374 ventoy_vlnk_part
*node
;
5380 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5382 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5383 ++n
, node
->device
, node
->disksig
,
5384 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5390 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5398 len
= (int)grub_strlen(args
[0]);
5399 if (grub_file_is_vlnk_suffix(args
[0], len
))
5408 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5411 const char *name
= NULL
;
5417 grub_env_unset(args
[1]);
5418 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5421 debug("VLNK SRC: <%s>\n", args
[0]);
5422 debug("VLNK DST: <%s>\n", name
);
5423 grub_env_set(args
[1], name
);
5431 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5435 grub_file_t file
= NULL
;
5446 len
= (int)grub_strlen(args
[0]);
5447 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5449 grub_printf("Invalid vlnk suffix\n");
5453 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5456 grub_printf("Failed to open %s\n", args
[0]);
5460 if (file
->size
!= 32768)
5462 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5466 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5467 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5469 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5474 check_free(file
, grub_file_close
);
5475 grub_errno
= GRUB_ERR_NONE
;
5479 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5485 g_iso_vd_id_publisher
[0] = 0;
5486 g_iso_vd_id_prepare
[0] = 0;
5487 g_iso_vd_id_application
[0] = 0;
5492 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5496 grub_file_t file
= NULL
;
5501 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5504 grub_printf("Failed to open %s\n", args
[0]);
5508 grub_file_seek(file
, 16 * 2048 + offset
);
5509 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5512 grub_file_seek(file
, 16 * 2048 + offset
);
5513 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5516 grub_file_seek(file
, 16 * 2048 + offset
);
5517 grub_file_read(file
, g_iso_vd_id_application
, 128);
5521 check_free(file
, grub_file_close
);
5522 grub_errno
= GRUB_ERR_NONE
;
5526 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5529 char *id
= g_iso_vd_id_publisher
;
5534 if (args
[0][0] == '1')
5536 id
= g_iso_vd_id_prepare
;
5538 else if (args
[0][0] == '2')
5540 id
= g_iso_vd_id_application
;
5543 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5548 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5553 grub_errno
= GRUB_ERR_NONE
;
5557 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5562 g_ventoy_fn_mutex
= 0;
5563 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5565 g_ventoy_fn_mutex
= 1;
5568 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5571 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5573 grub_uint64_t total
;
5574 grub_uint64_t required
;
5580 #ifdef GRUB_MACHINE_EFI
5581 grub_efi_get_reserved_page_num(&total
, &required
);
5582 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
5583 grub_printf("Required pages: %llu\n", (unsigned long long)required
);
5585 grub_printf("Non EFI mode!\n");
5590 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5593 int ventoy_env_init(void)
5597 grub_env_set("vtdebug_flag", "");
5599 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5600 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5601 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5602 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5604 ventoy_filt_register(0, ventoy_wrapper_open
);
5606 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5609 g_grub_param
->grub_env_get
= grub_env_get
;
5610 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5611 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5612 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5613 grub_env_set("env_param", buf
);
5614 grub_env_set("ventoy_env_param", buf
);
5616 grub_env_export("env_param");
5617 grub_env_export("ventoy_env_param");
5620 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5621 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5623 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5624 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5626 grub_env_export("vtoy_winpeshl_ini_addr");
5627 grub_env_export("vtoy_winpeshl_ini_size");
5629 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5630 grub_env_set("vtoy_chain_file_size", buf
);
5631 grub_env_export("vtoy_chain_file_size");
5633 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5634 grub_env_set("vtoy_chain_file_read", buf
);
5635 grub_env_export("vtoy_chain_file_read");
5642 static cmd_para ventoy_cmds
[] =
5644 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
5645 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
5646 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5647 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5648 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5649 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5650 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5651 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5652 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5653 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5654 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5655 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5656 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5657 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5658 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5659 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5660 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5661 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5662 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5663 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5664 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5665 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5666 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5667 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5668 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5669 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5670 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5672 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5673 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5674 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5675 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5676 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5677 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5678 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5680 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5681 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5682 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5683 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5684 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5685 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5686 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5687 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5688 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5689 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5692 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5693 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5694 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5695 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5696 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5697 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5698 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5699 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5700 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5701 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5702 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5704 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5705 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5706 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5707 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5708 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5709 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5710 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5712 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5713 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5714 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5715 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5716 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5717 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5718 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5719 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5720 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5721 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5723 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5724 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5725 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5726 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5727 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5728 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5729 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5730 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5731 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5733 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5734 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5735 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5736 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5739 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5740 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5741 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5743 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5744 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5745 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5748 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5749 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5750 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5751 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5752 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5753 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5754 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
5755 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5756 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
5757 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5758 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5759 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5760 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5761 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5763 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5764 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5765 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5766 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5767 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5768 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5769 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5770 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5771 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5772 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5773 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5774 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5776 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5777 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5778 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5779 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5780 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5781 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5782 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5783 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5784 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
5785 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
5786 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
5787 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
5788 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
5789 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
5790 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
5791 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
5792 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
5793 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
5794 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
5797 int ventoy_register_all_cmd(void)
5800 cmd_para
*cur
= NULL
;
5802 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5804 cur
= ventoy_cmds
+ i
;
5805 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5806 cur
->summary
, cur
->description
, cur
->parser
);
5812 int ventoy_unregister_all_cmd(void)
5816 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5818 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);