1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/random.h>
49 #include <grub/ventoy.h>
50 #include "ventoy_def.h"
53 GRUB_MOD_LICENSE ("GPLv3+");
55 static grub_uint8_t g_check_mbr_data
[] = {
56 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
62 initrd_info
*g_initrd_img_list
= NULL
;
63 initrd_info
*g_initrd_img_tail
= NULL
;
64 int g_initrd_img_count
= 0;
65 int g_valid_initrd_count
= 0;
66 int g_default_menu_mode
= 0;
67 int g_filt_dot_underscore_file
= 0;
68 int g_sort_case_sensitive
= 0;
69 int g_tree_view_menu_style
= 0;
70 static grub_file_t g_old_file
;
71 static int g_ventoy_last_entry_back
;
74 char g_img_swap_tmp_buf
[1024];
75 img_info g_img_swap_tmp
;
76 img_info
*g_ventoy_img_list
= NULL
;
78 int g_ventoy_img_count
= 0;
80 grub_device_t g_enum_dev
= NULL
;
81 grub_fs_t g_enum_fs
= NULL
;
82 int g_img_max_search_level
= -1;
83 img_iterator_node g_img_iterator_head
;
84 img_iterator_node
*g_img_iterator_tail
= NULL
;
86 grub_uint8_t g_ventoy_break_level
= 0;
87 grub_uint8_t g_ventoy_debug_level
= 0;
88 grub_uint8_t g_ventoy_chain_type
= 0;
90 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
91 grub_uint32_t g_ventoy_cpio_size
= 0;
92 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
93 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
95 int g_plugin_image_list
= 0;
97 ventoy_grub_param
*g_grub_param
= NULL
;
99 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
101 ventoy_img_chunk_list g_img_chunk_list
;
103 int g_wimboot_enable
= 0;
104 ventoy_img_chunk_list g_wimiso_chunk_list
;
105 char *g_wimiso_path
= NULL
;
106 grub_uint32_t g_wimiso_size
= 0;
108 int g_vhdboot_enable
= 0;
110 grub_uint64_t g_svd_replace_offset
= 0;
112 int g_conf_replace_count
= 0;
113 grub_uint64_t g_conf_replace_offset
[VTOY_MAX_CONF_REPLACE
] = { 0 };
114 conf_replace
*g_conf_replace_node
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
115 grub_uint8_t
*g_conf_replace_new_buf
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
116 int g_conf_replace_new_len
[VTOY_MAX_CONF_REPLACE
] = { 0 };
117 int g_conf_replace_new_len_align
[VTOY_MAX_CONF_REPLACE
] = { 0 };
119 int g_ventoy_disk_bios_id
= 0;
120 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
121 grub_uint64_t g_ventoy_disk_size
= 0;
122 grub_uint64_t g_ventoy_disk_part_size
[2];
124 char *g_tree_script_buf
= NULL
;
125 int g_tree_script_pos
= 0;
126 int g_tree_script_pre
= 0;
128 static char *g_list_script_buf
= NULL
;
129 static int g_list_script_pos
= 0;
131 static char *g_part_list_buf
= NULL
;
132 static int g_part_list_pos
= 0;
133 static grub_uint64_t g_part_end_max
= 0;
135 static int g_video_mode_max
= 0;
136 static int g_video_mode_num
= 0;
137 static ventoy_video_mode
*g_video_mode_list
= NULL
;
139 static int g_enumerate_time_checked
= 0;
140 static grub_uint64_t g_enumerate_start_time_ms
;
141 static grub_uint64_t g_enumerate_finish_time_ms
;
142 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
144 static char g_iso_vd_id_publisher
[130];
145 static char g_iso_vd_id_prepare
[130];
146 static char g_iso_vd_id_application
[130];
148 static int g_pager_flag
= 0;
149 static char g_old_pager
[32];
151 const char *g_menu_class
[img_type_max
] =
153 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
156 const char *g_menu_prefix
[img_type_max
] =
158 "iso", "wim", "efi", "img", "vhd", "vtoy"
161 static int g_vtoy_secondary_need_recover
= 0;
163 static int g_vtoy_load_prompt
= 0;
164 static char g_vtoy_prompt_msg
[64];
166 static char g_json_case_mis_path
[32];
168 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
170 int ventoy_get_fs_type(const char *fs
)
174 return ventoy_fs_max
;
176 else if (grub_strncmp(fs
, "exfat", 5) == 0)
178 return ventoy_fs_exfat
;
180 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
182 return ventoy_fs_ntfs
;
184 else if (grub_strncmp(fs
, "ext", 3) == 0)
186 return ventoy_fs_ext
;
188 else if (grub_strncmp(fs
, "xfs", 3) == 0)
190 return ventoy_fs_xfs
;
192 else if (grub_strncmp(fs
, "udf", 3) == 0)
194 return ventoy_fs_udf
;
196 else if (grub_strncmp(fs
, "fat", 3) == 0)
198 return ventoy_fs_fat
;
201 return ventoy_fs_max
;
204 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
223 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
225 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
229 static int ventoy_control_get_flag(const char *key
)
231 const char *val
= ventoy_get_env(key
);
233 if (val
&& val
[0] == '1' && val
[1] == 0)
240 static grub_err_t
ventoy_fs_close(grub_file_t file
)
242 grub_file_close(g_old_file
);
243 grub_free(file
->data
);
251 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
257 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
262 for (i
= 0; i
< g_video_mode_num
; i
++)
264 if (g_video_mode_list
[i
].width
== info
->width
&&
265 g_video_mode_list
[i
].height
== info
->height
&&
266 g_video_mode_list
[i
].bpp
== info
->bpp
)
272 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
273 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
274 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
277 if (g_video_mode_num
== g_video_mode_max
)
279 g_video_mode_max
*= 2;
280 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
286 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
288 if (v1
->bpp
== v2
->bpp
)
290 if (v1
->width
== v2
->width
)
292 if (v1
->height
== v2
->height
)
298 return (v1
->height
< v2
->height
) ? -1 : 1;
303 return (v1
->width
< v2
->width
) ? -1 : 1;
308 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
312 static int ventoy_enum_video_mode(void)
315 grub_video_adapter_t adapter
;
316 grub_video_driver_id_t id
;
317 ventoy_video_mode mode
;
319 g_video_mode_num
= 0;
320 g_video_mode_max
= 1024;
321 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
322 if (!g_video_mode_list
)
327 #ifdef GRUB_MACHINE_PCBIOS
328 grub_dl_load ("vbe");
331 id
= grub_video_get_driver_id ();
333 FOR_VIDEO_ADAPTERS (adapter
)
335 if (!adapter
->iterate
||
336 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
337 adapter
->init() != GRUB_ERR_NONE
)))
342 adapter
->iterate(ventoy_video_hook
, NULL
);
344 if (adapter
->id
!= id
)
350 /* sort video mode */
351 for (i
= 0; i
< g_video_mode_num
; i
++)
352 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
354 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
356 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
357 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
358 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
362 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
365 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
369 static struct grub_fs vtoy_fs
=
374 .fs_read
= ventoy_fs_read
,
375 .fs_close
= ventoy_fs_close
,
385 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
391 file
->data
= grub_malloc(rawFile
->size
+ 4096);
397 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
398 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
400 g_old_file
= rawFile
;
402 file
->size
= rawFile
->size
+ len
;
403 file
->device
= rawFile
->device
;
405 file
->not_easily_seekable
= 1;
410 static int ventoy_check_decimal_var(const char *name
, long *value
)
412 const char *value_str
= NULL
;
414 value_str
= grub_env_get(name
);
415 if (NULL
== value_str
)
417 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
420 if (!ventoy_is_decimal(value_str
))
422 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
425 *value
= grub_strtol(value_str
, NULL
, 10);
427 return GRUB_ERR_NONE
;
430 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
432 grub_uint64_t sectors
;
434 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
436 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
440 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
443 return sectors
* 512;
446 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
452 grub_uint32_t offset
;
454 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
457 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
461 len
= (int)file
->size
;
463 data
= (char *)grub_malloc(file
->size
);
469 grub_file_read(file
, data
, file
->size
);
470 grub_file_close(file
);
472 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
473 grub_script_execute_sourcecode(exec
);
475 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
476 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
477 grub_file_close(file
);
479 grub_script_execute_sourcecode("loopback -d efiboot");
483 *direntoff
= offset
+ 2;
488 static int ventoy_set_check_result(int ret
, const char *msg
)
492 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
493 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
494 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
498 grub_printf(VTOY_WARNING
"\n");
499 grub_printf(VTOY_WARNING
"\n");
500 grub_printf(VTOY_WARNING
"\n\n\n");
502 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
503 grub_printf("Error message: <%s>\n\n", msg
);
504 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
506 grub_printf("\n\nWill exit after 10 seconds ...... ");
514 static int ventoy_check_official_device(grub_device_t dev
)
518 grub_uint64_t offset
;
521 grub_uint8_t mbr
[512];
525 struct grub_partition
*partition
;
527 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
529 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
532 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
533 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
534 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
536 #ifndef GRUB_MACHINE_EFI
537 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
539 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
541 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
543 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
545 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
547 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
556 /* We must have partition 2 */
559 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
563 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
567 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
570 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
572 grub_file_close(file
);
573 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
576 partition
= dev
->disk
->partition
;
577 if (partition
->number
!= 0 || partition
->start
!= 2048)
579 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
584 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
586 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
587 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
588 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
590 grub_file_close(file
);
591 return ventoy_set_check_result(6, "Disk partition layout check failed.");
596 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
597 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
598 PartTbl
[1].SectorCount
!= 65536)
600 grub_file_close(file
);
601 return ventoy_set_check_result(6, "Disk partition layout check failed.");
607 offset
= partition
->start
+ partition
->len
;
608 partition
= file
->device
->disk
->partition
;
609 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
611 grub_file_close(file
);
612 return ventoy_set_check_result(7, "Disk partition layout check failed.");
616 grub_file_close(file
);
620 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
621 dev2
= grub_device_open(devname
);
624 return ventoy_set_check_result(8, "Disk open failed");
627 fs
= grub_fs_probe(dev2
);
630 grub_device_close(dev2
);
631 return ventoy_set_check_result(9, "FS probe failed");
634 fs
->fs_label(dev2
, &label
);
635 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
637 grub_device_close(dev2
);
638 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
641 grub_device_close(dev2
);
645 disk
= grub_disk_open(dev
->disk
->name
);
648 return ventoy_set_check_result(11, "Disk open failed");
651 grub_memset(mbr
, 0, 512);
652 grub_disk_read(disk
, 0, 0, 512, mbr
);
653 grub_disk_close(disk
);
655 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
657 return ventoy_set_check_result(12, "MBR check failed");
660 return ventoy_set_check_result(0, NULL
);
663 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
667 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
677 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
679 grub_uint64_t size
= 0;
682 char fullpath
[256] = {0};
685 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
688 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
691 debug("grub_file_open failed <%s>\n", fullpath
);
697 grub_file_close(file
);
701 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
705 char fullpath
[512] = {0};
708 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
711 file
= grub_file_open(fullpath
, type
);
714 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
721 int ventoy_is_dir_exist(const char *fmt
, ...)
728 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
732 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
735 grub_strncpy(pos
+ len
, "\" ]", 3);
737 debug("script exec %s\n", buf
);
739 if (0 == grub_script_execute_sourcecode(buf
))
747 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
750 grub_uint8_t
*outbuf
;
751 grub_uint8_t gzHdr
[10] =
753 0x1F, 0x8B, /* magic */
761 grub_memset(&s
, 0, sizeof(mz_stream
));
763 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
765 outbuf
= (grub_uint8_t
*)mem_out
;
767 mem_out_len
-= sizeof(gzHdr
) + 8;
768 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
769 outbuf
+= sizeof(gzHdr
);
771 s
.avail_in
= mem_in_len
;
774 s
.avail_out
= mem_out_len
;
777 mz_deflate(&s
, MZ_FINISH
);
781 outbuf
+= s
.total_out
;
782 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
783 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
785 return s
.total_out
+ sizeof(gzHdr
) + 8;
793 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
797 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
800 if (0 == grub_strcmp(args
[0], "on"))
803 grub_env_set("vtdebug_flag", "debug");
808 grub_env_set("vtdebug_flag", "");
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
814 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
818 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
820 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
821 grub_printf(" level:\r\n");
822 grub_printf(" 01/11: busybox / (+cat log)\r\n");
823 grub_printf(" 02/12: initrd / (+cat log)\r\n");
824 grub_printf(" 03/13: hook / (+cat log)\r\n");
826 grub_printf(" debug:\r\n");
827 grub_printf(" 0: debug is off\r\n");
828 grub_printf(" 1: debug is on\r\n");
830 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
833 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
835 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
837 g_ventoy_debug_level
= 1;
840 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
843 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
852 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
855 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
887 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
903 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
919 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
924 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
926 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
929 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
934 value_long
+= grub_strtol(args
[1], NULL
, 10);
936 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
937 grub_env_set(args
[0], buf
);
939 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
942 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
944 ulonglong value1
= 0;
945 ulonglong value2
= 0;
950 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
953 value1
= grub_strtoull(args
[0], NULL
, 10);
954 value2
= grub_strtoull(args
[1], NULL
, 10);
956 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
957 grub_env_set(args
[2], buf
);
959 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
962 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
977 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
980 debug("failed to open file <%s> for udf check\n", args
[0]);
984 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
986 grub_env_set(args
[1], buf
);
988 grub_file_close(file
);
994 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1002 g_wimboot_enable
= 0;
1004 grub_check_free(g_wimiso_path
);
1005 grub_check_free(g_wimiso_chunk_list
.chunk
);
1007 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1013 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1014 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1015 if (NULL
== g_wimiso_chunk_list
.chunk
)
1017 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1020 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1021 g_wimiso_chunk_list
.cur_chunk
= 0;
1023 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1025 g_wimboot_enable
= 1;
1026 g_wimiso_path
= grub_strdup(args
[0]);
1027 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1028 grub_file_close(file
);
1033 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1041 ventoy_iso9660_override
*dirent
;
1050 totlen
= sizeof(ventoy_chain_head
);
1052 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1054 debug("failed to load efiboot template %d\n", len
);
1060 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1062 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1065 debug("failed to open file <%s>\n", args
[0]);
1069 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1074 totlen
+= ventoy_align_2k(file
->size
);
1076 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1077 dirent
->first_sector
= len
/ 2048;
1078 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1079 dirent
->size
= (grub_uint32_t
)file
->size
;
1080 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1082 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1084 #ifdef GRUB_MACHINE_EFI
1085 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1087 data
= (char *)grub_malloc(totlen
);
1090 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1092 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1093 grub_check_free(buf
);
1095 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1096 grub_file_close(file
);
1098 ventoy_memfile_env_set(args
[1], data
, (ulonglong
)totlen
);
1103 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1109 g_vtoy_load_prompt
= 0;
1110 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1112 if (argc
== 2 && args
[0][0] == '1')
1114 g_vtoy_load_prompt
= 1;
1115 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1118 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1121 int ventoy_need_prompt_load_file(void)
1123 return g_vtoy_load_prompt
;
1126 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1128 grub_uint64_t ro
= 0;
1129 grub_uint64_t div
= 0;
1130 grub_ssize_t left
= size
;
1131 char *cur
= (char *)buf
;
1133 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1136 while (left
>= VTOY_SIZE_2MB
)
1138 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1139 cur
+= VTOY_SIZE_2MB
;
1140 left
-= VTOY_SIZE_2MB
;
1142 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1147 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1153 grub_file_read(file
, cur
, left
);
1156 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1162 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1167 enum grub_file_type type
;
1178 if (grub_strcmp(args
[0], "nodecompress") == 0)
1180 type
= VENTOY_FILE_TYPE
;
1184 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1187 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1190 debug("failed to open file <%s>\n", args
[1]);
1194 #ifdef GRUB_MACHINE_EFI
1195 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1197 buf
= (char *)grub_malloc(file
->size
);
1202 grub_file_close(file
);
1206 if (g_vtoy_load_prompt
)
1208 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1212 grub_file_read(file
, buf
, file
->size
);
1215 ventoy_memfile_env_set(args
[2], buf
, (ulonglong
)(file
->size
));
1217 grub_file_close(file
);
1223 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1239 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1242 debug("failed to open file <%s> for udf check\n", args
[0]);
1246 headlen
= sizeof(ventoy_chain_head
);
1248 #ifdef GRUB_MACHINE_EFI
1249 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1251 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1254 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1256 grub_file_read(file
, buf
+ headlen
, file
->size
);
1258 ventoy_memfile_env_set(args
[1], buf
, (ulonglong
)(file
->size
));
1260 grub_file_close(file
);
1266 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1272 if (grub_iso9660_is_joliet())
1274 debug("This time has joliet process\n");
1283 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1292 if (args
[0][0] == '1')
1294 grub_iso9660_set_nojoliet(1);
1298 grub_iso9660_set_nojoliet(0);
1304 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1309 grub_uint8_t buf
[32];
1320 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1323 debug("failed to open file <%s> for udf check\n", args
[0]);
1327 for (i
= 16; i
< 32; i
++)
1329 grub_file_seek(file
, i
* 2048);
1330 grub_file_read(file
, buf
, sizeof(buf
));
1338 grub_file_seek(file
, i
* 2048);
1339 grub_file_read(file
, buf
, sizeof(buf
));
1341 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1344 grub_file_seek(file
, i
* 2048);
1345 grub_file_read(file
, buf
, sizeof(buf
));
1347 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1348 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1354 grub_file_close(file
);
1356 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1361 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1363 long value_long1
= 0;
1364 long value_long2
= 0;
1366 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1368 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1371 value_long1
= grub_strtol(args
[0], NULL
, 10);
1372 value_long2
= grub_strtol(args
[2], NULL
, 10);
1374 if (0 == grub_strcmp(args
[1], "eq"))
1376 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1378 else if (0 == grub_strcmp(args
[1], "ne"))
1380 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1382 else if (0 == grub_strcmp(args
[1], "gt"))
1384 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1386 else if (0 == grub_strcmp(args
[1], "lt"))
1388 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1390 else if (0 == grub_strcmp(args
[1], "ge"))
1392 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1394 else if (0 == grub_strcmp(args
[1], "le"))
1396 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1400 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1406 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1409 char buf
[128] = {0};
1413 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1416 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1417 pos
= grub_strstr(buf
, ",");
1423 grub_env_set(args
[1], buf
);
1425 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1428 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1434 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1440 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1443 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1445 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1446 if (0 == grub_script_execute_sourcecode(buf
))
1448 debug("file %s exist, ventoy_compatible YES\n", buf
);
1449 grub_env_set("ventoy_compatible", "YES");
1450 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1454 debug("file %s NOT exist\n", buf
);
1458 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1459 pos
= grub_strstr(buf
, ")");
1465 disk
= grub_disk_open(buf
);
1468 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1469 grub_disk_close(disk
);
1471 g_img_swap_tmp_buf
[703] = 0;
1472 for (i
= 318; i
< 703; i
++)
1474 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1475 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1477 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1478 grub_env_set("ventoy_compatible", "YES");
1479 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1485 debug("failed to open disk <%s>\n", buf
);
1488 grub_env_set("ventoy_compatible", "NO");
1489 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1492 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1498 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1500 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1503 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1508 if (0 == g_sort_case_sensitive
)
1510 if (grub_islower(c1
))
1512 c1
= c1
- 'a' + 'A';
1515 if (grub_islower(c2
))
1517 c2
= c2
- 'a' + 'A';
1530 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1536 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1538 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1541 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1546 if (0 == g_sort_case_sensitive
)
1548 if (grub_islower(c1
))
1550 c1
= c1
- 'a' + 'A';
1553 if (grub_islower(c2
))
1555 c2
= c2
- 'a' + 'A';
1568 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1570 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1572 grub_memcpy(img1
, img2
, sizeof(img_info
));
1573 img1
->next
= g_img_swap_tmp
.next
;
1574 img1
->prev
= g_img_swap_tmp
.prev
;
1576 g_img_swap_tmp
.next
= img2
->next
;
1577 g_img_swap_tmp
.prev
= img2
->prev
;
1578 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1581 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1585 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1593 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1595 ventoy_vlnk_part
*node
= NULL
;
1596 grub_uint32_t SelfSig
;
1597 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1599 /* skip Ventoy partition 1/2 */
1600 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1601 if (partition
->number
< 2 && SelfSig
== *pSig
)
1606 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1609 node
->disksig
= *pSig
;
1610 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1611 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1612 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1614 node
->next
= g_vlnk_part_list
;
1615 g_vlnk_part_list
= node
;
1621 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1628 disk
= grub_disk_open(name
);
1631 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1632 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1633 grub_disk_close(disk
);
1639 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1641 const char *fs
[ventoy_fs_max
+ 1] =
1643 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1648 cur
->dev
= grub_device_open(cur
->device
);
1653 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1659 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1664 char *disk
, *device
;
1665 grub_uint32_t readcrc
, calccrc
;
1666 ventoy_vlnk_part
*cur
;
1667 grub_fs_t fs
= NULL
;
1669 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1673 grub_printf("VLNK invalid guid\n");
1679 readcrc
= vlnk
->crc32
;
1681 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1682 if (readcrc
!= calccrc
)
1686 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1692 if (!g_vlnk_part_list
)
1694 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1697 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1699 if (cur
->disksig
== vlnk
->disk_signature
)
1703 if (cur
->partoffset
== vlnk
->part_offset
)
1706 device
= cur
->device
;
1708 if (cur
->probe
== 0)
1711 ventoy_vlnk_probe_fs(cur
);
1721 struct grub_file file
;
1723 grub_memset(&file
, 0, sizeof(file
));
1724 file
.device
= cur
->dev
;
1725 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1728 cur
->fs
->fs_close(&file
);
1729 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1738 grub_printf("\n==== VLNK Information ====\n"
1739 "Disk Signature: %08x\n"
1740 "Partition Offset: %llu\n"
1741 "File Path: <%s>\n\n",
1742 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1746 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1750 grub_printf("Disk Find: [ NO ]\n");
1755 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1759 grub_printf("Part Find: [ NO ]\n");
1761 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1764 grub_printf("VLNK File: <%s>\n", dst
);
1771 return (1 - filefind
);
1774 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1779 grub_file_t file
= NULL
;
1784 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1786 else if (dir
[0] == '/')
1788 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1792 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1795 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1801 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1802 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1803 grub_file_close(file
);
1805 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1807 rc
= grub_file_add_vlnk(src
, dst
);
1813 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1823 const menu_tip
*tip
;
1824 img_iterator_node
*tmp
;
1825 img_iterator_node
*new_node
;
1826 img_iterator_node
*node
= (img_iterator_node
*)data
;
1828 if (g_enumerate_time_checked
== 0)
1830 g_enumerate_finish_time_ms
= grub_get_time_ms();
1831 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1834 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1836 g_enumerate_time_checked
= 1;
1840 len
= grub_strlen(filename
);
1844 if (node
->level
+ 1 > g_img_max_search_level
)
1849 if ((len
== 1 && filename
[0] == '.') ||
1850 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1855 if (!ventoy_img_name_valid(filename
, len
))
1860 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1865 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1867 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1868 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1871 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1876 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1879 new_node
->level
= node
->level
+ 1;
1880 new_node
->plugin_list_index
= index
;
1881 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1883 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1886 debug("Directory %s ignored...\n", new_node
->dir
);
1887 grub_free(new_node
);
1891 new_node
->tail
= node
->tail
;
1893 new_node
->parent
= node
;
1894 if (!node
->firstchild
)
1896 node
->firstchild
= new_node
;
1899 if (g_img_iterator_tail
)
1901 g_img_iterator_tail
->next
= new_node
;
1902 g_img_iterator_tail
= new_node
;
1906 g_img_iterator_head
.next
= new_node
;
1907 g_img_iterator_tail
= new_node
;
1913 debug("Find a file %s\n", filename
);
1919 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1921 type
= img_type_iso
;
1923 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1925 type
= img_type_wim
;
1927 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1928 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1930 type
= img_type_vhd
;
1932 #ifdef GRUB_MACHINE_EFI
1933 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1935 type
= img_type_efi
;
1938 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1940 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1942 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1943 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1948 type
= img_type_img
;
1950 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1952 type
= img_type_vtoy
;
1954 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1956 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1958 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1959 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1968 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1973 if (g_plugin_image_list
)
1975 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1976 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1977 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1979 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1982 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1984 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1989 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
1991 if (grub_file_is_vlnk_suffix(filename
, len
))
1994 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2001 img
= grub_zalloc(sizeof(img_info
));
2005 img
->plugin_list_index
= index
;
2006 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2008 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2010 img
->size
= info
->size
;
2011 if (vlnk
|| 0 == img
->size
)
2013 if (node
->dir
[0] == '/')
2015 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2019 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2023 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2025 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2030 if (g_ventoy_img_list
)
2032 tail
= *(node
->tail
);
2038 g_ventoy_img_list
= img
;
2041 img
->id
= g_ventoy_img_count
;
2043 if (node
&& NULL
== node
->firstiso
)
2045 node
->firstiso
= img
;
2056 *((img_info
**)(node
->tail
)) = img
;
2057 g_ventoy_img_count
++;
2059 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2061 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2064 img
->tip1
= tip
->tip1
;
2065 img
->tip2
= tip
->tip2
;
2068 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2071 img
->class = g_menu_class
[type
];
2073 img
->menu_prefix
= g_menu_prefix
[type
];
2075 if (img_type_iso
== type
)
2077 if (ventoy_plugin_check_memdisk(img
->path
))
2079 img
->menu_prefix
= "miso";
2083 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2090 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2092 int len
= GRUB_UINT_MAX
;
2093 const char *value
= NULL
;
2094 char name
[32] = {0};
2095 char plat
[32] = {0};
2096 char guidstr
[32] = {0};
2097 ventoy_guid guid
= VENTOY_GUID
;
2098 const char *fmt1
= NULL
;
2099 const char *fmt2
= NULL
;
2100 const char *fmt3
= NULL
;
2101 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2102 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2103 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2104 const char fmtcode
[]={
2105 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2106 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2107 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2108 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2109 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2110 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2113 grub_memset(name
, 0, sizeof(name
));
2114 puint
[0] = grub_swap_bytes32(0x56454e54);
2115 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2116 puint
[2] = grub_swap_bytes32(0x45525349);
2117 puint
[1] = grub_swap_bytes32(0x4f595f56);
2118 value
= ventoy_get_env(name
);
2120 grub_memset(name
, 0, sizeof(name
));
2121 puint
[1] = grub_swap_bytes32(0x5f544f50);
2122 puint
[0] = grub_swap_bytes32(0x56544c45);
2123 fmt1
= ventoy_get_env(name
);
2129 grub_memset(name
, 0, sizeof(name
));
2130 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2131 puint
[0] = grub_swap_bytes32(0x56544c45);
2132 fmt2
= ventoy_get_env(name
);
2134 grub_memset(name
, 0, sizeof(name
));
2135 puint
[1] = grub_swap_bytes32(0x5f434c52);
2136 puint
[0] = grub_swap_bytes32(0x56544c45);
2137 fmt3
= ventoy_get_env(name
);
2139 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2141 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2143 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2144 #pragma GCC diagnostic push
2145 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2146 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2147 fmt1
? fmt1
: fmtdata
,
2148 fmt2
? fmt2
: fmtdata
+ 4,
2149 value
? value
: "", plat
, guidstr
,
2150 fmt3
? fmt3
: fmtdata
+ 6);
2151 #pragma GCC diagnostic pop
2153 grub_memset(name
, 0, sizeof(name
));
2154 puint
[0] = grub_swap_bytes32(0x76746f79);
2155 puint
[2] = grub_swap_bytes32(0x656e7365);
2156 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2157 ventoy_set_env(name
, guidstr
);
2163 ventoy_password_get (char buf
[], unsigned buf_size
)
2165 unsigned i
, cur_len
= 0;
2167 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2171 key
= grub_getkey ();
2172 if (key
== '\n' || key
== '\r')
2175 if (key
== GRUB_TERM_ESC
)
2185 grub_term_restore_pos (pos
);
2186 for (i
= 0; i
< cur_len
; i
++)
2188 grub_term_restore_pos (pos
);
2190 for (i
= 0; i
< cur_len
; i
++)
2197 if (!grub_isprint (key
))
2200 if (cur_len
+ 2 < buf_size
)
2201 buf
[cur_len
++] = key
;
2206 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2212 return (key
!= GRUB_TERM_ESC
);
2215 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2219 grub_uint8_t md5
[16];
2223 grub_memset(input
, 0, sizeof(input
));
2225 grub_printf("Enter password: ");
2228 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2230 ventoy_password_get(input
, 128);
2231 if (grub_strcmp(pwd
->text
, input
) == 0)
2236 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2238 ventoy_password_get(input
, 128);
2239 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2240 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2245 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2247 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2248 ventoy_password_get(input
+ offset
, 128);
2250 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2251 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2257 grub_printf("Invalid password!\n\n");
2264 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2266 img_info
*minimg
= NULL
;
2267 img_info
*img
= (img_info
*)(node
->firstiso
);
2269 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2271 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2286 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2288 img_iterator_node
*Minchild
= NULL
;
2289 img_iterator_node
*child
= node
->firstchild
;
2291 while (child
&& child
->parent
== node
)
2293 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2297 child
= child
->next
;
2302 Minchild
->select
= 1;
2308 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2311 img_info
*img
= NULL
;
2312 const char *dir_class
= NULL
;
2313 const char *dir_alias
= NULL
;
2314 img_iterator_node
*child
= NULL
;
2315 const menu_tip
*tip
= NULL
;
2317 if (node
->isocnt
== 0 || node
->done
== 1)
2322 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2324 offset
= node
->parent
->dirlen
;
2327 if (node
== &g_img_iterator_head
)
2329 if (g_default_menu_mode
== 0)
2331 if (g_tree_view_menu_style
== 0)
2333 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2334 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2335 " echo 'return ...' \n"
2340 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2341 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2342 " echo 'return ...' \n"
2347 g_tree_script_pre
= g_tree_script_pos
;
2351 node
->dir
[node
->dirlen
- 1] = 0;
2352 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2355 dir_class
= "vtoydir";
2358 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2360 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2363 if (g_tree_view_menu_style
== 0)
2365 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2366 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2367 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2371 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2372 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2373 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2378 dir_alias
= node
->dir
+ offset
;
2380 if (g_tree_view_menu_style
== 0)
2382 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2383 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2384 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2388 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2389 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2390 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2394 if (g_tree_view_menu_style
== 0)
2396 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2397 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2398 " echo 'return ...' \n"
2399 "}\n", "<--", node
->dir
);
2403 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2404 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2405 " echo 'return ...' \n"
2410 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2412 ventoy_dynamic_tree_menu(child
);
2415 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2417 if (g_tree_view_menu_style
== 0)
2419 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2420 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2423 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2424 img
->unsupport
? "[***********] " : "",
2425 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2427 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2431 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2432 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2435 img
->unsupport
? "[***********] " : "",
2436 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2438 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2442 if (node
!= &g_img_iterator_head
)
2444 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2451 static int ventoy_set_default_menu(void)
2457 const char *strdata
= NULL
;
2458 img_info
*cur
= NULL
;
2459 img_info
*default_node
= NULL
;
2460 const char *default_image
= NULL
;
2462 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2463 if (default_image
&& default_image
[0] == '/')
2465 img_len
= grub_strlen(default_image
);
2467 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2469 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2481 if (0 == g_default_menu_mode
)
2483 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2487 def
= grub_strdup(default_image
);
2493 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2495 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2496 if (strdata
&& strdata
[0] == '/')
2498 pos
= def
+ grub_strlen(strdata
);
2509 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2512 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2516 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2524 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2526 img_info
*next
= NULL
;
2527 img_info
*cur
= g_ventoy_img_list
;
2540 g_ventoy_img_list
= NULL
;
2541 g_ventoy_img_count
= 0;
2543 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2546 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2549 img_info
*cur
= g_ventoy_img_list
;
2553 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2555 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2558 img_id
= grub_strtol(args
[0], NULL
, 10);
2559 if (img_id
>= g_ventoy_img_count
)
2561 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2564 debug("Find image %ld name \n", img_id
);
2566 while (cur
&& img_id
> 0)
2574 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2577 debug("image name is %s\n", cur
->name
);
2579 grub_env_set(args
[1], cur
->name
);
2581 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2584 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2588 img_info
*cur
= g_ventoy_img_list
;
2594 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2597 len
= (int)grub_strlen(args
[0]);
2601 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2610 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2613 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2614 grub_env_set("chosen", id
);
2615 grub_env_export("chosen");
2617 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2620 static char g_fake_vlnk_src
[512];
2621 static char g_fake_vlnk_dst
[512];
2622 static grub_uint64_t g_fake_vlnk_size
;
2623 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2629 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2631 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2632 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2634 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2636 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2639 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2645 g_fake_vlnk_src
[0] = 0;
2646 g_fake_vlnk_dst
[0] = 0;
2647 g_fake_vlnk_size
= 0;
2648 grub_file_vtoy_vlnk(NULL
, NULL
);
2650 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2654 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2659 const char *id
= NULL
;
2660 img_info
*cur
= NULL
;
2664 if (argc
< 1 || argc
> 3)
2666 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2669 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2671 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2672 grub_env_set(args
[0], pos
);
2675 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2676 grub_env_set(args
[1], value
);
2681 for (last
= pos
; *pos
; pos
++)
2688 grub_env_set(args
[2], last
+ 1);
2694 id
= grub_env_get("chosen");
2696 pos
= grub_strstr(id
, "VID_");
2699 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2703 cur
= g_ventoy_img_list
;
2708 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2711 grub_env_set(args
[0], cur
->path
);
2715 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2716 grub_env_set(args
[1], value
);
2721 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2722 grub_env_set(args
[2], cur
->name
);
2726 g_svd_replace_offset
= 0;
2728 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2732 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2736 grub_device_t dev
= NULL
;
2737 img_info
*cur
= NULL
;
2738 img_info
*tail
= NULL
;
2739 img_info
*min
= NULL
;
2740 img_info
*head
= NULL
;
2741 const char *strdata
= NULL
;
2742 char *device_name
= NULL
;
2744 img_iterator_node
*node
= NULL
;
2745 img_iterator_node
*tmp
= NULL
;
2751 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2754 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2756 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2761 g_enumerate_time_checked
= 0;
2762 g_enumerate_start_time_ms
= grub_get_time_ms();
2764 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2765 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2767 g_filt_dot_underscore_file
= 1;
2770 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2771 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2773 g_sort_case_sensitive
= 1;
2776 device_name
= grub_file_get_device_name(args
[0]);
2782 g_enum_dev
= dev
= grub_device_open(device_name
);
2788 g_enum_fs
= fs
= grub_fs_probe(dev
);
2794 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2796 debug("unsupported fs:<%s>\n", fs
->name
);
2797 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2801 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2803 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2804 if (strdata
&& strdata
[0] == '1')
2806 g_default_menu_mode
= 1;
2809 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2811 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2813 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2814 if (strdata
&& strdata
[0] == '/')
2816 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2817 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2819 g_img_iterator_head
.dir
[len
++] = '/';
2821 g_img_iterator_head
.dirlen
= len
;
2825 g_img_iterator_head
.dirlen
= 1;
2826 grub_strcpy(g_img_iterator_head
.dir
, "/");
2829 g_img_iterator_head
.tail
= &tail
;
2831 if (g_img_max_search_level
< 0)
2833 g_img_max_search_level
= GRUB_INT_MAX
;
2834 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2835 if (strdata
&& ventoy_is_decimal(strdata
))
2837 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2841 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2842 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2843 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2844 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2845 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2846 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2848 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2850 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2853 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2854 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2856 g_tree_view_menu_style
= 1;
2859 ventoy_set_default_menu();
2861 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2863 ventoy_dynamic_tree_menu(node
);
2867 node
= g_img_iterator_head
.next
;
2875 /* sort image list by image name */
2876 while (g_ventoy_img_list
)
2878 min
= g_ventoy_img_list
;
2879 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2881 if (ventoy_cmp_img(min
, cur
) > 0)
2889 min
->prev
->next
= min
->next
;
2894 min
->next
->prev
= min
->prev
;
2897 if (min
== g_ventoy_img_list
)
2899 g_ventoy_img_list
= min
->next
;
2917 g_ventoy_img_list
= head
;
2919 if (g_default_menu_mode
== 1)
2921 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2922 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2923 " echo 'return ...' \n"
2927 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2929 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2930 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2933 cur
->unsupport
? "[***********] " : "",
2934 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2936 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2939 g_tree_script_buf
[g_tree_script_pos
] = 0;
2940 g_list_script_buf
[g_list_script_pos
] = 0;
2942 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2943 grub_env_set(args
[1], buf
);
2947 check_free(device_name
, grub_free
);
2948 check_free(dev
, grub_device_close
);
2950 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2953 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2960 device_name
= grub_file_get_device_name(filename
);
2972 pos2
= grub_strstr(pos
, ",");
2975 pos2
= grub_strstr(pos
, ")");
2983 disk
= grub_disk_open(pos
);
2986 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2987 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2988 grub_disk_close(disk
);
2995 grub_free(device_name
);
2999 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3001 eltorito_descriptor desc
;
3003 grub_memset(&desc
, 0, sizeof(desc
));
3004 grub_file_seek(file
, 17 * 2048);
3005 grub_file_read(file
, &desc
, sizeof(desc
));
3007 if (desc
.type
!= 0 || desc
.version
!= 1)
3012 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3013 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3021 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3023 grub_uint8_t buf
[512];
3025 grub_file_seek(file
, sector
* 2048);
3026 grub_file_read(file
, buf
, sizeof(buf
));
3028 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3029 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3031 return *((grub_uint32_t
*)(buf
+ 40));
3037 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3041 grub_uint8_t buf
[512];
3042 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3044 grub_file_seek(file
, sector
* 2048);
3045 grub_file_read(file
, buf
, sizeof(buf
));
3047 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3049 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3053 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3058 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3060 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3062 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3066 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3068 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3073 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3075 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3077 if (buf
[36] == parttype
[i
])
3079 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3085 debug("%s does not contain efi eltorito\n", file
->name
);
3089 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3092 const char *fs
= NULL
;
3093 const char *val
= NULL
;
3094 const char *cdprompt
= NULL
;
3096 grub_uint8_t chksum
= 0;
3099 disk
= file
->device
->disk
;
3100 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3102 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3103 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3104 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3106 pos
= grub_strstr(file
->name
, "/");
3112 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3114 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3116 param
->vtoy_img_size
= file
->size
;
3118 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3119 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3121 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3123 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3124 param
->vtoy_reserved
[4] = 0;
3125 if (g_ventoy_chain_type
== 1) /* Windows */
3127 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3128 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3130 param
->vtoy_reserved
[4] = 1;
3134 fs
= ventoy_get_env("ventoy_fs_probe");
3135 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3137 param
->vtoy_reserved
[3] = 1;
3140 param
->vtoy_reserved
[5] = 0;
3141 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3142 if (val
&& val
[0] == '1' && val
[1] == 0)
3144 param
->vtoy_reserved
[5] = 1;
3147 /* ventoy_disk_signature used for vlnk */
3148 param
->vtoy_reserved
[6] = file
->vlnk
;
3149 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3151 /* calculate checksum */
3152 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3154 chksum
+= *((grub_uint8_t
*)param
+ i
);
3156 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3161 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3163 grub_uint32_t i
= 0;
3164 grub_uint64_t total
= 0;
3165 grub_uint64_t fileblk
= 0;
3166 ventoy_img_chunk
*chunk
= NULL
;
3168 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3170 chunk
= chunklist
->chunk
+ i
;
3172 if (chunk
->disk_start_sector
<= start
)
3174 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3178 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3181 fileblk
= (file
->size
+ 511) / 512;
3183 if (total
!= fileblk
)
3185 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3186 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3188 debug("maybe img file to be processed.\n");
3198 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3202 grub_uint32_t i
= 0;
3203 grub_uint32_t sector
= 0;
3204 grub_uint32_t count
= 0;
3205 grub_off_t size
= 0;
3206 grub_off_t read
= 0;
3208 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3209 if (fs_type
== ventoy_fs_exfat
)
3211 grub_fat_get_file_chunk(start
, file
, chunklist
);
3213 else if (fs_type
== ventoy_fs_ext
)
3215 grub_ext_get_file_chunk(start
, file
, chunklist
);
3219 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3220 file
->read_hook_data
= chunklist
;
3222 for (size
= file
->size
; size
> 0; size
-= read
)
3224 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3225 grub_file_read(file
, NULL
, read
);
3228 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3230 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3231 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3234 if (ventoy_fs_udf
== fs_type
)
3236 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3238 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3239 chunklist
->chunk
[i
].img_start_sector
= sector
;
3240 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3246 len
= (int)grub_strlen(file
->name
);
3247 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3248 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3249 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3250 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3252 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3254 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3264 chunklist
->chunk
[i
].img_start_sector
= sector
;
3265 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3273 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3277 grub_disk_addr_t start
;
3282 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3285 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3288 g_conf_replace_count
= 0;
3289 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3290 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3292 if (g_img_chunk_list
.chunk
)
3294 grub_free(g_img_chunk_list
.chunk
);
3297 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3299 grub_file_close(file
);
3300 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3303 /* get image chunk data */
3304 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3305 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3306 if (NULL
== g_img_chunk_list
.chunk
)
3308 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3311 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3312 g_img_chunk_list
.cur_chunk
= 0;
3314 start
= file
->device
->disk
->partition
->start
;
3316 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3318 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3319 grub_file_close(file
);
3323 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3326 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3327 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3328 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3331 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3335 grub_uint64_t offset
= 0;
3336 grub_uint32_t align
= 0;
3337 grub_file_t file
= NULL
;
3338 conf_replace
*node
= NULL
;
3339 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3340 ventoy_grub_param_file_replace
*replace
= NULL
;
3346 debug("select conf replace argc:%d\n", argc
);
3353 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3356 debug("Conf replace not found for %s\n", args
[1]);
3360 debug("Find %d conf replace for %s\n", n
, args
[1]);
3362 g_conf_replace_count
= n
;
3363 for (i
= 0; i
< n
; i
++)
3367 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3370 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3371 grub_file_close(file
);
3373 else if (node
->img
> 0)
3379 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3383 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3386 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3390 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3392 if (align
> vtoy_max_replace_file_size
)
3394 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3395 grub_file_close(file
);
3399 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3400 grub_file_close(file
);
3401 g_conf_replace_new_len
[i
] = (int)file
->size
;
3402 g_conf_replace_new_len_align
[i
] = align
;
3404 g_conf_replace_node
[i
] = node
;
3405 g_conf_replace_offset
[i
] = offset
+ 2;
3409 replace
= &(g_grub_param
->img_replace
[i
]);
3410 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3411 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3412 replace
->old_name_cnt
++;
3415 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3419 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3422 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3427 const char *ch
= var
;
3434 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3441 debug("Invalid variable letter <%c>\n", *ch
);
3448 debug("Invalid variable length:%d <%s>\n", n
, var
);
3452 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3461 grub_printf("\n=================== Variables Expansion ===================\n\n");
3464 grub_printf("<%s>: ", var
);
3467 while (i
< (len
- 1))
3470 if ((c
== '\n') || (c
== '\r'))
3480 else if (grub_isprint(c
))
3482 if (i
+ 1 < (len
- 1))
3484 grub_printf("%c", c
);
3494 expand
[i
- 1] = ' ';
3495 grub_printf("\r<%s>: %s", var
, expand
);
3498 grub_printf("\r<%s>: %s", var
, expand
);
3510 grub_snprintf(expand
, len
, "$$%s$$", var
);
3516 static int ventoy_auto_install_var_expand(install_template
*node
)
3524 char *newbuf
= NULL
;
3525 char *curline
= NULL
;
3526 char *nextline
= NULL
;
3527 grub_uint8_t
*code
= NULL
;
3529 var_node
*CurNode
= NULL
;
3530 var_node
*pVarList
= NULL
;
3532 code
= (grub_uint8_t
*)node
->filebuf
;
3534 if (node
->filelen
>= VTOY_SIZE_1MB
)
3536 debug("auto install script too long %d\n", node
->filelen
);
3540 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3542 debug("UCS-2 encoding NOT supported\n");
3546 start
= grub_strstr(node
->filebuf
, "$$");
3549 debug("no need to expand variable, no start.\n");
3553 end
= grub_strstr(start
+ 2, "$$");
3556 debug("no need to expand variable, no end.\n");
3560 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3561 newbuf
= grub_malloc(newlen
);
3564 debug("Failed to alloc newbuf %d\n", newlen
);
3568 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3570 nextline
= ventoy_get_line(curline
);
3572 start
= grub_strstr(curline
, "$$");
3575 end
= grub_strstr(start
+ 2, "$$");
3581 VTOY_APPEND_NEWBUF(curline
);
3583 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3585 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3587 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3594 value
[sizeof(value
) - 1] = 0;
3595 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3599 CurNode
= grub_zalloc(sizeof(var_node
));
3602 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3603 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3604 CurNode
->next
= pVarList
;
3610 VTOY_APPEND_NEWBUF(value
);
3612 VTOY_APPEND_NEWBUF(end
+ 2);
3616 VTOY_APPEND_NEWBUF(curline
);
3619 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3621 newbuf
[pos
- 1] = '\n';
3625 newbuf
[pos
++] = '\n';
3629 grub_free(node
->filebuf
);
3630 node
->filebuf
= newbuf
;
3631 node
->filelen
= pos
;
3635 CurNode
= pVarList
->next
;
3636 grub_free(pVarList
);
3643 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3649 grub_file_t file
= NULL
;
3650 char configfile
[128];
3651 install_template
*node
= NULL
;
3657 debug("select auto installation argc:%d\n", argc
);
3664 node
= ventoy_plugin_find_install_template(args
[0]);
3667 debug("Auto install template not found for %s\n", args
[0]);
3671 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3673 defidx
= node
->autosel
;
3674 if (node
->timeout
< 0)
3676 node
->cursel
= node
->autosel
- 1;
3677 debug("Auto install template auto select %d\n", node
->autosel
);
3682 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3688 if (node
->timeout
> 0)
3690 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3693 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" --class=\"sel_auto_install\" {\n"
3694 " echo %s\n}\n", "");
3696 for (i
= 0; i
< node
->templatenum
; i
++)
3698 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" --class=\"sel_auto_install\" {\n"
3700 node
->templatepath
[i
].path
);
3703 g_ventoy_menu_esc
= 1;
3704 g_ventoy_suppress_esc
= 1;
3705 g_ventoy_suppress_esc_default
= defidx
;
3707 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3708 grub_script_execute_sourcecode(configfile
);
3710 g_ventoy_menu_esc
= 0;
3711 g_ventoy_suppress_esc
= 0;
3712 g_ventoy_suppress_esc_default
= 1;
3716 node
->cursel
= g_ventoy_last_entry
- 1;
3719 grub_check_free(node
->filebuf
);
3722 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3724 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3725 node
->templatepath
[node
->cursel
].path
);
3728 node
->filebuf
= grub_malloc(file
->size
+ 8);
3731 grub_file_read(file
, node
->filebuf
, file
->size
);
3732 grub_file_close(file
);
3734 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3735 node
->filelen
= (int)file
->size
;
3737 ventoy_auto_install_var_expand(node
);
3742 debug("Failed to open auto install script <%s%s>\n",
3743 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3747 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3750 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3756 char configfile
[128];
3757 persistence_config
*node
;
3763 debug("select persistence argc:%d\n", argc
);
3770 node
= ventoy_plugin_find_persistent(args
[0]);
3773 debug("Persistence image not found for %s\n", args
[0]);
3777 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3779 defidx
= node
->autosel
;
3780 if (node
->timeout
< 0)
3782 node
->cursel
= node
->autosel
- 1;
3783 debug("Persistence image auto select %d\n", node
->autosel
);
3788 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3794 if (node
->timeout
> 0)
3796 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3799 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" --class=\"sel_persistence\" {\n"
3800 " echo %s\n}\n", "");
3802 for (i
= 0; i
< node
->backendnum
; i
++)
3804 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" --class=\"sel_persistence\" {\n"
3806 node
->backendpath
[i
].path
);
3810 g_ventoy_menu_esc
= 1;
3811 g_ventoy_suppress_esc
= 1;
3812 g_ventoy_suppress_esc_default
= defidx
;
3814 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3815 grub_script_execute_sourcecode(configfile
);
3817 g_ventoy_menu_esc
= 0;
3818 g_ventoy_suppress_esc
= 0;
3819 g_ventoy_suppress_esc_default
= 1;
3823 node
->cursel
= g_ventoy_last_entry
- 1;
3825 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3828 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3831 ventoy_img_chunk
*cur
;
3837 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3839 cur
= g_img_chunk_list
.chunk
+ i
;
3840 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3841 cur
->img_start_sector
, cur
->img_end_sector
,
3842 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3846 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3849 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3853 ventoy_img_chunk_list chunklist
;
3858 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3861 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3864 /* get image chunk data */
3865 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3866 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3867 if (NULL
== chunklist
.chunk
)
3869 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3872 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3873 chunklist
.cur_chunk
= 0;
3875 ventoy_get_block_list(file
, &chunklist
, 0);
3877 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3879 grub_printf("########## UNSUPPORTED ###############\n");
3882 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3884 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3886 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3887 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3890 grub_printf("\n==================================\n");
3892 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3894 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3895 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3896 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3897 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3898 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3902 grub_free(chunklist
.chunk
);
3903 grub_file_close(file
);
3905 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3908 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3911 ventoy_grub_param_file_replace
*replace
= NULL
;
3919 replace
= &(g_grub_param
->file_replace
);
3920 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3922 replace
->old_name_cnt
= 0;
3923 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3925 replace
->old_name_cnt
++;
3926 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3929 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3932 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3935 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3938 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3944 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3945 grub_env_set(args
[0], buf
);
3948 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3951 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3959 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3960 grub_printf("%s", g_list_script_buf
);
3964 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3965 grub_printf("%s", g_tree_script_buf
);
3971 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3973 img_info
*cur
= g_ventoy_img_list
;
3981 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3982 grub_printf("name:<%s>\n\n", cur
->name
);
3989 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3995 ventoy_plugin_dump_injection();
4000 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4006 ventoy_plugin_dump_auto_install();
4011 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4017 ventoy_plugin_dump_persistence();
4022 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4028 len1
= (int)grub_strlen(filename
);
4029 len2
= (int)grub_strlen(suffix
);
4036 for (i
= len1
- 1; i
>= 0; i
--)
4038 if (filename
[i
] == '.')
4049 if (filename
[i
- len2
- 1] != '_')
4054 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4062 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4068 if (argc
!= 1 && argc
!= 2)
4073 if (args
[0][0] == '0')
4075 if (g_ventoy_memdisk_mode
)
4080 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4087 else if (args
[0][0] == '1')
4089 return g_ventoy_iso_raw
? 0 : 1;
4091 else if (args
[0][0] == '2')
4093 return g_ventoy_iso_uefi_drv
? 0 : 1;
4095 else if (args
[0][0] == '3')
4097 if (g_ventoy_grub2_mode
)
4102 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4109 else if (args
[0][0] == '4')
4111 if (g_ventoy_wimboot_mode
)
4116 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4127 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4129 static int configfile_mode
= 0;
4130 char memfile
[128] = {0};
4137 * args[0]: 0:normal 1:configfile
4138 * args[1]: 0:list_buf 1:tree_buf
4143 debug("Invalid argc %d\n", argc
);
4149 if (args
[0][0] == '0')
4151 if (args
[1][0] == '0')
4153 grub_script_execute_sourcecode(g_list_script_buf
);
4157 grub_script_execute_sourcecode(g_tree_script_buf
);
4162 if (configfile_mode
)
4164 debug("Now already in F3 mode %d\n", configfile_mode
);
4168 if (args
[1][0] == '0')
4170 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4171 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4175 g_ventoy_last_entry
= -1;
4176 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4177 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4180 configfile_mode
= 1;
4181 grub_script_execute_sourcecode(memfile
);
4182 configfile_mode
= 0;
4188 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4199 g_ventoy_case_insensitive
= 1;
4200 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4201 g_ventoy_case_insensitive
= 0;
4207 grub_file_close(file
);
4213 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4218 const char *isopath
= NULL
;
4220 ventoy_mbr_head mbr
;
4227 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4230 isopath
= grub_env_get("vtoy_iso_part");
4233 debug("isopath is null %p\n", isopath
);
4237 debug("isopath is %s\n", isopath
);
4239 for (id
= 0; id
< 30 && (find
== 0); id
++)
4241 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4242 if (grub_strstr(isopath
, hdname
))
4244 debug("skip %s ...\n", hdname
);
4248 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4250 disk
= grub_disk_open(hdname
);
4253 debug("%s not exist\n", hdname
);
4257 grub_memset(&mbr
, 0, sizeof(mbr
));
4258 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4260 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4262 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4263 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4266 grub_env_set(args
[0], hdname
);
4270 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4274 debug("read %s failed\n", hdname
);
4277 grub_disk_close(disk
);
4283 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4294 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4297 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4300 debug("failed to open file %s\n", args
[0]);
4304 buf
= grub_malloc(len
);
4311 grub_file_read(file
, buf
, len
- 1);
4313 ventoy_get_line(buf
);
4314 ventoy_set_env(args
[1], buf
);
4318 grub_check_free(buf
);
4319 grub_file_close(file
);
4324 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4326 grub_uint64_t end_max
= 0;
4327 int *pCnt
= (int *)data
;
4332 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4333 "0 %llu linear /dev/ventoy %llu\n",
4334 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4336 end_max
= (partition
->len
+ partition
->start
) * 512;
4337 if (end_max
> g_part_end_max
)
4339 g_part_end_max
= end_max
;
4345 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4348 char *device_name
= NULL
;
4349 grub_device_t dev
= NULL
;
4354 g_part_list_pos
= 0;
4356 grub_env_unset("vtoy_img_part_file");
4363 device_name
= grub_file_get_device_name(args
[0]);
4366 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4370 dev
= grub_device_open(device_name
);
4373 debug("grub_device_open failed, %s\n", device_name
);
4377 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4379 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4380 grub_env_set("vtoy_img_part_file", buf
);
4382 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4383 grub_env_set("vtoy_img_part_cnt", buf
);
4385 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4386 grub_env_set("vtoy_img_max_part_end", buf
);
4390 check_free(device_name
, grub_free
);
4391 check_free(dev
, grub_device_close
);
4397 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4408 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4411 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4414 debug("failed to open file %s\n", args
[0]);
4418 buf
= grub_malloc(file
->size
+ 1);
4424 buf
[file
->size
] = 0;
4425 grub_file_read(file
, buf
, file
->size
);
4427 if (grub_strstr(buf
, args
[1]))
4434 grub_check_free(buf
);
4435 grub_file_close(file
);
4440 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4446 ventoy_iso9660_vd pvd
;
4453 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4456 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4459 debug("failed to open file %s\n", args
[0]);
4463 grub_file_seek(file
, 16 * 2048);
4464 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4465 if (len
!= sizeof(pvd
))
4467 debug("failed to read pvd %d\n", len
);
4471 grub_memset(buf
, 0, sizeof(buf
));
4472 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4473 ventoy_set_env(args
[1], buf
);
4475 grub_memset(buf
, 0, sizeof(buf
));
4476 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4477 ventoy_set_env(args
[2], buf
);
4481 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4482 ventoy_set_env(args
[3], buf
);
4485 grub_file_close(file
);
4490 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4501 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4504 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4507 debug("failed to open file %s\n", args
[0]);
4511 grub_memset(buf
, 0, sizeof(buf
));
4512 grub_file_seek(file
, 16 * 2048 + 813);
4513 len
= (int)grub_file_read(file
, buf
, 17);
4516 debug("failed to read create date %d\n", len
);
4520 ventoy_set_env(args
[1], buf
);
4523 grub_file_close(file
);
4528 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4534 ventoy_env_hook_root(1);
4539 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4545 ventoy_env_hook_root(0);
4550 #ifdef GRUB_MACHINE_EFI
4551 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4556 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4562 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4563 if (var
&& *var
== 1)
4571 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4580 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4585 grub_uint64_t FileSectors
= 0;
4586 ventoy_gpt_info
*gpt
= NULL
;
4587 ventoy_part_table
*pt
= NULL
;
4588 grub_uint8_t zeroguid
[16] = {0};
4593 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4596 debug("failed to open file %s\n", args
[0]);
4600 if (file
->size
% 512)
4602 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4606 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4612 FileSectors
= file
->size
/ 512;
4614 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4615 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4617 debug("This is EFI partition table\n");
4619 for (i
= 0; i
< 128; i
++)
4621 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4623 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4625 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4626 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4634 debug("This is MBR partition table\n");
4636 for (i
= 0; i
< 4; i
++)
4638 pt
= gpt
->MBR
.PartTbl
+ i
;
4639 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4641 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4642 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4643 (ulonglong
)FileSectors
);
4652 grub_file_close(file
);
4653 grub_check_free(gpt
);
4654 grub_errno
= GRUB_ERR_NONE
;
4658 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4667 for (i
= 0; i
< 500; i
++)
4669 ret
= grub_getkey_noblock();
4670 if (ret
== GRUB_TERM_NO_KEY
)
4679 grub_printf("\n\n Still have key input after clear.\n");
4687 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4694 int image_sector_size
;
4696 ventoy_chain_head
*chain
;
4697 ventoy_img_chunk
*chunk
;
4698 ventoy_os_param
*osparam
;
4699 ventoy_image_location
*location
;
4700 ventoy_image_disk_region
*region
;
4701 struct grub_acpi_table_header
*acpi
;
4710 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4712 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4718 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4720 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4722 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4726 img_chunk_num
= chain
->img_chunk_num
;
4728 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4729 datalen
= sizeof(ventoy_os_param
) + loclen
;
4731 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4732 acpi
= grub_zalloc(buflen
);
4738 /* Step1: Fill acpi table header */
4739 grub_memcpy(acpi
->signature
, "VTOY", 4);
4740 acpi
->length
= buflen
;
4742 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4743 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4745 acpi
->creator_id
[0] = 1;
4746 acpi
->creator_rev
= 1;
4748 /* Step2: Fill data */
4749 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4750 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4751 osparam
->vtoy_img_location_addr
= 0;
4752 osparam
->vtoy_img_location_len
= loclen
;
4753 osparam
->chksum
= 0;
4754 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4756 location
= (ventoy_image_location
*)(osparam
+ 1);
4757 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4758 location
->image_sector_size
= image_sector_size
;
4759 location
->disk_sector_size
= chain
->disk_sector_size
;
4760 location
->region_count
= img_chunk_num
;
4762 region
= location
->regions
;
4763 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4764 if (512 == image_sector_size
)
4766 for (i
= 0; i
< img_chunk_num
; i
++)
4768 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4769 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4770 region
->disk_start_sector
= chunk
->disk_start_sector
;
4777 for (i
= 0; i
< img_chunk_num
; i
++)
4779 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4780 region
->image_start_sector
= chunk
->img_start_sector
;
4781 region
->disk_start_sector
= chunk
->disk_start_sector
;
4787 /* Step3: Fill acpi checksum */
4789 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4791 /* load acpi table */
4792 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4793 grub_script_execute_sourcecode(cmd
);
4797 VENTOY_CMD_RETURN(0);
4800 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4806 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4807 g_ventoy_last_entry
= -1;
4812 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4818 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4823 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4825 const char *pos
= filename
+ 1;
4833 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4835 grub_strncpy((char *)data
, filename
, 128);
4846 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4849 char *device_name
= NULL
;
4850 grub_device_t dev
= NULL
;
4851 grub_fs_t fs
= NULL
;
4852 char buf
[128] = {0};
4858 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4862 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4864 device_name
= grub_file_get_device_name(args
[0]);
4867 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4871 dev
= grub_device_open(device_name
);
4874 debug("grub_device_open failed, %s\n", device_name
);
4878 fs
= grub_fs_probe(dev
);
4881 debug("grub_fs_probe failed, %s\n", device_name
);
4885 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4889 ventoy_set_env(args
[2], buf
);
4896 check_free(device_name
, grub_free
);
4897 check_free(dev
, grub_device_close
);
4902 int ventoy_load_part_table(const char *diskname
)
4909 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4910 if (!g_ventoy_part_info
)
4915 disk
= grub_disk_open(diskname
);
4918 debug("Failed to open disk %s\n", diskname
);
4922 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4924 g_ventoy_disk_bios_id
= disk
->id
;
4926 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4927 grub_disk_close(disk
);
4929 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4930 dev
= grub_device_open(name
);
4933 /* Check for official Ventoy device */
4934 ret
= ventoy_check_official_device(dev
);
4935 grub_device_close(dev
);
4943 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4944 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4949 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4956 ret
= ventoy_load_part_table(args
[0]);
4962 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4963 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4968 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4971 const char *vcfg
= NULL
;
4976 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4979 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4980 grub_env_set(args
[1], vcfg
);
4985 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4993 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4996 grub_uint8_t zeroguid
[16] = {0};
5001 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5004 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5006 if (id
>= 1 && id
<= 128)
5008 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5016 if (id
>= 1 && id
<= 4)
5018 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5028 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5031 char *device_name
= NULL
;
5032 grub_device_t dev
= NULL
;
5033 grub_fs_t fs
= NULL
;
5038 debug("get fs label for %s\n", args
[0]);
5042 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5046 device_name
= grub_file_get_device_name(args
[0]);
5049 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5053 dev
= grub_device_open(device_name
);
5056 debug("grub_device_open failed, %s\n", device_name
);
5060 fs
= grub_fs_probe(dev
);
5061 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5063 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5067 fs
->fs_label(dev
, &label
);
5070 debug("label=<%s>\n", label
);
5071 ventoy_set_env(args
[1], label
);
5079 check_free(device_name
, grub_free
);
5080 check_free(dev
, grub_device_close
);
5085 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5089 grub_snprintf((char *)data
, 256, "%s", filename
);
5096 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5098 if (info
->dir
&& filename
&& filename
[0] != '.')
5100 grub_snprintf((char *)data
, 256, "%s", filename
);
5107 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5110 char *device_name
= NULL
;
5111 grub_device_t dev
= NULL
;
5112 grub_fs_t fs
= NULL
;
5113 char name
[256] ={0};
5117 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5121 device_name
= grub_file_get_device_name(args
[0]);
5124 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5128 dev
= grub_device_open(device_name
);
5131 debug("grub_device_open failed, %s\n", device_name
);
5135 fs
= grub_fs_probe(dev
);
5138 debug("grub_fs_probe failed, %s\n", device_name
);
5142 fs
->fs_dir(dev
, args
[1], hook
, name
);
5145 ventoy_set_env(args
[2], name
);
5152 check_free(device_name
, grub_free
);
5153 check_free(dev
, grub_device_close
);
5158 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5161 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5164 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5167 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5170 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5180 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5184 for (pos
= args
[0]; *pos
; pos
++)
5198 grub_env_set(args
[1], args
[0]);
5208 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5218 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5223 len
= (int)grub_strlen(buf
);
5224 for (i
= len
; i
> 0; i
--)
5226 if (buf
[i
- 1] == '/')
5228 grub_env_set(args
[1], buf
+ i
);
5233 grub_env_set(args
[1], buf
);
5238 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5240 struct grub_video_mode_info info
;
5247 if (!g_video_mode_list
)
5249 ventoy_enum_video_mode();
5252 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5254 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5258 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5261 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5263 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5264 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5266 VENTOY_CMD_RETURN(0);
5269 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5271 struct grub_video_mode_info info
;
5278 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5280 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5284 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5287 grub_env_set(args
[0], buf
);
5289 VENTOY_CMD_RETURN(0);
5292 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5300 if (!g_video_mode_list
)
5305 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5306 if (id
< g_video_mode_num
)
5308 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5309 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5312 grub_env_set(args
[1], buf
);
5314 VENTOY_CMD_RETURN(0);
5317 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5320 grub_uint32_t loadsector
= 0;
5323 grub_uint32_t boot_catlog
= 0;
5324 grub_uint8_t buf
[512];
5330 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5334 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5337 debug("failed to open %s\n", args
[0]);
5341 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5342 if (boot_catlog
== 0)
5344 debug("No bootcatlog found\n");
5345 grub_file_close(file
);
5349 grub_memset(buf
, 0, sizeof(buf
));
5350 grub_file_seek(file
, boot_catlog
* 2048);
5351 grub_file_read(file
, buf
, sizeof(buf
));
5352 grub_file_close(file
);
5354 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5356 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5358 if (buf
[i
+ 32] == 0x88)
5360 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5361 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5367 if (loadsector
== 0)
5369 debug("No EFI eltorito info found\n");
5373 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5374 grub_env_set(args
[1], value
);
5375 VENTOY_CMD_RETURN(0);
5378 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5383 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5385 if (pfsdir
->initrd
[0])
5390 curpos
= pfsdir
->curpos
;
5391 len
= grub_strlen(filename
);
5395 if ((len
== 1 && filename
[0] == '.') ||
5396 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5401 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5404 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5405 pfsdir
->curpos
= curpos
+ printlen
;
5406 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5407 pfsdir
->curpos
= curpos
;
5408 pfsdir
->fullpath
[curpos
] = 0;
5412 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5415 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5416 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5418 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5420 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5429 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5433 char *device_name
= NULL
;
5434 grub_device_t dev
= NULL
;
5435 grub_fs_t fs
= NULL
;
5436 replace_fs_dir
*pfsdir
= NULL
;
5442 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5446 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5452 device_name
= grub_file_get_device_name(args
[0]);
5458 dev
= grub_device_open(device_name
);
5464 fs
= grub_fs_probe(dev
);
5473 pfsdir
->fullpath
[0] = '/';
5474 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5476 if (pfsdir
->initrd
[0])
5478 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5480 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5482 if (pfsdir
->initrd
[i
] == '/')
5484 pfsdir
->initrd
[i
] = '\\';
5488 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5489 grub_env_set(args
[1], pos
);
5493 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5498 grub_check_free(pfsdir
);
5499 grub_check_free(device_name
);
5500 check_free(dev
, grub_device_close
);
5502 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5505 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5507 const char *pager
= NULL
;
5513 pager
= grub_env_get("pager");
5517 grub_env_set("pager", "1");
5519 else if (pager
[0] == '1')
5525 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5527 grub_env_set("pager", "1");
5530 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5533 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5539 if (g_pager_flag
== 1)
5541 grub_env_unset("pager");
5543 else if (g_pager_flag
== 2)
5545 grub_env_set("pager", g_old_pager
);
5548 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5551 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5553 if (g_json_case_mis_path
[0])
5558 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5560 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5566 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5569 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5571 if (g_json_case_mis_path
[0])
5576 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5578 if (grub_strcasecmp(filename
, "ventoy") == 0)
5580 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5581 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5582 if (g_json_case_mis_path
[0])
5592 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5595 char *device_name
= NULL
;
5596 grub_device_t dev
= NULL
;
5597 grub_fs_t fs
= NULL
;
5598 chk_case_fs_dir fs_dir
;
5604 device_name
= grub_file_get_device_name(args
[0]);
5610 dev
= grub_device_open(device_name
);
5616 fs
= grub_fs_probe(dev
);
5622 fstype
= ventoy_get_fs_type(fs
->name
);
5623 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5628 g_json_case_mis_path
[0] = 0;
5631 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5633 if (g_json_case_mis_path
[0])
5635 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5640 grub_check_free(device_name
);
5641 check_free(dev
, grub_device_close
);
5643 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5646 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5649 grub_partition_t part
;
5650 char priority_str
[3]; /* Maximum value 15 */
5654 if (argc
< 2 || argc
> 3)
5655 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5656 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5658 /* Open the disk if it exists */
5659 disk
= grub_disk_open (args
[0]);
5662 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5666 part
= grub_partition_probe (disk
, args
[1]);
5669 grub_disk_close (disk
);
5670 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5671 "No such partition");
5674 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5676 grub_disk_close (disk
);
5677 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5678 "Not a GPT partition");
5681 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5682 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5686 grub_env_set (args
[2], priority_str
);
5687 grub_env_export (args
[2]);
5691 grub_printf ("Priority is %s\n", priority_str
);
5694 grub_disk_close (disk
);
5695 return GRUB_ERR_NONE
;
5699 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5703 grub_file_t file
= NULL
;
5704 grub_uint32_t loadrba
= 0;
5705 grub_uint32_t boot_catlog
= 0;
5706 grub_uint8_t sector
[512];
5707 boot_info_table
*info
= NULL
;
5712 /* This also trigger a iso9660 fs parse */
5713 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5718 joliet
= grub_iso9660_is_joliet();
5724 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5727 debug("failed to open %s\n", args
[0]);
5731 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5732 if (boot_catlog
== 0)
5734 debug("no bootcatlog found %u\n", boot_catlog
);
5738 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5741 debug("no bios eltorito rba found %u\n", loadrba
);
5745 grub_file_seek(file
, loadrba
* 2048);
5746 grub_file_read(file
, sector
, 512);
5748 info
= (boot_info_table
*)sector
;
5749 if (info
->bi_data0
== 0x7c6ceafa &&
5750 info
->bi_data1
== 0x90900000 &&
5751 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5752 info
->bi_BootFileLocation
== loadrba
)
5754 debug("bootloader is syslinux, %u.\n", loadrba
);
5760 grub_file_close(file
);
5761 grub_errno
= GRUB_ERR_NONE
;
5765 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5768 ventoy_vlnk_part
*node
;
5774 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5776 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5777 ++n
, node
->device
, node
->disksig
,
5778 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5784 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5792 len
= (int)grub_strlen(args
[0]);
5793 if (grub_file_is_vlnk_suffix(args
[0], len
))
5802 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5805 const char *name
= NULL
;
5811 grub_env_unset(args
[1]);
5812 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5815 debug("VLNK SRC: <%s>\n", args
[0]);
5816 debug("VLNK DST: <%s>\n", name
);
5817 grub_env_set(args
[1], name
);
5825 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5829 grub_file_t file
= NULL
;
5840 len
= (int)grub_strlen(args
[0]);
5841 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5843 grub_printf("Invalid vlnk suffix\n");
5847 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5850 grub_printf("Failed to open %s\n", args
[0]);
5854 if (file
->size
!= 32768)
5856 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5860 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5861 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5863 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5868 check_free(file
, grub_file_close
);
5869 grub_errno
= GRUB_ERR_NONE
;
5873 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5879 g_iso_vd_id_publisher
[0] = 0;
5880 g_iso_vd_id_prepare
[0] = 0;
5881 g_iso_vd_id_application
[0] = 0;
5886 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5890 grub_file_t file
= NULL
;
5895 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5898 grub_printf("Failed to open %s\n", args
[0]);
5902 grub_file_seek(file
, 16 * 2048 + offset
);
5903 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5906 grub_file_seek(file
, 16 * 2048 + offset
);
5907 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5910 grub_file_seek(file
, 16 * 2048 + offset
);
5911 grub_file_read(file
, g_iso_vd_id_application
, 128);
5915 check_free(file
, grub_file_close
);
5916 grub_errno
= GRUB_ERR_NONE
;
5920 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5923 char *id
= g_iso_vd_id_publisher
;
5928 if (args
[0][0] == '1')
5930 id
= g_iso_vd_id_prepare
;
5932 else if (args
[0][0] == '2')
5934 id
= g_iso_vd_id_application
;
5937 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5942 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5947 grub_errno
= GRUB_ERR_NONE
;
5951 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5956 g_ventoy_fn_mutex
= 0;
5957 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5959 g_ventoy_fn_mutex
= 1;
5962 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5965 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5967 grub_uint64_t total
;
5968 grub_uint64_t org_required
;
5969 grub_uint64_t new_required
;
5975 #ifdef GRUB_MACHINE_EFI
5976 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
5977 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
5978 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
5979 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
5984 grub_printf("Non EFI mode!\n");
5989 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5992 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5994 const char *env
= NULL
;
5999 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6004 if (ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6005 ventoy_check_mode_by_name(args
[0], "vtwimboot") ||
6006 ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6007 ventoy_check_mode_by_name(args
[0], "vtnormal")
6013 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6014 if (env
&& env
[0] == '0' && env
[1] == 0)
6022 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6030 const char *env
= NULL
;
6031 ulonglong fsize
= 0;
6033 int seldata
[16] = {0};
6038 len
= 8 * VTOY_SIZE_1KB
;
6039 cmd
= (char *)grub_malloc(len
);
6045 g_vtoy_secondary_need_recover
= 0;
6046 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6048 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6051 timeout
= (int)grub_strtol(env
, NULL
, 10);
6056 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6059 fsize
= grub_strtoull(args
[2], NULL
, 10);
6061 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in normal mode", "second_normal"); seldata
[n
++] = 1;
6063 if (grub_strcmp(args
[1], "Unix") != 0)
6065 if (grub_strcmp(args
[1], "Windows") == 0)
6067 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in wimboot mode", "second_wimboot"); seldata
[n
++] = 2;
6071 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in grub2 mode", "second_grub2"); seldata
[n
++] = 3;
6074 if (fsize
<= VTOY_SIZE_1GB
)
6076 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in memdisk mode", "second_memdisk"); seldata
[n
++] = 4;
6080 vtoy_dummy_menuentry(cmd
, pos
, len
, "File checksum", "second_checksum"); seldata
[n
++] = 5;
6083 g_ventoy_menu_esc
= 1;
6084 g_ventoy_suppress_esc
= 1;
6085 g_ventoy_suppress_esc_default
= 0;
6086 g_ventoy_secondary_menu_on
= 1;
6087 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6088 grub_script_execute_sourcecode(cfgfile
);
6089 g_ventoy_menu_esc
= 0;
6090 g_ventoy_suppress_esc
= 0;
6091 g_ventoy_suppress_esc_default
= 1;
6092 g_ventoy_secondary_menu_on
= 0;
6094 select
= seldata
[g_ventoy_last_entry
];
6098 g_ventoy_wimboot_mode
= 1;
6099 g_vtoy_secondary_need_recover
= 1;
6101 else if (select
== 3)
6103 g_ventoy_grub2_mode
= 1;
6104 g_vtoy_secondary_need_recover
= 2;
6106 else if (select
== 4)
6108 g_ventoy_memdisk_mode
= 1;
6109 g_vtoy_secondary_need_recover
= 3;
6111 else if (select
== 5)
6113 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6114 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6116 }while (select
== 5);
6122 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6128 if (g_vtoy_secondary_need_recover
== 1)
6130 g_ventoy_wimboot_mode
= 0;
6132 else if (g_vtoy_secondary_need_recover
== 2)
6134 g_ventoy_grub2_mode
= 0;
6136 else if (g_vtoy_secondary_need_recover
== 3)
6138 g_ventoy_memdisk_mode
= 0;
6141 g_vtoy_secondary_need_recover
= 0;
6143 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6146 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6151 if (args
[0][0] == '0')
6153 g_ventoy_case_insensitive
= 0;
6157 g_ventoy_case_insensitive
= 1;
6163 int ventoy_env_init(void)
6168 grub_env_set("vtdebug_flag", "");
6170 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6171 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6172 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6173 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6175 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6178 ventoy_filt_register(0, ventoy_wrapper_open
);
6180 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6183 g_grub_param
->grub_env_get
= grub_env_get
;
6184 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6185 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6186 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6187 grub_env_set("env_param", buf
);
6188 grub_env_set("ventoy_env_param", buf
);
6190 grub_env_export("env_param");
6191 grub_env_export("ventoy_env_param");
6194 grub_env_export("vtoy_winpeshl_ini_addr");
6195 grub_env_export("vtoy_winpeshl_ini_size");
6197 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6198 grub_env_set("vtoy_chain_file_size", buf
);
6199 grub_env_export("vtoy_chain_file_size");
6201 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6202 grub_env_set("vtoy_chain_file_read", buf
);
6203 grub_env_export("vtoy_chain_file_read");
6210 static cmd_para ventoy_cmds
[] =
6212 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6213 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6214 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6215 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6216 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6217 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6218 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6219 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6220 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6221 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6222 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6223 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6224 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6225 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6226 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6227 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6228 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6229 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6230 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6231 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6232 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6233 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6234 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6235 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6236 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6237 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6238 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6240 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6241 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6242 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6243 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6244 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6245 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6246 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6248 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6249 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6250 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6251 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6252 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6253 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6254 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6255 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6256 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6257 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6260 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6261 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6262 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6263 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6264 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6265 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6266 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6267 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6268 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6269 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6270 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6272 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6273 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6274 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6275 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6276 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6277 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6278 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6280 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6281 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6282 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6283 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6284 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6285 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6286 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6287 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6288 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6289 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6291 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6292 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6293 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6294 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6295 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6296 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6297 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6298 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6299 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6301 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6302 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6303 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6304 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6307 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6308 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6309 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6311 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6312 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6313 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6316 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6317 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6318 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6319 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6320 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6321 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6322 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6323 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6324 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6325 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6326 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6327 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6328 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6329 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6331 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6332 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6333 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6334 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6335 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6336 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6337 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6338 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6339 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6340 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6341 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6342 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6344 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6345 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6346 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6347 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6348 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6349 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6350 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6351 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6352 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6353 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6354 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6355 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6356 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6357 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6358 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6359 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6360 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6361 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6362 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6363 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6364 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6365 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6366 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6367 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6368 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6369 { "vt_limine_menu", ventoy_cmd_linux_limine_menu
, 0, NULL
, "", "", NULL
},
6370 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6373 int ventoy_register_all_cmd(void)
6376 cmd_para
*cur
= NULL
;
6378 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6380 cur
= ventoy_cmds
+ i
;
6381 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6382 cur
->summary
, cur
->description
, cur
->parser
);
6388 int ventoy_unregister_all_cmd(void)
6392 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6394 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);