1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/random.h>
49 #include <grub/ventoy.h>
50 #include "ventoy_def.h"
53 GRUB_MOD_LICENSE ("GPLv3+");
55 static grub_uint8_t g_check_mbr_data
[] = {
56 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
62 initrd_info
*g_initrd_img_list
= NULL
;
63 initrd_info
*g_initrd_img_tail
= NULL
;
64 int g_initrd_img_count
= 0;
65 int g_valid_initrd_count
= 0;
66 int g_default_menu_mode
= 0;
67 int g_filt_dot_underscore_file
= 0;
68 int g_sort_case_sensitive
= 0;
69 int g_tree_view_menu_style
= 0;
70 static grub_file_t g_old_file
;
71 static int g_ventoy_last_entry_back
;
74 char g_img_swap_tmp_buf
[1024];
75 img_info g_img_swap_tmp
;
76 img_info
*g_ventoy_img_list
= NULL
;
78 int g_ventoy_img_count
= 0;
80 grub_device_t g_enum_dev
= NULL
;
81 grub_fs_t g_enum_fs
= NULL
;
82 int g_img_max_search_level
= -1;
83 img_iterator_node g_img_iterator_head
;
84 img_iterator_node
*g_img_iterator_tail
= NULL
;
86 grub_uint8_t g_ventoy_break_level
= 0;
87 grub_uint8_t g_ventoy_debug_level
= 0;
88 grub_uint8_t g_ventoy_chain_type
= 0;
90 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
91 grub_uint32_t g_ventoy_cpio_size
= 0;
92 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
93 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
95 int g_plugin_image_list
= 0;
97 ventoy_grub_param
*g_grub_param
= NULL
;
99 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
101 ventoy_img_chunk_list g_img_chunk_list
;
103 int g_wimboot_enable
= 0;
104 ventoy_img_chunk_list g_wimiso_chunk_list
;
105 char *g_wimiso_path
= NULL
;
106 grub_uint32_t g_wimiso_size
= 0;
108 int g_vhdboot_enable
= 0;
110 grub_uint64_t g_svd_replace_offset
= 0;
112 int g_conf_replace_count
= 0;
113 grub_uint64_t g_conf_replace_offset
[VTOY_MAX_CONF_REPLACE
] = { 0 };
114 conf_replace
*g_conf_replace_node
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
115 grub_uint8_t
*g_conf_replace_new_buf
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
116 int g_conf_replace_new_len
[VTOY_MAX_CONF_REPLACE
] = { 0 };
117 int g_conf_replace_new_len_align
[VTOY_MAX_CONF_REPLACE
] = { 0 };
119 int g_ventoy_disk_bios_id
= 0;
120 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
121 grub_uint64_t g_ventoy_disk_size
= 0;
122 grub_uint64_t g_ventoy_disk_part_size
[2];
124 char *g_tree_script_buf
= NULL
;
125 int g_tree_script_pos
= 0;
126 int g_tree_script_pre
= 0;
128 static char *g_list_script_buf
= NULL
;
129 static int g_list_script_pos
= 0;
131 static char *g_part_list_buf
= NULL
;
132 static int g_part_list_pos
= 0;
133 static grub_uint64_t g_part_end_max
= 0;
135 static int g_video_mode_max
= 0;
136 static int g_video_mode_num
= 0;
137 static ventoy_video_mode
*g_video_mode_list
= NULL
;
139 static int g_enumerate_time_checked
= 0;
140 static grub_uint64_t g_enumerate_start_time_ms
;
141 static grub_uint64_t g_enumerate_finish_time_ms
;
142 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
144 static char g_iso_vd_id_publisher
[130];
145 static char g_iso_vd_id_prepare
[130];
146 static char g_iso_vd_id_application
[130];
148 static int g_pager_flag
= 0;
149 static char g_old_pager
[32];
151 const char *g_menu_class
[img_type_max
] =
153 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
156 const char *g_menu_prefix
[img_type_max
] =
158 "iso", "wim", "efi", "img", "vhd", "vtoy"
161 static int g_vtoy_secondary_need_recover
= 0;
163 static int g_vtoy_load_prompt
= 0;
164 static char g_vtoy_prompt_msg
[64];
166 static char g_json_case_mis_path
[32];
168 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
170 int ventoy_get_fs_type(const char *fs
)
174 return ventoy_fs_max
;
176 else if (grub_strncmp(fs
, "exfat", 5) == 0)
178 return ventoy_fs_exfat
;
180 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
182 return ventoy_fs_ntfs
;
184 else if (grub_strncmp(fs
, "ext", 3) == 0)
186 return ventoy_fs_ext
;
188 else if (grub_strncmp(fs
, "xfs", 3) == 0)
190 return ventoy_fs_xfs
;
192 else if (grub_strncmp(fs
, "udf", 3) == 0)
194 return ventoy_fs_udf
;
196 else if (grub_strncmp(fs
, "fat", 3) == 0)
198 return ventoy_fs_fat
;
201 return ventoy_fs_max
;
204 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
223 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
225 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
229 static int ventoy_control_get_flag(const char *key
)
231 const char *val
= ventoy_get_env(key
);
233 if (val
&& val
[0] == '1' && val
[1] == 0)
240 static grub_err_t
ventoy_fs_close(grub_file_t file
)
242 grub_file_close(g_old_file
);
243 grub_free(file
->data
);
251 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
257 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
262 for (i
= 0; i
< g_video_mode_num
; i
++)
264 if (g_video_mode_list
[i
].width
== info
->width
&&
265 g_video_mode_list
[i
].height
== info
->height
&&
266 g_video_mode_list
[i
].bpp
== info
->bpp
)
272 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
273 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
274 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
277 if (g_video_mode_num
== g_video_mode_max
)
279 g_video_mode_max
*= 2;
280 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
286 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
288 if (v1
->bpp
== v2
->bpp
)
290 if (v1
->width
== v2
->width
)
292 if (v1
->height
== v2
->height
)
298 return (v1
->height
< v2
->height
) ? -1 : 1;
303 return (v1
->width
< v2
->width
) ? -1 : 1;
308 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
312 static int ventoy_enum_video_mode(void)
315 grub_video_adapter_t adapter
;
316 grub_video_driver_id_t id
;
317 ventoy_video_mode mode
;
319 g_video_mode_num
= 0;
320 g_video_mode_max
= 1024;
321 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
322 if (!g_video_mode_list
)
327 #ifdef GRUB_MACHINE_PCBIOS
328 grub_dl_load ("vbe");
331 id
= grub_video_get_driver_id ();
333 FOR_VIDEO_ADAPTERS (adapter
)
335 if (!adapter
->iterate
||
336 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
337 adapter
->init() != GRUB_ERR_NONE
)))
342 adapter
->iterate(ventoy_video_hook
, NULL
);
344 if (adapter
->id
!= id
)
350 /* sort video mode */
351 for (i
= 0; i
< g_video_mode_num
; i
++)
352 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
354 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
356 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
357 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
358 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
362 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
365 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
369 static struct grub_fs vtoy_fs
=
374 .fs_read
= ventoy_fs_read
,
375 .fs_close
= ventoy_fs_close
,
385 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
391 file
->data
= grub_malloc(rawFile
->size
+ 4096);
397 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
398 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
400 g_old_file
= rawFile
;
402 file
->size
= rawFile
->size
+ len
;
403 file
->device
= rawFile
->device
;
405 file
->not_easily_seekable
= 1;
410 static int ventoy_check_decimal_var(const char *name
, long *value
)
412 const char *value_str
= NULL
;
414 value_str
= grub_env_get(name
);
415 if (NULL
== value_str
)
417 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
420 if (!ventoy_is_decimal(value_str
))
422 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
425 *value
= grub_strtol(value_str
, NULL
, 10);
427 return GRUB_ERR_NONE
;
430 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
432 grub_uint64_t sectors
;
434 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
436 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
440 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
443 return sectors
* 512;
446 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
452 grub_uint32_t offset
;
454 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
457 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
461 len
= (int)file
->size
;
463 data
= (char *)grub_malloc(file
->size
);
469 grub_file_read(file
, data
, file
->size
);
470 grub_file_close(file
);
472 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
473 grub_script_execute_sourcecode(exec
);
475 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
476 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
477 grub_file_close(file
);
479 grub_script_execute_sourcecode("loopback -d efiboot");
483 *direntoff
= offset
+ 2;
488 static int ventoy_set_check_result(int ret
, const char *msg
)
492 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
493 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
494 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
498 grub_printf(VTOY_WARNING
"\n");
499 grub_printf(VTOY_WARNING
"\n");
500 grub_printf(VTOY_WARNING
"\n\n\n");
502 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
503 grub_printf("Error message: <%s>\n\n", msg
);
504 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
506 grub_printf("\n\nWill exit after 10 seconds ...... ");
514 static int ventoy_check_official_device(grub_device_t dev
)
518 grub_uint64_t offset
;
521 grub_uint8_t mbr
[512];
525 struct grub_partition
*partition
;
527 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
529 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
532 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
533 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
534 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
536 #ifndef GRUB_MACHINE_EFI
537 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
539 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
541 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
543 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
545 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
547 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
556 /* We must have partition 2 */
559 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
563 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
567 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
570 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
572 grub_file_close(file
);
573 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
576 partition
= dev
->disk
->partition
;
577 if (partition
->number
!= 0 || partition
->start
!= 2048)
579 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
584 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
586 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
587 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
588 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
590 grub_file_close(file
);
591 return ventoy_set_check_result(6, "Disk partition layout check failed.");
596 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
597 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
598 PartTbl
[1].SectorCount
!= 65536)
600 grub_file_close(file
);
601 return ventoy_set_check_result(6, "Disk partition layout check failed.");
607 offset
= partition
->start
+ partition
->len
;
608 partition
= file
->device
->disk
->partition
;
609 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
611 grub_file_close(file
);
612 return ventoy_set_check_result(7, "Disk partition layout check failed.");
616 grub_file_close(file
);
620 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
621 dev2
= grub_device_open(devname
);
624 return ventoy_set_check_result(8, "Disk open failed");
627 fs
= grub_fs_probe(dev2
);
630 grub_device_close(dev2
);
631 return ventoy_set_check_result(9, "FS probe failed");
634 fs
->fs_label(dev2
, &label
);
635 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
637 grub_device_close(dev2
);
638 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
641 grub_device_close(dev2
);
645 disk
= grub_disk_open(dev
->disk
->name
);
648 return ventoy_set_check_result(11, "Disk open failed");
651 grub_memset(mbr
, 0, 512);
652 grub_disk_read(disk
, 0, 0, 512, mbr
);
653 grub_disk_close(disk
);
655 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
657 return ventoy_set_check_result(12, "MBR check failed");
660 return ventoy_set_check_result(0, NULL
);
663 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
667 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
677 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
679 grub_uint64_t size
= 0;
682 char fullpath
[256] = {0};
685 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
688 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
691 debug("grub_file_open failed <%s>\n", fullpath
);
697 grub_file_close(file
);
701 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
705 char fullpath
[512] = {0};
708 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
711 file
= grub_file_open(fullpath
, type
);
714 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
721 int ventoy_is_dir_exist(const char *fmt
, ...)
728 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
732 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
735 grub_strncpy(pos
+ len
, "\" ]", 3);
737 debug("script exec %s\n", buf
);
739 if (0 == grub_script_execute_sourcecode(buf
))
747 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
750 grub_uint8_t
*outbuf
;
751 grub_uint8_t gzHdr
[10] =
753 0x1F, 0x8B, /* magic */
761 grub_memset(&s
, 0, sizeof(mz_stream
));
763 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
765 outbuf
= (grub_uint8_t
*)mem_out
;
767 mem_out_len
-= sizeof(gzHdr
) + 8;
768 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
769 outbuf
+= sizeof(gzHdr
);
771 s
.avail_in
= mem_in_len
;
774 s
.avail_out
= mem_out_len
;
777 mz_deflate(&s
, MZ_FINISH
);
781 outbuf
+= s
.total_out
;
782 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
783 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
785 return s
.total_out
+ sizeof(gzHdr
) + 8;
793 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
797 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
800 if (0 == grub_strcmp(args
[0], "on"))
803 grub_env_set("vtdebug_flag", "debug");
808 grub_env_set("vtdebug_flag", "");
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
814 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
818 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
820 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
821 grub_printf(" level:\r\n");
822 grub_printf(" 01/11: busybox / (+cat log)\r\n");
823 grub_printf(" 02/12: initrd / (+cat log)\r\n");
824 grub_printf(" 03/13: hook / (+cat log)\r\n");
826 grub_printf(" debug:\r\n");
827 grub_printf(" 0: debug is off\r\n");
828 grub_printf(" 1: debug is on\r\n");
830 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
833 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
835 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
837 g_ventoy_debug_level
= 1;
840 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
843 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
852 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
855 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
887 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
903 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
919 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
924 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
926 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
929 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
934 value_long
+= grub_strtol(args
[1], NULL
, 10);
936 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
937 grub_env_set(args
[0], buf
);
939 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
942 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
944 ulonglong value1
= 0;
945 ulonglong value2
= 0;
950 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
953 value1
= grub_strtoull(args
[0], NULL
, 10);
954 value2
= grub_strtoull(args
[1], NULL
, 10);
956 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
957 grub_env_set(args
[2], buf
);
959 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
962 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
977 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
980 debug("failed to open file <%s> for udf check\n", args
[0]);
984 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
986 grub_env_set(args
[1], buf
);
988 grub_file_close(file
);
994 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1002 g_wimboot_enable
= 0;
1004 grub_check_free(g_wimiso_path
);
1005 grub_check_free(g_wimiso_chunk_list
.chunk
);
1007 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1013 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1014 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1015 if (NULL
== g_wimiso_chunk_list
.chunk
)
1017 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1020 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1021 g_wimiso_chunk_list
.cur_chunk
= 0;
1023 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1025 g_wimboot_enable
= 1;
1026 g_wimiso_path
= grub_strdup(args
[0]);
1027 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1028 grub_file_close(file
);
1033 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1041 ventoy_iso9660_override
*dirent
;
1050 totlen
= sizeof(ventoy_chain_head
);
1052 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1054 debug("failed to load efiboot template %d\n", len
);
1060 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1062 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1065 debug("failed to open file <%s>\n", args
[0]);
1069 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1074 totlen
+= ventoy_align_2k(file
->size
);
1076 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1077 dirent
->first_sector
= len
/ 2048;
1078 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1079 dirent
->size
= (grub_uint32_t
)file
->size
;
1080 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1082 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1084 #ifdef GRUB_MACHINE_EFI
1085 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1087 data
= (char *)grub_malloc(totlen
);
1090 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1092 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1093 grub_check_free(buf
);
1095 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1096 grub_file_close(file
);
1098 ventoy_memfile_env_set(args
[1], data
, (ulonglong
)totlen
);
1103 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1109 g_vtoy_load_prompt
= 0;
1110 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1112 if (argc
== 2 && args
[0][0] == '1')
1114 g_vtoy_load_prompt
= 1;
1115 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1118 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1121 int ventoy_need_prompt_load_file(void)
1123 return g_vtoy_load_prompt
;
1126 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1128 grub_uint64_t ro
= 0;
1129 grub_uint64_t div
= 0;
1130 grub_ssize_t left
= size
;
1131 char *cur
= (char *)buf
;
1133 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1136 while (left
>= VTOY_SIZE_2MB
)
1138 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1139 cur
+= VTOY_SIZE_2MB
;
1140 left
-= VTOY_SIZE_2MB
;
1142 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1147 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1153 grub_file_read(file
, cur
, left
);
1156 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1162 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1167 enum grub_file_type type
;
1178 if (grub_strcmp(args
[0], "nodecompress") == 0)
1180 type
= VENTOY_FILE_TYPE
;
1184 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1187 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1190 debug("failed to open file <%s>\n", args
[1]);
1194 #ifdef GRUB_MACHINE_EFI
1195 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1197 buf
= (char *)grub_malloc(file
->size
);
1202 grub_file_close(file
);
1206 if (g_vtoy_load_prompt
)
1208 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1212 grub_file_read(file
, buf
, file
->size
);
1215 ventoy_memfile_env_set(args
[2], buf
, (ulonglong
)(file
->size
));
1217 grub_file_close(file
);
1223 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1239 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1242 debug("failed to open file <%s> for udf check\n", args
[0]);
1246 headlen
= sizeof(ventoy_chain_head
);
1248 #ifdef GRUB_MACHINE_EFI
1249 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1251 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1254 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1256 grub_file_read(file
, buf
+ headlen
, file
->size
);
1258 ventoy_memfile_env_set(args
[1], buf
, (ulonglong
)(file
->size
));
1260 grub_file_close(file
);
1266 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1272 if (grub_iso9660_is_joliet())
1274 debug("This time has joliet process\n");
1283 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1292 if (args
[0][0] == '1')
1294 grub_iso9660_set_nojoliet(1);
1298 grub_iso9660_set_nojoliet(0);
1304 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1309 grub_uint8_t buf
[32];
1320 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1323 debug("failed to open file <%s> for udf check\n", args
[0]);
1327 for (i
= 16; i
< 32; i
++)
1329 grub_file_seek(file
, i
* 2048);
1330 grub_file_read(file
, buf
, sizeof(buf
));
1338 grub_file_seek(file
, i
* 2048);
1339 grub_file_read(file
, buf
, sizeof(buf
));
1341 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1344 grub_file_seek(file
, i
* 2048);
1345 grub_file_read(file
, buf
, sizeof(buf
));
1347 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1348 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1354 grub_file_close(file
);
1356 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1361 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1363 long value_long1
= 0;
1364 long value_long2
= 0;
1366 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1368 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1371 value_long1
= grub_strtol(args
[0], NULL
, 10);
1372 value_long2
= grub_strtol(args
[2], NULL
, 10);
1374 if (0 == grub_strcmp(args
[1], "eq"))
1376 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1378 else if (0 == grub_strcmp(args
[1], "ne"))
1380 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1382 else if (0 == grub_strcmp(args
[1], "gt"))
1384 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1386 else if (0 == grub_strcmp(args
[1], "lt"))
1388 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1390 else if (0 == grub_strcmp(args
[1], "ge"))
1392 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1394 else if (0 == grub_strcmp(args
[1], "le"))
1396 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1400 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1406 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1409 char buf
[128] = {0};
1413 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1416 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1417 pos
= grub_strstr(buf
, ",");
1423 grub_env_set(args
[1], buf
);
1425 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1428 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1434 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1440 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1443 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1445 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1446 if (0 == grub_script_execute_sourcecode(buf
))
1448 debug("file %s exist, ventoy_compatible YES\n", buf
);
1449 grub_env_set("ventoy_compatible", "YES");
1450 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1454 debug("file %s NOT exist\n", buf
);
1458 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1459 pos
= grub_strstr(buf
, ")");
1465 disk
= grub_disk_open(buf
);
1468 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1469 grub_disk_close(disk
);
1471 g_img_swap_tmp_buf
[703] = 0;
1472 for (i
= 318; i
< 703; i
++)
1474 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1475 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1477 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1478 grub_env_set("ventoy_compatible", "YES");
1479 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1485 debug("failed to open disk <%s>\n", buf
);
1488 grub_env_set("ventoy_compatible", "NO");
1489 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1492 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1498 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1500 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1503 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1508 if (0 == g_sort_case_sensitive
)
1510 if (grub_islower(c1
))
1512 c1
= c1
- 'a' + 'A';
1515 if (grub_islower(c2
))
1517 c2
= c2
- 'a' + 'A';
1530 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1536 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1538 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1541 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1546 if (0 == g_sort_case_sensitive
)
1548 if (grub_islower(c1
))
1550 c1
= c1
- 'a' + 'A';
1553 if (grub_islower(c2
))
1555 c2
= c2
- 'a' + 'A';
1568 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1570 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1572 grub_memcpy(img1
, img2
, sizeof(img_info
));
1573 img1
->next
= g_img_swap_tmp
.next
;
1574 img1
->prev
= g_img_swap_tmp
.prev
;
1576 g_img_swap_tmp
.next
= img2
->next
;
1577 g_img_swap_tmp
.prev
= img2
->prev
;
1578 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1581 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1585 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1593 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1595 ventoy_vlnk_part
*node
= NULL
;
1596 grub_uint32_t SelfSig
;
1597 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1599 /* skip Ventoy partition 1/2 */
1600 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1601 if (partition
->number
< 2 && SelfSig
== *pSig
)
1606 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1609 node
->disksig
= *pSig
;
1610 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1611 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1612 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1614 node
->next
= g_vlnk_part_list
;
1615 g_vlnk_part_list
= node
;
1621 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1628 disk
= grub_disk_open(name
);
1631 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1632 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1633 grub_disk_close(disk
);
1639 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1641 const char *fs
[ventoy_fs_max
+ 1] =
1643 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1648 cur
->dev
= grub_device_open(cur
->device
);
1653 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1659 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1664 char *disk
, *device
;
1665 grub_uint32_t readcrc
, calccrc
;
1666 ventoy_vlnk_part
*cur
;
1667 grub_fs_t fs
= NULL
;
1669 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1673 grub_printf("VLNK invalid guid\n");
1679 readcrc
= vlnk
->crc32
;
1681 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1682 if (readcrc
!= calccrc
)
1686 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1692 if (!g_vlnk_part_list
)
1694 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1697 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1699 if (cur
->disksig
== vlnk
->disk_signature
)
1703 if (cur
->partoffset
== vlnk
->part_offset
)
1706 device
= cur
->device
;
1708 if (cur
->probe
== 0)
1711 ventoy_vlnk_probe_fs(cur
);
1721 struct grub_file file
;
1723 grub_memset(&file
, 0, sizeof(file
));
1724 file
.device
= cur
->dev
;
1725 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1728 cur
->fs
->fs_close(&file
);
1729 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1738 grub_printf("\n==== VLNK Information ====\n"
1739 "Disk Signature: %08x\n"
1740 "Partition Offset: %llu\n"
1741 "File Path: <%s>\n\n",
1742 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1746 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1750 grub_printf("Disk Find: [ NO ]\n");
1755 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1759 grub_printf("Part Find: [ NO ]\n");
1761 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1764 grub_printf("VLNK File: <%s>\n", dst
);
1771 return (1 - filefind
);
1774 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1779 grub_file_t file
= NULL
;
1784 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1786 else if (dir
[0] == '/')
1788 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1792 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1795 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1801 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1802 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1803 grub_file_close(file
);
1805 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1807 rc
= grub_file_add_vlnk(src
, dst
);
1813 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1823 const menu_tip
*tip
;
1824 img_iterator_node
*tmp
;
1825 img_iterator_node
*new_node
;
1826 img_iterator_node
*node
= (img_iterator_node
*)data
;
1828 if (g_enumerate_time_checked
== 0)
1830 g_enumerate_finish_time_ms
= grub_get_time_ms();
1831 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1834 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1836 g_enumerate_time_checked
= 1;
1840 len
= grub_strlen(filename
);
1844 if (node
->level
+ 1 > g_img_max_search_level
)
1849 if ((len
== 1 && filename
[0] == '.') ||
1850 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1855 if (!ventoy_img_name_valid(filename
, len
))
1860 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1865 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1867 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1868 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1871 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1876 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1879 new_node
->level
= node
->level
+ 1;
1880 new_node
->plugin_list_index
= index
;
1881 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1883 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1886 debug("Directory %s ignored...\n", new_node
->dir
);
1887 grub_free(new_node
);
1891 new_node
->tail
= node
->tail
;
1893 new_node
->parent
= node
;
1894 if (!node
->firstchild
)
1896 node
->firstchild
= new_node
;
1899 if (g_img_iterator_tail
)
1901 g_img_iterator_tail
->next
= new_node
;
1902 g_img_iterator_tail
= new_node
;
1906 g_img_iterator_head
.next
= new_node
;
1907 g_img_iterator_tail
= new_node
;
1913 debug("Find a file %s\n", filename
);
1919 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1921 type
= img_type_iso
;
1923 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1925 type
= img_type_wim
;
1927 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1928 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1930 type
= img_type_vhd
;
1932 #ifdef GRUB_MACHINE_EFI
1933 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1935 type
= img_type_efi
;
1938 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1940 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1942 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1943 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1948 type
= img_type_img
;
1950 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1952 type
= img_type_vtoy
;
1954 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1956 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1958 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1959 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1968 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1973 if (g_plugin_image_list
)
1975 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1976 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1977 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1979 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1982 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1984 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1989 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
1991 if (grub_file_is_vlnk_suffix(filename
, len
))
1994 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2001 img
= grub_zalloc(sizeof(img_info
));
2005 img
->plugin_list_index
= index
;
2006 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2008 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2010 img
->size
= info
->size
;
2011 if (vlnk
|| 0 == img
->size
)
2013 if (node
->dir
[0] == '/')
2015 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2019 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2023 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2025 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2030 if (g_ventoy_img_list
)
2032 tail
= *(node
->tail
);
2038 g_ventoy_img_list
= img
;
2041 img
->id
= g_ventoy_img_count
;
2043 if (node
&& NULL
== node
->firstiso
)
2045 node
->firstiso
= img
;
2056 *((img_info
**)(node
->tail
)) = img
;
2057 g_ventoy_img_count
++;
2059 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2061 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2064 img
->tip1
= tip
->tip1
;
2065 img
->tip2
= tip
->tip2
;
2068 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2071 img
->class = g_menu_class
[type
];
2073 img
->menu_prefix
= g_menu_prefix
[type
];
2075 if (img_type_iso
== type
)
2077 if (ventoy_plugin_check_memdisk(img
->path
))
2079 img
->menu_prefix
= "miso";
2083 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2090 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2092 int len
= GRUB_UINT_MAX
;
2093 const char *value
= NULL
;
2094 char name
[32] = {0};
2095 char plat
[32] = {0};
2096 char guidstr
[32] = {0};
2097 ventoy_guid guid
= VENTOY_GUID
;
2098 const char *fmt1
= NULL
;
2099 const char *fmt2
= NULL
;
2100 const char *fmt3
= NULL
;
2101 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2102 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2103 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2104 const char fmtcode
[]={
2105 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2106 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2107 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2108 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2109 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2110 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2113 grub_memset(name
, 0, sizeof(name
));
2114 puint
[0] = grub_swap_bytes32(0x56454e54);
2115 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2116 puint
[2] = grub_swap_bytes32(0x45525349);
2117 puint
[1] = grub_swap_bytes32(0x4f595f56);
2118 value
= ventoy_get_env(name
);
2120 grub_memset(name
, 0, sizeof(name
));
2121 puint
[1] = grub_swap_bytes32(0x5f544f50);
2122 puint
[0] = grub_swap_bytes32(0x56544c45);
2123 fmt1
= ventoy_get_env(name
);
2129 grub_memset(name
, 0, sizeof(name
));
2130 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2131 puint
[0] = grub_swap_bytes32(0x56544c45);
2132 fmt2
= ventoy_get_env(name
);
2134 grub_memset(name
, 0, sizeof(name
));
2135 puint
[1] = grub_swap_bytes32(0x5f434c52);
2136 puint
[0] = grub_swap_bytes32(0x56544c45);
2137 fmt3
= ventoy_get_env(name
);
2139 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2141 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2143 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2144 #pragma GCC diagnostic push
2145 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2146 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2147 fmt1
? fmt1
: fmtdata
,
2148 fmt2
? fmt2
: fmtdata
+ 4,
2149 value
? value
: "", plat
, guidstr
,
2150 fmt3
? fmt3
: fmtdata
+ 6);
2151 #pragma GCC diagnostic pop
2153 grub_memset(name
, 0, sizeof(name
));
2154 puint
[0] = grub_swap_bytes32(0x76746f79);
2155 puint
[2] = grub_swap_bytes32(0x656e7365);
2156 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2157 ventoy_set_env(name
, guidstr
);
2163 ventoy_password_get (char buf
[], unsigned buf_size
)
2165 unsigned i
, cur_len
= 0;
2167 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2171 key
= grub_getkey ();
2172 if (key
== '\n' || key
== '\r')
2175 if (key
== GRUB_TERM_ESC
)
2185 grub_term_restore_pos (pos
);
2186 for (i
= 0; i
< cur_len
; i
++)
2188 grub_term_restore_pos (pos
);
2190 for (i
= 0; i
< cur_len
; i
++)
2197 if (!grub_isprint (key
))
2200 if (cur_len
+ 2 < buf_size
)
2201 buf
[cur_len
++] = key
;
2206 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2212 return (key
!= GRUB_TERM_ESC
);
2215 static int ventoy_get_password(char buf
[], unsigned buf_size
)
2217 const char *env
= NULL
;
2219 env
= grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2220 if (env
&& env
[0] == '0' && env
[1] == 0)
2222 return grub_password_get(buf
, buf_size
);
2226 return ventoy_password_get(buf
, buf_size
);
2230 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2234 grub_uint8_t md5
[16];
2238 grub_memset(input
, 0, sizeof(input
));
2240 grub_printf("Enter password: ");
2243 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2245 ventoy_get_password(input
, 128);
2246 if (grub_strcmp(pwd
->text
, input
) == 0)
2251 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2253 ventoy_get_password(input
, 128);
2254 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2255 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2260 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2262 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2263 ventoy_get_password(input
+ offset
, 128);
2265 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2266 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2272 grub_printf("Invalid password!\n\n");
2279 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2281 img_info
*minimg
= NULL
;
2282 img_info
*img
= (img_info
*)(node
->firstiso
);
2284 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2286 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2301 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2303 img_iterator_node
*Minchild
= NULL
;
2304 img_iterator_node
*child
= node
->firstchild
;
2306 while (child
&& child
->parent
== node
)
2308 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2312 child
= child
->next
;
2317 Minchild
->select
= 1;
2323 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2326 img_info
*img
= NULL
;
2327 const char *dir_class
= NULL
;
2328 const char *dir_alias
= NULL
;
2329 img_iterator_node
*child
= NULL
;
2330 const menu_tip
*tip
= NULL
;
2332 if (node
->isocnt
== 0 || node
->done
== 1)
2337 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2339 offset
= node
->parent
->dirlen
;
2342 if (node
== &g_img_iterator_head
)
2344 if (g_default_menu_mode
== 0)
2346 if (g_tree_view_menu_style
== 0)
2348 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2349 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2350 " echo 'return ...' \n"
2351 "}\n", "<--", ventoy_get_vmenu_title("VTMENU_RET_TO_LISTVIEW"));
2355 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2356 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2357 " echo 'return ...' \n"
2358 "}\n", ventoy_get_vmenu_title("VTMENU_RET_TO_LISTVIEW"));
2362 g_tree_script_pre
= g_tree_script_pos
;
2366 node
->dir
[node
->dirlen
- 1] = 0;
2367 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2370 dir_class
= "vtoydir";
2373 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2375 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2378 if (g_tree_view_menu_style
== 0)
2380 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2381 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2382 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2386 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2387 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2388 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2393 dir_alias
= node
->dir
+ offset
;
2395 if (g_tree_view_menu_style
== 0)
2397 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2398 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2399 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2403 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2404 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2405 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2409 if (g_tree_view_menu_style
== 0)
2411 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2412 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2413 " echo 'return ...' \n"
2414 "}\n", "<--", node
->dir
);
2418 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2419 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2420 " echo 'return ...' \n"
2425 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2427 ventoy_dynamic_tree_menu(child
);
2430 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2432 if (g_tree_view_menu_style
== 0)
2434 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2435 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2438 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2439 img
->unsupport
? "[***********] " : "",
2440 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2442 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2446 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2447 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2450 img
->unsupport
? "[***********] " : "",
2451 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2453 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2457 if (node
!= &g_img_iterator_head
)
2459 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2466 static int ventoy_set_default_menu(void)
2472 const char *strdata
= NULL
;
2473 img_info
*cur
= NULL
;
2474 img_info
*default_node
= NULL
;
2475 const char *default_image
= NULL
;
2477 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2478 if (default_image
&& default_image
[0] == '/')
2480 img_len
= grub_strlen(default_image
);
2482 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2484 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2496 if (0 == g_default_menu_mode
)
2498 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2502 def
= grub_strdup(default_image
);
2508 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2510 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2511 if (strdata
&& strdata
[0] == '/')
2513 pos
= def
+ grub_strlen(strdata
);
2524 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2527 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2531 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2539 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2541 img_info
*next
= NULL
;
2542 img_info
*cur
= g_ventoy_img_list
;
2555 g_ventoy_img_list
= NULL
;
2556 g_ventoy_img_count
= 0;
2558 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2561 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2564 img_info
*cur
= g_ventoy_img_list
;
2568 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2570 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2573 img_id
= grub_strtol(args
[0], NULL
, 10);
2574 if (img_id
>= g_ventoy_img_count
)
2576 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2579 debug("Find image %ld name \n", img_id
);
2581 while (cur
&& img_id
> 0)
2589 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2592 debug("image name is %s\n", cur
->name
);
2594 grub_env_set(args
[1], cur
->name
);
2596 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2599 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2603 img_info
*cur
= g_ventoy_img_list
;
2609 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2612 len
= (int)grub_strlen(args
[0]);
2616 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2625 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2628 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2629 grub_env_set("chosen", id
);
2630 grub_env_export("chosen");
2632 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2635 static char g_fake_vlnk_src
[512];
2636 static char g_fake_vlnk_dst
[512];
2637 static grub_uint64_t g_fake_vlnk_size
;
2638 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2644 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2646 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2647 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2649 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2651 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2654 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2660 g_fake_vlnk_src
[0] = 0;
2661 g_fake_vlnk_dst
[0] = 0;
2662 g_fake_vlnk_size
= 0;
2663 grub_file_vtoy_vlnk(NULL
, NULL
);
2665 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2669 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2674 const char *id
= NULL
;
2675 img_info
*cur
= NULL
;
2679 if (argc
< 1 || argc
> 3)
2681 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2684 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2686 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2687 grub_env_set(args
[0], pos
);
2690 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2691 grub_env_set(args
[1], value
);
2696 for (last
= pos
; *pos
; pos
++)
2703 grub_env_set(args
[2], last
+ 1);
2709 id
= grub_env_get("chosen");
2711 pos
= grub_strstr(id
, "VID_");
2714 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2718 cur
= g_ventoy_img_list
;
2723 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2726 grub_env_set(args
[0], cur
->path
);
2730 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2731 grub_env_set(args
[1], value
);
2736 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2737 grub_env_set(args
[2], cur
->name
);
2741 g_svd_replace_offset
= 0;
2743 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2747 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2751 grub_device_t dev
= NULL
;
2752 img_info
*cur
= NULL
;
2753 img_info
*tail
= NULL
;
2754 img_info
*min
= NULL
;
2755 img_info
*head
= NULL
;
2756 const char *strdata
= NULL
;
2757 char *device_name
= NULL
;
2759 img_iterator_node
*node
= NULL
;
2760 img_iterator_node
*tmp
= NULL
;
2766 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2769 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2771 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2776 g_enumerate_time_checked
= 0;
2777 g_enumerate_start_time_ms
= grub_get_time_ms();
2779 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2780 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2782 g_filt_dot_underscore_file
= 1;
2785 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2786 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2788 g_sort_case_sensitive
= 1;
2791 device_name
= grub_file_get_device_name(args
[0]);
2797 g_enum_dev
= dev
= grub_device_open(device_name
);
2803 g_enum_fs
= fs
= grub_fs_probe(dev
);
2809 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2811 debug("unsupported fs:<%s>\n", fs
->name
);
2812 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2816 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2818 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2819 if (strdata
&& strdata
[0] == '1')
2821 g_default_menu_mode
= 1;
2824 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2826 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2828 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2829 if (strdata
&& strdata
[0] == '/')
2831 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2832 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2834 g_img_iterator_head
.dir
[len
++] = '/';
2836 g_img_iterator_head
.dirlen
= len
;
2840 g_img_iterator_head
.dirlen
= 1;
2841 grub_strcpy(g_img_iterator_head
.dir
, "/");
2844 g_img_iterator_head
.tail
= &tail
;
2846 if (g_img_max_search_level
< 0)
2848 g_img_max_search_level
= GRUB_INT_MAX
;
2849 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2850 if (strdata
&& ventoy_is_decimal(strdata
))
2852 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2856 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2857 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2858 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2859 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2860 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2861 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2863 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2865 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2868 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2869 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2871 g_tree_view_menu_style
= 1;
2874 ventoy_set_default_menu();
2876 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2878 ventoy_dynamic_tree_menu(node
);
2882 node
= g_img_iterator_head
.next
;
2890 /* sort image list by image name */
2891 while (g_ventoy_img_list
)
2893 min
= g_ventoy_img_list
;
2894 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2896 if (ventoy_cmp_img(min
, cur
) > 0)
2904 min
->prev
->next
= min
->next
;
2909 min
->next
->prev
= min
->prev
;
2912 if (min
== g_ventoy_img_list
)
2914 g_ventoy_img_list
= min
->next
;
2932 g_ventoy_img_list
= head
;
2934 if (g_default_menu_mode
== 1)
2936 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2937 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2938 " echo 'return ...' \n"
2939 "}\n", "<--", ventoy_get_vmenu_title("VTMENU_RET_TO_TREEVIEW"));
2942 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2944 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2945 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2948 cur
->unsupport
? "[***********] " : "",
2949 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2951 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2954 g_tree_script_buf
[g_tree_script_pos
] = 0;
2955 g_list_script_buf
[g_list_script_pos
] = 0;
2957 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2958 grub_env_set(args
[1], buf
);
2962 check_free(device_name
, grub_free
);
2963 check_free(dev
, grub_device_close
);
2965 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2968 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2975 device_name
= grub_file_get_device_name(filename
);
2987 pos2
= grub_strstr(pos
, ",");
2990 pos2
= grub_strstr(pos
, ")");
2998 disk
= grub_disk_open(pos
);
3001 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3002 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3003 grub_disk_close(disk
);
3010 grub_free(device_name
);
3014 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3016 eltorito_descriptor desc
;
3018 grub_memset(&desc
, 0, sizeof(desc
));
3019 grub_file_seek(file
, 17 * 2048);
3020 grub_file_read(file
, &desc
, sizeof(desc
));
3022 if (desc
.type
!= 0 || desc
.version
!= 1)
3027 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3028 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3036 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3038 grub_uint8_t buf
[512];
3040 grub_file_seek(file
, sector
* 2048);
3041 grub_file_read(file
, buf
, sizeof(buf
));
3043 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3044 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3046 return *((grub_uint32_t
*)(buf
+ 40));
3052 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3056 grub_uint8_t buf
[512];
3057 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3059 grub_file_seek(file
, sector
* 2048);
3060 grub_file_read(file
, buf
, sizeof(buf
));
3062 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3064 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3068 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3073 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3075 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3077 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3081 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3083 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3088 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3090 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3092 if (buf
[36] == parttype
[i
])
3094 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3100 debug("%s does not contain efi eltorito\n", file
->name
);
3104 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3107 const char *fs
= NULL
;
3108 const char *val
= NULL
;
3109 const char *cdprompt
= NULL
;
3111 grub_uint8_t chksum
= 0;
3114 disk
= file
->device
->disk
;
3115 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3117 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3118 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3119 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3121 pos
= grub_strstr(file
->name
, "/");
3127 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3129 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3131 param
->vtoy_img_size
= file
->size
;
3133 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3134 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3136 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3138 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3139 param
->vtoy_reserved
[4] = 0;
3140 if (g_ventoy_chain_type
== 1) /* Windows */
3142 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3143 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3145 param
->vtoy_reserved
[4] = 1;
3149 fs
= ventoy_get_env("ventoy_fs_probe");
3150 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3152 param
->vtoy_reserved
[3] = 1;
3155 param
->vtoy_reserved
[5] = 0;
3156 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3157 if (val
&& val
[0] == '1' && val
[1] == 0)
3159 param
->vtoy_reserved
[5] = 1;
3162 /* ventoy_disk_signature used for vlnk */
3163 param
->vtoy_reserved
[6] = file
->vlnk
;
3164 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3166 /* calculate checksum */
3167 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3169 chksum
+= *((grub_uint8_t
*)param
+ i
);
3171 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3176 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3178 grub_uint32_t i
= 0;
3179 grub_uint64_t total
= 0;
3180 grub_uint64_t fileblk
= 0;
3181 ventoy_img_chunk
*chunk
= NULL
;
3183 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3185 chunk
= chunklist
->chunk
+ i
;
3187 if (chunk
->disk_start_sector
<= start
)
3189 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3193 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3196 fileblk
= (file
->size
+ 511) / 512;
3198 if (total
!= fileblk
)
3200 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3201 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3203 debug("maybe img file to be processed.\n");
3213 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3217 grub_uint32_t i
= 0;
3218 grub_uint32_t sector
= 0;
3219 grub_uint32_t count
= 0;
3220 grub_off_t size
= 0;
3221 grub_off_t read
= 0;
3223 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3224 if (fs_type
== ventoy_fs_exfat
)
3226 grub_fat_get_file_chunk(start
, file
, chunklist
);
3228 else if (fs_type
== ventoy_fs_ext
)
3230 grub_ext_get_file_chunk(start
, file
, chunklist
);
3234 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3235 file
->read_hook_data
= chunklist
;
3237 for (size
= file
->size
; size
> 0; size
-= read
)
3239 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3240 grub_file_read(file
, NULL
, read
);
3243 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3245 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3246 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3249 if (ventoy_fs_udf
== fs_type
)
3251 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3253 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3254 chunklist
->chunk
[i
].img_start_sector
= sector
;
3255 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3261 len
= (int)grub_strlen(file
->name
);
3262 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3263 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3264 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3265 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3267 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3269 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3279 chunklist
->chunk
[i
].img_start_sector
= sector
;
3280 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3288 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3292 grub_disk_addr_t start
;
3297 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3300 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3303 g_conf_replace_count
= 0;
3304 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3305 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3307 if (g_img_chunk_list
.chunk
)
3309 grub_free(g_img_chunk_list
.chunk
);
3312 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3314 grub_file_close(file
);
3315 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3318 /* get image chunk data */
3319 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3320 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3321 if (NULL
== g_img_chunk_list
.chunk
)
3323 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3326 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3327 g_img_chunk_list
.cur_chunk
= 0;
3329 start
= file
->device
->disk
->partition
->start
;
3331 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3333 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3334 grub_file_close(file
);
3338 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3341 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3342 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3343 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3346 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3350 grub_uint64_t offset
= 0;
3351 grub_uint32_t align
= 0;
3352 grub_file_t file
= NULL
;
3353 conf_replace
*node
= NULL
;
3354 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3355 ventoy_grub_param_file_replace
*replace
= NULL
;
3361 debug("select conf replace argc:%d\n", argc
);
3368 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3371 debug("Conf replace not found for %s\n", args
[1]);
3375 debug("Find %d conf replace for %s\n", n
, args
[1]);
3377 g_conf_replace_count
= n
;
3378 for (i
= 0; i
< n
; i
++)
3382 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3385 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3386 grub_file_close(file
);
3388 else if (node
->img
> 0)
3394 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3398 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3401 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3405 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3407 if (align
> vtoy_max_replace_file_size
)
3409 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3410 grub_file_close(file
);
3414 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3415 grub_file_close(file
);
3416 g_conf_replace_new_len
[i
] = (int)file
->size
;
3417 g_conf_replace_new_len_align
[i
] = align
;
3419 g_conf_replace_node
[i
] = node
;
3420 g_conf_replace_offset
[i
] = offset
+ 2;
3424 replace
= &(g_grub_param
->img_replace
[i
]);
3425 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3426 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3427 replace
->old_name_cnt
++;
3430 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3434 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3437 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3442 const char *ch
= var
;
3449 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3456 debug("Invalid variable letter <%c>\n", *ch
);
3463 debug("Invalid variable length:%d <%s>\n", n
, var
);
3467 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3476 grub_printf("\n=================== Variables Expansion ===================\n\n");
3479 grub_printf("<%s>: ", var
);
3482 while (i
< (len
- 1))
3485 if ((c
== '\n') || (c
== '\r'))
3495 else if (grub_isprint(c
))
3497 if (i
+ 1 < (len
- 1))
3499 grub_printf("%c", c
);
3509 expand
[i
- 1] = ' ';
3510 grub_printf("\r<%s>: %s", var
, expand
);
3513 grub_printf("\r<%s>: %s", var
, expand
);
3525 grub_snprintf(expand
, len
, "$$%s$$", var
);
3531 static int ventoy_auto_install_var_expand(install_template
*node
)
3539 char *newbuf
= NULL
;
3540 char *curline
= NULL
;
3541 char *nextline
= NULL
;
3542 grub_uint8_t
*code
= NULL
;
3544 var_node
*CurNode
= NULL
;
3545 var_node
*pVarList
= NULL
;
3547 code
= (grub_uint8_t
*)node
->filebuf
;
3549 if (node
->filelen
>= VTOY_SIZE_1MB
)
3551 debug("auto install script too long %d\n", node
->filelen
);
3555 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3557 debug("UCS-2 encoding NOT supported\n");
3561 start
= grub_strstr(node
->filebuf
, "$$");
3564 debug("no need to expand variable, no start.\n");
3568 end
= grub_strstr(start
+ 2, "$$");
3571 debug("no need to expand variable, no end.\n");
3575 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3576 newbuf
= grub_malloc(newlen
);
3579 debug("Failed to alloc newbuf %d\n", newlen
);
3583 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3585 nextline
= ventoy_get_line(curline
);
3587 start
= grub_strstr(curline
, "$$");
3590 end
= grub_strstr(start
+ 2, "$$");
3596 VTOY_APPEND_NEWBUF(curline
);
3598 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3600 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3602 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3609 value
[sizeof(value
) - 1] = 0;
3610 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3614 CurNode
= grub_zalloc(sizeof(var_node
));
3617 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3618 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3619 CurNode
->next
= pVarList
;
3625 VTOY_APPEND_NEWBUF(value
);
3627 VTOY_APPEND_NEWBUF(end
+ 2);
3631 VTOY_APPEND_NEWBUF(curline
);
3634 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3636 newbuf
[pos
- 1] = '\n';
3640 newbuf
[pos
++] = '\n';
3644 grub_free(node
->filebuf
);
3645 node
->filebuf
= newbuf
;
3646 node
->filelen
= pos
;
3650 CurNode
= pVarList
->next
;
3651 grub_free(pVarList
);
3658 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3664 grub_file_t file
= NULL
;
3665 char configfile
[128];
3666 install_template
*node
= NULL
;
3672 debug("select auto installation argc:%d\n", argc
);
3679 node
= ventoy_plugin_find_install_template(args
[0]);
3682 debug("Auto install template not found for %s\n", args
[0]);
3686 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3688 defidx
= node
->autosel
;
3689 if (node
->timeout
< 0)
3691 node
->cursel
= node
->autosel
- 1;
3692 debug("Auto install template auto select %d\n", node
->autosel
);
3697 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3703 if (node
->timeout
> 0)
3705 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3708 vtoy_ssprintf(buf
, pos
, "menuentry \"@VTMENU_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3709 " echo %s\n}\n", "");
3711 for (i
= 0; i
< node
->templatenum
; i
++)
3713 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3715 ventoy_get_vmenu_title("VTMENU_AUTOINS_USE"),
3716 node
->templatepath
[i
].path
);
3719 g_ventoy_menu_esc
= 1;
3720 g_ventoy_suppress_esc
= 1;
3721 g_ventoy_suppress_esc_default
= defidx
;
3723 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3724 grub_script_execute_sourcecode(configfile
);
3726 g_ventoy_menu_esc
= 0;
3727 g_ventoy_suppress_esc
= 0;
3728 g_ventoy_suppress_esc_default
= 1;
3732 node
->cursel
= g_ventoy_last_entry
- 1;
3735 grub_check_free(node
->filebuf
);
3738 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3740 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3741 node
->templatepath
[node
->cursel
].path
);
3744 node
->filebuf
= grub_malloc(file
->size
+ 8);
3747 grub_file_read(file
, node
->filebuf
, file
->size
);
3748 grub_file_close(file
);
3750 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3751 node
->filelen
= (int)file
->size
;
3753 ventoy_auto_install_var_expand(node
);
3758 debug("Failed to open auto install script <%s%s>\n",
3759 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3763 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3766 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3772 char configfile
[128];
3773 persistence_config
*node
;
3779 debug("select persistence argc:%d\n", argc
);
3786 node
= ventoy_plugin_find_persistent(args
[0]);
3789 debug("Persistence image not found for %s\n", args
[0]);
3793 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3795 defidx
= node
->autosel
;
3796 if (node
->timeout
< 0)
3798 node
->cursel
= node
->autosel
- 1;
3799 debug("Persistence image auto select %d\n", node
->autosel
);
3804 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3810 if (node
->timeout
> 0)
3812 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3815 vtoy_ssprintf(buf
, pos
, "menuentry \"@VTMENU_NO_PERSISTENCE\" --class=\"sel_persistence\" {\n"
3816 " echo %s\n}\n", "");
3818 for (i
= 0; i
< node
->backendnum
; i
++)
3820 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3822 ventoy_get_vmenu_title("VTMENU_PERSIST_USE"),
3823 node
->backendpath
[i
].path
);
3827 g_ventoy_menu_esc
= 1;
3828 g_ventoy_suppress_esc
= 1;
3829 g_ventoy_suppress_esc_default
= defidx
;
3831 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3832 grub_script_execute_sourcecode(configfile
);
3834 g_ventoy_menu_esc
= 0;
3835 g_ventoy_suppress_esc
= 0;
3836 g_ventoy_suppress_esc_default
= 1;
3840 node
->cursel
= g_ventoy_last_entry
- 1;
3842 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3845 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3848 ventoy_img_chunk
*cur
;
3854 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3856 cur
= g_img_chunk_list
.chunk
+ i
;
3857 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3858 cur
->img_start_sector
, cur
->img_end_sector
,
3859 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3863 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3866 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3870 ventoy_img_chunk_list chunklist
;
3875 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3878 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3881 /* get image chunk data */
3882 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3883 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3884 if (NULL
== chunklist
.chunk
)
3886 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3889 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3890 chunklist
.cur_chunk
= 0;
3892 ventoy_get_block_list(file
, &chunklist
, 0);
3894 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3896 grub_printf("########## UNSUPPORTED ###############\n");
3899 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3901 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3903 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3904 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3907 grub_printf("\n==================================\n");
3909 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3911 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3912 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3913 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3914 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3915 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3919 grub_free(chunklist
.chunk
);
3920 grub_file_close(file
);
3922 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3925 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3928 ventoy_grub_param_file_replace
*replace
= NULL
;
3936 replace
= &(g_grub_param
->file_replace
);
3937 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3939 replace
->old_name_cnt
= 0;
3940 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3942 replace
->old_name_cnt
++;
3943 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3946 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3949 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3952 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3955 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3961 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3962 grub_env_set(args
[0], buf
);
3965 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3968 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3976 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3977 grub_printf("%s", g_list_script_buf
);
3981 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3982 grub_printf("%s", g_tree_script_buf
);
3988 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3990 img_info
*cur
= g_ventoy_img_list
;
3998 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3999 grub_printf("name:<%s>\n\n", cur
->name
);
4006 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4012 ventoy_plugin_dump_injection();
4017 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4023 ventoy_plugin_dump_auto_install();
4028 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4034 ventoy_plugin_dump_persistence();
4039 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4045 len1
= (int)grub_strlen(filename
);
4046 len2
= (int)grub_strlen(suffix
);
4053 for (i
= len1
- 1; i
>= 0; i
--)
4055 if (filename
[i
] == '.')
4066 if (filename
[i
- len2
- 1] != '_')
4071 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4079 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4085 if (argc
!= 1 && argc
!= 2)
4090 if (args
[0][0] == '0')
4092 if (g_ventoy_memdisk_mode
)
4097 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4104 else if (args
[0][0] == '1')
4106 return g_ventoy_iso_raw
? 0 : 1;
4108 else if (args
[0][0] == '2')
4110 return g_ventoy_iso_uefi_drv
? 0 : 1;
4112 else if (args
[0][0] == '3')
4114 if (g_ventoy_grub2_mode
)
4119 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4126 else if (args
[0][0] == '4')
4128 if (g_ventoy_wimboot_mode
)
4133 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4144 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4146 static int configfile_mode
= 0;
4147 char memfile
[128] = {0};
4154 * args[0]: 0:normal 1:configfile
4155 * args[1]: 0:list_buf 1:tree_buf
4160 debug("Invalid argc %d\n", argc
);
4166 if (args
[0][0] == '0')
4168 if (args
[1][0] == '0')
4170 grub_script_execute_sourcecode(g_list_script_buf
);
4174 grub_script_execute_sourcecode(g_tree_script_buf
);
4179 if (configfile_mode
)
4181 debug("Now already in F3 mode %d\n", configfile_mode
);
4185 if (args
[1][0] == '0')
4187 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4188 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4192 g_ventoy_last_entry
= -1;
4193 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4194 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4197 configfile_mode
= 1;
4198 grub_script_execute_sourcecode(memfile
);
4199 configfile_mode
= 0;
4205 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4216 g_ventoy_case_insensitive
= 1;
4217 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4218 g_ventoy_case_insensitive
= 0;
4224 grub_file_close(file
);
4230 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4235 const char *isopath
= NULL
;
4237 ventoy_mbr_head mbr
;
4244 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4247 isopath
= grub_env_get("vtoy_iso_part");
4250 debug("isopath is null %p\n", isopath
);
4254 debug("isopath is %s\n", isopath
);
4256 for (id
= 0; id
< 30 && (find
== 0); id
++)
4258 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4259 if (grub_strstr(isopath
, hdname
))
4261 debug("skip %s ...\n", hdname
);
4265 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4267 disk
= grub_disk_open(hdname
);
4270 debug("%s not exist\n", hdname
);
4274 grub_memset(&mbr
, 0, sizeof(mbr
));
4275 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4277 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4279 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4280 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4283 grub_env_set(args
[0], hdname
);
4287 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4291 debug("read %s failed\n", hdname
);
4294 grub_disk_close(disk
);
4300 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4311 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4314 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4317 debug("failed to open file %s\n", args
[0]);
4321 buf
= grub_malloc(len
);
4328 grub_file_read(file
, buf
, len
- 1);
4330 ventoy_get_line(buf
);
4331 ventoy_set_env(args
[1], buf
);
4335 grub_check_free(buf
);
4336 grub_file_close(file
);
4341 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4343 grub_uint64_t end_max
= 0;
4344 int *pCnt
= (int *)data
;
4349 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4350 "0 %llu linear /dev/ventoy %llu\n",
4351 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4353 end_max
= (partition
->len
+ partition
->start
) * 512;
4354 if (end_max
> g_part_end_max
)
4356 g_part_end_max
= end_max
;
4362 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4365 char *device_name
= NULL
;
4366 grub_device_t dev
= NULL
;
4371 g_part_list_pos
= 0;
4373 grub_env_unset("vtoy_img_part_file");
4380 device_name
= grub_file_get_device_name(args
[0]);
4383 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4387 dev
= grub_device_open(device_name
);
4390 debug("grub_device_open failed, %s\n", device_name
);
4394 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4396 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4397 grub_env_set("vtoy_img_part_file", buf
);
4399 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4400 grub_env_set("vtoy_img_part_cnt", buf
);
4402 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4403 grub_env_set("vtoy_img_max_part_end", buf
);
4407 check_free(device_name
, grub_free
);
4408 check_free(dev
, grub_device_close
);
4414 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4425 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4428 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4431 debug("failed to open file %s\n", args
[0]);
4435 buf
= grub_malloc(file
->size
+ 1);
4441 buf
[file
->size
] = 0;
4442 grub_file_read(file
, buf
, file
->size
);
4444 if (grub_strstr(buf
, args
[1]))
4451 grub_check_free(buf
);
4452 grub_file_close(file
);
4457 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4463 ventoy_iso9660_vd pvd
;
4470 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4473 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4476 debug("failed to open file %s\n", args
[0]);
4480 grub_file_seek(file
, 16 * 2048);
4481 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4482 if (len
!= sizeof(pvd
))
4484 debug("failed to read pvd %d\n", len
);
4488 grub_memset(buf
, 0, sizeof(buf
));
4489 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4490 ventoy_set_env(args
[1], buf
);
4492 grub_memset(buf
, 0, sizeof(buf
));
4493 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4494 ventoy_set_env(args
[2], buf
);
4498 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4499 ventoy_set_env(args
[3], buf
);
4502 grub_file_close(file
);
4507 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4518 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4521 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4524 debug("failed to open file %s\n", args
[0]);
4528 grub_memset(buf
, 0, sizeof(buf
));
4529 grub_file_seek(file
, 16 * 2048 + 813);
4530 len
= (int)grub_file_read(file
, buf
, 17);
4533 debug("failed to read create date %d\n", len
);
4537 ventoy_set_env(args
[1], buf
);
4540 grub_file_close(file
);
4545 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4551 ventoy_env_hook_root(1);
4556 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4562 ventoy_env_hook_root(0);
4567 #ifdef GRUB_MACHINE_EFI
4568 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4573 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4579 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4580 if (var
&& *var
== 1)
4588 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4597 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4602 grub_uint64_t FileSectors
= 0;
4603 ventoy_gpt_info
*gpt
= NULL
;
4604 ventoy_part_table
*pt
= NULL
;
4605 grub_uint8_t zeroguid
[16] = {0};
4610 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4613 debug("failed to open file %s\n", args
[0]);
4617 if (file
->size
% 512)
4619 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4623 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4629 FileSectors
= file
->size
/ 512;
4631 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4632 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4634 debug("This is EFI partition table\n");
4636 for (i
= 0; i
< 128; i
++)
4638 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4640 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4642 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4643 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4651 debug("This is MBR partition table\n");
4653 for (i
= 0; i
< 4; i
++)
4655 pt
= gpt
->MBR
.PartTbl
+ i
;
4656 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4658 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4659 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4660 (ulonglong
)FileSectors
);
4669 grub_file_close(file
);
4670 grub_check_free(gpt
);
4671 grub_errno
= GRUB_ERR_NONE
;
4675 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4684 for (i
= 0; i
< 500; i
++)
4686 ret
= grub_getkey_noblock();
4687 if (ret
== GRUB_TERM_NO_KEY
)
4696 grub_printf("\n\n Still have key input after clear.\n");
4704 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4711 int image_sector_size
;
4713 ventoy_chain_head
*chain
;
4714 ventoy_img_chunk
*chunk
;
4715 ventoy_os_param
*osparam
;
4716 ventoy_image_location
*location
;
4717 ventoy_image_disk_region
*region
;
4718 struct grub_acpi_table_header
*acpi
;
4727 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4729 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4735 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4737 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4739 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4743 img_chunk_num
= chain
->img_chunk_num
;
4745 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4746 datalen
= sizeof(ventoy_os_param
) + loclen
;
4748 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4749 acpi
= grub_zalloc(buflen
);
4755 /* Step1: Fill acpi table header */
4756 grub_memcpy(acpi
->signature
, "VTOY", 4);
4757 acpi
->length
= buflen
;
4759 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4760 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4762 acpi
->creator_id
[0] = 1;
4763 acpi
->creator_rev
= 1;
4765 /* Step2: Fill data */
4766 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4767 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4768 osparam
->vtoy_img_location_addr
= 0;
4769 osparam
->vtoy_img_location_len
= loclen
;
4770 osparam
->chksum
= 0;
4771 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4773 location
= (ventoy_image_location
*)(osparam
+ 1);
4774 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4775 location
->image_sector_size
= image_sector_size
;
4776 location
->disk_sector_size
= chain
->disk_sector_size
;
4777 location
->region_count
= img_chunk_num
;
4779 region
= location
->regions
;
4780 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4781 if (512 == image_sector_size
)
4783 for (i
= 0; i
< img_chunk_num
; i
++)
4785 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4786 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4787 region
->disk_start_sector
= chunk
->disk_start_sector
;
4794 for (i
= 0; i
< img_chunk_num
; i
++)
4796 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4797 region
->image_start_sector
= chunk
->img_start_sector
;
4798 region
->disk_start_sector
= chunk
->disk_start_sector
;
4804 /* Step3: Fill acpi checksum */
4806 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4808 /* load acpi table */
4809 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4810 grub_script_execute_sourcecode(cmd
);
4814 VENTOY_CMD_RETURN(0);
4817 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4823 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4824 g_ventoy_last_entry
= -1;
4829 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4835 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4840 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4842 const char *pos
= filename
+ 1;
4850 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4852 grub_strncpy((char *)data
, filename
, 128);
4863 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4866 char *device_name
= NULL
;
4867 grub_device_t dev
= NULL
;
4868 grub_fs_t fs
= NULL
;
4869 char buf
[128] = {0};
4875 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4879 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4881 device_name
= grub_file_get_device_name(args
[0]);
4884 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4888 dev
= grub_device_open(device_name
);
4891 debug("grub_device_open failed, %s\n", device_name
);
4895 fs
= grub_fs_probe(dev
);
4898 debug("grub_fs_probe failed, %s\n", device_name
);
4902 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4906 ventoy_set_env(args
[2], buf
);
4913 check_free(device_name
, grub_free
);
4914 check_free(dev
, grub_device_close
);
4919 int ventoy_load_part_table(const char *diskname
)
4926 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4927 if (!g_ventoy_part_info
)
4932 disk
= grub_disk_open(diskname
);
4935 debug("Failed to open disk %s\n", diskname
);
4939 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4941 g_ventoy_disk_bios_id
= disk
->id
;
4943 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4944 grub_disk_close(disk
);
4946 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4947 dev
= grub_device_open(name
);
4950 /* Check for official Ventoy device */
4951 ret
= ventoy_check_official_device(dev
);
4952 grub_device_close(dev
);
4960 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4961 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4966 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4973 ret
= ventoy_load_part_table(args
[0]);
4979 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4980 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4985 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4988 const char *vcfg
= NULL
;
4993 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4996 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4997 grub_env_set(args
[1], vcfg
);
5002 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5010 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5013 grub_uint8_t zeroguid
[16] = {0};
5018 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5021 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5023 if (id
>= 1 && id
<= 128)
5025 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5033 if (id
>= 1 && id
<= 4)
5035 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5045 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5048 char *device_name
= NULL
;
5049 grub_device_t dev
= NULL
;
5050 grub_fs_t fs
= NULL
;
5055 debug("get fs label for %s\n", args
[0]);
5059 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5063 device_name
= grub_file_get_device_name(args
[0]);
5066 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5070 dev
= grub_device_open(device_name
);
5073 debug("grub_device_open failed, %s\n", device_name
);
5077 fs
= grub_fs_probe(dev
);
5078 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5080 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5084 fs
->fs_label(dev
, &label
);
5087 debug("label=<%s>\n", label
);
5088 ventoy_set_env(args
[1], label
);
5096 check_free(device_name
, grub_free
);
5097 check_free(dev
, grub_device_close
);
5102 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5106 grub_snprintf((char *)data
, 256, "%s", filename
);
5113 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5115 if (info
->dir
&& filename
&& filename
[0] != '.')
5117 grub_snprintf((char *)data
, 256, "%s", filename
);
5124 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5127 char *device_name
= NULL
;
5128 grub_device_t dev
= NULL
;
5129 grub_fs_t fs
= NULL
;
5130 char name
[256] ={0};
5134 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5138 device_name
= grub_file_get_device_name(args
[0]);
5141 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5145 dev
= grub_device_open(device_name
);
5148 debug("grub_device_open failed, %s\n", device_name
);
5152 fs
= grub_fs_probe(dev
);
5155 debug("grub_fs_probe failed, %s\n", device_name
);
5159 fs
->fs_dir(dev
, args
[1], hook
, name
);
5162 ventoy_set_env(args
[2], name
);
5169 check_free(device_name
, grub_free
);
5170 check_free(dev
, grub_device_close
);
5175 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5178 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5181 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5184 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5187 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5197 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5201 for (pos
= args
[0]; *pos
; pos
++)
5215 grub_env_set(args
[1], args
[0]);
5225 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5235 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5240 len
= (int)grub_strlen(buf
);
5241 for (i
= len
; i
> 0; i
--)
5243 if (buf
[i
- 1] == '/')
5245 grub_env_set(args
[1], buf
+ i
);
5250 grub_env_set(args
[1], buf
);
5255 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5257 struct grub_video_mode_info info
;
5264 if (!g_video_mode_list
)
5266 ventoy_enum_video_mode();
5269 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5271 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5275 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5278 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5280 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5281 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5283 VENTOY_CMD_RETURN(0);
5286 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5288 struct grub_video_mode_info info
;
5295 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5297 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5301 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5304 grub_env_set(args
[0], buf
);
5306 VENTOY_CMD_RETURN(0);
5309 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5317 if (!g_video_mode_list
)
5322 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5323 if (id
< g_video_mode_num
)
5325 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5326 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5329 grub_env_set(args
[1], buf
);
5331 VENTOY_CMD_RETURN(0);
5334 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5337 grub_uint32_t loadsector
= 0;
5340 grub_uint32_t boot_catlog
= 0;
5341 grub_uint8_t buf
[512];
5347 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5351 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5354 debug("failed to open %s\n", args
[0]);
5358 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5359 if (boot_catlog
== 0)
5361 debug("No bootcatlog found\n");
5362 grub_file_close(file
);
5366 grub_memset(buf
, 0, sizeof(buf
));
5367 grub_file_seek(file
, boot_catlog
* 2048);
5368 grub_file_read(file
, buf
, sizeof(buf
));
5369 grub_file_close(file
);
5371 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5373 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5375 if (buf
[i
+ 32] == 0x88)
5377 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5378 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5384 if (loadsector
== 0)
5386 debug("No EFI eltorito info found\n");
5390 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5391 grub_env_set(args
[1], value
);
5392 VENTOY_CMD_RETURN(0);
5395 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5400 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5402 if (pfsdir
->initrd
[0])
5407 curpos
= pfsdir
->curpos
;
5408 len
= grub_strlen(filename
);
5412 if ((len
== 1 && filename
[0] == '.') ||
5413 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5418 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5421 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5422 pfsdir
->curpos
= curpos
+ printlen
;
5423 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5424 pfsdir
->curpos
= curpos
;
5425 pfsdir
->fullpath
[curpos
] = 0;
5429 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5432 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5433 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5435 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5437 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5446 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5450 char *device_name
= NULL
;
5451 grub_device_t dev
= NULL
;
5452 grub_fs_t fs
= NULL
;
5453 replace_fs_dir
*pfsdir
= NULL
;
5459 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5463 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5469 device_name
= grub_file_get_device_name(args
[0]);
5475 dev
= grub_device_open(device_name
);
5481 fs
= grub_fs_probe(dev
);
5490 pfsdir
->fullpath
[0] = '/';
5491 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5493 if (pfsdir
->initrd
[0])
5495 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5497 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5499 if (pfsdir
->initrd
[i
] == '/')
5501 pfsdir
->initrd
[i
] = '\\';
5505 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5506 grub_env_set(args
[1], pos
);
5510 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5515 grub_check_free(pfsdir
);
5516 grub_check_free(device_name
);
5517 check_free(dev
, grub_device_close
);
5519 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5522 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5524 const char *pager
= NULL
;
5530 pager
= grub_env_get("pager");
5534 grub_env_set("pager", "1");
5536 else if (pager
[0] == '1')
5542 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5544 grub_env_set("pager", "1");
5547 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5550 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5556 if (g_pager_flag
== 1)
5558 grub_env_unset("pager");
5560 else if (g_pager_flag
== 2)
5562 grub_env_set("pager", g_old_pager
);
5565 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5568 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5570 if (g_json_case_mis_path
[0])
5575 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5577 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5583 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5586 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5588 if (g_json_case_mis_path
[0])
5593 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5595 if (grub_strcasecmp(filename
, "ventoy") == 0)
5597 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5598 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5599 if (g_json_case_mis_path
[0])
5609 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5612 char *device_name
= NULL
;
5613 grub_device_t dev
= NULL
;
5614 grub_fs_t fs
= NULL
;
5615 chk_case_fs_dir fs_dir
;
5621 device_name
= grub_file_get_device_name(args
[0]);
5627 dev
= grub_device_open(device_name
);
5633 fs
= grub_fs_probe(dev
);
5639 fstype
= ventoy_get_fs_type(fs
->name
);
5640 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5645 g_json_case_mis_path
[0] = 0;
5648 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5650 if (g_json_case_mis_path
[0])
5652 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5657 grub_check_free(device_name
);
5658 check_free(dev
, grub_device_close
);
5660 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5663 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5666 grub_partition_t part
;
5667 char priority_str
[3]; /* Maximum value 15 */
5671 if (argc
< 2 || argc
> 3)
5672 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5673 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5675 /* Open the disk if it exists */
5676 disk
= grub_disk_open (args
[0]);
5679 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5683 part
= grub_partition_probe (disk
, args
[1]);
5686 grub_disk_close (disk
);
5687 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5688 "No such partition");
5691 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5693 grub_disk_close (disk
);
5694 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5695 "Not a GPT partition");
5698 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5699 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5703 grub_env_set (args
[2], priority_str
);
5704 grub_env_export (args
[2]);
5708 grub_printf ("Priority is %s\n", priority_str
);
5711 grub_disk_close (disk
);
5712 return GRUB_ERR_NONE
;
5716 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5720 grub_file_t file
= NULL
;
5721 grub_uint32_t loadrba
= 0;
5722 grub_uint32_t boot_catlog
= 0;
5723 grub_uint8_t sector
[512];
5724 boot_info_table
*info
= NULL
;
5729 /* This also trigger a iso9660 fs parse */
5730 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5735 joliet
= grub_iso9660_is_joliet();
5741 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5744 debug("failed to open %s\n", args
[0]);
5748 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5749 if (boot_catlog
== 0)
5751 debug("no bootcatlog found %u\n", boot_catlog
);
5755 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5758 debug("no bios eltorito rba found %u\n", loadrba
);
5762 grub_file_seek(file
, loadrba
* 2048);
5763 grub_file_read(file
, sector
, 512);
5765 info
= (boot_info_table
*)sector
;
5766 if (info
->bi_data0
== 0x7c6ceafa &&
5767 info
->bi_data1
== 0x90900000 &&
5768 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5769 info
->bi_BootFileLocation
== loadrba
)
5771 debug("bootloader is syslinux, %u.\n", loadrba
);
5777 grub_file_close(file
);
5778 grub_errno
= GRUB_ERR_NONE
;
5782 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5785 ventoy_vlnk_part
*node
;
5791 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5793 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5794 ++n
, node
->device
, node
->disksig
,
5795 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5801 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5809 len
= (int)grub_strlen(args
[0]);
5810 if (grub_file_is_vlnk_suffix(args
[0], len
))
5819 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5822 const char *name
= NULL
;
5828 grub_env_unset(args
[1]);
5829 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5832 debug("VLNK SRC: <%s>\n", args
[0]);
5833 debug("VLNK DST: <%s>\n", name
);
5834 grub_env_set(args
[1], name
);
5842 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5846 grub_file_t file
= NULL
;
5857 len
= (int)grub_strlen(args
[0]);
5858 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5860 grub_printf("Invalid vlnk suffix\n");
5864 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5867 grub_printf("Failed to open %s\n", args
[0]);
5871 if (file
->size
!= 32768)
5873 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5877 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5878 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5880 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5885 check_free(file
, grub_file_close
);
5886 grub_errno
= GRUB_ERR_NONE
;
5890 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5896 g_iso_vd_id_publisher
[0] = 0;
5897 g_iso_vd_id_prepare
[0] = 0;
5898 g_iso_vd_id_application
[0] = 0;
5903 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5907 grub_file_t file
= NULL
;
5912 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5915 grub_printf("Failed to open %s\n", args
[0]);
5919 grub_file_seek(file
, 16 * 2048 + offset
);
5920 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5923 grub_file_seek(file
, 16 * 2048 + offset
);
5924 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5927 grub_file_seek(file
, 16 * 2048 + offset
);
5928 grub_file_read(file
, g_iso_vd_id_application
, 128);
5932 check_free(file
, grub_file_close
);
5933 grub_errno
= GRUB_ERR_NONE
;
5937 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5940 char *id
= g_iso_vd_id_publisher
;
5945 if (args
[0][0] == '1')
5947 id
= g_iso_vd_id_prepare
;
5949 else if (args
[0][0] == '2')
5951 id
= g_iso_vd_id_application
;
5954 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5959 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5964 grub_errno
= GRUB_ERR_NONE
;
5968 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5973 g_ventoy_fn_mutex
= 0;
5974 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5976 g_ventoy_fn_mutex
= 1;
5979 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5982 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5984 grub_uint64_t total
;
5985 grub_uint64_t org_required
;
5986 grub_uint64_t new_required
;
5992 #ifdef GRUB_MACHINE_EFI
5993 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
5994 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
5995 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
5996 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6001 grub_printf("Non EFI mode!\n");
6006 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6009 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6011 const char *env
= NULL
;
6016 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6021 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6022 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6023 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6024 ventoy_check_mode_by_name(args
[0], "vtnormal")
6030 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6031 if (env
&& env
[0] == '0' && env
[1] == 0)
6039 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6047 const char *env
= NULL
;
6048 ulonglong fsize
= 0;
6050 int seldata
[16] = {0};
6055 len
= 8 * VTOY_SIZE_1KB
;
6056 cmd
= (char *)grub_malloc(len
);
6062 g_vtoy_secondary_need_recover
= 0;
6063 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6065 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6068 timeout
= (int)grub_strtol(env
, NULL
, 10);
6073 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6076 fsize
= grub_strtoull(args
[2], NULL
, 10);
6078 vtoy_dummy_menuentry(cmd
, pos
, len
, "@VTMENU_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6080 if (grub_strcmp(args
[1], "Unix") != 0)
6082 if (grub_strcmp(args
[1], "Windows") == 0)
6084 vtoy_dummy_menuentry(cmd
, pos
, len
, "@VTMENU_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6088 vtoy_dummy_menuentry(cmd
, pos
, len
, "@VTMENU_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6091 if (fsize
<= VTOY_SIZE_1GB
)
6093 vtoy_dummy_menuentry(cmd
, pos
, len
, "@VTMENU_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6097 vtoy_dummy_menuentry(cmd
, pos
, len
, "@VTMENU_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6100 g_ventoy_menu_esc
= 1;
6101 g_ventoy_suppress_esc
= 1;
6102 g_ventoy_suppress_esc_default
= 0;
6103 g_ventoy_secondary_menu_on
= 1;
6104 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6105 grub_script_execute_sourcecode(cfgfile
);
6106 g_ventoy_menu_esc
= 0;
6107 g_ventoy_suppress_esc
= 0;
6108 g_ventoy_suppress_esc_default
= 1;
6109 g_ventoy_secondary_menu_on
= 0;
6111 select
= seldata
[g_ventoy_last_entry
];
6115 g_ventoy_wimboot_mode
= 1;
6116 g_vtoy_secondary_need_recover
= 1;
6118 else if (select
== 3)
6120 g_ventoy_grub2_mode
= 1;
6121 g_vtoy_secondary_need_recover
= 2;
6123 else if (select
== 4)
6125 g_ventoy_memdisk_mode
= 1;
6126 g_vtoy_secondary_need_recover
= 3;
6128 else if (select
== 5)
6130 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6131 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6133 }while (select
== 5);
6139 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6145 if (g_vtoy_secondary_need_recover
== 1)
6147 g_ventoy_wimboot_mode
= 0;
6149 else if (g_vtoy_secondary_need_recover
== 2)
6151 g_ventoy_grub2_mode
= 0;
6153 else if (g_vtoy_secondary_need_recover
== 3)
6155 g_ventoy_memdisk_mode
= 0;
6158 g_vtoy_secondary_need_recover
= 0;
6160 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6163 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6168 if (args
[0][0] == '0')
6170 g_ventoy_case_insensitive
= 0;
6174 g_ventoy_case_insensitive
= 1;
6180 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6185 ventoy_plugin_load_menu_lang(1, args
[0]);
6186 VENTOY_CMD_RETURN(0);
6189 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6194 ventoy_plugin_load_menu_lang(0, args
[0]);
6195 VENTOY_CMD_RETURN(0);
6198 int ventoy_env_init(void)
6203 grub_env_set("vtdebug_flag", "");
6205 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6206 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6207 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6208 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6210 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6213 ventoy_filt_register(0, ventoy_wrapper_open
);
6215 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6218 g_grub_param
->grub_env_get
= grub_env_get
;
6219 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6220 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6221 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6222 grub_env_set("env_param", buf
);
6223 grub_env_set("ventoy_env_param", buf
);
6225 grub_env_export("env_param");
6226 grub_env_export("ventoy_env_param");
6229 grub_env_export("vtoy_winpeshl_ini_addr");
6230 grub_env_export("vtoy_winpeshl_ini_size");
6232 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6233 grub_env_set("vtoy_chain_file_size", buf
);
6234 grub_env_export("vtoy_chain_file_size");
6236 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6237 grub_env_set("vtoy_chain_file_read", buf
);
6238 grub_env_export("vtoy_chain_file_read");
6240 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6241 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6242 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6249 static cmd_para ventoy_cmds
[] =
6251 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6252 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6253 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6254 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6255 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6256 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6257 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6258 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6259 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6260 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6261 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6262 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6263 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6264 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6265 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6266 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6267 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6268 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6269 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6270 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6271 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6272 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6273 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6274 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6275 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6276 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6277 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6279 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6280 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6281 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6282 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6283 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6284 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6285 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6287 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6288 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6289 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6290 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6291 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6292 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6293 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6294 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6295 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6296 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6299 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6300 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6301 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6302 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6303 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6304 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6305 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6306 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6307 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6308 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6309 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6311 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6312 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6313 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6314 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6315 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6316 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6317 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6319 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6320 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6321 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6322 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6323 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6324 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6325 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6326 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6327 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6328 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6330 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6331 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6332 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6333 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6334 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6335 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6336 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6337 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6338 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6340 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6341 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6342 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6343 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6346 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6347 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6348 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6350 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6351 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6352 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6355 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6356 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6357 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6358 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6359 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6360 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6361 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6362 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6363 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6364 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6365 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6366 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6367 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6368 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6370 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6371 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6372 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6373 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6374 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6375 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6376 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6377 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6378 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6379 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6380 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6381 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6383 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6384 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6385 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6386 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6387 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6388 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6389 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6390 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6391 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6392 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6393 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6394 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6395 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6396 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6397 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6398 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6399 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6400 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6401 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6402 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6403 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6404 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6405 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6406 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6407 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6408 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6409 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6410 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6411 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6412 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6415 int ventoy_register_all_cmd(void)
6418 cmd_para
*cur
= NULL
;
6420 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6422 cur
= ventoy_cmds
+ i
;
6423 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6424 cur
->summary
, cur
->description
, cur
->parser
);
6430 int ventoy_unregister_all_cmd(void)
6434 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6436 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);