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 const char *g_lower_chksum_name
[VTOY_CHKSUM_NUM
] = { "md5", "sha1", "sha256", "sha512" };
162 static int g_lower_chksum_namelen
[VTOY_CHKSUM_NUM
] = { 3, 4, 6, 6 };
163 static int g_chksum_retlen
[VTOY_CHKSUM_NUM
] = { 32, 40, 64, 128 };
165 static int g_vtoy_secondary_need_recover
= 0;
167 static int g_vtoy_load_prompt
= 0;
168 static char g_vtoy_prompt_msg
[64];
170 static char g_json_case_mis_path
[32];
172 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
174 int ventoy_get_fs_type(const char *fs
)
178 return ventoy_fs_max
;
180 else if (grub_strncmp(fs
, "exfat", 5) == 0)
182 return ventoy_fs_exfat
;
184 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
186 return ventoy_fs_ntfs
;
188 else if (grub_strncmp(fs
, "ext", 3) == 0)
190 return ventoy_fs_ext
;
192 else if (grub_strncmp(fs
, "xfs", 3) == 0)
194 return ventoy_fs_xfs
;
196 else if (grub_strncmp(fs
, "udf", 3) == 0)
198 return ventoy_fs_udf
;
200 else if (grub_strncmp(fs
, "fat", 3) == 0)
202 return ventoy_fs_fat
;
205 return ventoy_fs_max
;
208 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
227 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
229 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
233 static int ventoy_control_get_flag(const char *key
)
235 const char *val
= ventoy_get_env(key
);
237 if (val
&& val
[0] == '1' && val
[1] == 0)
244 static grub_err_t
ventoy_fs_close(grub_file_t file
)
246 grub_file_close(g_old_file
);
247 grub_free(file
->data
);
255 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
261 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
266 for (i
= 0; i
< g_video_mode_num
; i
++)
268 if (g_video_mode_list
[i
].width
== info
->width
&&
269 g_video_mode_list
[i
].height
== info
->height
&&
270 g_video_mode_list
[i
].bpp
== info
->bpp
)
276 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
277 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
278 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
281 if (g_video_mode_num
== g_video_mode_max
)
283 g_video_mode_max
*= 2;
284 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
290 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
292 if (v1
->bpp
== v2
->bpp
)
294 if (v1
->width
== v2
->width
)
296 if (v1
->height
== v2
->height
)
302 return (v1
->height
< v2
->height
) ? -1 : 1;
307 return (v1
->width
< v2
->width
) ? -1 : 1;
312 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
316 static int ventoy_enum_video_mode(void)
319 grub_video_adapter_t adapter
;
320 grub_video_driver_id_t id
;
321 ventoy_video_mode mode
;
323 g_video_mode_num
= 0;
324 g_video_mode_max
= 1024;
325 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
326 if (!g_video_mode_list
)
331 #ifdef GRUB_MACHINE_PCBIOS
332 grub_dl_load ("vbe");
335 id
= grub_video_get_driver_id ();
337 FOR_VIDEO_ADAPTERS (adapter
)
339 if (!adapter
->iterate
||
340 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
341 adapter
->init() != GRUB_ERR_NONE
)))
346 adapter
->iterate(ventoy_video_hook
, NULL
);
348 if (adapter
->id
!= id
)
354 /* sort video mode */
355 for (i
= 0; i
< g_video_mode_num
; i
++)
356 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
358 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
360 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
361 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
362 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
366 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
369 static int ventoy_pre_parse_data(char *src
, int size
)
375 if (size
< 20 || grub_strncmp(src
, "ventoy_left_top_color", 21))
381 while (*pos
&& *pos
!= '\r' && *pos
!= '\n')
389 if (grub_strlen(src
) > 200)
394 grub_snprintf(buf
, sizeof(buf
),
395 "regexp -s 1:%s -s 2:%s -s 3:%s \"@([^@]*)@([^@]*)@([^@]*)@\" \"%s\"",
396 ventoy_left_key
, ventoy_top_key
, ventoy_color_key
, src
);
398 grub_script_execute_sourcecode(buf
);
405 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
409 static struct grub_fs vtoy_fs
=
414 .fs_read
= ventoy_fs_read
,
415 .fs_close
= ventoy_fs_close
,
425 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
431 file
->data
= grub_malloc(rawFile
->size
+ 4096);
437 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
438 ventoy_pre_parse_data((char *)file
->data
, (int)rawFile
->size
);
439 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
441 g_old_file
= rawFile
;
443 file
->size
= rawFile
->size
+ len
;
444 file
->device
= rawFile
->device
;
446 file
->not_easily_seekable
= 1;
451 static int ventoy_check_decimal_var(const char *name
, long *value
)
453 const char *value_str
= NULL
;
455 value_str
= grub_env_get(name
);
456 if (NULL
== value_str
)
458 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
461 if (!ventoy_is_decimal(value_str
))
463 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
466 *value
= grub_strtol(value_str
, NULL
, 10);
468 return GRUB_ERR_NONE
;
471 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
473 grub_uint64_t sectors
;
475 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
477 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
481 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
484 return sectors
* 512;
487 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
493 grub_uint32_t offset
;
495 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
498 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
502 len
= (int)file
->size
;
504 data
= (char *)grub_malloc(file
->size
);
510 grub_file_read(file
, data
, file
->size
);
511 grub_file_close(file
);
513 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
514 grub_script_execute_sourcecode(exec
);
516 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
517 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
518 grub_file_close(file
);
520 grub_script_execute_sourcecode("loopback -d efiboot");
524 *direntoff
= offset
+ 2;
529 static int ventoy_set_check_result(int ret
, const char *msg
)
533 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
534 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
535 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
540 grub_printf(VTOY_WARNING
"\n");
541 grub_printf(VTOY_WARNING
"\n");
542 grub_printf(VTOY_WARNING
"\n\n\n");
544 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
545 grub_printf("Error message: <%s>\n\n", msg
);
546 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
553 static int ventoy_check_official_device(grub_device_t dev
)
557 grub_uint64_t offset
;
560 grub_uint8_t mbr
[512];
564 struct grub_partition
*partition
;
566 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
568 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
571 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
572 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
573 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
575 #ifndef GRUB_MACHINE_EFI
576 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
578 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
580 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
582 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
584 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
586 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
595 /* We must have partition 2 */
598 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
602 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
606 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
609 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
611 grub_file_close(file
);
612 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
615 partition
= dev
->disk
->partition
;
616 if (partition
->number
!= 0 || partition
->start
!= 2048)
618 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
623 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
625 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
626 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
627 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
629 grub_file_close(file
);
630 return ventoy_set_check_result(6, "Disk partition layout check failed.");
635 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
636 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
637 PartTbl
[1].SectorCount
!= 65536)
639 grub_file_close(file
);
640 return ventoy_set_check_result(6, "Disk partition layout check failed.");
646 offset
= partition
->start
+ partition
->len
;
647 partition
= file
->device
->disk
->partition
;
648 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
650 grub_file_close(file
);
651 return ventoy_set_check_result(7, "Disk partition layout check failed.");
655 grub_file_close(file
);
659 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
660 dev2
= grub_device_open(devname
);
663 return ventoy_set_check_result(8, "Disk open failed");
666 fs
= grub_fs_probe(dev2
);
669 grub_device_close(dev2
);
670 return ventoy_set_check_result(9, "FS probe failed");
673 fs
->fs_label(dev2
, &label
);
674 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
676 grub_device_close(dev2
);
677 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
680 grub_device_close(dev2
);
684 disk
= grub_disk_open(dev
->disk
->name
);
687 return ventoy_set_check_result(11, "Disk open failed");
690 grub_memset(mbr
, 0, 512);
691 grub_disk_read(disk
, 0, 0, 512, mbr
);
692 grub_disk_close(disk
);
694 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
696 return ventoy_set_check_result(12, "MBR check failed");
699 return ventoy_set_check_result(0, NULL
);
702 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
706 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
716 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
718 grub_uint64_t size
= 0;
721 char fullpath
[256] = {0};
724 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
727 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
730 debug("grub_file_open failed <%s>\n", fullpath
);
736 grub_file_close(file
);
740 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
744 char fullpath
[512] = {0};
747 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
750 file
= grub_file_open(fullpath
, type
);
753 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
760 int ventoy_is_dir_exist(const char *fmt
, ...)
767 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
771 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
774 grub_strncpy(pos
+ len
, "\" ]", 3);
776 debug("script exec %s\n", buf
);
778 if (0 == grub_script_execute_sourcecode(buf
))
786 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
789 grub_uint8_t
*outbuf
;
790 grub_uint8_t gzHdr
[10] =
792 0x1F, 0x8B, /* magic */
800 grub_memset(&s
, 0, sizeof(mz_stream
));
802 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
804 outbuf
= (grub_uint8_t
*)mem_out
;
806 mem_out_len
-= sizeof(gzHdr
) + 8;
807 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
808 outbuf
+= sizeof(gzHdr
);
810 s
.avail_in
= mem_in_len
;
813 s
.avail_out
= mem_out_len
;
816 mz_deflate(&s
, MZ_FINISH
);
820 outbuf
+= s
.total_out
;
821 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
822 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
824 return s
.total_out
+ sizeof(gzHdr
) + 8;
832 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
836 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
839 if (0 == grub_strcmp(args
[0], "on"))
842 grub_env_set("vtdebug_flag", "debug");
847 grub_env_set("vtdebug_flag", "");
850 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
853 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
857 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
859 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
860 grub_printf(" level:\r\n");
861 grub_printf(" 01/11: busybox / (+cat log)\r\n");
862 grub_printf(" 02/12: initrd / (+cat log)\r\n");
863 grub_printf(" 03/13: hook / (+cat log)\r\n");
865 grub_printf(" debug:\r\n");
866 grub_printf(" 0: debug is off\r\n");
867 grub_printf(" 1: debug is on\r\n");
869 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
872 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
874 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
876 g_ventoy_debug_level
= 1;
879 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
882 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
891 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
894 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
926 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
942 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
958 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
963 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
965 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
968 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
973 value_long
+= grub_strtol(args
[1], NULL
, 10);
975 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
976 grub_env_set(args
[0], buf
);
978 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
981 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
983 ulonglong value1
= 0;
984 ulonglong value2
= 0;
989 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
992 value1
= grub_strtoull(args
[0], NULL
, 10);
993 value2
= grub_strtoull(args
[1], NULL
, 10);
995 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
996 grub_env_set(args
[2], buf
);
998 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1001 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1016 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1019 debug("failed to open file <%s> for udf check\n", args
[0]);
1023 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
1025 grub_env_set(args
[1], buf
);
1027 grub_file_close(file
);
1033 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1041 g_wimboot_enable
= 0;
1043 grub_check_free(g_wimiso_path
);
1044 grub_check_free(g_wimiso_chunk_list
.chunk
);
1046 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1052 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1053 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1054 if (NULL
== g_wimiso_chunk_list
.chunk
)
1056 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1059 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1060 g_wimiso_chunk_list
.cur_chunk
= 0;
1062 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1064 g_wimboot_enable
= 1;
1065 g_wimiso_path
= grub_strdup(args
[0]);
1066 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1067 grub_file_close(file
);
1072 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1080 ventoy_iso9660_override
*dirent
;
1089 totlen
= sizeof(ventoy_chain_head
);
1091 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1093 debug("failed to load efiboot template %d\n", len
);
1099 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1101 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1104 debug("failed to open file <%s>\n", args
[0]);
1108 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1113 totlen
+= ventoy_align_2k(file
->size
);
1115 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1116 dirent
->first_sector
= len
/ 2048;
1117 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1118 dirent
->size
= (grub_uint32_t
)file
->size
;
1119 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1121 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1123 #ifdef GRUB_MACHINE_EFI
1124 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1126 data
= (char *)grub_malloc(totlen
);
1129 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1131 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1132 grub_check_free(buf
);
1134 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1135 grub_file_close(file
);
1137 ventoy_memfile_env_set(args
[1], data
, (ulonglong
)totlen
);
1142 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1148 g_vtoy_load_prompt
= 0;
1149 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1151 if (argc
== 2 && args
[0][0] == '1')
1153 g_vtoy_load_prompt
= 1;
1154 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1157 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1160 int ventoy_need_prompt_load_file(void)
1162 return g_vtoy_load_prompt
;
1165 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1167 grub_uint64_t ro
= 0;
1168 grub_uint64_t div
= 0;
1169 grub_ssize_t left
= size
;
1170 char *cur
= (char *)buf
;
1172 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1175 while (left
>= VTOY_SIZE_2MB
)
1177 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1178 cur
+= VTOY_SIZE_2MB
;
1179 left
-= VTOY_SIZE_2MB
;
1181 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1186 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1192 grub_file_read(file
, cur
, left
);
1195 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1201 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1206 enum grub_file_type type
;
1217 if (grub_strcmp(args
[0], "nodecompress") == 0)
1219 type
= VENTOY_FILE_TYPE
;
1223 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1226 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1229 debug("failed to open file <%s>\n", args
[1]);
1233 #ifdef GRUB_MACHINE_EFI
1234 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1236 buf
= (char *)grub_malloc(file
->size
);
1241 grub_file_close(file
);
1245 if (g_vtoy_load_prompt
)
1247 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1251 grub_file_read(file
, buf
, file
->size
);
1254 ventoy_memfile_env_set(args
[2], buf
, (ulonglong
)(file
->size
));
1256 grub_file_close(file
);
1262 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1278 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1281 debug("failed to open file <%s> for udf check\n", args
[0]);
1285 headlen
= sizeof(ventoy_chain_head
);
1287 #ifdef GRUB_MACHINE_EFI
1288 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1290 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1293 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1295 grub_file_read(file
, buf
+ headlen
, file
->size
);
1297 ventoy_memfile_env_set(args
[1], buf
, (ulonglong
)(file
->size
));
1299 grub_file_close(file
);
1305 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1311 if (grub_iso9660_is_joliet())
1313 debug("This time has joliet process\n");
1322 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1331 if (args
[0][0] == '1')
1333 grub_iso9660_set_nojoliet(1);
1337 grub_iso9660_set_nojoliet(0);
1343 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1348 grub_uint8_t buf
[32];
1359 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1362 debug("failed to open file <%s> for udf check\n", args
[0]);
1366 for (i
= 16; i
< 32; i
++)
1368 grub_file_seek(file
, i
* 2048);
1369 grub_file_read(file
, buf
, sizeof(buf
));
1377 grub_file_seek(file
, i
* 2048);
1378 grub_file_read(file
, buf
, sizeof(buf
));
1380 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1383 grub_file_seek(file
, i
* 2048);
1384 grub_file_read(file
, buf
, sizeof(buf
));
1386 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1387 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1393 grub_file_close(file
);
1395 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1400 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1402 long value_long1
= 0;
1403 long value_long2
= 0;
1405 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1407 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1410 value_long1
= grub_strtol(args
[0], NULL
, 10);
1411 value_long2
= grub_strtol(args
[2], NULL
, 10);
1413 if (0 == grub_strcmp(args
[1], "eq"))
1415 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1417 else if (0 == grub_strcmp(args
[1], "ne"))
1419 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1421 else if (0 == grub_strcmp(args
[1], "gt"))
1423 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1425 else if (0 == grub_strcmp(args
[1], "lt"))
1427 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1429 else if (0 == grub_strcmp(args
[1], "ge"))
1431 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1433 else if (0 == grub_strcmp(args
[1], "le"))
1435 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1439 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1445 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1448 char buf
[128] = {0};
1452 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1455 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1456 pos
= grub_strstr(buf
, ",");
1462 grub_env_set(args
[1], buf
);
1464 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1467 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1473 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1479 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1482 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1484 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1485 if (0 == grub_script_execute_sourcecode(buf
))
1487 debug("file %s exist, ventoy_compatible YES\n", buf
);
1488 grub_env_set("ventoy_compatible", "YES");
1489 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1493 debug("file %s NOT exist\n", buf
);
1497 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1498 pos
= grub_strstr(buf
, ")");
1504 disk
= grub_disk_open(buf
);
1507 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1508 grub_disk_close(disk
);
1510 g_img_swap_tmp_buf
[703] = 0;
1511 for (i
= 318; i
< 703; i
++)
1513 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1514 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1516 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1517 grub_env_set("ventoy_compatible", "YES");
1518 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1524 debug("failed to open disk <%s>\n", buf
);
1527 grub_env_set("ventoy_compatible", "NO");
1528 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1531 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1537 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1539 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1542 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1547 if (0 == g_sort_case_sensitive
)
1549 if (grub_islower(c1
))
1551 c1
= c1
- 'a' + 'A';
1554 if (grub_islower(c2
))
1556 c2
= c2
- 'a' + 'A';
1569 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1575 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1577 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1580 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1585 if (0 == g_sort_case_sensitive
)
1587 if (grub_islower(c1
))
1589 c1
= c1
- 'a' + 'A';
1592 if (grub_islower(c2
))
1594 c2
= c2
- 'a' + 'A';
1607 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1609 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1611 grub_memcpy(img1
, img2
, sizeof(img_info
));
1612 img1
->next
= g_img_swap_tmp
.next
;
1613 img1
->prev
= g_img_swap_tmp
.prev
;
1615 g_img_swap_tmp
.next
= img2
->next
;
1616 g_img_swap_tmp
.prev
= img2
->prev
;
1617 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1620 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1624 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1632 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1634 ventoy_vlnk_part
*node
= NULL
;
1635 grub_uint32_t SelfSig
;
1636 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1638 /* skip Ventoy partition 1/2 */
1639 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1640 if (partition
->number
< 2 && SelfSig
== *pSig
)
1645 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1648 node
->disksig
= *pSig
;
1649 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1650 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1651 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1653 node
->next
= g_vlnk_part_list
;
1654 g_vlnk_part_list
= node
;
1660 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1667 disk
= grub_disk_open(name
);
1670 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1671 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1672 grub_disk_close(disk
);
1678 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1680 const char *fs
[ventoy_fs_max
+ 1] =
1682 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1687 cur
->dev
= grub_device_open(cur
->device
);
1692 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1698 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1703 char *disk
, *device
;
1704 grub_uint32_t readcrc
, calccrc
;
1705 ventoy_vlnk_part
*cur
;
1706 grub_fs_t fs
= NULL
;
1708 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1712 grub_printf("VLNK invalid guid\n");
1718 readcrc
= vlnk
->crc32
;
1720 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1721 if (readcrc
!= calccrc
)
1725 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1731 if (!g_vlnk_part_list
)
1733 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1736 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1738 if (cur
->disksig
== vlnk
->disk_signature
)
1742 if (cur
->partoffset
== vlnk
->part_offset
)
1745 device
= cur
->device
;
1747 if (cur
->probe
== 0)
1750 ventoy_vlnk_probe_fs(cur
);
1760 struct grub_file file
;
1762 grub_memset(&file
, 0, sizeof(file
));
1763 file
.device
= cur
->dev
;
1764 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1767 cur
->fs
->fs_close(&file
);
1768 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1777 grub_printf("\n==== VLNK Information ====\n"
1778 "Disk Signature: %08x\n"
1779 "Partition Offset: %llu\n"
1780 "File Path: <%s>\n\n",
1781 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1785 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1789 grub_printf("Disk Find: [ NO ]\n");
1794 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1798 grub_printf("Part Find: [ NO ]\n");
1800 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1803 grub_printf("VLNK File: <%s>\n", dst
);
1810 return (1 - filefind
);
1813 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1818 grub_file_t file
= NULL
;
1823 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1825 else if (dir
[0] == '/')
1827 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1831 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1834 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1840 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1841 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1842 grub_file_close(file
);
1844 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1846 rc
= grub_file_add_vlnk(src
, dst
);
1852 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1862 const menu_tip
*tip
;
1863 img_iterator_node
*tmp
;
1864 img_iterator_node
*new_node
;
1865 img_iterator_node
*node
= (img_iterator_node
*)data
;
1867 if (g_enumerate_time_checked
== 0)
1869 g_enumerate_finish_time_ms
= grub_get_time_ms();
1870 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1873 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1875 g_enumerate_time_checked
= 1;
1879 len
= grub_strlen(filename
);
1883 if (node
->level
+ 1 > g_img_max_search_level
)
1888 if ((len
== 1 && filename
[0] == '.') ||
1889 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1894 if (!ventoy_img_name_valid(filename
, len
))
1899 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1904 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1906 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1907 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1910 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1915 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1918 new_node
->level
= node
->level
+ 1;
1919 new_node
->plugin_list_index
= index
;
1920 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1922 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1925 debug("Directory %s ignored...\n", new_node
->dir
);
1926 grub_free(new_node
);
1930 new_node
->tail
= node
->tail
;
1932 new_node
->parent
= node
;
1933 if (!node
->firstchild
)
1935 node
->firstchild
= new_node
;
1938 if (g_img_iterator_tail
)
1940 g_img_iterator_tail
->next
= new_node
;
1941 g_img_iterator_tail
= new_node
;
1945 g_img_iterator_head
.next
= new_node
;
1946 g_img_iterator_tail
= new_node
;
1952 debug("Find a file %s\n", filename
);
1958 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1960 type
= img_type_iso
;
1962 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1964 type
= img_type_wim
;
1966 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1967 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1969 type
= img_type_vhd
;
1971 #ifdef GRUB_MACHINE_EFI
1972 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1974 type
= img_type_efi
;
1977 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1979 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1981 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1982 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1987 type
= img_type_img
;
1989 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1991 type
= img_type_vtoy
;
1993 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1995 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1997 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1998 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
2007 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
2012 if (g_plugin_image_list
)
2014 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2015 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
2016 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
2018 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2021 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2023 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2028 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2030 if (grub_file_is_vlnk_suffix(filename
, len
))
2033 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2040 img
= grub_zalloc(sizeof(img_info
));
2044 img
->plugin_list_index
= index
;
2045 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2047 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2049 img
->size
= info
->size
;
2050 if (vlnk
|| 0 == img
->size
)
2052 if (node
->dir
[0] == '/')
2054 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2058 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2062 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2064 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2069 if (g_ventoy_img_list
)
2071 tail
= *(node
->tail
);
2077 g_ventoy_img_list
= img
;
2080 img
->id
= g_ventoy_img_count
;
2082 if (node
&& NULL
== node
->firstiso
)
2084 node
->firstiso
= img
;
2095 *((img_info
**)(node
->tail
)) = img
;
2096 g_ventoy_img_count
++;
2098 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2100 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2103 img
->tip1
= tip
->tip1
;
2104 img
->tip2
= tip
->tip2
;
2107 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2110 img
->class = g_menu_class
[type
];
2112 img
->menu_prefix
= g_menu_prefix
[type
];
2114 if (img_type_iso
== type
)
2116 if (ventoy_plugin_check_memdisk(img
->path
))
2118 img
->menu_prefix
= "miso";
2121 else if (img_type_img
== type
)
2123 if (ventoy_plugin_check_memdisk(img
->path
))
2125 img
->menu_prefix
= "mimg";
2129 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2136 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2138 int len
= GRUB_UINT_MAX
;
2139 const char *value
= NULL
;
2140 char name
[32] = {0};
2141 char plat
[32] = {0};
2142 char guidstr
[32] = {0};
2143 ventoy_guid guid
= VENTOY_GUID
;
2144 const char *fmt1
= NULL
;
2145 const char *fmt2
= NULL
;
2146 const char *fmt3
= NULL
;
2147 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2148 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2149 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2150 const char fmtcode
[]={
2151 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2152 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2153 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2154 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2155 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2156 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2159 grub_memset(name
, 0, sizeof(name
));
2160 puint
[0] = grub_swap_bytes32(0x56454e54);
2161 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2162 puint
[2] = grub_swap_bytes32(0x45525349);
2163 puint
[1] = grub_swap_bytes32(0x4f595f56);
2164 value
= ventoy_get_env(name
);
2166 grub_memset(name
, 0, sizeof(name
));
2167 puint
[1] = grub_swap_bytes32(0x5f544f50);
2168 puint
[0] = grub_swap_bytes32(0x56544c45);
2169 fmt1
= ventoy_get_env(name
);
2175 grub_memset(name
, 0, sizeof(name
));
2176 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2177 puint
[0] = grub_swap_bytes32(0x56544c45);
2178 fmt2
= ventoy_get_env(name
);
2180 grub_memset(name
, 0, sizeof(name
));
2181 puint
[1] = grub_swap_bytes32(0x5f434c52);
2182 puint
[0] = grub_swap_bytes32(0x56544c45);
2183 fmt3
= ventoy_get_env(name
);
2185 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2187 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2189 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2190 #pragma GCC diagnostic push
2191 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2192 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2193 fmt1
? fmt1
: fmtdata
,
2194 fmt2
? fmt2
: fmtdata
+ 4,
2195 value
? value
: "", plat
, guidstr
,
2196 fmt3
? fmt3
: fmtdata
+ 6);
2197 #pragma GCC diagnostic pop
2199 grub_memset(name
, 0, sizeof(name
));
2200 puint
[0] = grub_swap_bytes32(0x76746f79);
2201 puint
[2] = grub_swap_bytes32(0x656e7365);
2202 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2203 ventoy_set_env(name
, guidstr
);
2209 ventoy_password_get (char buf
[], unsigned buf_size
)
2211 unsigned i
, cur_len
= 0;
2213 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2217 key
= grub_getkey ();
2218 if (key
== '\n' || key
== '\r')
2221 if (key
== GRUB_TERM_ESC
)
2231 grub_term_restore_pos (pos
);
2232 for (i
= 0; i
< cur_len
; i
++)
2234 grub_term_restore_pos (pos
);
2236 for (i
= 0; i
< cur_len
; i
++)
2243 if (!grub_isprint (key
))
2246 if (cur_len
+ 2 < buf_size
)
2247 buf
[cur_len
++] = key
;
2252 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2258 return (key
!= GRUB_TERM_ESC
);
2261 static int ventoy_get_password(char buf
[], unsigned buf_size
)
2263 const char *env
= NULL
;
2265 env
= grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2266 if (env
&& env
[0] == '0' && env
[1] == 0)
2268 return grub_password_get(buf
, buf_size
);
2272 return ventoy_password_get(buf
, buf_size
);
2276 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2280 grub_uint8_t md5
[16];
2284 grub_memset(input
, 0, sizeof(input
));
2286 grub_printf("Enter password: ");
2289 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2291 ventoy_get_password(input
, 128);
2292 if (grub_strcmp(pwd
->text
, input
) == 0)
2297 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2299 ventoy_get_password(input
, 128);
2300 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2301 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2306 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2308 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2309 ventoy_get_password(input
+ offset
, 128);
2311 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2312 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2318 grub_printf("Invalid password!\n\n");
2325 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2327 img_info
*minimg
= NULL
;
2328 img_info
*img
= (img_info
*)(node
->firstiso
);
2330 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2332 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2347 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2349 img_iterator_node
*Minchild
= NULL
;
2350 img_iterator_node
*child
= node
->firstchild
;
2352 while (child
&& child
->parent
== node
)
2354 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2358 child
= child
->next
;
2363 Minchild
->select
= 1;
2369 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2372 img_info
*img
= NULL
;
2373 const char *dir_class
= NULL
;
2374 const char *dir_alias
= NULL
;
2375 img_iterator_node
*child
= NULL
;
2376 const menu_tip
*tip
= NULL
;
2378 if (node
->isocnt
== 0 || node
->done
== 1)
2383 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2385 offset
= node
->parent
->dirlen
;
2388 if (node
== &g_img_iterator_head
)
2390 if (g_default_menu_mode
== 0)
2392 if (g_tree_view_menu_style
== 0)
2394 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2395 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2396 " echo 'return ...' \n"
2397 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2401 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2402 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2403 " echo 'return ...' \n"
2404 "}\n", ventoy_get_vmenu_title("VTLANG_RET_TO_LISTVIEW"));
2408 g_tree_script_pre
= g_tree_script_pos
;
2412 node
->dir
[node
->dirlen
- 1] = 0;
2413 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2416 dir_class
= "vtoydir";
2419 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2421 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2424 if (g_tree_view_menu_style
== 0)
2426 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2427 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2428 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2432 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2433 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2434 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2439 dir_alias
= node
->dir
+ offset
;
2441 if (g_tree_view_menu_style
== 0)
2443 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2444 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2445 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2449 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2450 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2451 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2455 if (g_tree_view_menu_style
== 0)
2457 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2458 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2459 " echo 'return ...' \n"
2460 "}\n", "<--", node
->dir
);
2464 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2465 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2466 " echo 'return ...' \n"
2471 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2473 ventoy_dynamic_tree_menu(child
);
2476 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2478 if (g_tree_view_menu_style
== 0)
2480 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2481 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2484 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2485 img
->unsupport
? "[***********] " : "",
2486 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2488 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2492 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2493 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2496 img
->unsupport
? "[***********] " : "",
2497 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2499 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2503 if (node
!= &g_img_iterator_head
)
2505 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2512 static int ventoy_set_default_menu(void)
2518 const char *strdata
= NULL
;
2519 img_info
*cur
= NULL
;
2520 img_info
*default_node
= NULL
;
2521 const char *default_image
= NULL
;
2523 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2524 if (default_image
&& default_image
[0] == '/')
2526 img_len
= grub_strlen(default_image
);
2528 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2530 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2542 if (0 == g_default_menu_mode
)
2544 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2548 def
= grub_strdup(default_image
);
2554 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2556 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2557 if (strdata
&& strdata
[0] == '/')
2559 pos
= def
+ grub_strlen(strdata
);
2570 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2573 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2577 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2585 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2587 img_info
*next
= NULL
;
2588 img_info
*cur
= g_ventoy_img_list
;
2601 g_ventoy_img_list
= NULL
;
2602 g_ventoy_img_count
= 0;
2604 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2607 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2610 img_info
*cur
= g_ventoy_img_list
;
2614 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2616 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2619 img_id
= grub_strtol(args
[0], NULL
, 10);
2620 if (img_id
>= g_ventoy_img_count
)
2622 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2625 debug("Find image %ld name \n", img_id
);
2627 while (cur
&& img_id
> 0)
2635 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2638 debug("image name is %s\n", cur
->name
);
2640 grub_env_set(args
[1], cur
->name
);
2642 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2645 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2649 img_info
*cur
= g_ventoy_img_list
;
2655 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2658 len
= (int)grub_strlen(args
[0]);
2662 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2671 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2674 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2675 grub_env_set("chosen", id
);
2676 grub_env_export("chosen");
2678 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2681 static char g_fake_vlnk_src
[512];
2682 static char g_fake_vlnk_dst
[512];
2683 static grub_uint64_t g_fake_vlnk_size
;
2684 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2690 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2692 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2693 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2695 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2697 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2700 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2706 g_fake_vlnk_src
[0] = 0;
2707 g_fake_vlnk_dst
[0] = 0;
2708 g_fake_vlnk_size
= 0;
2709 grub_file_vtoy_vlnk(NULL
, NULL
);
2711 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2715 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2720 const char *id
= NULL
;
2721 img_info
*cur
= NULL
;
2725 if (argc
< 1 || argc
> 3)
2727 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2730 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2732 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2733 grub_env_set(args
[0], pos
);
2736 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2737 grub_env_set(args
[1], value
);
2742 for (last
= pos
; *pos
; pos
++)
2749 grub_env_set(args
[2], last
+ 1);
2755 id
= grub_env_get("chosen");
2757 pos
= grub_strstr(id
, "VID_");
2760 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2764 cur
= g_ventoy_img_list
;
2769 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2772 grub_env_set(args
[0], cur
->path
);
2776 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2777 grub_env_set(args
[1], value
);
2782 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2783 grub_env_set(args
[2], cur
->name
);
2787 g_svd_replace_offset
= 0;
2789 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2793 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2797 grub_device_t dev
= NULL
;
2798 img_info
*cur
= NULL
;
2799 img_info
*tail
= NULL
;
2800 img_info
*min
= NULL
;
2801 img_info
*head
= NULL
;
2802 const char *strdata
= NULL
;
2803 char *device_name
= NULL
;
2805 img_iterator_node
*node
= NULL
;
2806 img_iterator_node
*tmp
= NULL
;
2812 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2815 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2817 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2822 g_enumerate_time_checked
= 0;
2823 g_enumerate_start_time_ms
= grub_get_time_ms();
2825 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2826 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2828 g_filt_dot_underscore_file
= 1;
2831 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2832 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2834 g_sort_case_sensitive
= 1;
2837 device_name
= grub_file_get_device_name(args
[0]);
2843 g_enum_dev
= dev
= grub_device_open(device_name
);
2849 g_enum_fs
= fs
= grub_fs_probe(dev
);
2855 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2857 debug("unsupported fs:<%s>\n", fs
->name
);
2858 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2862 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2864 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2865 if (strdata
&& strdata
[0] == '1')
2867 g_default_menu_mode
= 1;
2870 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2872 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2874 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2875 if (strdata
&& strdata
[0] == '/')
2877 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2878 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2880 g_img_iterator_head
.dir
[len
++] = '/';
2882 g_img_iterator_head
.dirlen
= len
;
2886 g_img_iterator_head
.dirlen
= 1;
2887 grub_strcpy(g_img_iterator_head
.dir
, "/");
2890 g_img_iterator_head
.tail
= &tail
;
2892 if (g_img_max_search_level
< 0)
2894 g_img_max_search_level
= GRUB_INT_MAX
;
2895 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2896 if (strdata
&& ventoy_is_decimal(strdata
))
2898 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2902 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2903 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2904 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2905 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2906 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2907 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2909 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2911 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2914 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2915 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2917 g_tree_view_menu_style
= 1;
2920 ventoy_set_default_menu();
2922 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2924 ventoy_dynamic_tree_menu(node
);
2928 node
= g_img_iterator_head
.next
;
2936 /* sort image list by image name */
2937 while (g_ventoy_img_list
)
2939 min
= g_ventoy_img_list
;
2940 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2942 if (ventoy_cmp_img(min
, cur
) > 0)
2950 min
->prev
->next
= min
->next
;
2955 min
->next
->prev
= min
->prev
;
2958 if (min
== g_ventoy_img_list
)
2960 g_ventoy_img_list
= min
->next
;
2978 g_ventoy_img_list
= head
;
2980 if (g_default_menu_mode
== 1)
2982 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2983 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2984 " echo 'return ...' \n"
2985 "}\n", "<--", ventoy_get_vmenu_title("VTLANG_RET_TO_TREEVIEW"));
2988 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2990 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2991 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2994 cur
->unsupport
? "[***********] " : "",
2995 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2997 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
3000 g_tree_script_buf
[g_tree_script_pos
] = 0;
3001 g_list_script_buf
[g_list_script_pos
] = 0;
3003 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
3004 grub_env_set(args
[1], buf
);
3008 check_free(device_name
, grub_free
);
3009 check_free(dev
, grub_device_close
);
3011 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3014 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
3021 device_name
= grub_file_get_device_name(filename
);
3033 pos2
= grub_strstr(pos
, ",");
3036 pos2
= grub_strstr(pos
, ")");
3044 disk
= grub_disk_open(pos
);
3047 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3048 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3049 grub_disk_close(disk
);
3056 grub_free(device_name
);
3060 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3062 eltorito_descriptor desc
;
3064 grub_memset(&desc
, 0, sizeof(desc
));
3065 grub_file_seek(file
, 17 * 2048);
3066 grub_file_read(file
, &desc
, sizeof(desc
));
3068 if (desc
.type
!= 0 || desc
.version
!= 1)
3073 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3074 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3082 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3084 grub_uint8_t buf
[512];
3086 grub_file_seek(file
, sector
* 2048);
3087 grub_file_read(file
, buf
, sizeof(buf
));
3089 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3090 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3092 return *((grub_uint32_t
*)(buf
+ 40));
3098 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3102 grub_uint8_t buf
[512];
3103 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3105 grub_file_seek(file
, sector
* 2048);
3106 grub_file_read(file
, buf
, sizeof(buf
));
3108 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3110 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3114 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3119 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3121 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3123 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3127 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3129 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3134 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3136 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3138 if (buf
[36] == parttype
[i
])
3140 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3146 debug("%s does not contain efi eltorito\n", file
->name
);
3150 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3153 const char *fs
= NULL
;
3154 const char *val
= NULL
;
3155 const char *cdprompt
= NULL
;
3157 grub_uint8_t chksum
= 0;
3160 disk
= file
->device
->disk
;
3161 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3163 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3164 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3165 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3167 pos
= grub_strstr(file
->name
, "/");
3173 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3175 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3177 param
->vtoy_img_size
= file
->size
;
3179 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3180 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3182 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3184 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3185 param
->vtoy_reserved
[4] = 0;
3186 if (g_ventoy_chain_type
== 1) /* Windows */
3188 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3189 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3191 param
->vtoy_reserved
[4] = 1;
3195 fs
= ventoy_get_env("ventoy_fs_probe");
3196 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3198 param
->vtoy_reserved
[3] = 1;
3201 param
->vtoy_reserved
[5] = 0;
3202 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3203 if (val
&& val
[0] == '1' && val
[1] == 0)
3205 param
->vtoy_reserved
[5] = 1;
3208 /* ventoy_disk_signature used for vlnk */
3209 param
->vtoy_reserved
[6] = file
->vlnk
;
3210 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3212 /* calculate checksum */
3213 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3215 chksum
+= *((grub_uint8_t
*)param
+ i
);
3217 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3222 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3224 grub_uint32_t i
= 0;
3225 grub_uint64_t total
= 0;
3226 grub_uint64_t fileblk
= 0;
3227 ventoy_img_chunk
*chunk
= NULL
;
3229 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3231 chunk
= chunklist
->chunk
+ i
;
3233 if (chunk
->disk_start_sector
<= start
)
3235 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3239 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3242 fileblk
= (file
->size
+ 511) / 512;
3244 if (total
!= fileblk
)
3246 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3247 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3249 debug("maybe img file to be processed.\n");
3259 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3263 grub_uint32_t i
= 0;
3264 grub_uint32_t sector
= 0;
3265 grub_uint32_t count
= 0;
3266 grub_off_t size
= 0;
3267 grub_off_t read
= 0;
3269 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3270 if (fs_type
== ventoy_fs_exfat
)
3272 grub_fat_get_file_chunk(start
, file
, chunklist
);
3274 else if (fs_type
== ventoy_fs_ext
)
3276 grub_ext_get_file_chunk(start
, file
, chunklist
);
3280 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3281 file
->read_hook_data
= chunklist
;
3283 for (size
= file
->size
; size
> 0; size
-= read
)
3285 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3286 grub_file_read(file
, NULL
, read
);
3289 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3291 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3292 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3295 if (ventoy_fs_udf
== fs_type
)
3297 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3299 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3300 chunklist
->chunk
[i
].img_start_sector
= sector
;
3301 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3307 len
= (int)grub_strlen(file
->name
);
3308 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3309 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3310 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3311 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3313 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3315 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3325 chunklist
->chunk
[i
].img_start_sector
= sector
;
3326 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3334 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3338 grub_disk_addr_t start
;
3343 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3346 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3349 g_conf_replace_count
= 0;
3350 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3351 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3353 if (g_img_chunk_list
.chunk
)
3355 grub_free(g_img_chunk_list
.chunk
);
3358 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3360 grub_file_close(file
);
3361 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3364 /* get image chunk data */
3365 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3366 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3367 if (NULL
== g_img_chunk_list
.chunk
)
3369 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3372 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3373 g_img_chunk_list
.cur_chunk
= 0;
3375 start
= file
->device
->disk
->partition
->start
;
3377 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3379 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3380 grub_file_close(file
);
3384 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3387 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3388 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3389 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3392 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3396 grub_uint64_t offset
= 0;
3397 grub_uint32_t align
= 0;
3398 grub_file_t file
= NULL
;
3399 conf_replace
*node
= NULL
;
3400 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3401 ventoy_grub_param_file_replace
*replace
= NULL
;
3407 debug("select conf replace argc:%d\n", argc
);
3414 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3417 debug("Conf replace not found for %s\n", args
[1]);
3421 debug("Find %d conf replace for %s\n", n
, args
[1]);
3423 g_conf_replace_count
= n
;
3424 for (i
= 0; i
< n
; i
++)
3428 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3431 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3432 grub_file_close(file
);
3434 else if (node
->img
> 0)
3440 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3444 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3447 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3451 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3453 if (align
> vtoy_max_replace_file_size
)
3455 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3456 grub_file_close(file
);
3460 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3461 grub_file_close(file
);
3462 g_conf_replace_new_len
[i
] = (int)file
->size
;
3463 g_conf_replace_new_len_align
[i
] = align
;
3465 g_conf_replace_node
[i
] = node
;
3466 g_conf_replace_offset
[i
] = offset
+ 2;
3470 replace
= &(g_grub_param
->img_replace
[i
]);
3471 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3472 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3473 replace
->old_name_cnt
++;
3476 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3480 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3483 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3488 const char *ch
= var
;
3495 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3502 debug("Invalid variable letter <%c>\n", *ch
);
3509 debug("Invalid variable length:%d <%s>\n", n
, var
);
3513 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3522 grub_printf("\n=================== Variables Expansion ===================\n\n");
3525 grub_printf("<%s>: ", var
);
3528 while (i
< (len
- 1))
3531 if ((c
== '\n') || (c
== '\r'))
3541 else if (grub_isprint(c
))
3543 if (i
+ 1 < (len
- 1))
3545 grub_printf("%c", c
);
3555 expand
[i
- 1] = ' ';
3556 grub_printf("\r<%s>: %s", var
, expand
);
3559 grub_printf("\r<%s>: %s", var
, expand
);
3571 grub_snprintf(expand
, len
, "$$%s$$", var
);
3577 static int ventoy_auto_install_var_expand(install_template
*node
)
3585 char *newbuf
= NULL
;
3586 char *curline
= NULL
;
3587 char *nextline
= NULL
;
3588 grub_uint8_t
*code
= NULL
;
3590 var_node
*CurNode
= NULL
;
3591 var_node
*pVarList
= NULL
;
3593 code
= (grub_uint8_t
*)node
->filebuf
;
3595 if (node
->filelen
>= VTOY_SIZE_1MB
)
3597 debug("auto install script too long %d\n", node
->filelen
);
3601 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3603 debug("UCS-2 encoding NOT supported\n");
3607 start
= grub_strstr(node
->filebuf
, "$$");
3610 debug("no need to expand variable, no start.\n");
3614 end
= grub_strstr(start
+ 2, "$$");
3617 debug("no need to expand variable, no end.\n");
3621 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3622 newbuf
= grub_malloc(newlen
);
3625 debug("Failed to alloc newbuf %d\n", newlen
);
3629 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3631 nextline
= ventoy_get_line(curline
);
3633 start
= grub_strstr(curline
, "$$");
3636 end
= grub_strstr(start
+ 2, "$$");
3642 VTOY_APPEND_NEWBUF(curline
);
3644 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3646 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3648 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3655 value
[sizeof(value
) - 1] = 0;
3656 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3660 CurNode
= grub_zalloc(sizeof(var_node
));
3663 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3664 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3665 CurNode
->next
= pVarList
;
3671 VTOY_APPEND_NEWBUF(value
);
3673 VTOY_APPEND_NEWBUF(end
+ 2);
3677 VTOY_APPEND_NEWBUF(curline
);
3680 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3682 newbuf
[pos
- 1] = '\n';
3686 newbuf
[pos
++] = '\n';
3690 grub_free(node
->filebuf
);
3691 node
->filebuf
= newbuf
;
3692 node
->filelen
= pos
;
3696 CurNode
= pVarList
->next
;
3697 grub_free(pVarList
);
3704 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3710 grub_file_t file
= NULL
;
3711 char configfile
[128];
3712 install_template
*node
= NULL
;
3718 debug("select auto installation argc:%d\n", argc
);
3725 node
= ventoy_plugin_find_install_template(args
[0]);
3728 debug("Auto install template not found for %s\n", args
[0]);
3732 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3734 defidx
= node
->autosel
;
3735 if (node
->timeout
< 0)
3737 node
->cursel
= node
->autosel
- 1;
3738 debug("Auto install template auto select %d\n", node
->autosel
);
3743 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3749 if (node
->timeout
> 0)
3751 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3754 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3755 " echo %s\n}\n", "");
3757 for (i
= 0; i
< node
->templatenum
; i
++)
3759 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3761 ventoy_get_vmenu_title("VTLANG_AUTOINS_USE"),
3762 node
->templatepath
[i
].path
);
3765 g_ventoy_menu_esc
= 1;
3766 g_ventoy_suppress_esc
= 1;
3767 g_ventoy_suppress_esc_default
= defidx
;
3768 g_ventoy_secondary_menu_on
= 1;
3770 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3771 grub_script_execute_sourcecode(configfile
);
3773 g_ventoy_menu_esc
= 0;
3774 g_ventoy_suppress_esc
= 0;
3775 g_ventoy_suppress_esc_default
= 1;
3776 g_ventoy_secondary_menu_on
= 0;
3780 node
->cursel
= g_ventoy_last_entry
- 1;
3783 grub_check_free(node
->filebuf
);
3786 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3788 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3789 node
->templatepath
[node
->cursel
].path
);
3792 node
->filebuf
= grub_malloc(file
->size
+ 8);
3795 grub_file_read(file
, node
->filebuf
, file
->size
);
3796 grub_file_close(file
);
3798 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3799 node
->filelen
= (int)file
->size
;
3801 ventoy_auto_install_var_expand(node
);
3806 debug("Failed to open auto install script <%s%s>\n",
3807 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3814 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3820 char configfile
[128];
3821 persistence_config
*node
;
3827 debug("select persistence argc:%d\n", argc
);
3834 node
= ventoy_plugin_find_persistent(args
[0]);
3837 debug("Persistence image not found for %s\n", args
[0]);
3841 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3843 defidx
= node
->autosel
;
3844 if (node
->timeout
< 0)
3846 node
->cursel
= node
->autosel
- 1;
3847 debug("Persistence image auto select %d\n", node
->autosel
);
3852 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3858 if (node
->timeout
> 0)
3860 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3863 vtoy_ssprintf(buf
, pos
, "menuentry \"$VTLANG_NO_PERSIST\" --class=\"sel_persistence\" {\n"
3864 " echo %s\n}\n", "");
3866 for (i
= 0; i
< node
->backendnum
; i
++)
3868 vtoy_ssprintf(buf
, pos
, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3870 ventoy_get_vmenu_title("VTLANG_PERSIST_USE"),
3871 node
->backendpath
[i
].path
);
3875 g_ventoy_menu_esc
= 1;
3876 g_ventoy_suppress_esc
= 1;
3877 g_ventoy_suppress_esc_default
= defidx
;
3878 g_ventoy_secondary_menu_on
= 1;
3880 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3881 grub_script_execute_sourcecode(configfile
);
3883 g_ventoy_menu_esc
= 0;
3884 g_ventoy_suppress_esc
= 0;
3885 g_ventoy_suppress_esc_default
= 1;
3886 g_ventoy_secondary_menu_on
= 0;
3890 node
->cursel
= g_ventoy_last_entry
- 1;
3892 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3895 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3898 ventoy_img_chunk
*cur
;
3904 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3906 cur
= g_img_chunk_list
.chunk
+ i
;
3907 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3908 cur
->img_start_sector
, cur
->img_end_sector
,
3909 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3913 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3916 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3920 ventoy_img_chunk_list chunklist
;
3925 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3928 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3931 /* get image chunk data */
3932 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3933 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3934 if (NULL
== chunklist
.chunk
)
3936 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3939 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3940 chunklist
.cur_chunk
= 0;
3942 ventoy_get_block_list(file
, &chunklist
, 0);
3944 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3946 grub_printf("########## UNSUPPORTED ###############\n");
3949 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3951 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3953 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3954 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3957 grub_printf("\n==================================\n");
3959 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3961 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3962 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3963 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3964 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3965 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3969 grub_free(chunklist
.chunk
);
3970 grub_file_close(file
);
3972 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3975 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3978 ventoy_grub_param_file_replace
*replace
= NULL
;
3986 replace
= &(g_grub_param
->file_replace
);
3987 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3989 replace
->old_name_cnt
= 0;
3990 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3992 replace
->old_name_cnt
++;
3993 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3996 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3999 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4002 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4005 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
4011 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
4012 grub_env_set(args
[0], buf
);
4015 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4018 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4026 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4027 grub_printf("%s", g_list_script_buf
);
4031 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
4032 grub_printf("%s", g_tree_script_buf
);
4038 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4040 img_info
*cur
= g_ventoy_img_list
;
4048 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4049 grub_printf("name:<%s>\n\n", cur
->name
);
4056 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4062 ventoy_plugin_dump_injection();
4067 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4073 ventoy_plugin_dump_auto_install();
4078 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4084 ventoy_plugin_dump_persistence();
4089 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4095 len1
= (int)grub_strlen(filename
);
4096 len2
= (int)grub_strlen(suffix
);
4103 for (i
= len1
- 1; i
>= 0; i
--)
4105 if (filename
[i
] == '.')
4116 if (filename
[i
- len2
- 1] != '_')
4121 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4129 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4135 if (argc
!= 1 && argc
!= 2)
4140 if (args
[0][0] == '0')
4142 if (g_ventoy_memdisk_mode
)
4147 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4154 else if (args
[0][0] == '1')
4156 return g_ventoy_iso_raw
? 0 : 1;
4158 else if (args
[0][0] == '2')
4160 return g_ventoy_iso_uefi_drv
? 0 : 1;
4162 else if (args
[0][0] == '3')
4164 if (g_ventoy_grub2_mode
)
4169 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4176 else if (args
[0][0] == '4')
4178 if (g_ventoy_wimboot_mode
)
4183 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4194 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4196 static int configfile_mode
= 0;
4197 char memfile
[128] = {0};
4204 * args[0]: 0:normal 1:configfile
4205 * args[1]: 0:list_buf 1:tree_buf
4210 debug("Invalid argc %d\n", argc
);
4216 if (args
[0][0] == '0')
4218 if (args
[1][0] == '0')
4220 grub_script_execute_sourcecode(g_list_script_buf
);
4224 grub_script_execute_sourcecode(g_tree_script_buf
);
4229 if (configfile_mode
)
4231 debug("Now already in F3 mode %d\n", configfile_mode
);
4235 if (args
[1][0] == '0')
4237 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4238 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4242 g_ventoy_last_entry
= -1;
4243 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4244 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4247 configfile_mode
= 1;
4248 grub_script_execute_sourcecode(memfile
);
4249 configfile_mode
= 0;
4255 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4266 g_ventoy_case_insensitive
= 1;
4267 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4268 g_ventoy_case_insensitive
= 0;
4274 grub_file_close(file
);
4280 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4285 const char *isopath
= NULL
;
4287 ventoy_mbr_head mbr
;
4294 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4297 isopath
= grub_env_get("vtoy_iso_part");
4300 debug("isopath is null %p\n", isopath
);
4304 debug("isopath is %s\n", isopath
);
4306 for (id
= 0; id
< 30 && (find
== 0); id
++)
4308 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4309 if (grub_strstr(isopath
, hdname
))
4311 debug("skip %s ...\n", hdname
);
4315 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4317 disk
= grub_disk_open(hdname
);
4320 debug("%s not exist\n", hdname
);
4324 grub_memset(&mbr
, 0, sizeof(mbr
));
4325 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4327 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4329 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4330 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4333 grub_env_set(args
[0], hdname
);
4337 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4341 debug("read %s failed\n", hdname
);
4344 grub_disk_close(disk
);
4350 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4361 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4364 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4367 debug("failed to open file %s\n", args
[0]);
4371 buf
= grub_malloc(len
);
4378 grub_file_read(file
, buf
, len
- 1);
4380 ventoy_get_line(buf
);
4381 ventoy_set_env(args
[1], buf
);
4385 grub_check_free(buf
);
4386 grub_file_close(file
);
4391 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4393 grub_uint64_t end_max
= 0;
4394 int *pCnt
= (int *)data
;
4399 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4400 "0 %llu linear /dev/ventoy %llu\n",
4401 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4403 end_max
= (partition
->len
+ partition
->start
) * 512;
4404 if (end_max
> g_part_end_max
)
4406 g_part_end_max
= end_max
;
4412 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4415 char *device_name
= NULL
;
4416 grub_device_t dev
= NULL
;
4421 g_part_list_pos
= 0;
4423 grub_env_unset("vtoy_img_part_file");
4430 device_name
= grub_file_get_device_name(args
[0]);
4433 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4437 dev
= grub_device_open(device_name
);
4440 debug("grub_device_open failed, %s\n", device_name
);
4444 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4446 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4447 grub_env_set("vtoy_img_part_file", buf
);
4449 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4450 grub_env_set("vtoy_img_part_cnt", buf
);
4452 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4453 grub_env_set("vtoy_img_max_part_end", buf
);
4457 check_free(device_name
, grub_free
);
4458 check_free(dev
, grub_device_close
);
4464 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4475 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4478 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4481 debug("failed to open file %s\n", args
[0]);
4485 buf
= grub_malloc(file
->size
+ 1);
4491 buf
[file
->size
] = 0;
4492 grub_file_read(file
, buf
, file
->size
);
4494 if (grub_strstr(buf
, args
[1]))
4501 grub_check_free(buf
);
4502 grub_file_close(file
);
4507 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4513 ventoy_iso9660_vd pvd
;
4520 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4523 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4526 debug("failed to open file %s\n", args
[0]);
4530 grub_file_seek(file
, 16 * 2048);
4531 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4532 if (len
!= sizeof(pvd
))
4534 debug("failed to read pvd %d\n", len
);
4538 grub_memset(buf
, 0, sizeof(buf
));
4539 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4540 ventoy_set_env(args
[1], buf
);
4542 grub_memset(buf
, 0, sizeof(buf
));
4543 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4544 ventoy_set_env(args
[2], buf
);
4548 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4549 ventoy_set_env(args
[3], buf
);
4552 grub_file_close(file
);
4557 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4568 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4571 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4574 debug("failed to open file %s\n", args
[0]);
4578 grub_memset(buf
, 0, sizeof(buf
));
4579 grub_file_seek(file
, 16 * 2048 + 813);
4580 len
= (int)grub_file_read(file
, buf
, 17);
4583 debug("failed to read create date %d\n", len
);
4587 ventoy_set_env(args
[1], buf
);
4590 grub_file_close(file
);
4595 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4601 ventoy_env_hook_root(1);
4606 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4612 ventoy_env_hook_root(0);
4617 #ifdef GRUB_MACHINE_EFI
4618 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4623 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4629 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4630 if (var
&& *var
== 1)
4638 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4647 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4652 grub_uint64_t FileSectors
= 0;
4653 ventoy_gpt_info
*gpt
= NULL
;
4654 ventoy_part_table
*pt
= NULL
;
4655 grub_uint8_t zeroguid
[16] = {0};
4660 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4663 debug("failed to open file %s\n", args
[0]);
4667 if (file
->size
% 512)
4669 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4673 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4679 FileSectors
= file
->size
/ 512;
4681 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4682 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4684 debug("This is EFI partition table\n");
4686 for (i
= 0; i
< 128; i
++)
4688 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4690 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4692 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4693 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4701 debug("This is MBR partition table\n");
4703 for (i
= 0; i
< 4; i
++)
4705 pt
= gpt
->MBR
.PartTbl
+ i
;
4706 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4708 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4709 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4710 (ulonglong
)FileSectors
);
4719 grub_file_close(file
);
4720 grub_check_free(gpt
);
4721 grub_errno
= GRUB_ERR_NONE
;
4725 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4734 for (i
= 0; i
< 500; i
++)
4736 ret
= grub_getkey_noblock();
4737 if (ret
== GRUB_TERM_NO_KEY
)
4746 grub_printf("\n\n Still have key input after clear.\n");
4754 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4761 int image_sector_size
;
4763 ventoy_chain_head
*chain
;
4764 ventoy_img_chunk
*chunk
;
4765 ventoy_os_param
*osparam
;
4766 ventoy_image_location
*location
;
4767 ventoy_image_disk_region
*region
;
4768 struct grub_acpi_table_header
*acpi
;
4777 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4779 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4785 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4787 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4789 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4793 img_chunk_num
= chain
->img_chunk_num
;
4795 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4796 datalen
= sizeof(ventoy_os_param
) + loclen
;
4798 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4799 acpi
= grub_zalloc(buflen
);
4805 /* Step1: Fill acpi table header */
4806 grub_memcpy(acpi
->signature
, "VTOY", 4);
4807 acpi
->length
= buflen
;
4809 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4810 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4812 acpi
->creator_id
[0] = 1;
4813 acpi
->creator_rev
= 1;
4815 /* Step2: Fill data */
4816 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4817 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4818 osparam
->vtoy_img_location_addr
= 0;
4819 osparam
->vtoy_img_location_len
= loclen
;
4820 osparam
->chksum
= 0;
4821 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4823 location
= (ventoy_image_location
*)(osparam
+ 1);
4824 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4825 location
->image_sector_size
= image_sector_size
;
4826 location
->disk_sector_size
= chain
->disk_sector_size
;
4827 location
->region_count
= img_chunk_num
;
4829 region
= location
->regions
;
4830 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4831 if (512 == image_sector_size
)
4833 for (i
= 0; i
< img_chunk_num
; i
++)
4835 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4836 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4837 region
->disk_start_sector
= chunk
->disk_start_sector
;
4844 for (i
= 0; i
< img_chunk_num
; i
++)
4846 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4847 region
->image_start_sector
= chunk
->img_start_sector
;
4848 region
->disk_start_sector
= chunk
->disk_start_sector
;
4854 /* Step3: Fill acpi checksum */
4856 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4858 /* load acpi table */
4859 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4860 grub_script_execute_sourcecode(cmd
);
4864 VENTOY_CMD_RETURN(0);
4867 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4873 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4874 g_ventoy_last_entry
= -1;
4879 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4885 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4890 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4892 const char *pos
= filename
+ 1;
4900 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4902 grub_strncpy((char *)data
, filename
, 128);
4913 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4916 char *device_name
= NULL
;
4917 grub_device_t dev
= NULL
;
4918 grub_fs_t fs
= NULL
;
4919 char buf
[128] = {0};
4925 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4929 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4931 device_name
= grub_file_get_device_name(args
[0]);
4934 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4938 dev
= grub_device_open(device_name
);
4941 debug("grub_device_open failed, %s\n", device_name
);
4945 fs
= grub_fs_probe(dev
);
4948 debug("grub_fs_probe failed, %s\n", device_name
);
4952 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4956 ventoy_set_env(args
[2], buf
);
4963 check_free(device_name
, grub_free
);
4964 check_free(dev
, grub_device_close
);
4969 int ventoy_load_part_table(const char *diskname
)
4976 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4977 if (!g_ventoy_part_info
)
4982 disk
= grub_disk_open(diskname
);
4985 debug("Failed to open disk %s\n", diskname
);
4989 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4991 g_ventoy_disk_bios_id
= disk
->id
;
4993 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4994 grub_disk_close(disk
);
4996 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4997 dev
= grub_device_open(name
);
5000 /* Check for official Ventoy device */
5001 ret
= ventoy_check_official_device(dev
);
5002 grub_device_close(dev
);
5010 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5011 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5016 static void ventoy_prompt_end(void)
5021 grub_printf("\n\n\n");
5022 grub_printf(" 1 --- Exit grub\n");
5023 grub_printf(" 2 --- Reboot\n");
5024 grub_printf(" 3 --- Shut down\n");
5025 grub_printf("Please enter your choice: ");
5031 if (c
>= '1' && c
<= '3')
5036 grub_printf("%c", c
);
5040 else if (c
== '\r' || c
== '\n')
5054 grub_script_execute_sourcecode("halt");
5063 grub_printf("\rPlease enter your choice: ");
5064 grub_printf("\rPlease enter your choice: ");
5071 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5078 ret
= ventoy_load_part_table(args
[0]);
5081 ventoy_prompt_end();
5084 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
5085 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
5090 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5093 const char *vcfg
= NULL
;
5098 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5101 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5102 grub_env_set(args
[1], vcfg
);
5107 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5115 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5118 grub_uint8_t zeroguid
[16] = {0};
5123 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5126 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5128 if (id
>= 1 && id
<= 128)
5130 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5138 if (id
>= 1 && id
<= 4)
5140 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5150 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5153 char *device_name
= NULL
;
5154 grub_device_t dev
= NULL
;
5155 grub_fs_t fs
= NULL
;
5160 debug("get fs label for %s\n", args
[0]);
5164 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5168 device_name
= grub_file_get_device_name(args
[0]);
5171 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5175 dev
= grub_device_open(device_name
);
5178 debug("grub_device_open failed, %s\n", device_name
);
5182 fs
= grub_fs_probe(dev
);
5183 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5185 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5189 fs
->fs_label(dev
, &label
);
5192 debug("label=<%s>\n", label
);
5193 ventoy_set_env(args
[1], label
);
5201 check_free(device_name
, grub_free
);
5202 check_free(dev
, grub_device_close
);
5207 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5211 grub_snprintf((char *)data
, 256, "%s", filename
);
5218 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5220 if (info
->dir
&& filename
&& filename
[0] != '.')
5222 grub_snprintf((char *)data
, 256, "%s", filename
);
5229 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5232 char *device_name
= NULL
;
5233 grub_device_t dev
= NULL
;
5234 grub_fs_t fs
= NULL
;
5235 char name
[256] ={0};
5239 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5243 device_name
= grub_file_get_device_name(args
[0]);
5246 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5250 dev
= grub_device_open(device_name
);
5253 debug("grub_device_open failed, %s\n", device_name
);
5257 fs
= grub_fs_probe(dev
);
5260 debug("grub_fs_probe failed, %s\n", device_name
);
5264 fs
->fs_dir(dev
, args
[1], hook
, name
);
5267 ventoy_set_env(args
[2], name
);
5274 check_free(device_name
, grub_free
);
5275 check_free(dev
, grub_device_close
);
5280 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5283 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5286 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5289 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5292 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5302 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5306 for (pos
= args
[0]; *pos
; pos
++)
5320 grub_env_set(args
[1], args
[0]);
5330 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5340 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5345 len
= (int)grub_strlen(buf
);
5346 for (i
= len
; i
> 0; i
--)
5348 if (buf
[i
- 1] == '/')
5350 grub_env_set(args
[1], buf
+ i
);
5355 grub_env_set(args
[1], buf
);
5360 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5362 struct grub_video_mode_info info
;
5369 if (!g_video_mode_list
)
5371 ventoy_enum_video_mode();
5374 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5376 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5380 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5383 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5385 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5386 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5388 VENTOY_CMD_RETURN(0);
5391 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5393 struct grub_video_mode_info info
;
5400 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5402 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5406 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5409 grub_env_set(args
[0], buf
);
5411 VENTOY_CMD_RETURN(0);
5414 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5422 if (!g_video_mode_list
)
5427 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5428 if (id
< g_video_mode_num
)
5430 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5431 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5434 grub_env_set(args
[1], buf
);
5436 VENTOY_CMD_RETURN(0);
5439 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5442 grub_uint32_t loadsector
= 0;
5445 grub_uint32_t boot_catlog
= 0;
5446 grub_uint8_t buf
[512];
5452 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5456 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5459 debug("failed to open %s\n", args
[0]);
5463 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5464 if (boot_catlog
== 0)
5466 debug("No bootcatlog found\n");
5467 grub_file_close(file
);
5471 grub_memset(buf
, 0, sizeof(buf
));
5472 grub_file_seek(file
, boot_catlog
* 2048);
5473 grub_file_read(file
, buf
, sizeof(buf
));
5474 grub_file_close(file
);
5476 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5478 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5480 if (buf
[i
+ 32] == 0x88)
5482 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5483 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5489 if (loadsector
== 0)
5491 debug("No EFI eltorito info found\n");
5495 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5496 grub_env_set(args
[1], value
);
5497 VENTOY_CMD_RETURN(0);
5500 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5505 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5507 if (pfsdir
->initrd
[0])
5512 curpos
= pfsdir
->curpos
;
5513 len
= grub_strlen(filename
);
5517 if ((len
== 1 && filename
[0] == '.') ||
5518 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5523 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5526 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5527 pfsdir
->curpos
= curpos
+ printlen
;
5528 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5529 pfsdir
->curpos
= curpos
;
5530 pfsdir
->fullpath
[curpos
] = 0;
5534 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5537 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5538 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5540 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5542 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5551 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5555 char *device_name
= NULL
;
5556 grub_device_t dev
= NULL
;
5557 grub_fs_t fs
= NULL
;
5558 replace_fs_dir
*pfsdir
= NULL
;
5564 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5568 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5574 device_name
= grub_file_get_device_name(args
[0]);
5580 dev
= grub_device_open(device_name
);
5586 fs
= grub_fs_probe(dev
);
5595 pfsdir
->fullpath
[0] = '/';
5596 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5598 if (pfsdir
->initrd
[0])
5600 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5602 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5604 if (pfsdir
->initrd
[i
] == '/')
5606 pfsdir
->initrd
[i
] = '\\';
5610 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5611 grub_env_set(args
[1], pos
);
5615 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5620 grub_check_free(pfsdir
);
5621 grub_check_free(device_name
);
5622 check_free(dev
, grub_device_close
);
5624 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5627 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5629 const char *pager
= NULL
;
5635 pager
= grub_env_get("pager");
5639 grub_env_set("pager", "1");
5641 else if (pager
[0] == '1')
5647 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5649 grub_env_set("pager", "1");
5652 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5655 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5661 if (g_pager_flag
== 1)
5663 grub_env_unset("pager");
5665 else if (g_pager_flag
== 2)
5667 grub_env_set("pager", g_old_pager
);
5670 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5673 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5675 if (g_json_case_mis_path
[0])
5680 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5682 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5688 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5691 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5693 if (g_json_case_mis_path
[0])
5698 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5700 if (grub_strcasecmp(filename
, "ventoy") == 0)
5702 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5703 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5704 if (g_json_case_mis_path
[0])
5714 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5717 char *device_name
= NULL
;
5718 grub_device_t dev
= NULL
;
5719 grub_fs_t fs
= NULL
;
5720 chk_case_fs_dir fs_dir
;
5726 device_name
= grub_file_get_device_name(args
[0]);
5732 dev
= grub_device_open(device_name
);
5738 fs
= grub_fs_probe(dev
);
5744 fstype
= ventoy_get_fs_type(fs
->name
);
5745 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5750 g_json_case_mis_path
[0] = 0;
5753 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5755 if (g_json_case_mis_path
[0])
5757 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5762 grub_check_free(device_name
);
5763 check_free(dev
, grub_device_close
);
5765 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5768 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5771 grub_partition_t part
;
5772 char priority_str
[3]; /* Maximum value 15 */
5776 if (argc
< 2 || argc
> 3)
5777 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5778 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5780 /* Open the disk if it exists */
5781 disk
= grub_disk_open (args
[0]);
5784 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5788 part
= grub_partition_probe (disk
, args
[1]);
5791 grub_disk_close (disk
);
5792 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5793 "No such partition");
5796 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5798 grub_disk_close (disk
);
5799 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5800 "Not a GPT partition");
5803 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5804 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5808 grub_env_set (args
[2], priority_str
);
5809 grub_env_export (args
[2]);
5813 grub_printf ("Priority is %s\n", priority_str
);
5816 grub_disk_close (disk
);
5817 return GRUB_ERR_NONE
;
5821 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5825 grub_file_t file
= NULL
;
5826 grub_uint32_t loadrba
= 0;
5827 grub_uint32_t boot_catlog
= 0;
5828 grub_uint8_t sector
[512];
5829 boot_info_table
*info
= NULL
;
5834 /* This also trigger a iso9660 fs parse */
5835 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5840 joliet
= grub_iso9660_is_joliet();
5846 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5849 debug("failed to open %s\n", args
[0]);
5853 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5854 if (boot_catlog
== 0)
5856 debug("no bootcatlog found %u\n", boot_catlog
);
5860 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5863 debug("no bios eltorito rba found %u\n", loadrba
);
5867 grub_file_seek(file
, loadrba
* 2048);
5868 grub_file_read(file
, sector
, 512);
5870 info
= (boot_info_table
*)sector
;
5871 if (info
->bi_data0
== 0x7c6ceafa &&
5872 info
->bi_data1
== 0x90900000 &&
5873 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5874 info
->bi_BootFileLocation
== loadrba
)
5876 debug("bootloader is syslinux, %u.\n", loadrba
);
5882 grub_file_close(file
);
5883 grub_errno
= GRUB_ERR_NONE
;
5887 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5890 ventoy_vlnk_part
*node
;
5896 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5898 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5899 ++n
, node
->device
, node
->disksig
,
5900 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5906 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5914 len
= (int)grub_strlen(args
[0]);
5915 if (grub_file_is_vlnk_suffix(args
[0], len
))
5924 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5927 const char *name
= NULL
;
5933 grub_env_unset(args
[1]);
5934 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5937 debug("VLNK SRC: <%s>\n", args
[0]);
5938 debug("VLNK DST: <%s>\n", name
);
5939 grub_env_set(args
[1], name
);
5947 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5951 grub_file_t file
= NULL
;
5962 len
= (int)grub_strlen(args
[0]);
5963 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5965 grub_printf("Invalid vlnk suffix\n");
5969 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5972 grub_printf("Failed to open %s\n", args
[0]);
5976 if (file
->size
!= 32768)
5978 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5982 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5983 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5985 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5990 check_free(file
, grub_file_close
);
5991 grub_errno
= GRUB_ERR_NONE
;
5995 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6001 g_iso_vd_id_publisher
[0] = 0;
6002 g_iso_vd_id_prepare
[0] = 0;
6003 g_iso_vd_id_application
[0] = 0;
6008 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6012 grub_file_t file
= NULL
;
6017 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
6020 grub_printf("Failed to open %s\n", args
[0]);
6024 grub_file_seek(file
, 16 * 2048 + offset
);
6025 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
6028 grub_file_seek(file
, 16 * 2048 + offset
);
6029 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
6032 grub_file_seek(file
, 16 * 2048 + offset
);
6033 grub_file_read(file
, g_iso_vd_id_application
, 128);
6037 check_free(file
, grub_file_close
);
6038 grub_errno
= GRUB_ERR_NONE
;
6042 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6045 char *id
= g_iso_vd_id_publisher
;
6050 if (args
[0][0] == '1')
6052 id
= g_iso_vd_id_prepare
;
6054 else if (args
[0][0] == '2')
6056 id
= g_iso_vd_id_application
;
6059 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6064 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
6069 grub_errno
= GRUB_ERR_NONE
;
6073 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6078 g_ventoy_fn_mutex
= 0;
6079 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
6081 g_ventoy_fn_mutex
= 1;
6084 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6087 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6089 grub_uint64_t total
;
6090 grub_uint64_t org_required
;
6091 grub_uint64_t new_required
;
6097 #ifdef GRUB_MACHINE_EFI
6098 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6099 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6100 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6101 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6106 grub_printf("Non EFI mode!\n");
6111 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6114 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6116 const char *env
= NULL
;
6121 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6126 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6127 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6128 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6129 ventoy_check_mode_by_name(args
[0], "vtnormal")
6135 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6136 if (env
&& env
[0] == '0' && env
[1] == 0)
6144 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6152 const char *env
= NULL
;
6153 ulonglong fsize
= 0;
6155 int seldata
[16] = {0};
6160 len
= 8 * VTOY_SIZE_1KB
;
6161 cmd
= (char *)grub_malloc(len
);
6167 g_vtoy_secondary_need_recover
= 0;
6168 grub_env_unset("VTOY_SECOND_EXIT");
6169 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6171 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6174 timeout
= (int)grub_strtol(env
, NULL
, 10);
6179 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6182 fsize
= grub_strtoull(args
[2], NULL
, 10);
6184 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_NORMAL_MODE", "second_normal"); seldata
[n
++] = 1;
6186 if (grub_strcmp(args
[1], "Unix") != 0)
6188 if (grub_strcmp(args
[1], "Windows") == 0)
6190 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_WIMBOOT_MODE", "second_wimboot"); seldata
[n
++] = 2;
6194 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_GRUB2_MODE", "second_grub2"); seldata
[n
++] = 3;
6197 if (fsize
<= VTOY_SIZE_1GB
)
6199 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_MEMDISK_MODE", "second_memdisk"); seldata
[n
++] = 4;
6203 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_FILE_CHKSUM", "second_checksum"); seldata
[n
++] = 5;
6204 vtoy_dummy_menuentry(cmd
, pos
, len
, "$VTLANG_RETURN_PRV_NOESC", "second_return"); seldata
[n
++] = 6;
6207 grub_errno
= GRUB_ERR_NONE
;
6208 g_ventoy_menu_esc
= 1;
6209 g_ventoy_suppress_esc
= 1;
6210 g_ventoy_suppress_esc_default
= 0;
6211 g_ventoy_secondary_menu_on
= 1;
6212 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6213 grub_script_execute_sourcecode(cfgfile
);
6214 g_ventoy_menu_esc
= 0;
6215 g_ventoy_suppress_esc
= 0;
6216 g_ventoy_suppress_esc_default
= 1;
6217 g_ventoy_secondary_menu_on
= 0;
6219 select
= seldata
[g_ventoy_last_entry
];
6223 g_ventoy_wimboot_mode
= 1;
6224 g_vtoy_secondary_need_recover
= 1;
6226 else if (select
== 3)
6228 g_ventoy_grub2_mode
= 1;
6229 g_vtoy_secondary_need_recover
= 2;
6231 else if (select
== 4)
6233 g_ventoy_memdisk_mode
= 1;
6234 g_vtoy_secondary_need_recover
= 3;
6236 else if (select
== 5)
6238 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6239 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6241 else if (select
== 6)
6243 grub_env_set("VTOY_SECOND_EXIT", "1");
6245 }while (select
== 5);
6248 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6251 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6257 if (g_vtoy_secondary_need_recover
== 1)
6259 g_ventoy_wimboot_mode
= 0;
6261 else if (g_vtoy_secondary_need_recover
== 2)
6263 g_ventoy_grub2_mode
= 0;
6265 else if (g_vtoy_secondary_need_recover
== 3)
6267 g_ventoy_memdisk_mode
= 0;
6270 g_vtoy_secondary_need_recover
= 0;
6272 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6275 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6280 if (args
[0][0] == '0')
6282 g_ventoy_case_insensitive
= 0;
6286 g_ventoy_case_insensitive
= 1;
6292 static grub_err_t
ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6297 ventoy_plugin_load_menu_lang(1, args
[0]);
6298 VENTOY_CMD_RETURN(0);
6301 static grub_err_t
ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6306 ventoy_plugin_load_menu_lang(0, args
[0]);
6307 VENTOY_CMD_RETURN(0);
6310 static int ventoy_chksum_pathcmp(int chktype
, char *rlpath
, char *rdpath
)
6317 pos1
= ventoy_str_basename(rlpath
);
6318 pos2
= ventoy_str_basename(rdpath
);
6319 return grub_strcmp(pos1
, pos2
);
6321 else if (chktype
== 3 || chktype
== 4)
6323 if (grub_strcmp(rlpath
, rdpath
) == 0 || grub_strcmp(rlpath
+ 1, rdpath
) == 0)
6332 static int ventoy_find_checksum
6347 char *currline
= NULL
;
6348 char *nextline
= NULL
;
6350 ulen
= (int)grub_strlen(uname
);
6352 /* read file to buffer */
6353 buf
= grub_malloc(file
->size
+ 4);
6358 grub_file_read(file
, buf
, file
->size
);
6359 buf
[file
->size
] = 0;
6361 /* parse each line */
6362 for (currline
= buf
; currline
; currline
= nextline
)
6364 nextline
= ventoy_get_line(currline
);
6365 VTOY_SKIP_SPACE(currline
);
6367 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6369 pos
= grub_strchr(currline
, '=');
6370 pos1
= grub_strchr(currline
, '(');
6371 pos2
= grub_strchr(currline
, ')');
6373 if (pos
&& pos1
&& pos2
)
6376 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6378 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6379 grub_memcpy(chksum
, pos
, retlen
);
6384 else if (ventoy_str_len_alnum(currline
, retlen
))
6386 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, retlen
);
6387 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6389 grub_memcpy(chksum
, currline
, retlen
);
6400 static int ventoy_check_chkfile(const char *isopart
, char *path
, const char *lchkname
, grub_file_t
*pfile
)
6406 grub_file_t file
= NULL
;
6408 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s.%s", isopart
, path
, lchkname
);
6414 cnt
= ventoy_str_chrcnt(path
, '/');
6417 pos
= grub_strrchr(path
, '/');
6421 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, path
);
6430 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6433 ret
= (cnt
> 1) ? 3 : 4;
6444 check_free(file
, grub_file_close
);
6449 static grub_err_t
ventoy_cmd_cmp_checksum(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6454 grub_file_t file
= NULL
;
6455 const char *calc_value
= NULL
;
6456 const char *isopart
= NULL
;
6458 char readchk
[256] = {0};
6459 char filebuf
[512] = {0};
6464 index
= (int)grub_strtol(args
[0], NULL
, 10);
6465 if (argc
!= 2 || index
< 0 || index
>= VTOY_CHKSUM_NUM
)
6470 grub_strncpy(uchkname
, g_lower_chksum_name
[index
], sizeof(uchkname
));
6471 ventoy_str_toupper(uchkname
);
6473 isopart
= grub_env_get("vtoy_iso_part");
6474 calc_value
= grub_env_get("VT_LAST_CHECK_SUM");
6476 chktype
= ventoy_check_chkfile(isopart
, args
[1], g_lower_chksum_name
[index
], &file
);
6479 grub_printf("\n\nNo checksum file found.\n");
6485 grub_snprintf(fchksum
, sizeof(fchksum
), ".%s", g_lower_chksum_name
[index
]);
6486 grub_memset(filebuf
, 0, sizeof(filebuf
));
6487 grub_file_read(file
, filebuf
, 511);
6489 pos
= grub_strchr(filebuf
, '=');
6492 VTOY_SKIP_SPACE_NEXT(pos
, 1);
6493 grub_memcpy(readchk
, pos
, g_chksum_retlen
[index
]);
6497 grub_memcpy(readchk
, filebuf
, g_chksum_retlen
[index
]);
6500 else if (chktype
== 3 || chktype
== 4)
6502 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6503 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], chktype
, readchk
);
6504 if (readchk
[0] == 0)
6506 grub_printf("\n\n%s value not found in %s.\n", uchkname
, fchksum
);
6512 grub_snprintf(fchksum
, sizeof(fchksum
), "local VENTOY_CHECKSUM");
6513 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], chktype
, readchk
);
6514 if (readchk
[0] == 0)
6516 grub_file_close(file
);
6517 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6520 grub_snprintf(fchksum
, sizeof(fchksum
), "global VENTOY_CHECKSUM");
6521 ventoy_find_checksum(file
, uchkname
, g_chksum_retlen
[index
], args
[1], 3, readchk
);
6522 if (readchk
[0] == 0)
6524 grub_printf("\n\n%s value not found in both local and global VENTOY_CHECKSUM.\n", uchkname
);
6531 if (grub_strcasecmp(calc_value
, readchk
) == 0)
6533 grub_printf("\n\nCheck %s value with %s file. [ SUCCESS ]\n", uchkname
, fchksum
);
6537 grub_printf("\n\nCheck %s value with %s file. [ ERROR ]\n", uchkname
, fchksum
);
6538 grub_printf("The %s value in %s file is:\n%s\n", uchkname
, fchksum
, readchk
);
6543 check_free(file
, grub_file_close
);
6544 VENTOY_CMD_RETURN(0);
6547 static int ventoy_find_all_checksum
6552 int exists
[VTOY_CHKSUM_NUM
],
6564 char *currline
= NULL
;
6565 char *nextline
= NULL
;
6566 const char *uname
= NULL
;
6570 /* read file to buffer */
6571 buf
= grub_malloc(file
->size
+ 4);
6576 grub_file_read(file
, buf
, file
->size
);
6577 buf
[file
->size
] = 0;
6579 /* parse each line */
6580 for (currline
= buf
; currline
; currline
= nextline
)
6582 nextline
= ventoy_get_line(currline
);
6583 VTOY_SKIP_SPACE(currline
);
6585 for (i
= 0; i
< VTOY_CHKSUM_NUM
; i
++)
6592 uname
= g_lower_chksum_name
[i
];
6593 ulen
= g_lower_chksum_namelen
[i
];
6595 if (grub_strncasecmp(currline
, uname
, ulen
) == 0)
6597 pos
= grub_strchr(currline
, '=');
6598 pos1
= grub_strchr(currline
, '(');
6599 pos2
= grub_strchr(currline
, ')');
6601 if (pos
&& pos1
&& pos2
)
6605 if (ventoy_chksum_pathcmp(chktype
, path
, pos1
+ 1) == 0)
6613 else if (ventoy_str_len_alnum(currline
, g_chksum_retlen
[i
]))
6615 VTOY_SKIP_SPACE_NEXT_EX(pos
, currline
, g_chksum_retlen
[i
]);
6616 if (ventoy_chksum_pathcmp(chktype
, path
, pos
) == 0)
6623 if (tot
>= VTOY_CHKSUM_NUM
)
6637 static grub_err_t
ventoy_cmd_vtoychksum_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6644 grub_file_t file
= NULL
;
6645 const char *isopart
= NULL
;
6646 int exists
[VTOY_CHKSUM_NUM
] = { 0, 0, 0, 0 };
6652 isopart
= grub_env_get("vtoy_iso_part");
6654 for (i
= 0; i
< VTOY_CHKSUM_NUM
; i
++)
6656 if (ventoy_check_file_exist("%s%s.%s", isopart
, args
[0], g_lower_chksum_name
[i
]))
6663 if (totexist
== VTOY_CHKSUM_NUM
)
6668 cnt
= ventoy_str_chrcnt(args
[0], '/');
6671 pos
= grub_strrchr(args
[0], '/');
6674 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s/VENTOY_CHECKSUM", isopart
, args
[0]);
6679 if (tip
== 0 && file
->size
> (32 * VTOY_SIZE_1KB
))
6682 grub_printf("Reading checksum file...\n");
6686 debug("parse local VENTOY_CHECKSUM\n");
6687 ventoy_find_all_checksum(file
, args
[0], 2, exists
, &totexist
);
6688 grub_file_close(file
);
6692 if (totexist
== VTOY_CHKSUM_NUM
)
6697 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s/VENTOY_CHECKSUM", isopart
);
6700 if (tip
== 0 && file
->size
> (32 * VTOY_SIZE_1KB
))
6703 grub_printf("Reading checksum file...\n");
6707 debug("parse global VENTOY_CHECKSUM\n");
6708 ventoy_find_all_checksum(file
, args
[0], (cnt
> 1) ? 3 : 4, exists
, &totexist
);
6709 grub_file_close(file
);
6714 ventoy_env_int_set("VT_EXIST_MD5", exists
[0]);
6715 ventoy_env_int_set("VT_EXIST_SHA1", exists
[1]);
6716 ventoy_env_int_set("VT_EXIST_SHA256", exists
[2]);
6717 ventoy_env_int_set("VT_EXIST_SHA512", exists
[3]);
6719 VENTOY_CMD_RETURN(0);
6723 static const char * ventoy_menu_lang_read_hook(struct grub_env_var
*var
, const char *val
)
6726 return ventoy_get_vmenu_title(val
);
6729 int ventoy_env_init(void)
6734 grub_env_set("vtdebug_flag", "");
6736 grub_register_vtoy_menu_lang_hook(ventoy_menu_lang_read_hook
);
6737 ventoy_ctrl_var_init();
6738 ventoy_global_var_init();
6740 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6741 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6742 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6743 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6745 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6748 ventoy_filt_register(0, ventoy_wrapper_open
);
6750 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6753 g_grub_param
->grub_env_get
= grub_env_get
;
6754 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6755 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6756 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6757 grub_env_set("env_param", buf
);
6758 grub_env_set("ventoy_env_param", buf
);
6760 grub_env_export("env_param");
6761 grub_env_export("ventoy_env_param");
6764 grub_env_export("vtoy_winpeshl_ini_addr");
6765 grub_env_export("vtoy_winpeshl_ini_size");
6767 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6768 grub_env_set("vtoy_chain_file_size", buf
);
6769 grub_env_export("vtoy_chain_file_size");
6771 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6772 grub_env_set("vtoy_chain_file_read", buf
);
6773 grub_env_export("vtoy_chain_file_read");
6775 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_get_vmenu_title
);
6776 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf
);
6777 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6779 grub_snprintf(buf
, sizeof(buf
), "%s-%s", GRUB_TARGET_CPU
, GRUB_PLATFORM
);
6780 grub_env_set("grub_cpu_platform", buf
);
6781 grub_env_export("grub_cpu_platform");
6788 static cmd_para ventoy_cmds
[] =
6790 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6791 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6792 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6793 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6794 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6795 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6796 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6797 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6798 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6799 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6800 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6801 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6802 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6803 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6804 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6805 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6806 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6807 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6808 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6809 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6810 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6811 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6812 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6813 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6814 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6815 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6816 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6818 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6819 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6820 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6821 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6822 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6823 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6824 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6826 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6827 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6828 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6829 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6830 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6831 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6832 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6833 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6834 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6835 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6838 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6839 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6840 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6841 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6842 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6843 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6844 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6845 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6846 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6847 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6848 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6850 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6851 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6852 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6853 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6854 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6855 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6856 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6858 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6859 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6860 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6861 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6862 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6863 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6864 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6865 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6866 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6867 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6869 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6870 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6871 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6872 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6873 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6874 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6875 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6876 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6877 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6879 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6880 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6881 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6882 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6885 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6886 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6887 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6889 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6890 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6891 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6894 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6895 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6896 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6897 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6898 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6899 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6900 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6901 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6902 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6903 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6904 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6905 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6906 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6907 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6909 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6910 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6911 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6912 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6913 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6914 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6915 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6916 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6917 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6918 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6919 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6920 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6922 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6923 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6924 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6925 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6926 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6927 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6928 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6929 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6930 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6931 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6932 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6933 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6934 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6935 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6936 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6937 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6938 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6939 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6940 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6941 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6942 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6943 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6944 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6945 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6946 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6947 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6948 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6949 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang
, 0, NULL
, "", "", NULL
},
6950 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang
, 0, NULL
, "", "", NULL
},
6951 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang
, 0, NULL
, "", "", NULL
},
6952 { "vt_vtoychksum_exist", ventoy_cmd_vtoychksum_exist
, 0, NULL
, "", "", NULL
},
6953 { "vt_cmp_checksum", ventoy_cmd_cmp_checksum
, 0, NULL
, "", "", NULL
},
6957 int ventoy_register_all_cmd(void)
6960 cmd_para
*cur
= NULL
;
6962 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6964 cur
= ventoy_cmds
+ i
;
6965 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6966 cur
->summary
, cur
->description
, cur
->parser
);
6972 int ventoy_unregister_all_cmd(void)
6976 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6978 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);