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_conf_replace_offset
= 0;
111 grub_uint64_t g_svd_replace_offset
= 0;
112 conf_replace
*g_conf_replace_node
= NULL
;
113 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
114 int g_conf_replace_new_len
= 0;
115 int g_conf_replace_new_len_align
= 0;
117 int g_ventoy_disk_bios_id
= 0;
118 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
119 grub_uint64_t g_ventoy_disk_size
= 0;
120 grub_uint64_t g_ventoy_disk_part_size
[2];
122 char *g_tree_script_buf
= NULL
;
123 int g_tree_script_pos
= 0;
124 int g_tree_script_pre
= 0;
126 static char *g_list_script_buf
= NULL
;
127 static int g_list_script_pos
= 0;
129 static char *g_part_list_buf
= NULL
;
130 static int g_part_list_pos
= 0;
131 static grub_uint64_t g_part_end_max
= 0;
133 static int g_video_mode_max
= 0;
134 static int g_video_mode_num
= 0;
135 static ventoy_video_mode
*g_video_mode_list
= NULL
;
137 static int g_enumerate_time_checked
= 0;
138 static grub_uint64_t g_enumerate_start_time_ms
;
139 static grub_uint64_t g_enumerate_finish_time_ms
;
140 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
142 static char g_iso_vd_id_publisher
[130];
143 static char g_iso_vd_id_prepare
[130];
144 static char g_iso_vd_id_application
[130];
146 static int g_pager_flag
= 0;
147 static char g_old_pager
[32];
149 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
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_load_prompt
= 0;
162 static char g_vtoy_prompt_msg
[64];
164 static char g_json_case_mis_path
[32];
166 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
168 int ventoy_get_fs_type(const char *fs
)
172 return ventoy_fs_max
;
174 else if (grub_strncmp(fs
, "exfat", 5) == 0)
176 return ventoy_fs_exfat
;
178 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
180 return ventoy_fs_ntfs
;
182 else if (grub_strncmp(fs
, "ext", 3) == 0)
184 return ventoy_fs_ext
;
186 else if (grub_strncmp(fs
, "xfs", 3) == 0)
188 return ventoy_fs_xfs
;
190 else if (grub_strncmp(fs
, "udf", 3) == 0)
192 return ventoy_fs_udf
;
194 else if (grub_strncmp(fs
, "fat", 3) == 0)
196 return ventoy_fs_fat
;
199 return ventoy_fs_max
;
202 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
221 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
223 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
227 static int ventoy_control_get_flag(const char *key
)
229 const char *val
= ventoy_get_env(key
);
231 if (val
&& val
[0] == '1' && val
[1] == 0)
238 static grub_err_t
ventoy_fs_close(grub_file_t file
)
240 grub_file_close(g_old_file
);
241 grub_free(file
->data
);
249 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
255 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
260 for (i
= 0; i
< g_video_mode_num
; i
++)
262 if (g_video_mode_list
[i
].width
== info
->width
&&
263 g_video_mode_list
[i
].height
== info
->height
&&
264 g_video_mode_list
[i
].bpp
== info
->bpp
)
270 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
271 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
272 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
275 if (g_video_mode_num
== g_video_mode_max
)
277 g_video_mode_max
*= 2;
278 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
284 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
286 if (v1
->bpp
== v2
->bpp
)
288 if (v1
->width
== v2
->width
)
290 if (v1
->height
== v2
->height
)
296 return (v1
->height
< v2
->height
) ? -1 : 1;
301 return (v1
->width
< v2
->width
) ? -1 : 1;
306 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
310 static int ventoy_enum_video_mode(void)
313 grub_video_adapter_t adapter
;
314 grub_video_driver_id_t id
;
315 ventoy_video_mode mode
;
317 g_video_mode_num
= 0;
318 g_video_mode_max
= 1024;
319 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
320 if (!g_video_mode_list
)
325 #ifdef GRUB_MACHINE_PCBIOS
326 grub_dl_load ("vbe");
329 id
= grub_video_get_driver_id ();
331 FOR_VIDEO_ADAPTERS (adapter
)
333 if (!adapter
->iterate
||
334 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
335 adapter
->init() != GRUB_ERR_NONE
)))
340 adapter
->iterate(ventoy_video_hook
, NULL
);
342 if (adapter
->id
!= id
)
348 /* sort video mode */
349 for (i
= 0; i
< g_video_mode_num
; i
++)
350 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
352 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
354 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
355 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
356 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
360 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
363 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
367 static struct grub_fs vtoy_fs
=
372 .fs_read
= ventoy_fs_read
,
373 .fs_close
= ventoy_fs_close
,
383 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
389 file
->data
= grub_malloc(rawFile
->size
+ 4096);
395 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
396 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
398 g_old_file
= rawFile
;
400 file
->size
= rawFile
->size
+ len
;
401 file
->device
= rawFile
->device
;
403 file
->not_easily_seekable
= 1;
408 static int ventoy_check_decimal_var(const char *name
, long *value
)
410 const char *value_str
= NULL
;
412 value_str
= grub_env_get(name
);
413 if (NULL
== value_str
)
415 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
418 if (!ventoy_is_decimal(value_str
))
420 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
423 *value
= grub_strtol(value_str
, NULL
, 10);
425 return GRUB_ERR_NONE
;
428 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
430 grub_uint64_t sectors
;
432 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
434 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
438 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
441 return sectors
* 512;
444 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
450 grub_uint32_t offset
;
452 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
455 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
459 len
= (int)file
->size
;
461 data
= (char *)grub_malloc(file
->size
);
467 grub_file_read(file
, data
, file
->size
);
468 grub_file_close(file
);
470 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
471 grub_script_execute_sourcecode(exec
);
473 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
474 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
475 grub_file_close(file
);
477 grub_script_execute_sourcecode("loopback -d efiboot");
481 *direntoff
= offset
+ 2;
486 static int ventoy_set_check_result(int ret
, const char *msg
)
490 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
491 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
492 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
496 grub_printf(VTOY_WARNING
"\n");
497 grub_printf(VTOY_WARNING
"\n");
498 grub_printf(VTOY_WARNING
"\n\n\n");
500 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
501 grub_printf("Error message: <%s>\n\n", msg
);
502 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
504 grub_printf("\n\nWill exit after 10 seconds ...... ");
512 static int ventoy_check_official_device(grub_device_t dev
)
516 grub_uint64_t offset
;
519 grub_uint8_t mbr
[512];
523 struct grub_partition
*partition
;
525 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
527 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
530 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
531 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
532 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
534 #ifndef GRUB_MACHINE_EFI
535 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
537 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
539 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
541 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
543 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
545 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
554 /* We must have partition 2 */
557 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
561 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
565 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
568 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
570 grub_file_close(file
);
571 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
574 partition
= dev
->disk
->partition
;
575 if (partition
->number
!= 0 || partition
->start
!= 2048)
577 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
582 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
584 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
585 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
586 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
588 grub_file_close(file
);
589 return ventoy_set_check_result(6, "Disk partition layout check failed.");
594 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
595 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
596 PartTbl
[1].SectorCount
!= 65536)
598 grub_file_close(file
);
599 return ventoy_set_check_result(6, "Disk partition layout check failed.");
605 offset
= partition
->start
+ partition
->len
;
606 partition
= file
->device
->disk
->partition
;
607 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
609 grub_file_close(file
);
610 return ventoy_set_check_result(7, "Disk partition layout check failed.");
614 grub_file_close(file
);
618 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
619 dev2
= grub_device_open(devname
);
622 return ventoy_set_check_result(8, "Disk open failed");
625 fs
= grub_fs_probe(dev2
);
628 grub_device_close(dev2
);
629 return ventoy_set_check_result(9, "FS probe failed");
632 fs
->fs_label(dev2
, &label
);
633 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
635 grub_device_close(dev2
);
636 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
639 grub_device_close(dev2
);
643 disk
= grub_disk_open(dev
->disk
->name
);
646 return ventoy_set_check_result(11, "Disk open failed");
649 grub_memset(mbr
, 0, 512);
650 grub_disk_read(disk
, 0, 0, 512, mbr
);
651 grub_disk_close(disk
);
653 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
655 return ventoy_set_check_result(12, "MBR check failed");
658 return ventoy_set_check_result(0, NULL
);
661 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
665 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
675 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
677 grub_uint64_t size
= 0;
680 char fullpath
[256] = {0};
683 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
686 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
689 debug("grub_file_open failed <%s>\n", fullpath
);
695 grub_file_close(file
);
699 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
703 char fullpath
[512] = {0};
706 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
709 file
= grub_file_open(fullpath
, type
);
712 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
719 int ventoy_is_dir_exist(const char *fmt
, ...)
726 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
730 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
733 grub_strncpy(pos
+ len
, "\" ]", 3);
735 debug("script exec %s\n", buf
);
737 if (0 == grub_script_execute_sourcecode(buf
))
745 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
748 grub_uint8_t
*outbuf
;
749 grub_uint8_t gzHdr
[10] =
751 0x1F, 0x8B, /* magic */
759 grub_memset(&s
, 0, sizeof(mz_stream
));
761 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
763 outbuf
= (grub_uint8_t
*)mem_out
;
765 mem_out_len
-= sizeof(gzHdr
) + 8;
766 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
767 outbuf
+= sizeof(gzHdr
);
769 s
.avail_in
= mem_in_len
;
772 s
.avail_out
= mem_out_len
;
775 mz_deflate(&s
, MZ_FINISH
);
779 outbuf
+= s
.total_out
;
780 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
781 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
783 return s
.total_out
+ sizeof(gzHdr
) + 8;
791 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
795 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
798 if (0 == grub_strcmp(args
[0], "on"))
801 grub_env_set("vtdebug_flag", "debug");
806 grub_env_set("vtdebug_flag", "");
809 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
812 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
816 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
818 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
819 grub_printf(" level:\r\n");
820 grub_printf(" 01/11: busybox / (+cat log)\r\n");
821 grub_printf(" 02/12: initrd / (+cat log)\r\n");
822 grub_printf(" 03/13: hook / (+cat log)\r\n");
824 grub_printf(" debug:\r\n");
825 grub_printf(" 0: debug is off\r\n");
826 grub_printf(" 1: debug is on\r\n");
828 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
831 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
833 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
835 g_ventoy_debug_level
= 1;
838 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
841 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
850 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
853 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
885 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
901 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
917 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
922 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
924 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
927 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
932 value_long
+= grub_strtol(args
[1], NULL
, 10);
934 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
935 grub_env_set(args
[0], buf
);
937 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
940 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
942 ulonglong value1
= 0;
943 ulonglong value2
= 0;
948 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
951 value1
= grub_strtoull(args
[0], NULL
, 10);
952 value2
= grub_strtoull(args
[1], NULL
, 10);
954 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
955 grub_env_set(args
[2], buf
);
957 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
960 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
975 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
978 debug("failed to open file <%s> for udf check\n", args
[0]);
982 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
984 grub_env_set(args
[1], buf
);
986 grub_file_close(file
);
992 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1000 g_wimboot_enable
= 0;
1002 grub_check_free(g_wimiso_path
);
1003 grub_check_free(g_wimiso_chunk_list
.chunk
);
1005 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1011 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1012 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1013 if (NULL
== g_wimiso_chunk_list
.chunk
)
1015 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1018 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1019 g_wimiso_chunk_list
.cur_chunk
= 0;
1021 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1023 g_wimboot_enable
= 1;
1024 g_wimiso_path
= grub_strdup(args
[0]);
1025 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1026 grub_file_close(file
);
1031 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 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1099 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1100 grub_env_set(name
, value
);
1102 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1103 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1104 grub_env_set(name
, value
);
1109 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1115 g_vtoy_load_prompt
= 0;
1116 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1118 if (argc
== 2 && args
[0][0] == '1')
1120 g_vtoy_load_prompt
= 1;
1121 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1124 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1127 int ventoy_need_prompt_load_file(void)
1129 return g_vtoy_load_prompt
;
1132 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1134 grub_uint64_t ro
= 0;
1135 grub_uint64_t div
= 0;
1136 grub_ssize_t left
= size
;
1137 char *cur
= (char *)buf
;
1139 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1142 while (left
>= VTOY_SIZE_2MB
)
1144 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1145 cur
+= VTOY_SIZE_2MB
;
1146 left
-= VTOY_SIZE_2MB
;
1148 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1149 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1155 grub_file_read(file
, cur
, left
);
1158 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1164 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1171 enum grub_file_type type
;
1182 if (grub_strcmp(args
[0], "nodecompress") == 0)
1184 type
= VENTOY_FILE_TYPE
;
1188 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1191 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1194 debug("failed to open file <%s>\n", args
[1]);
1198 #ifdef GRUB_MACHINE_EFI
1199 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1201 buf
= (char *)grub_malloc(file
->size
);
1206 grub_file_close(file
);
1210 if (g_vtoy_load_prompt
)
1212 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1216 grub_file_read(file
, buf
, file
->size
);
1219 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1220 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1221 grub_env_set(name
, value
);
1223 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1224 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1225 grub_env_set(name
, value
);
1227 grub_file_close(file
);
1233 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1251 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1254 debug("failed to open file <%s> for udf check\n", args
[0]);
1258 headlen
= sizeof(ventoy_chain_head
);
1260 #ifdef GRUB_MACHINE_EFI
1261 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1263 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1266 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1268 grub_file_read(file
, buf
+ headlen
, file
->size
);
1270 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1271 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1272 grub_env_set(name
, value
);
1274 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1275 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1276 grub_env_set(name
, value
);
1278 grub_file_close(file
);
1284 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1290 if (grub_iso9660_is_joliet())
1292 debug("This time has joliet process\n");
1301 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1310 if (args
[0][0] == '1')
1312 grub_iso9660_set_nojoliet(1);
1316 grub_iso9660_set_nojoliet(0);
1322 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1327 grub_uint8_t buf
[32];
1338 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1341 debug("failed to open file <%s> for udf check\n", args
[0]);
1345 for (i
= 16; i
< 32; i
++)
1347 grub_file_seek(file
, i
* 2048);
1348 grub_file_read(file
, buf
, sizeof(buf
));
1356 grub_file_seek(file
, i
* 2048);
1357 grub_file_read(file
, buf
, sizeof(buf
));
1359 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1362 grub_file_seek(file
, i
* 2048);
1363 grub_file_read(file
, buf
, sizeof(buf
));
1365 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1366 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1372 grub_file_close(file
);
1374 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1379 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1381 long value_long1
= 0;
1382 long value_long2
= 0;
1384 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1386 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1389 value_long1
= grub_strtol(args
[0], NULL
, 10);
1390 value_long2
= grub_strtol(args
[2], NULL
, 10);
1392 if (0 == grub_strcmp(args
[1], "eq"))
1394 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1396 else if (0 == grub_strcmp(args
[1], "ne"))
1398 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1400 else if (0 == grub_strcmp(args
[1], "gt"))
1402 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1404 else if (0 == grub_strcmp(args
[1], "lt"))
1406 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1408 else if (0 == grub_strcmp(args
[1], "ge"))
1410 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1412 else if (0 == grub_strcmp(args
[1], "le"))
1414 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1418 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1424 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1427 char buf
[128] = {0};
1431 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1434 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1435 pos
= grub_strstr(buf
, ",");
1441 grub_env_set(args
[1], buf
);
1443 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1446 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1452 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1458 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1461 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1463 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1464 if (0 == grub_script_execute_sourcecode(buf
))
1466 debug("file %s exist, ventoy_compatible YES\n", buf
);
1467 grub_env_set("ventoy_compatible", "YES");
1468 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1472 debug("file %s NOT exist\n", buf
);
1476 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1477 pos
= grub_strstr(buf
, ")");
1483 disk
= grub_disk_open(buf
);
1486 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1487 grub_disk_close(disk
);
1489 g_img_swap_tmp_buf
[703] = 0;
1490 for (i
= 318; i
< 703; i
++)
1492 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1493 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1495 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1496 grub_env_set("ventoy_compatible", "YES");
1497 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1503 debug("failed to open disk <%s>\n", buf
);
1506 grub_env_set("ventoy_compatible", "NO");
1507 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1510 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1516 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1518 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1521 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1526 if (0 == g_sort_case_sensitive
)
1528 if (grub_islower(c1
))
1530 c1
= c1
- 'a' + 'A';
1533 if (grub_islower(c2
))
1535 c2
= c2
- 'a' + 'A';
1548 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1554 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1556 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1559 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1564 if (0 == g_sort_case_sensitive
)
1566 if (grub_islower(c1
))
1568 c1
= c1
- 'a' + 'A';
1571 if (grub_islower(c2
))
1573 c2
= c2
- 'a' + 'A';
1586 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1588 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1590 grub_memcpy(img1
, img2
, sizeof(img_info
));
1591 img1
->next
= g_img_swap_tmp
.next
;
1592 img1
->prev
= g_img_swap_tmp
.prev
;
1594 g_img_swap_tmp
.next
= img2
->next
;
1595 g_img_swap_tmp
.prev
= img2
->prev
;
1596 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1599 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1603 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1611 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1613 ventoy_vlnk_part
*node
= NULL
;
1614 grub_uint32_t SelfSig
;
1615 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1617 /* skip Ventoy partition 1/2 */
1618 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1619 if (partition
->number
< 2 && SelfSig
== *pSig
)
1624 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1627 node
->disksig
= *pSig
;
1628 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1629 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1630 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1632 node
->next
= g_vlnk_part_list
;
1633 g_vlnk_part_list
= node
;
1639 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1646 disk
= grub_disk_open(name
);
1649 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1650 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1651 grub_disk_close(disk
);
1657 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1659 const char *fs
[ventoy_fs_max
+ 1] =
1661 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1666 cur
->dev
= grub_device_open(cur
->device
);
1671 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1677 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1682 char *disk
, *device
;
1683 grub_uint32_t readcrc
, calccrc
;
1684 ventoy_vlnk_part
*cur
;
1685 grub_fs_t fs
= NULL
;
1687 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1691 grub_printf("VLNK invalid guid\n");
1697 readcrc
= vlnk
->crc32
;
1699 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1700 if (readcrc
!= calccrc
)
1704 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1710 if (!g_vlnk_part_list
)
1712 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1715 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1717 if (cur
->disksig
== vlnk
->disk_signature
)
1721 if (cur
->partoffset
== vlnk
->part_offset
)
1724 device
= cur
->device
;
1726 if (cur
->probe
== 0)
1729 ventoy_vlnk_probe_fs(cur
);
1739 struct grub_file file
;
1741 grub_memset(&file
, 0, sizeof(file
));
1742 file
.device
= cur
->dev
;
1743 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1746 cur
->fs
->fs_close(&file
);
1747 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1756 grub_printf("\n==== VLNK Information ====\n"
1757 "Disk Signature: %08x\n"
1758 "Partition Offset: %llu\n"
1759 "File Path: <%s>\n\n",
1760 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1764 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1768 grub_printf("Disk Find: [ NO ]\n");
1773 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1777 grub_printf("Part Find: [ NO ]\n");
1779 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1782 grub_printf("VLNK File: <%s>\n", dst
);
1789 return (1 - filefind
);
1792 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1797 grub_file_t file
= NULL
;
1802 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1804 else if (dir
[0] == '/')
1806 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1810 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1813 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1819 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1820 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1821 grub_file_close(file
);
1823 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1825 rc
= grub_file_add_vlnk(src
, dst
);
1831 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1841 const menu_tip
*tip
;
1842 img_iterator_node
*tmp
;
1843 img_iterator_node
*new_node
;
1844 img_iterator_node
*node
= (img_iterator_node
*)data
;
1846 if (g_enumerate_time_checked
== 0)
1848 g_enumerate_finish_time_ms
= grub_get_time_ms();
1849 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1852 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1854 g_enumerate_time_checked
= 1;
1858 len
= grub_strlen(filename
);
1862 if (node
->level
+ 1 > g_img_max_search_level
)
1867 if ((len
== 1 && filename
[0] == '.') ||
1868 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1873 if (!ventoy_img_name_valid(filename
, len
))
1878 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1883 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1885 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1886 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1889 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1894 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1897 new_node
->level
= node
->level
+ 1;
1898 new_node
->plugin_list_index
= index
;
1899 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1901 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1904 debug("Directory %s ignored...\n", new_node
->dir
);
1905 grub_free(new_node
);
1909 new_node
->tail
= node
->tail
;
1911 new_node
->parent
= node
;
1912 if (!node
->firstchild
)
1914 node
->firstchild
= new_node
;
1917 if (g_img_iterator_tail
)
1919 g_img_iterator_tail
->next
= new_node
;
1920 g_img_iterator_tail
= new_node
;
1924 g_img_iterator_head
.next
= new_node
;
1925 g_img_iterator_tail
= new_node
;
1931 debug("Find a file %s\n", filename
);
1937 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1939 type
= img_type_iso
;
1941 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1943 type
= img_type_wim
;
1945 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1946 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1948 type
= img_type_vhd
;
1950 #ifdef GRUB_MACHINE_EFI
1951 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1953 type
= img_type_efi
;
1956 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1958 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1960 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1961 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1966 type
= img_type_img
;
1968 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1970 type
= img_type_vtoy
;
1972 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1974 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1976 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1977 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1986 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1991 if (g_plugin_image_list
)
1993 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1994 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1995 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1997 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2000 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2002 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2007 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2009 if (grub_file_is_vlnk_suffix(filename
, len
))
2012 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2019 img
= grub_zalloc(sizeof(img_info
));
2023 img
->plugin_list_index
= index
;
2024 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2026 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2028 img
->size
= info
->size
;
2029 if (vlnk
|| 0 == img
->size
)
2031 if (node
->dir
[0] == '/')
2033 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2037 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2041 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2043 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2048 if (g_ventoy_img_list
)
2050 tail
= *(node
->tail
);
2056 g_ventoy_img_list
= img
;
2059 img
->id
= g_ventoy_img_count
;
2061 if (node
&& NULL
== node
->firstiso
)
2063 node
->firstiso
= img
;
2074 *((img_info
**)(node
->tail
)) = img
;
2075 g_ventoy_img_count
++;
2077 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2079 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2082 img
->tip1
= tip
->tip1
;
2083 img
->tip2
= tip
->tip2
;
2086 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2089 img
->class = g_menu_class
[type
];
2091 img
->menu_prefix
= g_menu_prefix
[type
];
2093 if (img_type_iso
== type
)
2095 if (ventoy_plugin_check_memdisk(img
->path
))
2097 img
->menu_prefix
= "miso";
2101 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2108 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2110 int len
= GRUB_UINT_MAX
;
2111 const char *value
= NULL
;
2112 char name
[32] = {0};
2113 char plat
[32] = {0};
2114 char guidstr
[32] = {0};
2115 ventoy_guid guid
= VENTOY_GUID
;
2116 const char *fmt1
= NULL
;
2117 const char *fmt2
= NULL
;
2118 const char *fmt3
= NULL
;
2119 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2120 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2121 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2122 const char fmtcode
[]={
2123 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2124 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2125 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2126 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2127 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2128 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2131 grub_memset(name
, 0, sizeof(name
));
2132 puint
[0] = grub_swap_bytes32(0x56454e54);
2133 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2134 puint
[2] = grub_swap_bytes32(0x45525349);
2135 puint
[1] = grub_swap_bytes32(0x4f595f56);
2136 value
= ventoy_get_env(name
);
2138 grub_memset(name
, 0, sizeof(name
));
2139 puint
[1] = grub_swap_bytes32(0x5f544f50);
2140 puint
[0] = grub_swap_bytes32(0x56544c45);
2141 fmt1
= ventoy_get_env(name
);
2147 grub_memset(name
, 0, sizeof(name
));
2148 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2149 puint
[0] = grub_swap_bytes32(0x56544c45);
2150 fmt2
= ventoy_get_env(name
);
2152 grub_memset(name
, 0, sizeof(name
));
2153 puint
[1] = grub_swap_bytes32(0x5f434c52);
2154 puint
[0] = grub_swap_bytes32(0x56544c45);
2155 fmt3
= ventoy_get_env(name
);
2157 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2159 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2161 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2162 #pragma GCC diagnostic push
2163 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2164 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2165 fmt1
? fmt1
: fmtdata
,
2166 fmt2
? fmt2
: fmtdata
+ 4,
2167 value
? value
: "", plat
, guidstr
,
2168 fmt3
? fmt3
: fmtdata
+ 6);
2169 #pragma GCC diagnostic pop
2171 grub_memset(name
, 0, sizeof(name
));
2172 puint
[0] = grub_swap_bytes32(0x76746f79);
2173 puint
[2] = grub_swap_bytes32(0x656e7365);
2174 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2175 ventoy_set_env(name
, guidstr
);
2180 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2184 grub_uint8_t md5
[16];
2188 grub_memset(input
, 0, sizeof(input
));
2190 grub_printf("Enter password: ");
2193 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2195 grub_password_get(input
, 128);
2196 if (grub_strcmp(pwd
->text
, input
) == 0)
2201 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2203 grub_password_get(input
, 128);
2204 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2205 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2210 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2212 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2213 grub_password_get(input
+ offset
, 128);
2215 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2216 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2222 grub_printf("Invalid password!\n\n");
2229 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2231 img_info
*minimg
= NULL
;
2232 img_info
*img
= (img_info
*)(node
->firstiso
);
2234 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2236 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2251 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2253 img_iterator_node
*Minchild
= NULL
;
2254 img_iterator_node
*child
= node
->firstchild
;
2256 while (child
&& child
->parent
== node
)
2258 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2262 child
= child
->next
;
2267 Minchild
->select
= 1;
2273 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2276 img_info
*img
= NULL
;
2277 const char *dir_class
= NULL
;
2278 const char *dir_alias
= NULL
;
2279 img_iterator_node
*child
= NULL
;
2280 const menu_tip
*tip
= NULL
;
2282 if (node
->isocnt
== 0 || node
->done
== 1)
2287 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2289 offset
= node
->parent
->dirlen
;
2292 if (node
== &g_img_iterator_head
)
2294 if (g_default_menu_mode
== 0)
2296 if (g_tree_view_menu_style
== 0)
2298 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2299 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2300 " echo 'return ...' \n"
2305 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2306 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2307 " echo 'return ...' \n"
2312 g_tree_script_pre
= g_tree_script_pos
;
2316 node
->dir
[node
->dirlen
- 1] = 0;
2317 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2320 dir_class
= "vtoydir";
2323 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2325 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2328 if (g_tree_view_menu_style
== 0)
2330 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2331 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2332 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2336 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2337 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2338 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2343 dir_alias
= node
->dir
+ offset
;
2345 if (g_tree_view_menu_style
== 0)
2347 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2348 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2349 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2353 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2354 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2355 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2359 if (g_tree_view_menu_style
== 0)
2361 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2362 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2363 " echo 'return ...' \n"
2364 "}\n", "<--", node
->dir
);
2368 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2369 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2370 " echo 'return ...' \n"
2375 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2377 ventoy_dynamic_tree_menu(child
);
2380 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2382 if (g_tree_view_menu_style
== 0)
2384 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2385 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2388 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2389 img
->unsupport
? "[***********] " : "",
2390 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2392 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2396 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2397 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2400 img
->unsupport
? "[***********] " : "",
2401 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2403 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2407 if (node
!= &g_img_iterator_head
)
2409 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2416 static int ventoy_set_default_menu(void)
2422 const char *strdata
= NULL
;
2423 img_info
*cur
= NULL
;
2424 img_info
*default_node
= NULL
;
2425 const char *default_image
= NULL
;
2427 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2428 if (default_image
&& default_image
[0] == '/')
2430 img_len
= grub_strlen(default_image
);
2432 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2434 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2446 if (0 == g_default_menu_mode
)
2448 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2452 def
= grub_strdup(default_image
);
2458 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2460 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2461 if (strdata
&& strdata
[0] == '/')
2463 pos
= def
+ grub_strlen(strdata
);
2474 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2477 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2481 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2489 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2491 img_info
*next
= NULL
;
2492 img_info
*cur
= g_ventoy_img_list
;
2505 g_ventoy_img_list
= NULL
;
2506 g_ventoy_img_count
= 0;
2508 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2511 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2514 img_info
*cur
= g_ventoy_img_list
;
2518 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2520 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2523 img_id
= grub_strtol(args
[0], NULL
, 10);
2524 if (img_id
>= g_ventoy_img_count
)
2526 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2529 debug("Find image %ld name \n", img_id
);
2531 while (cur
&& img_id
> 0)
2539 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2542 debug("image name is %s\n", cur
->name
);
2544 grub_env_set(args
[1], cur
->name
);
2546 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2549 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2553 img_info
*cur
= g_ventoy_img_list
;
2559 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2562 len
= (int)grub_strlen(args
[0]);
2566 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2575 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2578 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2579 grub_env_set("chosen", id
);
2580 grub_env_export("chosen");
2582 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2585 static char g_fake_vlnk_src
[512];
2586 static char g_fake_vlnk_dst
[512];
2587 static grub_uint64_t g_fake_vlnk_size
;
2588 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2594 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2596 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2597 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2599 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2601 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2604 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2610 g_fake_vlnk_src
[0] = 0;
2611 g_fake_vlnk_dst
[0] = 0;
2612 g_fake_vlnk_size
= 0;
2613 grub_file_vtoy_vlnk(NULL
, NULL
);
2615 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2619 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2624 const char *id
= NULL
;
2625 img_info
*cur
= NULL
;
2629 if (argc
< 1 || argc
> 3)
2631 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2634 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2636 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2637 grub_env_set(args
[0], pos
);
2640 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2641 grub_env_set(args
[1], value
);
2646 for (last
= pos
; *pos
; pos
++)
2653 grub_env_set(args
[2], last
+ 1);
2659 id
= grub_env_get("chosen");
2661 pos
= grub_strstr(id
, "VID_");
2664 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2668 cur
= g_ventoy_img_list
;
2673 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2676 grub_env_set(args
[0], cur
->path
);
2680 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2681 grub_env_set(args
[1], value
);
2686 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2687 grub_env_set(args
[2], cur
->name
);
2691 g_svd_replace_offset
= 0;
2693 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2697 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2701 grub_device_t dev
= NULL
;
2702 img_info
*cur
= NULL
;
2703 img_info
*tail
= NULL
;
2704 img_info
*min
= NULL
;
2705 img_info
*head
= NULL
;
2706 const char *strdata
= NULL
;
2707 char *device_name
= NULL
;
2709 img_iterator_node
*node
= NULL
;
2710 img_iterator_node
*tmp
= NULL
;
2716 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2719 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2721 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2726 g_enumerate_time_checked
= 0;
2727 g_enumerate_start_time_ms
= grub_get_time_ms();
2729 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2730 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2732 g_filt_dot_underscore_file
= 1;
2735 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2736 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2738 g_sort_case_sensitive
= 1;
2741 device_name
= grub_file_get_device_name(args
[0]);
2747 g_enum_dev
= dev
= grub_device_open(device_name
);
2753 g_enum_fs
= fs
= grub_fs_probe(dev
);
2759 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2761 debug("unsupported fs:<%s>\n", fs
->name
);
2762 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2766 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2768 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2769 if (strdata
&& strdata
[0] == '1')
2771 g_default_menu_mode
= 1;
2774 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2776 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2778 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2779 if (strdata
&& strdata
[0] == '/')
2781 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2782 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2784 g_img_iterator_head
.dir
[len
++] = '/';
2786 g_img_iterator_head
.dirlen
= len
;
2790 g_img_iterator_head
.dirlen
= 1;
2791 grub_strcpy(g_img_iterator_head
.dir
, "/");
2794 g_img_iterator_head
.tail
= &tail
;
2796 if (g_img_max_search_level
< 0)
2798 g_img_max_search_level
= GRUB_INT_MAX
;
2799 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2800 if (strdata
&& ventoy_is_decimal(strdata
))
2802 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2806 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2807 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2808 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2809 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2810 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2811 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2813 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2815 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2818 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2819 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2821 g_tree_view_menu_style
= 1;
2824 ventoy_set_default_menu();
2826 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2828 ventoy_dynamic_tree_menu(node
);
2832 node
= g_img_iterator_head
.next
;
2840 /* sort image list by image name */
2841 while (g_ventoy_img_list
)
2843 min
= g_ventoy_img_list
;
2844 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2846 if (ventoy_cmp_img(min
, cur
) > 0)
2854 min
->prev
->next
= min
->next
;
2859 min
->next
->prev
= min
->prev
;
2862 if (min
== g_ventoy_img_list
)
2864 g_ventoy_img_list
= min
->next
;
2882 g_ventoy_img_list
= head
;
2884 if (g_default_menu_mode
== 1)
2886 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2887 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2888 " echo 'return ...' \n"
2892 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2894 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2895 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2898 cur
->unsupport
? "[***********] " : "",
2899 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2901 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2904 g_tree_script_buf
[g_tree_script_pos
] = 0;
2905 g_list_script_buf
[g_list_script_pos
] = 0;
2907 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2908 grub_env_set(args
[1], buf
);
2912 check_free(device_name
, grub_free
);
2913 check_free(dev
, grub_device_close
);
2915 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2918 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2925 device_name
= grub_file_get_device_name(filename
);
2937 pos2
= grub_strstr(pos
, ",");
2940 pos2
= grub_strstr(pos
, ")");
2948 disk
= grub_disk_open(pos
);
2951 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2952 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2953 grub_disk_close(disk
);
2960 grub_free(device_name
);
2964 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2966 eltorito_descriptor desc
;
2968 grub_memset(&desc
, 0, sizeof(desc
));
2969 grub_file_seek(file
, 17 * 2048);
2970 grub_file_read(file
, &desc
, sizeof(desc
));
2972 if (desc
.type
!= 0 || desc
.version
!= 1)
2977 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2978 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2986 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2988 grub_uint8_t buf
[512];
2990 grub_file_seek(file
, sector
* 2048);
2991 grub_file_read(file
, buf
, sizeof(buf
));
2993 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2994 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2996 return *((grub_uint32_t
*)(buf
+ 40));
3002 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3006 grub_uint8_t buf
[512];
3007 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3009 grub_file_seek(file
, sector
* 2048);
3010 grub_file_read(file
, buf
, sizeof(buf
));
3012 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3014 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3018 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3023 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3025 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3027 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3031 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3033 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3038 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3040 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3042 if (buf
[36] == parttype
[i
])
3044 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3050 debug("%s does not contain efi eltorito\n", file
->name
);
3054 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3057 const char *fs
= NULL
;
3058 const char *val
= NULL
;
3059 const char *cdprompt
= NULL
;
3061 grub_uint8_t chksum
= 0;
3064 disk
= file
->device
->disk
;
3065 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3067 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3068 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3069 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3071 pos
= grub_strstr(file
->name
, "/");
3077 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3079 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3081 param
->vtoy_img_size
= file
->size
;
3083 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3084 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3086 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3088 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3089 param
->vtoy_reserved
[4] = 0;
3090 if (g_ventoy_chain_type
== 1) /* Windows */
3092 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3093 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3095 param
->vtoy_reserved
[4] = 1;
3099 fs
= ventoy_get_env("ventoy_fs_probe");
3100 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3102 param
->vtoy_reserved
[3] = 1;
3105 param
->vtoy_reserved
[5] = 0;
3106 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3107 if (val
&& val
[0] == '1' && val
[1] == 0)
3109 param
->vtoy_reserved
[5] = 1;
3112 /* ventoy_disk_signature used for vlnk */
3113 param
->vtoy_reserved
[6] = file
->vlnk
;
3114 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3116 /* calculate checksum */
3117 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3119 chksum
+= *((grub_uint8_t
*)param
+ i
);
3121 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3126 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3128 grub_uint32_t i
= 0;
3129 grub_uint64_t total
= 0;
3130 grub_uint64_t fileblk
= 0;
3131 ventoy_img_chunk
*chunk
= NULL
;
3133 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3135 chunk
= chunklist
->chunk
+ i
;
3137 if (chunk
->disk_start_sector
<= start
)
3139 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3143 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3146 fileblk
= (file
->size
+ 511) / 512;
3148 if (total
!= fileblk
)
3150 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3151 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3153 debug("maybe img file to be processed.\n");
3163 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3167 grub_uint32_t i
= 0;
3168 grub_uint32_t sector
= 0;
3169 grub_uint32_t count
= 0;
3170 grub_off_t size
= 0;
3171 grub_off_t read
= 0;
3173 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3174 if (fs_type
== ventoy_fs_exfat
)
3176 grub_fat_get_file_chunk(start
, file
, chunklist
);
3178 else if (fs_type
== ventoy_fs_ext
)
3180 grub_ext_get_file_chunk(start
, file
, chunklist
);
3184 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3185 file
->read_hook_data
= chunklist
;
3187 for (size
= file
->size
; size
> 0; size
-= read
)
3189 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3190 grub_file_read(file
, NULL
, read
);
3193 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3195 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3196 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3199 if (ventoy_fs_udf
== fs_type
)
3201 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3203 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3204 chunklist
->chunk
[i
].img_start_sector
= sector
;
3205 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3211 len
= (int)grub_strlen(file
->name
);
3212 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3213 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3214 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3215 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3217 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3219 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3229 chunklist
->chunk
[i
].img_start_sector
= sector
;
3230 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3238 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3242 grub_disk_addr_t start
;
3247 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3250 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3253 g_conf_replace_node
= NULL
;
3254 g_conf_replace_offset
= 0;
3256 if (g_img_chunk_list
.chunk
)
3258 grub_free(g_img_chunk_list
.chunk
);
3261 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3263 grub_file_close(file
);
3264 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3267 /* get image chunk data */
3268 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3269 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3270 if (NULL
== g_img_chunk_list
.chunk
)
3272 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3275 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3276 g_img_chunk_list
.cur_chunk
= 0;
3278 start
= file
->device
->disk
->partition
->start
;
3280 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3282 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3283 grub_file_close(file
);
3287 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3290 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3291 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3292 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3295 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3297 grub_uint64_t offset
= 0;
3298 grub_uint32_t align
= 0;
3299 grub_file_t file
= NULL
;
3300 conf_replace
*node
= NULL
;
3306 debug("select conf replace argc:%d\n", argc
);
3313 node
= ventoy_plugin_find_conf_replace(args
[1]);
3316 debug("Conf replace not found for %s\n", args
[1]);
3320 debug("Find conf replace for %s\n", args
[1]);
3322 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3325 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3326 grub_file_close(file
);
3328 else if (node
->img
> 0)
3334 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3338 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3341 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3345 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3347 if (align
> vtoy_max_replace_file_size
)
3349 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3353 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3354 g_conf_replace_new_len
= (int)file
->size
;
3355 g_conf_replace_new_len_align
= align
;
3357 g_conf_replace_node
= node
;
3358 g_conf_replace_offset
= offset
+ 2;
3362 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3363 g_grub_param
->img_replace
.old_name_cnt
= 1;
3364 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3367 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3372 grub_file_close(file
);
3374 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3377 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3382 const char *ch
= var
;
3389 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3396 debug("Invalid variable letter <%c>\n", *ch
);
3403 debug("Invalid variable length:%d <%s>\n", n
, var
);
3407 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3416 grub_printf("\n=================== Variables Expansion ===================\n\n");
3419 grub_printf("<%s>: ", var
);
3422 while (i
< (len
- 1))
3425 if ((c
== '\n') || (c
== '\r'))
3435 else if (grub_isprint(c
))
3437 if (i
+ 1 < (len
- 1))
3439 grub_printf("%c", c
);
3449 expand
[i
- 1] = ' ';
3450 grub_printf("\r<%s>: %s", var
, expand
);
3453 grub_printf("\r<%s>: %s", var
, expand
);
3465 grub_snprintf(expand
, len
, "$$%s$$", var
);
3471 static int ventoy_auto_install_var_expand(install_template
*node
)
3479 char *newbuf
= NULL
;
3480 char *curline
= NULL
;
3481 char *nextline
= NULL
;
3482 grub_uint8_t
*code
= NULL
;
3484 var_node
*CurNode
= NULL
;
3485 var_node
*pVarList
= NULL
;
3487 code
= (grub_uint8_t
*)node
->filebuf
;
3489 if (node
->filelen
>= VTOY_SIZE_1MB
)
3491 debug("auto install script too long %d\n", node
->filelen
);
3495 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3497 debug("UCS-2 encoding NOT supported\n");
3501 start
= grub_strstr(node
->filebuf
, "$$");
3504 debug("no need to expand variable, no start.\n");
3508 end
= grub_strstr(start
+ 2, "$$");
3511 debug("no need to expand variable, no end.\n");
3515 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3516 newbuf
= grub_malloc(newlen
);
3519 debug("Failed to alloc newbuf %d\n", newlen
);
3523 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3525 nextline
= ventoy_get_line(curline
);
3527 start
= grub_strstr(curline
, "$$");
3530 end
= grub_strstr(start
+ 2, "$$");
3536 VTOY_APPEND_NEWBUF(curline
);
3538 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3540 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3542 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3549 value
[sizeof(value
) - 1] = 0;
3550 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3554 CurNode
= grub_zalloc(sizeof(var_node
));
3557 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3558 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3559 CurNode
->next
= pVarList
;
3565 VTOY_APPEND_NEWBUF(value
);
3567 VTOY_APPEND_NEWBUF(end
+ 2);
3571 VTOY_APPEND_NEWBUF(curline
);
3574 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3576 newbuf
[pos
- 1] = '\n';
3580 newbuf
[pos
++] = '\n';
3584 grub_free(node
->filebuf
);
3585 node
->filebuf
= newbuf
;
3586 node
->filelen
= pos
;
3590 CurNode
= pVarList
->next
;
3591 grub_free(pVarList
);
3598 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3604 grub_file_t file
= NULL
;
3605 char configfile
[128];
3606 install_template
*node
= NULL
;
3612 debug("select auto installation argc:%d\n", argc
);
3619 node
= ventoy_plugin_find_install_template(args
[0]);
3622 debug("Auto install template not found for %s\n", args
[0]);
3626 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3628 defidx
= node
->autosel
;
3629 if (node
->timeout
< 0)
3631 node
->cursel
= node
->autosel
- 1;
3632 debug("Auto install template auto select %d\n", node
->autosel
);
3637 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3643 if (node
->timeout
> 0)
3645 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3648 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3649 " echo %s\n}\n", "");
3651 for (i
= 0; i
< node
->templatenum
; i
++)
3653 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3655 node
->templatepath
[i
].path
);
3658 g_ventoy_menu_esc
= 1;
3659 g_ventoy_suppress_esc
= 1;
3660 g_ventoy_suppress_esc_default
= defidx
;
3662 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3663 grub_script_execute_sourcecode(configfile
);
3665 g_ventoy_menu_esc
= 0;
3666 g_ventoy_suppress_esc
= 0;
3667 g_ventoy_suppress_esc_default
= 1;
3671 node
->cursel
= g_ventoy_last_entry
- 1;
3673 grub_check_free(node
->filebuf
);
3676 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3678 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3679 node
->templatepath
[node
->cursel
].path
);
3682 node
->filebuf
= grub_malloc(file
->size
+ 8);
3685 grub_file_read(file
, node
->filebuf
, file
->size
);
3686 grub_file_close(file
);
3688 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3689 node
->filelen
= (int)file
->size
;
3691 ventoy_auto_install_var_expand(node
);
3696 debug("Failed to open auto install script <%s%s>\n",
3697 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3701 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3704 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3710 char configfile
[128];
3711 persistence_config
*node
;
3717 debug("select persistence argc:%d\n", argc
);
3724 node
= ventoy_plugin_find_persistent(args
[0]);
3727 debug("Persistence image not found for %s\n", args
[0]);
3731 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3733 defidx
= node
->autosel
;
3734 if (node
->timeout
< 0)
3736 node
->cursel
= node
->autosel
- 1;
3737 debug("Persistence image auto select %d\n", node
->autosel
);
3742 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3748 if (node
->timeout
> 0)
3750 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3753 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3754 " echo %s\n}\n", "");
3756 for (i
= 0; i
< node
->backendnum
; i
++)
3758 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3760 node
->backendpath
[i
].path
);
3764 g_ventoy_menu_esc
= 1;
3765 g_ventoy_suppress_esc
= 1;
3766 g_ventoy_suppress_esc_default
= defidx
;
3768 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3769 grub_script_execute_sourcecode(configfile
);
3771 g_ventoy_menu_esc
= 0;
3772 g_ventoy_suppress_esc
= 0;
3773 g_ventoy_suppress_esc_default
= 1;
3777 node
->cursel
= g_ventoy_last_entry
- 1;
3779 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3782 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3785 ventoy_img_chunk
*cur
;
3791 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3793 cur
= g_img_chunk_list
.chunk
+ i
;
3794 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3795 cur
->img_start_sector
, cur
->img_end_sector
,
3796 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3800 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3803 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3807 ventoy_img_chunk_list chunklist
;
3812 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3815 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3818 /* get image chunk data */
3819 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3820 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3821 if (NULL
== chunklist
.chunk
)
3823 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3826 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3827 chunklist
.cur_chunk
= 0;
3829 ventoy_get_block_list(file
, &chunklist
, 0);
3831 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3833 grub_printf("########## UNSUPPORTED ###############\n");
3836 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3838 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3840 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3841 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3844 grub_printf("\n==================================\n");
3846 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3848 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3849 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3850 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3851 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3852 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3856 grub_free(chunklist
.chunk
);
3857 grub_file_close(file
);
3859 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3862 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3865 ventoy_grub_param_file_replace
*replace
= NULL
;
3873 replace
= &(g_grub_param
->file_replace
);
3874 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3876 replace
->old_name_cnt
= 0;
3877 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3879 replace
->old_name_cnt
++;
3880 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3883 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3886 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3889 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3892 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3898 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3899 grub_env_set(args
[0], buf
);
3902 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3905 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3913 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3914 grub_printf("%s", g_list_script_buf
);
3918 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3919 grub_printf("%s", g_tree_script_buf
);
3925 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3927 img_info
*cur
= g_ventoy_img_list
;
3935 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3936 grub_printf("name:<%s>\n\n", cur
->name
);
3943 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3949 ventoy_plugin_dump_injection();
3954 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3960 ventoy_plugin_dump_auto_install();
3965 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3971 ventoy_plugin_dump_persistence();
3976 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
3982 len1
= (int)grub_strlen(filename
);
3983 len2
= (int)grub_strlen(suffix
);
3990 for (i
= len1
- 1; i
>= 0; i
--)
3992 if (filename
[i
] == '.')
4003 if (filename
[i
- len2
- 1] != '_')
4008 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4016 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4022 if (argc
!= 1 && argc
!= 2)
4027 if (args
[0][0] == '0')
4029 if (g_ventoy_memdisk_mode
)
4034 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4041 else if (args
[0][0] == '1')
4043 return g_ventoy_iso_raw
? 0 : 1;
4045 else if (args
[0][0] == '2')
4047 return g_ventoy_iso_uefi_drv
? 0 : 1;
4049 else if (args
[0][0] == '3')
4051 if (g_ventoy_grub2_mode
)
4056 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4063 else if (args
[0][0] == '4')
4065 if (g_ventoy_wimboot_mode
)
4070 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4081 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4083 static int configfile_mode
= 0;
4084 char memfile
[128] = {0};
4091 * args[0]: 0:normal 1:configfile
4092 * args[1]: 0:list_buf 1:tree_buf
4097 debug("Invalid argc %d\n", argc
);
4103 if (args
[0][0] == '0')
4105 if (args
[1][0] == '0')
4107 grub_script_execute_sourcecode(g_list_script_buf
);
4111 grub_script_execute_sourcecode(g_tree_script_buf
);
4116 if (configfile_mode
)
4118 debug("Now already in F3 mode %d\n", configfile_mode
);
4122 if (args
[1][0] == '0')
4124 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4125 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4129 g_ventoy_last_entry
= -1;
4130 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4131 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4134 configfile_mode
= 1;
4135 grub_script_execute_sourcecode(memfile
);
4136 configfile_mode
= 0;
4142 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4153 g_ventoy_case_insensitive
= 1;
4154 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4155 g_ventoy_case_insensitive
= 0;
4161 grub_file_close(file
);
4167 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4172 const char *isopath
= NULL
;
4174 ventoy_mbr_head mbr
;
4181 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4184 isopath
= grub_env_get("vtoy_iso_part");
4187 debug("isopath is null %p\n", isopath
);
4191 debug("isopath is %s\n", isopath
);
4193 for (id
= 0; id
< 30 && (find
== 0); id
++)
4195 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4196 if (grub_strstr(isopath
, hdname
))
4198 debug("skip %s ...\n", hdname
);
4202 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4204 disk
= grub_disk_open(hdname
);
4207 debug("%s not exist\n", hdname
);
4211 grub_memset(&mbr
, 0, sizeof(mbr
));
4212 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4214 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4216 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4217 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4220 grub_env_set(args
[0], hdname
);
4224 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4228 debug("read %s failed\n", hdname
);
4231 grub_disk_close(disk
);
4237 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4248 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4251 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4254 debug("failed to open file %s\n", args
[0]);
4258 buf
= grub_malloc(len
);
4265 grub_file_read(file
, buf
, len
- 1);
4267 ventoy_get_line(buf
);
4268 ventoy_set_env(args
[1], buf
);
4272 grub_check_free(buf
);
4273 grub_file_close(file
);
4278 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4280 grub_uint64_t end_max
= 0;
4281 int *pCnt
= (int *)data
;
4286 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4287 "0 %llu linear /dev/ventoy %llu\n",
4288 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4290 end_max
= (partition
->len
+ partition
->start
) * 512;
4291 if (end_max
> g_part_end_max
)
4293 g_part_end_max
= end_max
;
4299 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4302 char *device_name
= NULL
;
4303 grub_device_t dev
= NULL
;
4308 g_part_list_pos
= 0;
4310 grub_env_unset("vtoy_img_part_file");
4317 device_name
= grub_file_get_device_name(args
[0]);
4320 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4324 dev
= grub_device_open(device_name
);
4327 debug("grub_device_open failed, %s\n", device_name
);
4331 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4333 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4334 grub_env_set("vtoy_img_part_file", buf
);
4336 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4337 grub_env_set("vtoy_img_part_cnt", buf
);
4339 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4340 grub_env_set("vtoy_img_max_part_end", buf
);
4344 check_free(device_name
, grub_free
);
4345 check_free(dev
, grub_device_close
);
4351 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4362 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4365 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4368 debug("failed to open file %s\n", args
[0]);
4372 buf
= grub_malloc(file
->size
+ 1);
4378 buf
[file
->size
] = 0;
4379 grub_file_read(file
, buf
, file
->size
);
4381 if (grub_strstr(buf
, args
[1]))
4388 grub_check_free(buf
);
4389 grub_file_close(file
);
4394 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4400 ventoy_iso9660_vd pvd
;
4407 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4410 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4413 debug("failed to open file %s\n", args
[0]);
4417 grub_file_seek(file
, 16 * 2048);
4418 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4419 if (len
!= sizeof(pvd
))
4421 debug("failed to read pvd %d\n", len
);
4425 grub_memset(buf
, 0, sizeof(buf
));
4426 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4427 ventoy_set_env(args
[1], buf
);
4429 grub_memset(buf
, 0, sizeof(buf
));
4430 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4431 ventoy_set_env(args
[2], buf
);
4435 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4436 ventoy_set_env(args
[3], buf
);
4439 grub_file_close(file
);
4444 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4455 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4458 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4461 debug("failed to open file %s\n", args
[0]);
4465 grub_memset(buf
, 0, sizeof(buf
));
4466 grub_file_seek(file
, 16 * 2048 + 813);
4467 len
= (int)grub_file_read(file
, buf
, 17);
4470 debug("failed to read create date %d\n", len
);
4474 ventoy_set_env(args
[1], buf
);
4477 grub_file_close(file
);
4482 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4488 ventoy_env_hook_root(1);
4493 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4499 ventoy_env_hook_root(0);
4504 #ifdef GRUB_MACHINE_EFI
4505 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4510 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4516 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4517 if (var
&& *var
== 1)
4525 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4534 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4539 grub_uint64_t FileSectors
= 0;
4540 ventoy_gpt_info
*gpt
= NULL
;
4541 ventoy_part_table
*pt
= NULL
;
4542 grub_uint8_t zeroguid
[16] = {0};
4547 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4550 debug("failed to open file %s\n", args
[0]);
4554 if (file
->size
% 512)
4556 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4560 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4566 FileSectors
= file
->size
/ 512;
4568 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4569 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4571 debug("This is EFI partition table\n");
4573 for (i
= 0; i
< 128; i
++)
4575 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4577 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4579 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4580 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4588 debug("This is MBR partition table\n");
4590 for (i
= 0; i
< 4; i
++)
4592 pt
= gpt
->MBR
.PartTbl
+ i
;
4593 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4595 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4596 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4597 (ulonglong
)FileSectors
);
4606 grub_file_close(file
);
4607 grub_check_free(gpt
);
4608 grub_errno
= GRUB_ERR_NONE
;
4612 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4621 for (i
= 0; i
< 500; i
++)
4623 ret
= grub_getkey_noblock();
4624 if (ret
== GRUB_TERM_NO_KEY
)
4633 grub_printf("\n\n Still have key input after clear.\n");
4641 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4648 int image_sector_size
;
4650 ventoy_chain_head
*chain
;
4651 ventoy_img_chunk
*chunk
;
4652 ventoy_os_param
*osparam
;
4653 ventoy_image_location
*location
;
4654 ventoy_image_disk_region
*region
;
4655 struct grub_acpi_table_header
*acpi
;
4664 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4666 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4672 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4674 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4676 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4680 img_chunk_num
= chain
->img_chunk_num
;
4682 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4683 datalen
= sizeof(ventoy_os_param
) + loclen
;
4685 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4686 acpi
= grub_zalloc(buflen
);
4692 /* Step1: Fill acpi table header */
4693 grub_memcpy(acpi
->signature
, "VTOY", 4);
4694 acpi
->length
= buflen
;
4696 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4697 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4699 acpi
->creator_id
[0] = 1;
4700 acpi
->creator_rev
= 1;
4702 /* Step2: Fill data */
4703 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4704 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4705 osparam
->vtoy_img_location_addr
= 0;
4706 osparam
->vtoy_img_location_len
= loclen
;
4707 osparam
->chksum
= 0;
4708 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4710 location
= (ventoy_image_location
*)(osparam
+ 1);
4711 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4712 location
->image_sector_size
= image_sector_size
;
4713 location
->disk_sector_size
= chain
->disk_sector_size
;
4714 location
->region_count
= img_chunk_num
;
4716 region
= location
->regions
;
4717 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4718 if (512 == image_sector_size
)
4720 for (i
= 0; i
< img_chunk_num
; i
++)
4722 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4723 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4724 region
->disk_start_sector
= chunk
->disk_start_sector
;
4731 for (i
= 0; i
< img_chunk_num
; i
++)
4733 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4734 region
->image_start_sector
= chunk
->img_start_sector
;
4735 region
->disk_start_sector
= chunk
->disk_start_sector
;
4741 /* Step3: Fill acpi checksum */
4743 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4745 /* load acpi table */
4746 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4747 grub_script_execute_sourcecode(cmd
);
4751 VENTOY_CMD_RETURN(0);
4754 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4760 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4761 g_ventoy_last_entry
= -1;
4766 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4772 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4777 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4779 const char *pos
= filename
+ 1;
4787 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4789 grub_strncpy((char *)data
, filename
, 128);
4800 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4803 char *device_name
= NULL
;
4804 grub_device_t dev
= NULL
;
4805 grub_fs_t fs
= NULL
;
4806 char buf
[128] = {0};
4812 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4816 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4818 device_name
= grub_file_get_device_name(args
[0]);
4821 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4825 dev
= grub_device_open(device_name
);
4828 debug("grub_device_open failed, %s\n", device_name
);
4832 fs
= grub_fs_probe(dev
);
4835 debug("grub_fs_probe failed, %s\n", device_name
);
4839 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4843 ventoy_set_env(args
[2], buf
);
4850 check_free(device_name
, grub_free
);
4851 check_free(dev
, grub_device_close
);
4856 int ventoy_load_part_table(const char *diskname
)
4863 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4864 if (!g_ventoy_part_info
)
4869 disk
= grub_disk_open(diskname
);
4872 debug("Failed to open disk %s\n", diskname
);
4876 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4878 g_ventoy_disk_bios_id
= disk
->id
;
4880 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4881 grub_disk_close(disk
);
4883 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4884 dev
= grub_device_open(name
);
4887 /* Check for official Ventoy device */
4888 ret
= ventoy_check_official_device(dev
);
4889 grub_device_close(dev
);
4897 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4898 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4903 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4910 ret
= ventoy_load_part_table(args
[0]);
4916 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4917 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4922 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4925 const char *vcfg
= NULL
;
4930 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4933 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4934 grub_env_set(args
[1], vcfg
);
4939 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4947 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4950 grub_uint8_t zeroguid
[16] = {0};
4955 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4958 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4960 if (id
>= 1 && id
<= 128)
4962 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4970 if (id
>= 1 && id
<= 4)
4972 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4982 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4985 char *device_name
= NULL
;
4986 grub_device_t dev
= NULL
;
4987 grub_fs_t fs
= NULL
;
4992 debug("get fs label for %s\n", args
[0]);
4996 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5000 device_name
= grub_file_get_device_name(args
[0]);
5003 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5007 dev
= grub_device_open(device_name
);
5010 debug("grub_device_open failed, %s\n", device_name
);
5014 fs
= grub_fs_probe(dev
);
5015 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5017 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5021 fs
->fs_label(dev
, &label
);
5024 debug("label=<%s>\n", label
);
5025 ventoy_set_env(args
[1], label
);
5033 check_free(device_name
, grub_free
);
5034 check_free(dev
, grub_device_close
);
5039 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5043 grub_snprintf((char *)data
, 256, "%s", filename
);
5050 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5052 if (info
->dir
&& filename
&& filename
[0] != '.')
5054 grub_snprintf((char *)data
, 256, "%s", filename
);
5061 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5064 char *device_name
= NULL
;
5065 grub_device_t dev
= NULL
;
5066 grub_fs_t fs
= NULL
;
5067 char name
[256] ={0};
5071 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5075 device_name
= grub_file_get_device_name(args
[0]);
5078 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5082 dev
= grub_device_open(device_name
);
5085 debug("grub_device_open failed, %s\n", device_name
);
5089 fs
= grub_fs_probe(dev
);
5092 debug("grub_fs_probe failed, %s\n", device_name
);
5096 fs
->fs_dir(dev
, args
[1], hook
, name
);
5099 ventoy_set_env(args
[2], name
);
5106 check_free(device_name
, grub_free
);
5107 check_free(dev
, grub_device_close
);
5112 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5115 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5118 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5121 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5124 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5134 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5138 for (pos
= args
[0]; *pos
; pos
++)
5152 grub_env_set(args
[1], args
[0]);
5162 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5172 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5177 len
= (int)grub_strlen(buf
);
5178 for (i
= len
; i
> 0; i
--)
5180 if (buf
[i
- 1] == '/')
5182 grub_env_set(args
[1], buf
+ i
);
5187 grub_env_set(args
[1], buf
);
5192 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5194 struct grub_video_mode_info info
;
5201 if (!g_video_mode_list
)
5203 ventoy_enum_video_mode();
5206 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5208 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5212 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5215 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5217 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5218 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5220 VENTOY_CMD_RETURN(0);
5223 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5225 struct grub_video_mode_info info
;
5232 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5234 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5238 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5241 grub_env_set(args
[0], buf
);
5243 VENTOY_CMD_RETURN(0);
5246 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5254 if (!g_video_mode_list
)
5259 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5260 if (id
< g_video_mode_num
)
5262 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5263 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5266 grub_env_set(args
[1], buf
);
5268 VENTOY_CMD_RETURN(0);
5271 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5274 grub_uint32_t loadsector
= 0;
5277 grub_uint32_t boot_catlog
= 0;
5278 grub_uint8_t buf
[512];
5284 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5288 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5291 debug("failed to open %s\n", args
[0]);
5295 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5296 if (boot_catlog
== 0)
5298 debug("No bootcatlog found\n");
5299 grub_file_close(file
);
5303 grub_memset(buf
, 0, sizeof(buf
));
5304 grub_file_seek(file
, boot_catlog
* 2048);
5305 grub_file_read(file
, buf
, sizeof(buf
));
5306 grub_file_close(file
);
5308 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5310 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5312 if (buf
[i
+ 32] == 0x88)
5314 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5315 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5321 if (loadsector
== 0)
5323 debug("No EFI eltorito info found\n");
5327 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5328 grub_env_set(args
[1], value
);
5329 VENTOY_CMD_RETURN(0);
5332 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5337 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5339 if (pfsdir
->initrd
[0])
5344 curpos
= pfsdir
->curpos
;
5345 len
= grub_strlen(filename
);
5349 if ((len
== 1 && filename
[0] == '.') ||
5350 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5355 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5358 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5359 pfsdir
->curpos
= curpos
+ printlen
;
5360 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5361 pfsdir
->curpos
= curpos
;
5362 pfsdir
->fullpath
[curpos
] = 0;
5366 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5369 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5370 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5372 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5374 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5383 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5387 char *device_name
= NULL
;
5388 grub_device_t dev
= NULL
;
5389 grub_fs_t fs
= NULL
;
5390 replace_fs_dir
*pfsdir
= NULL
;
5396 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5400 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5406 device_name
= grub_file_get_device_name(args
[0]);
5412 dev
= grub_device_open(device_name
);
5418 fs
= grub_fs_probe(dev
);
5427 pfsdir
->fullpath
[0] = '/';
5428 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5430 if (pfsdir
->initrd
[0])
5432 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5434 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5436 if (pfsdir
->initrd
[i
] == '/')
5438 pfsdir
->initrd
[i
] = '\\';
5442 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5443 grub_env_set(args
[1], pos
);
5447 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5452 grub_check_free(pfsdir
);
5453 grub_check_free(device_name
);
5454 check_free(dev
, grub_device_close
);
5456 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5459 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5461 const char *pager
= NULL
;
5467 pager
= grub_env_get("pager");
5471 grub_env_set("pager", "1");
5473 else if (pager
[0] == '1')
5479 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5481 grub_env_set("pager", "1");
5484 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5487 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5493 if (g_pager_flag
== 1)
5495 grub_env_unset("pager");
5497 else if (g_pager_flag
== 2)
5499 grub_env_set("pager", g_old_pager
);
5502 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5505 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5507 if (g_json_case_mis_path
[0])
5512 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5514 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5520 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5523 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5525 if (g_json_case_mis_path
[0])
5530 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5532 if (grub_strcasecmp(filename
, "ventoy") == 0)
5534 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5535 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5536 if (g_json_case_mis_path
[0])
5546 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5549 char *device_name
= NULL
;
5550 grub_device_t dev
= NULL
;
5551 grub_fs_t fs
= NULL
;
5552 chk_case_fs_dir fs_dir
;
5558 device_name
= grub_file_get_device_name(args
[0]);
5564 dev
= grub_device_open(device_name
);
5570 fs
= grub_fs_probe(dev
);
5576 fstype
= ventoy_get_fs_type(fs
->name
);
5577 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5582 g_json_case_mis_path
[0] = 0;
5585 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5587 if (g_json_case_mis_path
[0])
5589 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5594 grub_check_free(device_name
);
5595 check_free(dev
, grub_device_close
);
5597 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5600 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5603 grub_partition_t part
;
5604 char priority_str
[3]; /* Maximum value 15 */
5608 if (argc
< 2 || argc
> 3)
5609 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5610 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5612 /* Open the disk if it exists */
5613 disk
= grub_disk_open (args
[0]);
5616 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5620 part
= grub_partition_probe (disk
, args
[1]);
5623 grub_disk_close (disk
);
5624 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5625 "No such partition");
5628 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5630 grub_disk_close (disk
);
5631 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5632 "Not a GPT partition");
5635 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5636 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5640 grub_env_set (args
[2], priority_str
);
5641 grub_env_export (args
[2]);
5645 grub_printf ("Priority is %s\n", priority_str
);
5648 grub_disk_close (disk
);
5649 return GRUB_ERR_NONE
;
5653 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5657 grub_file_t file
= NULL
;
5658 grub_uint32_t loadrba
= 0;
5659 grub_uint32_t boot_catlog
= 0;
5660 grub_uint8_t sector
[512];
5661 boot_info_table
*info
= NULL
;
5666 /* This also trigger a iso9660 fs parse */
5667 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5672 joliet
= grub_iso9660_is_joliet();
5678 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5681 debug("failed to open %s\n", args
[0]);
5685 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5686 if (boot_catlog
== 0)
5688 debug("no bootcatlog found %u\n", boot_catlog
);
5692 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5695 debug("no bios eltorito rba found %u\n", loadrba
);
5699 grub_file_seek(file
, loadrba
* 2048);
5700 grub_file_read(file
, sector
, 512);
5702 info
= (boot_info_table
*)sector
;
5703 if (info
->bi_data0
== 0x7c6ceafa &&
5704 info
->bi_data1
== 0x90900000 &&
5705 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5706 info
->bi_BootFileLocation
== loadrba
)
5708 debug("bootloader is syslinux, %u.\n", loadrba
);
5714 grub_file_close(file
);
5715 grub_errno
= GRUB_ERR_NONE
;
5719 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5722 ventoy_vlnk_part
*node
;
5728 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5730 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5731 ++n
, node
->device
, node
->disksig
,
5732 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5738 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5746 len
= (int)grub_strlen(args
[0]);
5747 if (grub_file_is_vlnk_suffix(args
[0], len
))
5756 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5759 const char *name
= NULL
;
5765 grub_env_unset(args
[1]);
5766 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5769 debug("VLNK SRC: <%s>\n", args
[0]);
5770 debug("VLNK DST: <%s>\n", name
);
5771 grub_env_set(args
[1], name
);
5779 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5783 grub_file_t file
= NULL
;
5794 len
= (int)grub_strlen(args
[0]);
5795 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5797 grub_printf("Invalid vlnk suffix\n");
5801 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5804 grub_printf("Failed to open %s\n", args
[0]);
5808 if (file
->size
!= 32768)
5810 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5814 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5815 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5817 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5822 check_free(file
, grub_file_close
);
5823 grub_errno
= GRUB_ERR_NONE
;
5827 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5833 g_iso_vd_id_publisher
[0] = 0;
5834 g_iso_vd_id_prepare
[0] = 0;
5835 g_iso_vd_id_application
[0] = 0;
5840 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5844 grub_file_t file
= NULL
;
5849 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5852 grub_printf("Failed to open %s\n", args
[0]);
5856 grub_file_seek(file
, 16 * 2048 + offset
);
5857 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5860 grub_file_seek(file
, 16 * 2048 + offset
);
5861 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5864 grub_file_seek(file
, 16 * 2048 + offset
);
5865 grub_file_read(file
, g_iso_vd_id_application
, 128);
5869 check_free(file
, grub_file_close
);
5870 grub_errno
= GRUB_ERR_NONE
;
5874 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5877 char *id
= g_iso_vd_id_publisher
;
5882 if (args
[0][0] == '1')
5884 id
= g_iso_vd_id_prepare
;
5886 else if (args
[0][0] == '2')
5888 id
= g_iso_vd_id_application
;
5891 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5896 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5901 grub_errno
= GRUB_ERR_NONE
;
5905 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5910 g_ventoy_fn_mutex
= 0;
5911 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5913 g_ventoy_fn_mutex
= 1;
5916 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5919 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5921 grub_uint64_t total
;
5922 grub_uint64_t org_required
;
5923 grub_uint64_t new_required
;
5929 #ifdef GRUB_MACHINE_EFI
5930 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
5931 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
5932 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
5933 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
5938 grub_printf("Non EFI mode!\n");
5943 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5946 int ventoy_env_init(void)
5950 grub_env_set("vtdebug_flag", "");
5952 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5953 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5954 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5955 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5957 ventoy_filt_register(0, ventoy_wrapper_open
);
5959 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5962 g_grub_param
->grub_env_get
= grub_env_get
;
5963 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5964 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5965 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5966 grub_env_set("env_param", buf
);
5967 grub_env_set("ventoy_env_param", buf
);
5969 grub_env_export("env_param");
5970 grub_env_export("ventoy_env_param");
5973 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5974 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5976 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5977 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5979 grub_env_export("vtoy_winpeshl_ini_addr");
5980 grub_env_export("vtoy_winpeshl_ini_size");
5982 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5983 grub_env_set("vtoy_chain_file_size", buf
);
5984 grub_env_export("vtoy_chain_file_size");
5986 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5987 grub_env_set("vtoy_chain_file_read", buf
);
5988 grub_env_export("vtoy_chain_file_read");
5995 static cmd_para ventoy_cmds
[] =
5997 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
5998 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
5999 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6000 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6001 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6002 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6003 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6004 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6005 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6006 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6007 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6008 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6009 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6010 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6011 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6012 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6013 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6014 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6015 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6016 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6017 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6018 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6019 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6020 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6021 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6022 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6023 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6025 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6026 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6027 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6028 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6029 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6030 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6031 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6033 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6034 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6035 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6036 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6037 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6038 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6039 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6040 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6041 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6042 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6045 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6046 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6047 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6048 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6049 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6050 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6051 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6052 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6053 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6054 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6055 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6057 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6058 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6059 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6060 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6061 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6062 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6063 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6065 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6066 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6067 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6068 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6069 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6070 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6071 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6072 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6073 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6074 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6076 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6077 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6078 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6079 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6080 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6081 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6082 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6083 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6084 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6086 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6087 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6088 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6089 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6092 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6093 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6094 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6096 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6097 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6098 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6101 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6102 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6103 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6104 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6105 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6106 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6107 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6108 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6109 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6110 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6111 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6112 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6113 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6114 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6116 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6117 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6118 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6119 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6120 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6121 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6122 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6123 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6124 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6125 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6126 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6127 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6129 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6130 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6131 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6132 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6133 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6134 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6135 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6136 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6137 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6138 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6139 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6140 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6141 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6142 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6143 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6144 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6145 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6146 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6147 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6150 int ventoy_register_all_cmd(void)
6153 cmd_para
*cur
= NULL
;
6155 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6157 cur
= ventoy_cmds
+ i
;
6158 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6159 cur
->summary
, cur
->description
, cur
->parser
);
6165 int ventoy_unregister_all_cmd(void)
6169 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6171 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);