1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/random.h>
49 #include <grub/ventoy.h>
50 #include "ventoy_def.h"
53 GRUB_MOD_LICENSE ("GPLv3+");
55 static grub_uint8_t g_check_mbr_data
[] = {
56 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
62 initrd_info
*g_initrd_img_list
= NULL
;
63 initrd_info
*g_initrd_img_tail
= NULL
;
64 int g_initrd_img_count
= 0;
65 int g_valid_initrd_count
= 0;
66 int g_default_menu_mode
= 0;
67 int g_filt_dot_underscore_file
= 0;
68 int g_sort_case_sensitive
= 0;
69 int g_tree_view_menu_style
= 0;
70 static grub_file_t g_old_file
;
71 static int g_ventoy_last_entry_back
;
74 char g_img_swap_tmp_buf
[1024];
75 img_info g_img_swap_tmp
;
76 img_info
*g_ventoy_img_list
= NULL
;
78 int g_ventoy_img_count
= 0;
80 grub_device_t g_enum_dev
= NULL
;
81 grub_fs_t g_enum_fs
= NULL
;
82 int g_img_max_search_level
= -1;
83 img_iterator_node g_img_iterator_head
;
84 img_iterator_node
*g_img_iterator_tail
= NULL
;
86 grub_uint8_t g_ventoy_break_level
= 0;
87 grub_uint8_t g_ventoy_debug_level
= 0;
88 grub_uint8_t g_ventoy_chain_type
= 0;
90 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
91 grub_uint32_t g_ventoy_cpio_size
= 0;
92 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
93 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
95 int g_plugin_image_list
= 0;
97 ventoy_grub_param
*g_grub_param
= NULL
;
99 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
101 ventoy_img_chunk_list g_img_chunk_list
;
103 int g_wimboot_enable
= 0;
104 ventoy_img_chunk_list g_wimiso_chunk_list
;
105 char *g_wimiso_path
= NULL
;
106 grub_uint32_t g_wimiso_size
= 0;
108 int g_vhdboot_enable
= 0;
110 grub_uint64_t g_svd_replace_offset
= 0;
112 int g_conf_replace_count
= 0;
113 grub_uint64_t g_conf_replace_offset
[VTOY_MAX_CONF_REPLACE
] = { 0 };
114 conf_replace
*g_conf_replace_node
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
115 grub_uint8_t
*g_conf_replace_new_buf
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
116 int g_conf_replace_new_len
[VTOY_MAX_CONF_REPLACE
] = { 0 };
117 int g_conf_replace_new_len_align
[VTOY_MAX_CONF_REPLACE
] = { 0 };
119 int g_ventoy_disk_bios_id
= 0;
120 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
121 grub_uint64_t g_ventoy_disk_size
= 0;
122 grub_uint64_t g_ventoy_disk_part_size
[2];
124 char *g_tree_script_buf
= NULL
;
125 int g_tree_script_pos
= 0;
126 int g_tree_script_pre
= 0;
128 static char *g_list_script_buf
= NULL
;
129 static int g_list_script_pos
= 0;
131 static char *g_part_list_buf
= NULL
;
132 static int g_part_list_pos
= 0;
133 static grub_uint64_t g_part_end_max
= 0;
135 static int g_video_mode_max
= 0;
136 static int g_video_mode_num
= 0;
137 static ventoy_video_mode
*g_video_mode_list
= NULL
;
139 static int g_enumerate_time_checked
= 0;
140 static grub_uint64_t g_enumerate_start_time_ms
;
141 static grub_uint64_t g_enumerate_finish_time_ms
;
142 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
144 static char g_iso_vd_id_publisher
[130];
145 static char g_iso_vd_id_prepare
[130];
146 static char g_iso_vd_id_application
[130];
148 static int g_pager_flag
= 0;
149 static char g_old_pager
[32];
151 const char *g_menu_class
[img_type_max
] =
153 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
156 const char *g_menu_prefix
[img_type_max
] =
158 "iso", "wim", "efi", "img", "vhd", "vtoy"
161 static int g_vtoy_secondary_need_recover
= 0;
163 static int g_vtoy_load_prompt
= 0;
164 static char g_vtoy_prompt_msg
[64];
166 static char g_json_case_mis_path
[32];
168 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
170 int ventoy_get_fs_type(const char *fs
)
174 return ventoy_fs_max
;
176 else if (grub_strncmp(fs
, "exfat", 5) == 0)
178 return ventoy_fs_exfat
;
180 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
182 return ventoy_fs_ntfs
;
184 else if (grub_strncmp(fs
, "ext", 3) == 0)
186 return ventoy_fs_ext
;
188 else if (grub_strncmp(fs
, "xfs", 3) == 0)
190 return ventoy_fs_xfs
;
192 else if (grub_strncmp(fs
, "udf", 3) == 0)
194 return ventoy_fs_udf
;
196 else if (grub_strncmp(fs
, "fat", 3) == 0)
198 return ventoy_fs_fat
;
201 return ventoy_fs_max
;
204 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
223 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
225 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
229 static int ventoy_control_get_flag(const char *key
)
231 const char *val
= ventoy_get_env(key
);
233 if (val
&& val
[0] == '1' && val
[1] == 0)
240 static grub_err_t
ventoy_fs_close(grub_file_t file
)
242 grub_file_close(g_old_file
);
243 grub_free(file
->data
);
251 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
257 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
262 for (i
= 0; i
< g_video_mode_num
; i
++)
264 if (g_video_mode_list
[i
].width
== info
->width
&&
265 g_video_mode_list
[i
].height
== info
->height
&&
266 g_video_mode_list
[i
].bpp
== info
->bpp
)
272 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
273 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
274 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
277 if (g_video_mode_num
== g_video_mode_max
)
279 g_video_mode_max
*= 2;
280 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
286 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
288 if (v1
->bpp
== v2
->bpp
)
290 if (v1
->width
== v2
->width
)
292 if (v1
->height
== v2
->height
)
298 return (v1
->height
< v2
->height
) ? -1 : 1;
303 return (v1
->width
< v2
->width
) ? -1 : 1;
308 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
312 static int ventoy_enum_video_mode(void)
315 grub_video_adapter_t adapter
;
316 grub_video_driver_id_t id
;
317 ventoy_video_mode mode
;
319 g_video_mode_num
= 0;
320 g_video_mode_max
= 1024;
321 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
322 if (!g_video_mode_list
)
327 #ifdef GRUB_MACHINE_PCBIOS
328 grub_dl_load ("vbe");
331 id
= grub_video_get_driver_id ();
333 FOR_VIDEO_ADAPTERS (adapter
)
335 if (!adapter
->iterate
||
336 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
337 adapter
->init() != GRUB_ERR_NONE
)))
342 adapter
->iterate(ventoy_video_hook
, NULL
);
344 if (adapter
->id
!= id
)
350 /* sort video mode */
351 for (i
= 0; i
< g_video_mode_num
; i
++)
352 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
354 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
356 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
357 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
358 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
362 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
365 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
369 static struct grub_fs vtoy_fs
=
374 .fs_read
= ventoy_fs_read
,
375 .fs_close
= ventoy_fs_close
,
385 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
391 file
->data
= grub_malloc(rawFile
->size
+ 4096);
397 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
398 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
400 g_old_file
= rawFile
;
402 file
->size
= rawFile
->size
+ len
;
403 file
->device
= rawFile
->device
;
405 file
->not_easily_seekable
= 1;
410 static int ventoy_check_decimal_var(const char *name
, long *value
)
412 const char *value_str
= NULL
;
414 value_str
= grub_env_get(name
);
415 if (NULL
== value_str
)
417 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
420 if (!ventoy_is_decimal(value_str
))
422 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
425 *value
= grub_strtol(value_str
, NULL
, 10);
427 return GRUB_ERR_NONE
;
430 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
432 grub_uint64_t sectors
;
434 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
436 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
440 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
443 return sectors
* 512;
446 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
452 grub_uint32_t offset
;
454 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
457 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
461 len
= (int)file
->size
;
463 data
= (char *)grub_malloc(file
->size
);
469 grub_file_read(file
, data
, file
->size
);
470 grub_file_close(file
);
472 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
473 grub_script_execute_sourcecode(exec
);
475 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
476 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
477 grub_file_close(file
);
479 grub_script_execute_sourcecode("loopback -d efiboot");
483 *direntoff
= offset
+ 2;
488 static int ventoy_set_check_result(int ret
, const char *msg
)
492 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
493 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
494 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
498 grub_printf(VTOY_WARNING
"\n");
499 grub_printf(VTOY_WARNING
"\n");
500 grub_printf(VTOY_WARNING
"\n\n\n");
502 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
503 grub_printf("Error message: <%s>\n\n", msg
);
504 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
506 grub_printf("\n\nWill exit after 10 seconds ...... ");
514 static int ventoy_check_official_device(grub_device_t dev
)
518 grub_uint64_t offset
;
521 grub_uint8_t mbr
[512];
525 struct grub_partition
*partition
;
527 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
529 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
532 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
533 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
534 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
536 #ifndef GRUB_MACHINE_EFI
537 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
539 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
541 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
543 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
545 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
547 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
556 /* We must have partition 2 */
559 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
563 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
567 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
570 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
572 grub_file_close(file
);
573 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
576 partition
= dev
->disk
->partition
;
577 if (partition
->number
!= 0 || partition
->start
!= 2048)
579 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
584 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
586 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
587 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
588 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
590 grub_file_close(file
);
591 return ventoy_set_check_result(6, "Disk partition layout check failed.");
596 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
597 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
598 PartTbl
[1].SectorCount
!= 65536)
600 grub_file_close(file
);
601 return ventoy_set_check_result(6, "Disk partition layout check failed.");
607 offset
= partition
->start
+ partition
->len
;
608 partition
= file
->device
->disk
->partition
;
609 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
611 grub_file_close(file
);
612 return ventoy_set_check_result(7, "Disk partition layout check failed.");
616 grub_file_close(file
);
620 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
621 dev2
= grub_device_open(devname
);
624 return ventoy_set_check_result(8, "Disk open failed");
627 fs
= grub_fs_probe(dev2
);
630 grub_device_close(dev2
);
631 return ventoy_set_check_result(9, "FS probe failed");
634 fs
->fs_label(dev2
, &label
);
635 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
637 grub_device_close(dev2
);
638 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
641 grub_device_close(dev2
);
645 disk
= grub_disk_open(dev
->disk
->name
);
648 return ventoy_set_check_result(11, "Disk open failed");
651 grub_memset(mbr
, 0, 512);
652 grub_disk_read(disk
, 0, 0, 512, mbr
);
653 grub_disk_close(disk
);
655 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
657 return ventoy_set_check_result(12, "MBR check failed");
660 return ventoy_set_check_result(0, NULL
);
663 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
667 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
677 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
679 grub_uint64_t size
= 0;
682 char fullpath
[256] = {0};
685 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
688 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
691 debug("grub_file_open failed <%s>\n", fullpath
);
697 grub_file_close(file
);
701 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
705 char fullpath
[512] = {0};
708 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
711 file
= grub_file_open(fullpath
, type
);
714 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
721 int ventoy_is_dir_exist(const char *fmt
, ...)
728 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
732 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
735 grub_strncpy(pos
+ len
, "\" ]", 3);
737 debug("script exec %s\n", buf
);
739 if (0 == grub_script_execute_sourcecode(buf
))
747 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
750 grub_uint8_t
*outbuf
;
751 grub_uint8_t gzHdr
[10] =
753 0x1F, 0x8B, /* magic */
761 grub_memset(&s
, 0, sizeof(mz_stream
));
763 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
765 outbuf
= (grub_uint8_t
*)mem_out
;
767 mem_out_len
-= sizeof(gzHdr
) + 8;
768 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
769 outbuf
+= sizeof(gzHdr
);
771 s
.avail_in
= mem_in_len
;
774 s
.avail_out
= mem_out_len
;
777 mz_deflate(&s
, MZ_FINISH
);
781 outbuf
+= s
.total_out
;
782 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
783 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
785 return s
.total_out
+ sizeof(gzHdr
) + 8;
793 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
797 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
800 if (0 == grub_strcmp(args
[0], "on"))
803 grub_env_set("vtdebug_flag", "debug");
808 grub_env_set("vtdebug_flag", "");
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
814 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
818 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
820 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
821 grub_printf(" level:\r\n");
822 grub_printf(" 01/11: busybox / (+cat log)\r\n");
823 grub_printf(" 02/12: initrd / (+cat log)\r\n");
824 grub_printf(" 03/13: hook / (+cat log)\r\n");
826 grub_printf(" debug:\r\n");
827 grub_printf(" 0: debug is off\r\n");
828 grub_printf(" 1: debug is on\r\n");
830 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
833 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
835 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
837 g_ventoy_debug_level
= 1;
840 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
843 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
852 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
855 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
887 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
903 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
919 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
924 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
926 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
929 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
934 value_long
+= grub_strtol(args
[1], NULL
, 10);
936 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
937 grub_env_set(args
[0], buf
);
939 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
942 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
944 ulonglong value1
= 0;
945 ulonglong value2
= 0;
950 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
953 value1
= grub_strtoull(args
[0], NULL
, 10);
954 value2
= grub_strtoull(args
[1], NULL
, 10);
956 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
957 grub_env_set(args
[2], buf
);
959 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
962 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
977 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
980 debug("failed to open file <%s> for udf check\n", args
[0]);
984 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
986 grub_env_set(args
[1], buf
);
988 grub_file_close(file
);
994 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1002 g_wimboot_enable
= 0;
1004 grub_check_free(g_wimiso_path
);
1005 grub_check_free(g_wimiso_chunk_list
.chunk
);
1007 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1013 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1014 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1015 if (NULL
== g_wimiso_chunk_list
.chunk
)
1017 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1020 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1021 g_wimiso_chunk_list
.cur_chunk
= 0;
1023 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1025 g_wimboot_enable
= 1;
1026 g_wimiso_path
= grub_strdup(args
[0]);
1027 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1028 grub_file_close(file
);
1033 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1043 ventoy_iso9660_override
*dirent
;
1052 totlen
= sizeof(ventoy_chain_head
);
1054 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1056 debug("failed to load efiboot template %d\n", len
);
1062 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1064 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1067 debug("failed to open file <%s>\n", args
[0]);
1071 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1076 totlen
+= ventoy_align_2k(file
->size
);
1078 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1079 dirent
->first_sector
= len
/ 2048;
1080 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1081 dirent
->size
= (grub_uint32_t
)file
->size
;
1082 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1084 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1086 #ifdef GRUB_MACHINE_EFI
1087 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1089 data
= (char *)grub_malloc(totlen
);
1092 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1094 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1095 grub_check_free(buf
);
1097 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1098 grub_file_close(file
);
1100 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1101 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1102 grub_env_set(name
, value
);
1104 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1105 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1106 grub_env_set(name
, value
);
1111 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1117 g_vtoy_load_prompt
= 0;
1118 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1120 if (argc
== 2 && args
[0][0] == '1')
1122 g_vtoy_load_prompt
= 1;
1123 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1126 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1129 int ventoy_need_prompt_load_file(void)
1131 return g_vtoy_load_prompt
;
1134 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1136 grub_uint64_t ro
= 0;
1137 grub_uint64_t div
= 0;
1138 grub_ssize_t left
= size
;
1139 char *cur
= (char *)buf
;
1141 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1144 while (left
>= VTOY_SIZE_2MB
)
1146 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1147 cur
+= VTOY_SIZE_2MB
;
1148 left
-= VTOY_SIZE_2MB
;
1150 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1155 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1161 grub_file_read(file
, cur
, left
);
1164 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1170 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1177 enum grub_file_type type
;
1188 if (grub_strcmp(args
[0], "nodecompress") == 0)
1190 type
= VENTOY_FILE_TYPE
;
1194 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1197 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1200 debug("failed to open file <%s>\n", args
[1]);
1204 #ifdef GRUB_MACHINE_EFI
1205 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1207 buf
= (char *)grub_malloc(file
->size
);
1212 grub_file_close(file
);
1216 if (g_vtoy_load_prompt
)
1218 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1222 grub_file_read(file
, buf
, file
->size
);
1225 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1226 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1227 grub_env_set(name
, value
);
1229 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1230 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1231 grub_env_set(name
, value
);
1233 grub_file_close(file
);
1239 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1257 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1260 debug("failed to open file <%s> for udf check\n", args
[0]);
1264 headlen
= sizeof(ventoy_chain_head
);
1266 #ifdef GRUB_MACHINE_EFI
1267 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1269 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1272 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1274 grub_file_read(file
, buf
+ headlen
, file
->size
);
1276 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1277 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1278 grub_env_set(name
, value
);
1280 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1281 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1282 grub_env_set(name
, value
);
1284 grub_file_close(file
);
1290 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1296 if (grub_iso9660_is_joliet())
1298 debug("This time has joliet process\n");
1307 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1316 if (args
[0][0] == '1')
1318 grub_iso9660_set_nojoliet(1);
1322 grub_iso9660_set_nojoliet(0);
1328 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1333 grub_uint8_t buf
[32];
1344 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1347 debug("failed to open file <%s> for udf check\n", args
[0]);
1351 for (i
= 16; i
< 32; i
++)
1353 grub_file_seek(file
, i
* 2048);
1354 grub_file_read(file
, buf
, sizeof(buf
));
1362 grub_file_seek(file
, i
* 2048);
1363 grub_file_read(file
, buf
, sizeof(buf
));
1365 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1368 grub_file_seek(file
, i
* 2048);
1369 grub_file_read(file
, buf
, sizeof(buf
));
1371 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1372 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1378 grub_file_close(file
);
1380 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1385 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1387 long value_long1
= 0;
1388 long value_long2
= 0;
1390 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1392 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1395 value_long1
= grub_strtol(args
[0], NULL
, 10);
1396 value_long2
= grub_strtol(args
[2], NULL
, 10);
1398 if (0 == grub_strcmp(args
[1], "eq"))
1400 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1402 else if (0 == grub_strcmp(args
[1], "ne"))
1404 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1406 else if (0 == grub_strcmp(args
[1], "gt"))
1408 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1410 else if (0 == grub_strcmp(args
[1], "lt"))
1412 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1414 else if (0 == grub_strcmp(args
[1], "ge"))
1416 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1418 else if (0 == grub_strcmp(args
[1], "le"))
1420 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1424 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1430 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1433 char buf
[128] = {0};
1437 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1440 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1441 pos
= grub_strstr(buf
, ",");
1447 grub_env_set(args
[1], buf
);
1449 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1452 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1458 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1464 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1467 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1469 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1470 if (0 == grub_script_execute_sourcecode(buf
))
1472 debug("file %s exist, ventoy_compatible YES\n", buf
);
1473 grub_env_set("ventoy_compatible", "YES");
1474 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1478 debug("file %s NOT exist\n", buf
);
1482 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1483 pos
= grub_strstr(buf
, ")");
1489 disk
= grub_disk_open(buf
);
1492 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1493 grub_disk_close(disk
);
1495 g_img_swap_tmp_buf
[703] = 0;
1496 for (i
= 318; i
< 703; i
++)
1498 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1499 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1501 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1502 grub_env_set("ventoy_compatible", "YES");
1503 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1509 debug("failed to open disk <%s>\n", buf
);
1512 grub_env_set("ventoy_compatible", "NO");
1513 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1516 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1522 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1524 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1527 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1532 if (0 == g_sort_case_sensitive
)
1534 if (grub_islower(c1
))
1536 c1
= c1
- 'a' + 'A';
1539 if (grub_islower(c2
))
1541 c2
= c2
- 'a' + 'A';
1554 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1560 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1562 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1565 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1570 if (0 == g_sort_case_sensitive
)
1572 if (grub_islower(c1
))
1574 c1
= c1
- 'a' + 'A';
1577 if (grub_islower(c2
))
1579 c2
= c2
- 'a' + 'A';
1592 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1594 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1596 grub_memcpy(img1
, img2
, sizeof(img_info
));
1597 img1
->next
= g_img_swap_tmp
.next
;
1598 img1
->prev
= g_img_swap_tmp
.prev
;
1600 g_img_swap_tmp
.next
= img2
->next
;
1601 g_img_swap_tmp
.prev
= img2
->prev
;
1602 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1605 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1609 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1617 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1619 ventoy_vlnk_part
*node
= NULL
;
1620 grub_uint32_t SelfSig
;
1621 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1623 /* skip Ventoy partition 1/2 */
1624 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1625 if (partition
->number
< 2 && SelfSig
== *pSig
)
1630 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1633 node
->disksig
= *pSig
;
1634 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1635 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1636 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1638 node
->next
= g_vlnk_part_list
;
1639 g_vlnk_part_list
= node
;
1645 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1652 disk
= grub_disk_open(name
);
1655 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1656 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1657 grub_disk_close(disk
);
1663 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1665 const char *fs
[ventoy_fs_max
+ 1] =
1667 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1672 cur
->dev
= grub_device_open(cur
->device
);
1677 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1683 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1688 char *disk
, *device
;
1689 grub_uint32_t readcrc
, calccrc
;
1690 ventoy_vlnk_part
*cur
;
1691 grub_fs_t fs
= NULL
;
1693 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1697 grub_printf("VLNK invalid guid\n");
1703 readcrc
= vlnk
->crc32
;
1705 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1706 if (readcrc
!= calccrc
)
1710 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1716 if (!g_vlnk_part_list
)
1718 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1721 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1723 if (cur
->disksig
== vlnk
->disk_signature
)
1727 if (cur
->partoffset
== vlnk
->part_offset
)
1730 device
= cur
->device
;
1732 if (cur
->probe
== 0)
1735 ventoy_vlnk_probe_fs(cur
);
1745 struct grub_file file
;
1747 grub_memset(&file
, 0, sizeof(file
));
1748 file
.device
= cur
->dev
;
1749 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1752 cur
->fs
->fs_close(&file
);
1753 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1762 grub_printf("\n==== VLNK Information ====\n"
1763 "Disk Signature: %08x\n"
1764 "Partition Offset: %llu\n"
1765 "File Path: <%s>\n\n",
1766 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1770 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1774 grub_printf("Disk Find: [ NO ]\n");
1779 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1783 grub_printf("Part Find: [ NO ]\n");
1785 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1788 grub_printf("VLNK File: <%s>\n", dst
);
1795 return (1 - filefind
);
1798 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1803 grub_file_t file
= NULL
;
1808 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1810 else if (dir
[0] == '/')
1812 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1816 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1819 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1825 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1826 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1827 grub_file_close(file
);
1829 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1831 rc
= grub_file_add_vlnk(src
, dst
);
1837 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1847 const menu_tip
*tip
;
1848 img_iterator_node
*tmp
;
1849 img_iterator_node
*new_node
;
1850 img_iterator_node
*node
= (img_iterator_node
*)data
;
1852 if (g_enumerate_time_checked
== 0)
1854 g_enumerate_finish_time_ms
= grub_get_time_ms();
1855 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1858 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1860 g_enumerate_time_checked
= 1;
1864 len
= grub_strlen(filename
);
1868 if (node
->level
+ 1 > g_img_max_search_level
)
1873 if ((len
== 1 && filename
[0] == '.') ||
1874 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1879 if (!ventoy_img_name_valid(filename
, len
))
1884 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1889 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1891 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1892 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1895 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1900 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1903 new_node
->level
= node
->level
+ 1;
1904 new_node
->plugin_list_index
= index
;
1905 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1907 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1910 debug("Directory %s ignored...\n", new_node
->dir
);
1911 grub_free(new_node
);
1915 new_node
->tail
= node
->tail
;
1917 new_node
->parent
= node
;
1918 if (!node
->firstchild
)
1920 node
->firstchild
= new_node
;
1923 if (g_img_iterator_tail
)
1925 g_img_iterator_tail
->next
= new_node
;
1926 g_img_iterator_tail
= new_node
;
1930 g_img_iterator_head
.next
= new_node
;
1931 g_img_iterator_tail
= new_node
;
1937 debug("Find a file %s\n", filename
);
1943 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1945 type
= img_type_iso
;
1947 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1949 type
= img_type_wim
;
1951 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1952 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1954 type
= img_type_vhd
;
1956 #ifdef GRUB_MACHINE_EFI
1957 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1959 type
= img_type_efi
;
1962 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1964 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1966 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1967 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1972 type
= img_type_img
;
1974 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1976 type
= img_type_vtoy
;
1978 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1980 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1982 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1983 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1992 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1997 if (g_plugin_image_list
)
1999 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2000 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
2001 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
2003 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2006 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2008 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2013 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2015 if (grub_file_is_vlnk_suffix(filename
, len
))
2018 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2025 img
= grub_zalloc(sizeof(img_info
));
2029 img
->plugin_list_index
= index
;
2030 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2032 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2034 img
->size
= info
->size
;
2035 if (vlnk
|| 0 == img
->size
)
2037 if (node
->dir
[0] == '/')
2039 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2043 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2047 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2049 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2054 if (g_ventoy_img_list
)
2056 tail
= *(node
->tail
);
2062 g_ventoy_img_list
= img
;
2065 img
->id
= g_ventoy_img_count
;
2067 if (node
&& NULL
== node
->firstiso
)
2069 node
->firstiso
= img
;
2080 *((img_info
**)(node
->tail
)) = img
;
2081 g_ventoy_img_count
++;
2083 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2085 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2088 img
->tip1
= tip
->tip1
;
2089 img
->tip2
= tip
->tip2
;
2092 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2095 img
->class = g_menu_class
[type
];
2097 img
->menu_prefix
= g_menu_prefix
[type
];
2099 if (img_type_iso
== type
)
2101 if (ventoy_plugin_check_memdisk(img
->path
))
2103 img
->menu_prefix
= "miso";
2107 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2114 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2116 int len
= GRUB_UINT_MAX
;
2117 const char *value
= NULL
;
2118 char name
[32] = {0};
2119 char plat
[32] = {0};
2120 char guidstr
[32] = {0};
2121 ventoy_guid guid
= VENTOY_GUID
;
2122 const char *fmt1
= NULL
;
2123 const char *fmt2
= NULL
;
2124 const char *fmt3
= NULL
;
2125 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2126 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2127 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2128 const char fmtcode
[]={
2129 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2130 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2131 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2132 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2133 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2134 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2137 grub_memset(name
, 0, sizeof(name
));
2138 puint
[0] = grub_swap_bytes32(0x56454e54);
2139 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2140 puint
[2] = grub_swap_bytes32(0x45525349);
2141 puint
[1] = grub_swap_bytes32(0x4f595f56);
2142 value
= ventoy_get_env(name
);
2144 grub_memset(name
, 0, sizeof(name
));
2145 puint
[1] = grub_swap_bytes32(0x5f544f50);
2146 puint
[0] = grub_swap_bytes32(0x56544c45);
2147 fmt1
= ventoy_get_env(name
);
2153 grub_memset(name
, 0, sizeof(name
));
2154 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2155 puint
[0] = grub_swap_bytes32(0x56544c45);
2156 fmt2
= ventoy_get_env(name
);
2158 grub_memset(name
, 0, sizeof(name
));
2159 puint
[1] = grub_swap_bytes32(0x5f434c52);
2160 puint
[0] = grub_swap_bytes32(0x56544c45);
2161 fmt3
= ventoy_get_env(name
);
2163 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2165 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2167 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2168 #pragma GCC diagnostic push
2169 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2170 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2171 fmt1
? fmt1
: fmtdata
,
2172 fmt2
? fmt2
: fmtdata
+ 4,
2173 value
? value
: "", plat
, guidstr
,
2174 fmt3
? fmt3
: fmtdata
+ 6);
2175 #pragma GCC diagnostic pop
2177 grub_memset(name
, 0, sizeof(name
));
2178 puint
[0] = grub_swap_bytes32(0x76746f79);
2179 puint
[2] = grub_swap_bytes32(0x656e7365);
2180 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2181 ventoy_set_env(name
, guidstr
);
2187 ventoy_password_get (char buf
[], unsigned buf_size
)
2189 unsigned i
, cur_len
= 0;
2191 struct grub_term_coordinate
*pos
= grub_term_save_pos ();
2195 key
= grub_getkey ();
2196 if (key
== '\n' || key
== '\r')
2199 if (key
== GRUB_TERM_ESC
)
2209 grub_term_restore_pos (pos
);
2210 for (i
= 0; i
< cur_len
; i
++)
2212 grub_term_restore_pos (pos
);
2214 for (i
= 0; i
< cur_len
; i
++)
2221 if (!grub_isprint (key
))
2224 if (cur_len
+ 2 < buf_size
)
2225 buf
[cur_len
++] = key
;
2230 grub_memset (buf
+ cur_len
, 0, buf_size
- cur_len
);
2236 return (key
!= GRUB_TERM_ESC
);
2239 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2243 grub_uint8_t md5
[16];
2247 grub_memset(input
, 0, sizeof(input
));
2249 grub_printf("Enter password: ");
2252 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2254 ventoy_password_get(input
, 128);
2255 if (grub_strcmp(pwd
->text
, input
) == 0)
2260 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2262 ventoy_password_get(input
, 128);
2263 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2264 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2269 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2271 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2272 ventoy_password_get(input
+ offset
, 128);
2274 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2275 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2281 grub_printf("Invalid password!\n\n");
2288 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2290 img_info
*minimg
= NULL
;
2291 img_info
*img
= (img_info
*)(node
->firstiso
);
2293 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2295 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2310 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2312 img_iterator_node
*Minchild
= NULL
;
2313 img_iterator_node
*child
= node
->firstchild
;
2315 while (child
&& child
->parent
== node
)
2317 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2321 child
= child
->next
;
2326 Minchild
->select
= 1;
2332 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2335 img_info
*img
= NULL
;
2336 const char *dir_class
= NULL
;
2337 const char *dir_alias
= NULL
;
2338 img_iterator_node
*child
= NULL
;
2339 const menu_tip
*tip
= NULL
;
2341 if (node
->isocnt
== 0 || node
->done
== 1)
2346 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2348 offset
= node
->parent
->dirlen
;
2351 if (node
== &g_img_iterator_head
)
2353 if (g_default_menu_mode
== 0)
2355 if (g_tree_view_menu_style
== 0)
2357 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2358 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2359 " echo 'return ...' \n"
2364 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2365 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2366 " echo 'return ...' \n"
2371 g_tree_script_pre
= g_tree_script_pos
;
2375 node
->dir
[node
->dirlen
- 1] = 0;
2376 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2379 dir_class
= "vtoydir";
2382 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2384 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2387 if (g_tree_view_menu_style
== 0)
2389 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2390 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2391 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2395 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2396 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2397 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2402 dir_alias
= node
->dir
+ offset
;
2404 if (g_tree_view_menu_style
== 0)
2406 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2407 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2408 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2412 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2413 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2414 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2418 if (g_tree_view_menu_style
== 0)
2420 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2421 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2422 " echo 'return ...' \n"
2423 "}\n", "<--", node
->dir
);
2427 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2428 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2429 " echo 'return ...' \n"
2434 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2436 ventoy_dynamic_tree_menu(child
);
2439 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2441 if (g_tree_view_menu_style
== 0)
2443 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2444 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2447 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2448 img
->unsupport
? "[***********] " : "",
2449 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2451 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2455 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2456 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2459 img
->unsupport
? "[***********] " : "",
2460 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2462 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2466 if (node
!= &g_img_iterator_head
)
2468 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2475 static int ventoy_set_default_menu(void)
2481 const char *strdata
= NULL
;
2482 img_info
*cur
= NULL
;
2483 img_info
*default_node
= NULL
;
2484 const char *default_image
= NULL
;
2486 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2487 if (default_image
&& default_image
[0] == '/')
2489 img_len
= grub_strlen(default_image
);
2491 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2493 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2505 if (0 == g_default_menu_mode
)
2507 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2511 def
= grub_strdup(default_image
);
2517 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2519 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2520 if (strdata
&& strdata
[0] == '/')
2522 pos
= def
+ grub_strlen(strdata
);
2533 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2536 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2540 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2548 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2550 img_info
*next
= NULL
;
2551 img_info
*cur
= g_ventoy_img_list
;
2564 g_ventoy_img_list
= NULL
;
2565 g_ventoy_img_count
= 0;
2567 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2570 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2573 img_info
*cur
= g_ventoy_img_list
;
2577 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2579 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2582 img_id
= grub_strtol(args
[0], NULL
, 10);
2583 if (img_id
>= g_ventoy_img_count
)
2585 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2588 debug("Find image %ld name \n", img_id
);
2590 while (cur
&& img_id
> 0)
2598 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2601 debug("image name is %s\n", cur
->name
);
2603 grub_env_set(args
[1], cur
->name
);
2605 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2608 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2612 img_info
*cur
= g_ventoy_img_list
;
2618 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2621 len
= (int)grub_strlen(args
[0]);
2625 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2634 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2637 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2638 grub_env_set("chosen", id
);
2639 grub_env_export("chosen");
2641 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2644 static char g_fake_vlnk_src
[512];
2645 static char g_fake_vlnk_dst
[512];
2646 static grub_uint64_t g_fake_vlnk_size
;
2647 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2653 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2655 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2656 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2658 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2660 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2663 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2669 g_fake_vlnk_src
[0] = 0;
2670 g_fake_vlnk_dst
[0] = 0;
2671 g_fake_vlnk_size
= 0;
2672 grub_file_vtoy_vlnk(NULL
, NULL
);
2674 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2678 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2683 const char *id
= NULL
;
2684 img_info
*cur
= NULL
;
2688 if (argc
< 1 || argc
> 3)
2690 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2693 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2695 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2696 grub_env_set(args
[0], pos
);
2699 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2700 grub_env_set(args
[1], value
);
2705 for (last
= pos
; *pos
; pos
++)
2712 grub_env_set(args
[2], last
+ 1);
2718 id
= grub_env_get("chosen");
2720 pos
= grub_strstr(id
, "VID_");
2723 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2727 cur
= g_ventoy_img_list
;
2732 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2735 grub_env_set(args
[0], cur
->path
);
2739 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2740 grub_env_set(args
[1], value
);
2745 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2746 grub_env_set(args
[2], cur
->name
);
2750 g_svd_replace_offset
= 0;
2752 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2756 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2760 grub_device_t dev
= NULL
;
2761 img_info
*cur
= NULL
;
2762 img_info
*tail
= NULL
;
2763 img_info
*min
= NULL
;
2764 img_info
*head
= NULL
;
2765 const char *strdata
= NULL
;
2766 char *device_name
= NULL
;
2768 img_iterator_node
*node
= NULL
;
2769 img_iterator_node
*tmp
= NULL
;
2775 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2778 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2780 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2785 g_enumerate_time_checked
= 0;
2786 g_enumerate_start_time_ms
= grub_get_time_ms();
2788 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2789 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2791 g_filt_dot_underscore_file
= 1;
2794 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2795 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2797 g_sort_case_sensitive
= 1;
2800 device_name
= grub_file_get_device_name(args
[0]);
2806 g_enum_dev
= dev
= grub_device_open(device_name
);
2812 g_enum_fs
= fs
= grub_fs_probe(dev
);
2818 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2820 debug("unsupported fs:<%s>\n", fs
->name
);
2821 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2825 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2827 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2828 if (strdata
&& strdata
[0] == '1')
2830 g_default_menu_mode
= 1;
2833 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2835 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2837 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2838 if (strdata
&& strdata
[0] == '/')
2840 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2841 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2843 g_img_iterator_head
.dir
[len
++] = '/';
2845 g_img_iterator_head
.dirlen
= len
;
2849 g_img_iterator_head
.dirlen
= 1;
2850 grub_strcpy(g_img_iterator_head
.dir
, "/");
2853 g_img_iterator_head
.tail
= &tail
;
2855 if (g_img_max_search_level
< 0)
2857 g_img_max_search_level
= GRUB_INT_MAX
;
2858 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2859 if (strdata
&& ventoy_is_decimal(strdata
))
2861 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2865 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2866 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2867 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2868 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2869 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2870 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2872 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2874 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2877 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2878 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2880 g_tree_view_menu_style
= 1;
2883 ventoy_set_default_menu();
2885 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2887 ventoy_dynamic_tree_menu(node
);
2891 node
= g_img_iterator_head
.next
;
2899 /* sort image list by image name */
2900 while (g_ventoy_img_list
)
2902 min
= g_ventoy_img_list
;
2903 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2905 if (ventoy_cmp_img(min
, cur
) > 0)
2913 min
->prev
->next
= min
->next
;
2918 min
->next
->prev
= min
->prev
;
2921 if (min
== g_ventoy_img_list
)
2923 g_ventoy_img_list
= min
->next
;
2941 g_ventoy_img_list
= head
;
2943 if (g_default_menu_mode
== 1)
2945 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2946 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2947 " echo 'return ...' \n"
2951 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2953 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2954 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2957 cur
->unsupport
? "[***********] " : "",
2958 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2960 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2963 g_tree_script_buf
[g_tree_script_pos
] = 0;
2964 g_list_script_buf
[g_list_script_pos
] = 0;
2966 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2967 grub_env_set(args
[1], buf
);
2971 check_free(device_name
, grub_free
);
2972 check_free(dev
, grub_device_close
);
2974 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2977 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2984 device_name
= grub_file_get_device_name(filename
);
2996 pos2
= grub_strstr(pos
, ",");
2999 pos2
= grub_strstr(pos
, ")");
3007 disk
= grub_disk_open(pos
);
3010 grub_disk_read(disk
, 0, 0x180, 16, guid
);
3011 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
3012 grub_disk_close(disk
);
3019 grub_free(device_name
);
3023 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
3025 eltorito_descriptor desc
;
3027 grub_memset(&desc
, 0, sizeof(desc
));
3028 grub_file_seek(file
, 17 * 2048);
3029 grub_file_read(file
, &desc
, sizeof(desc
));
3031 if (desc
.type
!= 0 || desc
.version
!= 1)
3036 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
3037 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
3045 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
3047 grub_uint8_t buf
[512];
3049 grub_file_seek(file
, sector
* 2048);
3050 grub_file_read(file
, buf
, sizeof(buf
));
3052 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3053 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3055 return *((grub_uint32_t
*)(buf
+ 40));
3061 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3065 grub_uint8_t buf
[512];
3066 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3068 grub_file_seek(file
, sector
* 2048);
3069 grub_file_read(file
, buf
, sizeof(buf
));
3071 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3073 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3077 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3082 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3084 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3086 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3090 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3092 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3097 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3099 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3101 if (buf
[36] == parttype
[i
])
3103 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3109 debug("%s does not contain efi eltorito\n", file
->name
);
3113 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3116 const char *fs
= NULL
;
3117 const char *val
= NULL
;
3118 const char *cdprompt
= NULL
;
3120 grub_uint8_t chksum
= 0;
3123 disk
= file
->device
->disk
;
3124 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3126 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3127 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3128 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3130 pos
= grub_strstr(file
->name
, "/");
3136 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3138 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3140 param
->vtoy_img_size
= file
->size
;
3142 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3143 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3145 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3147 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3148 param
->vtoy_reserved
[4] = 0;
3149 if (g_ventoy_chain_type
== 1) /* Windows */
3151 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3152 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3154 param
->vtoy_reserved
[4] = 1;
3158 fs
= ventoy_get_env("ventoy_fs_probe");
3159 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3161 param
->vtoy_reserved
[3] = 1;
3164 param
->vtoy_reserved
[5] = 0;
3165 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3166 if (val
&& val
[0] == '1' && val
[1] == 0)
3168 param
->vtoy_reserved
[5] = 1;
3171 /* ventoy_disk_signature used for vlnk */
3172 param
->vtoy_reserved
[6] = file
->vlnk
;
3173 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3175 /* calculate checksum */
3176 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3178 chksum
+= *((grub_uint8_t
*)param
+ i
);
3180 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3185 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3187 grub_uint32_t i
= 0;
3188 grub_uint64_t total
= 0;
3189 grub_uint64_t fileblk
= 0;
3190 ventoy_img_chunk
*chunk
= NULL
;
3192 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3194 chunk
= chunklist
->chunk
+ i
;
3196 if (chunk
->disk_start_sector
<= start
)
3198 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3202 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3205 fileblk
= (file
->size
+ 511) / 512;
3207 if (total
!= fileblk
)
3209 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3210 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3212 debug("maybe img file to be processed.\n");
3222 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3226 grub_uint32_t i
= 0;
3227 grub_uint32_t sector
= 0;
3228 grub_uint32_t count
= 0;
3229 grub_off_t size
= 0;
3230 grub_off_t read
= 0;
3232 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3233 if (fs_type
== ventoy_fs_exfat
)
3235 grub_fat_get_file_chunk(start
, file
, chunklist
);
3237 else if (fs_type
== ventoy_fs_ext
)
3239 grub_ext_get_file_chunk(start
, file
, chunklist
);
3243 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3244 file
->read_hook_data
= chunklist
;
3246 for (size
= file
->size
; size
> 0; size
-= read
)
3248 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3249 grub_file_read(file
, NULL
, read
);
3252 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3254 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3255 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3258 if (ventoy_fs_udf
== fs_type
)
3260 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3262 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3263 chunklist
->chunk
[i
].img_start_sector
= sector
;
3264 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3270 len
= (int)grub_strlen(file
->name
);
3271 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3272 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3273 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3274 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3276 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3278 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3288 chunklist
->chunk
[i
].img_start_sector
= sector
;
3289 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3297 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3301 grub_disk_addr_t start
;
3306 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3309 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3312 g_conf_replace_count
= 0;
3313 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3314 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3316 if (g_img_chunk_list
.chunk
)
3318 grub_free(g_img_chunk_list
.chunk
);
3321 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3323 grub_file_close(file
);
3324 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3327 /* get image chunk data */
3328 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3329 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3330 if (NULL
== g_img_chunk_list
.chunk
)
3332 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3335 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3336 g_img_chunk_list
.cur_chunk
= 0;
3338 start
= file
->device
->disk
->partition
->start
;
3340 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3342 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3343 grub_file_close(file
);
3347 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3350 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3351 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3352 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3355 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3359 grub_uint64_t offset
= 0;
3360 grub_uint32_t align
= 0;
3361 grub_file_t file
= NULL
;
3362 conf_replace
*node
= NULL
;
3363 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3364 ventoy_grub_param_file_replace
*replace
= NULL
;
3370 debug("select conf replace argc:%d\n", argc
);
3377 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3380 debug("Conf replace not found for %s\n", args
[1]);
3384 debug("Find %d conf replace for %s\n", n
, args
[1]);
3386 g_conf_replace_count
= n
;
3387 for (i
= 0; i
< n
; i
++)
3391 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3394 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3395 grub_file_close(file
);
3397 else if (node
->img
> 0)
3403 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3407 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3410 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3414 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3416 if (align
> vtoy_max_replace_file_size
)
3418 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3419 grub_file_close(file
);
3423 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3424 grub_file_close(file
);
3425 g_conf_replace_new_len
[i
] = (int)file
->size
;
3426 g_conf_replace_new_len_align
[i
] = align
;
3428 g_conf_replace_node
[i
] = node
;
3429 g_conf_replace_offset
[i
] = offset
+ 2;
3433 replace
= &(g_grub_param
->img_replace
[i
]);
3434 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3435 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3436 replace
->old_name_cnt
++;
3439 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3443 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3446 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3451 const char *ch
= var
;
3458 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3465 debug("Invalid variable letter <%c>\n", *ch
);
3472 debug("Invalid variable length:%d <%s>\n", n
, var
);
3476 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3485 grub_printf("\n=================== Variables Expansion ===================\n\n");
3488 grub_printf("<%s>: ", var
);
3491 while (i
< (len
- 1))
3494 if ((c
== '\n') || (c
== '\r'))
3504 else if (grub_isprint(c
))
3506 if (i
+ 1 < (len
- 1))
3508 grub_printf("%c", c
);
3518 expand
[i
- 1] = ' ';
3519 grub_printf("\r<%s>: %s", var
, expand
);
3522 grub_printf("\r<%s>: %s", var
, expand
);
3534 grub_snprintf(expand
, len
, "$$%s$$", var
);
3540 static int ventoy_auto_install_var_expand(install_template
*node
)
3548 char *newbuf
= NULL
;
3549 char *curline
= NULL
;
3550 char *nextline
= NULL
;
3551 grub_uint8_t
*code
= NULL
;
3553 var_node
*CurNode
= NULL
;
3554 var_node
*pVarList
= NULL
;
3556 code
= (grub_uint8_t
*)node
->filebuf
;
3558 if (node
->filelen
>= VTOY_SIZE_1MB
)
3560 debug("auto install script too long %d\n", node
->filelen
);
3564 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3566 debug("UCS-2 encoding NOT supported\n");
3570 start
= grub_strstr(node
->filebuf
, "$$");
3573 debug("no need to expand variable, no start.\n");
3577 end
= grub_strstr(start
+ 2, "$$");
3580 debug("no need to expand variable, no end.\n");
3584 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3585 newbuf
= grub_malloc(newlen
);
3588 debug("Failed to alloc newbuf %d\n", newlen
);
3592 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3594 nextline
= ventoy_get_line(curline
);
3596 start
= grub_strstr(curline
, "$$");
3599 end
= grub_strstr(start
+ 2, "$$");
3605 VTOY_APPEND_NEWBUF(curline
);
3607 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3609 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3611 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3618 value
[sizeof(value
) - 1] = 0;
3619 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3623 CurNode
= grub_zalloc(sizeof(var_node
));
3626 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3627 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3628 CurNode
->next
= pVarList
;
3634 VTOY_APPEND_NEWBUF(value
);
3636 VTOY_APPEND_NEWBUF(end
+ 2);
3640 VTOY_APPEND_NEWBUF(curline
);
3643 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3645 newbuf
[pos
- 1] = '\n';
3649 newbuf
[pos
++] = '\n';
3653 grub_free(node
->filebuf
);
3654 node
->filebuf
= newbuf
;
3655 node
->filelen
= pos
;
3659 CurNode
= pVarList
->next
;
3660 grub_free(pVarList
);
3667 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3673 grub_file_t file
= NULL
;
3674 char configfile
[128];
3675 install_template
*node
= NULL
;
3681 debug("select auto installation argc:%d\n", argc
);
3688 node
= ventoy_plugin_find_install_template(args
[0]);
3691 debug("Auto install template not found for %s\n", args
[0]);
3695 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3697 defidx
= node
->autosel
;
3698 if (node
->timeout
< 0)
3700 node
->cursel
= node
->autosel
- 1;
3701 debug("Auto install template auto select %d\n", node
->autosel
);
3706 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3712 if (node
->timeout
> 0)
3714 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3717 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" --class=\"sel_auto_install\" {\n"
3718 " echo %s\n}\n", "");
3720 for (i
= 0; i
< node
->templatenum
; i
++)
3722 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" --class=\"sel_auto_install\" {\n"
3724 node
->templatepath
[i
].path
);
3727 g_ventoy_menu_esc
= 1;
3728 g_ventoy_suppress_esc
= 1;
3729 g_ventoy_suppress_esc_default
= defidx
;
3731 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3732 grub_script_execute_sourcecode(configfile
);
3734 g_ventoy_menu_esc
= 0;
3735 g_ventoy_suppress_esc
= 0;
3736 g_ventoy_suppress_esc_default
= 1;
3740 node
->cursel
= g_ventoy_last_entry
- 1;
3743 grub_check_free(node
->filebuf
);
3746 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3748 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3749 node
->templatepath
[node
->cursel
].path
);
3752 node
->filebuf
= grub_malloc(file
->size
+ 8);
3755 grub_file_read(file
, node
->filebuf
, file
->size
);
3756 grub_file_close(file
);
3758 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3759 node
->filelen
= (int)file
->size
;
3761 ventoy_auto_install_var_expand(node
);
3766 debug("Failed to open auto install script <%s%s>\n",
3767 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3771 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3774 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3780 char configfile
[128];
3781 persistence_config
*node
;
3787 debug("select persistence argc:%d\n", argc
);
3794 node
= ventoy_plugin_find_persistent(args
[0]);
3797 debug("Persistence image not found for %s\n", args
[0]);
3801 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3803 defidx
= node
->autosel
;
3804 if (node
->timeout
< 0)
3806 node
->cursel
= node
->autosel
- 1;
3807 debug("Persistence image auto select %d\n", node
->autosel
);
3812 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3818 if (node
->timeout
> 0)
3820 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3823 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" --class=\"sel_persistence\" {\n"
3824 " echo %s\n}\n", "");
3826 for (i
= 0; i
< node
->backendnum
; i
++)
3828 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" --class=\"sel_persistence\" {\n"
3830 node
->backendpath
[i
].path
);
3834 g_ventoy_menu_esc
= 1;
3835 g_ventoy_suppress_esc
= 1;
3836 g_ventoy_suppress_esc_default
= defidx
;
3838 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3839 grub_script_execute_sourcecode(configfile
);
3841 g_ventoy_menu_esc
= 0;
3842 g_ventoy_suppress_esc
= 0;
3843 g_ventoy_suppress_esc_default
= 1;
3847 node
->cursel
= g_ventoy_last_entry
- 1;
3849 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3852 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3855 ventoy_img_chunk
*cur
;
3861 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3863 cur
= g_img_chunk_list
.chunk
+ i
;
3864 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3865 cur
->img_start_sector
, cur
->img_end_sector
,
3866 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3870 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3873 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3877 ventoy_img_chunk_list chunklist
;
3882 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3885 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3888 /* get image chunk data */
3889 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3890 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3891 if (NULL
== chunklist
.chunk
)
3893 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3896 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3897 chunklist
.cur_chunk
= 0;
3899 ventoy_get_block_list(file
, &chunklist
, 0);
3901 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3903 grub_printf("########## UNSUPPORTED ###############\n");
3906 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3908 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3910 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3911 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3914 grub_printf("\n==================================\n");
3916 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3918 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3919 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3920 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3921 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3922 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3926 grub_free(chunklist
.chunk
);
3927 grub_file_close(file
);
3929 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3932 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3935 ventoy_grub_param_file_replace
*replace
= NULL
;
3943 replace
= &(g_grub_param
->file_replace
);
3944 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3946 replace
->old_name_cnt
= 0;
3947 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3949 replace
->old_name_cnt
++;
3950 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3953 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3956 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3959 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3962 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3968 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3969 grub_env_set(args
[0], buf
);
3972 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3975 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3983 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3984 grub_printf("%s", g_list_script_buf
);
3988 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3989 grub_printf("%s", g_tree_script_buf
);
3995 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3997 img_info
*cur
= g_ventoy_img_list
;
4005 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
4006 grub_printf("name:<%s>\n\n", cur
->name
);
4013 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4019 ventoy_plugin_dump_injection();
4024 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4030 ventoy_plugin_dump_auto_install();
4035 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4041 ventoy_plugin_dump_persistence();
4046 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
4052 len1
= (int)grub_strlen(filename
);
4053 len2
= (int)grub_strlen(suffix
);
4060 for (i
= len1
- 1; i
>= 0; i
--)
4062 if (filename
[i
] == '.')
4073 if (filename
[i
- len2
- 1] != '_')
4078 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4086 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4092 if (argc
!= 1 && argc
!= 2)
4097 if (args
[0][0] == '0')
4099 if (g_ventoy_memdisk_mode
)
4104 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4111 else if (args
[0][0] == '1')
4113 return g_ventoy_iso_raw
? 0 : 1;
4115 else if (args
[0][0] == '2')
4117 return g_ventoy_iso_uefi_drv
? 0 : 1;
4119 else if (args
[0][0] == '3')
4121 if (g_ventoy_grub2_mode
)
4126 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4133 else if (args
[0][0] == '4')
4135 if (g_ventoy_wimboot_mode
)
4140 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4151 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4153 static int configfile_mode
= 0;
4154 char memfile
[128] = {0};
4161 * args[0]: 0:normal 1:configfile
4162 * args[1]: 0:list_buf 1:tree_buf
4167 debug("Invalid argc %d\n", argc
);
4173 if (args
[0][0] == '0')
4175 if (args
[1][0] == '0')
4177 grub_script_execute_sourcecode(g_list_script_buf
);
4181 grub_script_execute_sourcecode(g_tree_script_buf
);
4186 if (configfile_mode
)
4188 debug("Now already in F3 mode %d\n", configfile_mode
);
4192 if (args
[1][0] == '0')
4194 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4195 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4199 g_ventoy_last_entry
= -1;
4200 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4201 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4204 configfile_mode
= 1;
4205 grub_script_execute_sourcecode(memfile
);
4206 configfile_mode
= 0;
4212 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4223 g_ventoy_case_insensitive
= 1;
4224 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4225 g_ventoy_case_insensitive
= 0;
4231 grub_file_close(file
);
4237 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4242 const char *isopath
= NULL
;
4244 ventoy_mbr_head mbr
;
4251 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4254 isopath
= grub_env_get("vtoy_iso_part");
4257 debug("isopath is null %p\n", isopath
);
4261 debug("isopath is %s\n", isopath
);
4263 for (id
= 0; id
< 30 && (find
== 0); id
++)
4265 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4266 if (grub_strstr(isopath
, hdname
))
4268 debug("skip %s ...\n", hdname
);
4272 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4274 disk
= grub_disk_open(hdname
);
4277 debug("%s not exist\n", hdname
);
4281 grub_memset(&mbr
, 0, sizeof(mbr
));
4282 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4284 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4286 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4287 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4290 grub_env_set(args
[0], hdname
);
4294 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4298 debug("read %s failed\n", hdname
);
4301 grub_disk_close(disk
);
4307 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4318 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4321 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4324 debug("failed to open file %s\n", args
[0]);
4328 buf
= grub_malloc(len
);
4335 grub_file_read(file
, buf
, len
- 1);
4337 ventoy_get_line(buf
);
4338 ventoy_set_env(args
[1], buf
);
4342 grub_check_free(buf
);
4343 grub_file_close(file
);
4348 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4350 grub_uint64_t end_max
= 0;
4351 int *pCnt
= (int *)data
;
4356 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4357 "0 %llu linear /dev/ventoy %llu\n",
4358 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4360 end_max
= (partition
->len
+ partition
->start
) * 512;
4361 if (end_max
> g_part_end_max
)
4363 g_part_end_max
= end_max
;
4369 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4372 char *device_name
= NULL
;
4373 grub_device_t dev
= NULL
;
4378 g_part_list_pos
= 0;
4380 grub_env_unset("vtoy_img_part_file");
4387 device_name
= grub_file_get_device_name(args
[0]);
4390 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4394 dev
= grub_device_open(device_name
);
4397 debug("grub_device_open failed, %s\n", device_name
);
4401 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4403 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4404 grub_env_set("vtoy_img_part_file", buf
);
4406 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4407 grub_env_set("vtoy_img_part_cnt", buf
);
4409 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4410 grub_env_set("vtoy_img_max_part_end", buf
);
4414 check_free(device_name
, grub_free
);
4415 check_free(dev
, grub_device_close
);
4421 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4432 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4435 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4438 debug("failed to open file %s\n", args
[0]);
4442 buf
= grub_malloc(file
->size
+ 1);
4448 buf
[file
->size
] = 0;
4449 grub_file_read(file
, buf
, file
->size
);
4451 if (grub_strstr(buf
, args
[1]))
4458 grub_check_free(buf
);
4459 grub_file_close(file
);
4464 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4470 ventoy_iso9660_vd pvd
;
4477 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4480 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4483 debug("failed to open file %s\n", args
[0]);
4487 grub_file_seek(file
, 16 * 2048);
4488 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4489 if (len
!= sizeof(pvd
))
4491 debug("failed to read pvd %d\n", len
);
4495 grub_memset(buf
, 0, sizeof(buf
));
4496 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4497 ventoy_set_env(args
[1], buf
);
4499 grub_memset(buf
, 0, sizeof(buf
));
4500 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4501 ventoy_set_env(args
[2], buf
);
4505 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4506 ventoy_set_env(args
[3], buf
);
4509 grub_file_close(file
);
4514 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4525 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4528 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4531 debug("failed to open file %s\n", args
[0]);
4535 grub_memset(buf
, 0, sizeof(buf
));
4536 grub_file_seek(file
, 16 * 2048 + 813);
4537 len
= (int)grub_file_read(file
, buf
, 17);
4540 debug("failed to read create date %d\n", len
);
4544 ventoy_set_env(args
[1], buf
);
4547 grub_file_close(file
);
4552 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4558 ventoy_env_hook_root(1);
4563 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4569 ventoy_env_hook_root(0);
4574 #ifdef GRUB_MACHINE_EFI
4575 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4580 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4586 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4587 if (var
&& *var
== 1)
4595 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4604 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4609 grub_uint64_t FileSectors
= 0;
4610 ventoy_gpt_info
*gpt
= NULL
;
4611 ventoy_part_table
*pt
= NULL
;
4612 grub_uint8_t zeroguid
[16] = {0};
4617 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4620 debug("failed to open file %s\n", args
[0]);
4624 if (file
->size
% 512)
4626 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4630 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4636 FileSectors
= file
->size
/ 512;
4638 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4639 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4641 debug("This is EFI partition table\n");
4643 for (i
= 0; i
< 128; i
++)
4645 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4647 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4649 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4650 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4658 debug("This is MBR partition table\n");
4660 for (i
= 0; i
< 4; i
++)
4662 pt
= gpt
->MBR
.PartTbl
+ i
;
4663 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4665 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4666 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4667 (ulonglong
)FileSectors
);
4676 grub_file_close(file
);
4677 grub_check_free(gpt
);
4678 grub_errno
= GRUB_ERR_NONE
;
4682 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4691 for (i
= 0; i
< 500; i
++)
4693 ret
= grub_getkey_noblock();
4694 if (ret
== GRUB_TERM_NO_KEY
)
4703 grub_printf("\n\n Still have key input after clear.\n");
4711 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4718 int image_sector_size
;
4720 ventoy_chain_head
*chain
;
4721 ventoy_img_chunk
*chunk
;
4722 ventoy_os_param
*osparam
;
4723 ventoy_image_location
*location
;
4724 ventoy_image_disk_region
*region
;
4725 struct grub_acpi_table_header
*acpi
;
4734 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4736 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4742 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4744 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4746 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4750 img_chunk_num
= chain
->img_chunk_num
;
4752 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4753 datalen
= sizeof(ventoy_os_param
) + loclen
;
4755 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4756 acpi
= grub_zalloc(buflen
);
4762 /* Step1: Fill acpi table header */
4763 grub_memcpy(acpi
->signature
, "VTOY", 4);
4764 acpi
->length
= buflen
;
4766 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4767 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4769 acpi
->creator_id
[0] = 1;
4770 acpi
->creator_rev
= 1;
4772 /* Step2: Fill data */
4773 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4774 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4775 osparam
->vtoy_img_location_addr
= 0;
4776 osparam
->vtoy_img_location_len
= loclen
;
4777 osparam
->chksum
= 0;
4778 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4780 location
= (ventoy_image_location
*)(osparam
+ 1);
4781 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4782 location
->image_sector_size
= image_sector_size
;
4783 location
->disk_sector_size
= chain
->disk_sector_size
;
4784 location
->region_count
= img_chunk_num
;
4786 region
= location
->regions
;
4787 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4788 if (512 == image_sector_size
)
4790 for (i
= 0; i
< img_chunk_num
; i
++)
4792 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4793 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4794 region
->disk_start_sector
= chunk
->disk_start_sector
;
4801 for (i
= 0; i
< img_chunk_num
; i
++)
4803 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4804 region
->image_start_sector
= chunk
->img_start_sector
;
4805 region
->disk_start_sector
= chunk
->disk_start_sector
;
4811 /* Step3: Fill acpi checksum */
4813 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4815 /* load acpi table */
4816 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4817 grub_script_execute_sourcecode(cmd
);
4821 VENTOY_CMD_RETURN(0);
4824 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4830 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4831 g_ventoy_last_entry
= -1;
4836 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4842 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4847 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4849 const char *pos
= filename
+ 1;
4857 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4859 grub_strncpy((char *)data
, filename
, 128);
4870 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4873 char *device_name
= NULL
;
4874 grub_device_t dev
= NULL
;
4875 grub_fs_t fs
= NULL
;
4876 char buf
[128] = {0};
4882 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4886 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4888 device_name
= grub_file_get_device_name(args
[0]);
4891 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4895 dev
= grub_device_open(device_name
);
4898 debug("grub_device_open failed, %s\n", device_name
);
4902 fs
= grub_fs_probe(dev
);
4905 debug("grub_fs_probe failed, %s\n", device_name
);
4909 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4913 ventoy_set_env(args
[2], buf
);
4920 check_free(device_name
, grub_free
);
4921 check_free(dev
, grub_device_close
);
4926 int ventoy_load_part_table(const char *diskname
)
4933 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4934 if (!g_ventoy_part_info
)
4939 disk
= grub_disk_open(diskname
);
4942 debug("Failed to open disk %s\n", diskname
);
4946 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4948 g_ventoy_disk_bios_id
= disk
->id
;
4950 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4951 grub_disk_close(disk
);
4953 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4954 dev
= grub_device_open(name
);
4957 /* Check for official Ventoy device */
4958 ret
= ventoy_check_official_device(dev
);
4959 grub_device_close(dev
);
4967 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4968 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4973 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4980 ret
= ventoy_load_part_table(args
[0]);
4986 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4987 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4992 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4995 const char *vcfg
= NULL
;
5000 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
5003 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
5004 grub_env_set(args
[1], vcfg
);
5009 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
5017 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5020 grub_uint8_t zeroguid
[16] = {0};
5025 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5028 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
5030 if (id
>= 1 && id
<= 128)
5032 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
5040 if (id
>= 1 && id
<= 4)
5042 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
5052 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5055 char *device_name
= NULL
;
5056 grub_device_t dev
= NULL
;
5057 grub_fs_t fs
= NULL
;
5062 debug("get fs label for %s\n", args
[0]);
5066 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5070 device_name
= grub_file_get_device_name(args
[0]);
5073 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5077 dev
= grub_device_open(device_name
);
5080 debug("grub_device_open failed, %s\n", device_name
);
5084 fs
= grub_fs_probe(dev
);
5085 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5087 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5091 fs
->fs_label(dev
, &label
);
5094 debug("label=<%s>\n", label
);
5095 ventoy_set_env(args
[1], label
);
5103 check_free(device_name
, grub_free
);
5104 check_free(dev
, grub_device_close
);
5109 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5113 grub_snprintf((char *)data
, 256, "%s", filename
);
5120 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5122 if (info
->dir
&& filename
&& filename
[0] != '.')
5124 grub_snprintf((char *)data
, 256, "%s", filename
);
5131 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5134 char *device_name
= NULL
;
5135 grub_device_t dev
= NULL
;
5136 grub_fs_t fs
= NULL
;
5137 char name
[256] ={0};
5141 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5145 device_name
= grub_file_get_device_name(args
[0]);
5148 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5152 dev
= grub_device_open(device_name
);
5155 debug("grub_device_open failed, %s\n", device_name
);
5159 fs
= grub_fs_probe(dev
);
5162 debug("grub_fs_probe failed, %s\n", device_name
);
5166 fs
->fs_dir(dev
, args
[1], hook
, name
);
5169 ventoy_set_env(args
[2], name
);
5176 check_free(device_name
, grub_free
);
5177 check_free(dev
, grub_device_close
);
5182 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5185 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5188 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5191 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5194 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5204 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5208 for (pos
= args
[0]; *pos
; pos
++)
5222 grub_env_set(args
[1], args
[0]);
5232 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5242 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5247 len
= (int)grub_strlen(buf
);
5248 for (i
= len
; i
> 0; i
--)
5250 if (buf
[i
- 1] == '/')
5252 grub_env_set(args
[1], buf
+ i
);
5257 grub_env_set(args
[1], buf
);
5262 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5264 struct grub_video_mode_info info
;
5271 if (!g_video_mode_list
)
5273 ventoy_enum_video_mode();
5276 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5278 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5282 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5285 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5287 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5288 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5290 VENTOY_CMD_RETURN(0);
5293 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5295 struct grub_video_mode_info info
;
5302 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5304 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5308 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5311 grub_env_set(args
[0], buf
);
5313 VENTOY_CMD_RETURN(0);
5316 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5324 if (!g_video_mode_list
)
5329 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5330 if (id
< g_video_mode_num
)
5332 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5333 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5336 grub_env_set(args
[1], buf
);
5338 VENTOY_CMD_RETURN(0);
5341 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5344 grub_uint32_t loadsector
= 0;
5347 grub_uint32_t boot_catlog
= 0;
5348 grub_uint8_t buf
[512];
5354 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5358 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5361 debug("failed to open %s\n", args
[0]);
5365 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5366 if (boot_catlog
== 0)
5368 debug("No bootcatlog found\n");
5369 grub_file_close(file
);
5373 grub_memset(buf
, 0, sizeof(buf
));
5374 grub_file_seek(file
, boot_catlog
* 2048);
5375 grub_file_read(file
, buf
, sizeof(buf
));
5376 grub_file_close(file
);
5378 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5380 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5382 if (buf
[i
+ 32] == 0x88)
5384 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5385 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5391 if (loadsector
== 0)
5393 debug("No EFI eltorito info found\n");
5397 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5398 grub_env_set(args
[1], value
);
5399 VENTOY_CMD_RETURN(0);
5402 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5407 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5409 if (pfsdir
->initrd
[0])
5414 curpos
= pfsdir
->curpos
;
5415 len
= grub_strlen(filename
);
5419 if ((len
== 1 && filename
[0] == '.') ||
5420 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5425 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5428 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5429 pfsdir
->curpos
= curpos
+ printlen
;
5430 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5431 pfsdir
->curpos
= curpos
;
5432 pfsdir
->fullpath
[curpos
] = 0;
5436 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5439 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5440 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5442 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5444 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5453 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5457 char *device_name
= NULL
;
5458 grub_device_t dev
= NULL
;
5459 grub_fs_t fs
= NULL
;
5460 replace_fs_dir
*pfsdir
= NULL
;
5466 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5470 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5476 device_name
= grub_file_get_device_name(args
[0]);
5482 dev
= grub_device_open(device_name
);
5488 fs
= grub_fs_probe(dev
);
5497 pfsdir
->fullpath
[0] = '/';
5498 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5500 if (pfsdir
->initrd
[0])
5502 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5504 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5506 if (pfsdir
->initrd
[i
] == '/')
5508 pfsdir
->initrd
[i
] = '\\';
5512 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5513 grub_env_set(args
[1], pos
);
5517 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5522 grub_check_free(pfsdir
);
5523 grub_check_free(device_name
);
5524 check_free(dev
, grub_device_close
);
5526 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5529 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5531 const char *pager
= NULL
;
5537 pager
= grub_env_get("pager");
5541 grub_env_set("pager", "1");
5543 else if (pager
[0] == '1')
5549 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5551 grub_env_set("pager", "1");
5554 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5557 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5563 if (g_pager_flag
== 1)
5565 grub_env_unset("pager");
5567 else if (g_pager_flag
== 2)
5569 grub_env_set("pager", g_old_pager
);
5572 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5575 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5577 if (g_json_case_mis_path
[0])
5582 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5584 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5590 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5593 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5595 if (g_json_case_mis_path
[0])
5600 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5602 if (grub_strcasecmp(filename
, "ventoy") == 0)
5604 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5605 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5606 if (g_json_case_mis_path
[0])
5616 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5619 char *device_name
= NULL
;
5620 grub_device_t dev
= NULL
;
5621 grub_fs_t fs
= NULL
;
5622 chk_case_fs_dir fs_dir
;
5628 device_name
= grub_file_get_device_name(args
[0]);
5634 dev
= grub_device_open(device_name
);
5640 fs
= grub_fs_probe(dev
);
5646 fstype
= ventoy_get_fs_type(fs
->name
);
5647 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5652 g_json_case_mis_path
[0] = 0;
5655 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5657 if (g_json_case_mis_path
[0])
5659 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5664 grub_check_free(device_name
);
5665 check_free(dev
, grub_device_close
);
5667 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5670 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5673 grub_partition_t part
;
5674 char priority_str
[3]; /* Maximum value 15 */
5678 if (argc
< 2 || argc
> 3)
5679 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5680 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5682 /* Open the disk if it exists */
5683 disk
= grub_disk_open (args
[0]);
5686 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5690 part
= grub_partition_probe (disk
, args
[1]);
5693 grub_disk_close (disk
);
5694 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5695 "No such partition");
5698 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5700 grub_disk_close (disk
);
5701 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5702 "Not a GPT partition");
5705 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5706 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5710 grub_env_set (args
[2], priority_str
);
5711 grub_env_export (args
[2]);
5715 grub_printf ("Priority is %s\n", priority_str
);
5718 grub_disk_close (disk
);
5719 return GRUB_ERR_NONE
;
5723 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5727 grub_file_t file
= NULL
;
5728 grub_uint32_t loadrba
= 0;
5729 grub_uint32_t boot_catlog
= 0;
5730 grub_uint8_t sector
[512];
5731 boot_info_table
*info
= NULL
;
5736 /* This also trigger a iso9660 fs parse */
5737 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5742 joliet
= grub_iso9660_is_joliet();
5748 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5751 debug("failed to open %s\n", args
[0]);
5755 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5756 if (boot_catlog
== 0)
5758 debug("no bootcatlog found %u\n", boot_catlog
);
5762 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5765 debug("no bios eltorito rba found %u\n", loadrba
);
5769 grub_file_seek(file
, loadrba
* 2048);
5770 grub_file_read(file
, sector
, 512);
5772 info
= (boot_info_table
*)sector
;
5773 if (info
->bi_data0
== 0x7c6ceafa &&
5774 info
->bi_data1
== 0x90900000 &&
5775 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5776 info
->bi_BootFileLocation
== loadrba
)
5778 debug("bootloader is syslinux, %u.\n", loadrba
);
5784 grub_file_close(file
);
5785 grub_errno
= GRUB_ERR_NONE
;
5789 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5792 ventoy_vlnk_part
*node
;
5798 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5800 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5801 ++n
, node
->device
, node
->disksig
,
5802 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5808 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5816 len
= (int)grub_strlen(args
[0]);
5817 if (grub_file_is_vlnk_suffix(args
[0], len
))
5826 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5829 const char *name
= NULL
;
5835 grub_env_unset(args
[1]);
5836 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5839 debug("VLNK SRC: <%s>\n", args
[0]);
5840 debug("VLNK DST: <%s>\n", name
);
5841 grub_env_set(args
[1], name
);
5849 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5853 grub_file_t file
= NULL
;
5864 len
= (int)grub_strlen(args
[0]);
5865 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5867 grub_printf("Invalid vlnk suffix\n");
5871 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5874 grub_printf("Failed to open %s\n", args
[0]);
5878 if (file
->size
!= 32768)
5880 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5884 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5885 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5887 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5892 check_free(file
, grub_file_close
);
5893 grub_errno
= GRUB_ERR_NONE
;
5897 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5903 g_iso_vd_id_publisher
[0] = 0;
5904 g_iso_vd_id_prepare
[0] = 0;
5905 g_iso_vd_id_application
[0] = 0;
5910 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5914 grub_file_t file
= NULL
;
5919 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5922 grub_printf("Failed to open %s\n", args
[0]);
5926 grub_file_seek(file
, 16 * 2048 + offset
);
5927 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5930 grub_file_seek(file
, 16 * 2048 + offset
);
5931 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5934 grub_file_seek(file
, 16 * 2048 + offset
);
5935 grub_file_read(file
, g_iso_vd_id_application
, 128);
5939 check_free(file
, grub_file_close
);
5940 grub_errno
= GRUB_ERR_NONE
;
5944 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5947 char *id
= g_iso_vd_id_publisher
;
5952 if (args
[0][0] == '1')
5954 id
= g_iso_vd_id_prepare
;
5956 else if (args
[0][0] == '2')
5958 id
= g_iso_vd_id_application
;
5961 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5966 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5971 grub_errno
= GRUB_ERR_NONE
;
5975 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5980 g_ventoy_fn_mutex
= 0;
5981 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5983 g_ventoy_fn_mutex
= 1;
5986 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5989 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5991 grub_uint64_t total
;
5992 grub_uint64_t org_required
;
5993 grub_uint64_t new_required
;
5999 #ifdef GRUB_MACHINE_EFI
6000 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
6001 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
6002 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
6003 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
6008 grub_printf("Non EFI mode!\n");
6013 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6016 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6018 const char *env
= NULL
;
6023 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
6028 if (ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
6029 ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
6030 ventoy_check_mode_by_name(args
[0], "vtwimboot"))
6035 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6036 if (env
&& env
[0] == '0' && env
[1] == 0)
6044 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6052 const char *env
= NULL
;
6053 ulonglong fsize
= 0;
6055 int seldata
[16] = {0};
6060 len
= 8 * VTOY_SIZE_1KB
;
6061 cmd
= (char *)grub_malloc(len
);
6067 g_vtoy_secondary_need_recover
= 0;
6068 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6070 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6073 timeout
= (int)grub_strtol(env
, NULL
, 10);
6078 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6081 fsize
= grub_strtoull(args
[2], NULL
, 10);
6083 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in normal mode", "second_normal"); seldata
[n
++] = 1;
6085 if (grub_strcmp(args
[1], "Unix") != 0)
6087 if (grub_strcmp(args
[1], "Windows") == 0)
6089 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in wimboot mode", "second_wimboot"); seldata
[n
++] = 2;
6093 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in grub2 mode", "second_grub2"); seldata
[n
++] = 3;
6096 if (fsize
<= VTOY_SIZE_1GB
)
6098 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in memdisk mode", "second_memdisk"); seldata
[n
++] = 4;
6102 vtoy_dummy_menuentry(cmd
, pos
, len
, "File checksum", "second_checksum"); seldata
[n
++] = 5;
6105 g_ventoy_menu_esc
= 1;
6106 g_ventoy_suppress_esc
= 1;
6107 g_ventoy_suppress_esc_default
= 0;
6108 g_ventoy_secondary_menu_on
= 1;
6109 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6110 grub_script_execute_sourcecode(cfgfile
);
6111 g_ventoy_menu_esc
= 0;
6112 g_ventoy_suppress_esc
= 0;
6113 g_ventoy_suppress_esc_default
= 1;
6114 g_ventoy_secondary_menu_on
= 0;
6116 select
= seldata
[g_ventoy_last_entry
];
6120 g_ventoy_wimboot_mode
= 1;
6121 g_vtoy_secondary_need_recover
= 1;
6123 else if (select
== 3)
6125 g_ventoy_grub2_mode
= 1;
6126 g_vtoy_secondary_need_recover
= 2;
6128 else if (select
== 4)
6130 g_ventoy_memdisk_mode
= 1;
6131 g_vtoy_secondary_need_recover
= 3;
6133 else if (select
== 5)
6135 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6136 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6138 }while (select
== 5);
6144 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6150 if (g_vtoy_secondary_need_recover
== 1)
6152 g_ventoy_wimboot_mode
= 0;
6154 else if (g_vtoy_secondary_need_recover
== 2)
6156 g_ventoy_grub2_mode
= 0;
6158 else if (g_vtoy_secondary_need_recover
== 3)
6160 g_ventoy_memdisk_mode
= 0;
6163 g_vtoy_secondary_need_recover
= 0;
6165 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6168 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6173 if (args
[0][0] == '0')
6175 g_ventoy_case_insensitive
= 0;
6179 g_ventoy_case_insensitive
= 1;
6185 int ventoy_env_init(void)
6190 grub_env_set("vtdebug_flag", "");
6192 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6193 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6194 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6195 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6197 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6200 ventoy_filt_register(0, ventoy_wrapper_open
);
6202 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6205 g_grub_param
->grub_env_get
= grub_env_get
;
6206 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6207 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6208 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6209 grub_env_set("env_param", buf
);
6210 grub_env_set("ventoy_env_param", buf
);
6212 grub_env_export("env_param");
6213 grub_env_export("ventoy_env_param");
6216 grub_env_export("vtoy_winpeshl_ini_addr");
6217 grub_env_export("vtoy_winpeshl_ini_size");
6219 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6220 grub_env_set("vtoy_chain_file_size", buf
);
6221 grub_env_export("vtoy_chain_file_size");
6223 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6224 grub_env_set("vtoy_chain_file_read", buf
);
6225 grub_env_export("vtoy_chain_file_read");
6232 static cmd_para ventoy_cmds
[] =
6234 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6235 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6236 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6237 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6238 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6239 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6240 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6241 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6242 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6243 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6244 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6245 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6246 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6247 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6248 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6249 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6250 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6251 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6252 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6253 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6254 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6255 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6256 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6257 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6258 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6259 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6260 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6262 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6263 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6264 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6265 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6266 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6267 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6268 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6270 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6271 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6272 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6273 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6274 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6275 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6276 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6277 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6278 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6279 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6282 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6283 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6284 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6285 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6286 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6287 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6288 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6289 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6290 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6291 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6292 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6294 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6295 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6296 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6297 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6298 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6299 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6300 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6302 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6303 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6304 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6305 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6306 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6307 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6308 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6309 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6310 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6311 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6313 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6314 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6315 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6316 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6317 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6318 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6319 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6320 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6321 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6323 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6324 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6325 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6326 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6329 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6330 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6331 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6333 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6334 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6335 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6338 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6339 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6340 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6341 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6342 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6343 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6344 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6345 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6346 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6347 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6348 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6349 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6350 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6351 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6353 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6354 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6355 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6356 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6357 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6358 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6359 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6360 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6361 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6362 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6363 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6364 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6366 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6367 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6368 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6369 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6370 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6371 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6372 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6373 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6374 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6375 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6376 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6377 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6378 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6379 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6380 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6381 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6382 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6383 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6384 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6385 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6386 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6387 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6388 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6389 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6390 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6391 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6394 int ventoy_register_all_cmd(void)
6397 cmd_para
*cur
= NULL
;
6399 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6401 cur
= ventoy_cmds
+ i
;
6402 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6403 cur
->summary
, cur
->description
, cur
->parser
);
6409 int ventoy_unregister_all_cmd(void)
6413 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6415 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);