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/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 static grub_uint8_t g_check_mbr_data
[] = {
55 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 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 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
61 initrd_info
*g_initrd_img_list
= NULL
;
62 initrd_info
*g_initrd_img_tail
= NULL
;
63 int g_initrd_img_count
= 0;
64 int g_valid_initrd_count
= 0;
65 int g_default_menu_mode
= 0;
66 int g_filt_dot_underscore_file
= 0;
67 int g_sort_case_sensitive
= 0;
68 int g_tree_view_menu_style
= 0;
69 static grub_file_t g_old_file
;
70 static int g_ventoy_last_entry_back
;
73 char g_img_swap_tmp_buf
[1024];
74 img_info g_img_swap_tmp
;
75 img_info
*g_ventoy_img_list
= NULL
;
77 int g_ventoy_img_count
= 0;
79 grub_device_t g_enum_dev
= NULL
;
80 grub_fs_t g_enum_fs
= NULL
;
81 int g_img_max_search_level
= -1;
82 img_iterator_node g_img_iterator_head
;
83 img_iterator_node
*g_img_iterator_tail
= NULL
;
85 grub_uint8_t g_ventoy_break_level
= 0;
86 grub_uint8_t g_ventoy_debug_level
= 0;
87 grub_uint8_t g_ventoy_chain_type
= 0;
89 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
90 grub_uint32_t g_ventoy_cpio_size
= 0;
91 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
92 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
94 int g_plugin_image_list
= 0;
96 ventoy_grub_param
*g_grub_param
= NULL
;
98 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
100 ventoy_img_chunk_list g_img_chunk_list
;
102 int g_wimboot_enable
= 0;
103 ventoy_img_chunk_list g_wimiso_chunk_list
;
104 char *g_wimiso_path
= NULL
;
106 int g_vhdboot_enable
= 0;
108 grub_uint64_t g_conf_replace_offset
= 0;
109 grub_uint64_t g_svd_replace_offset
= 0;
110 conf_replace
*g_conf_replace_node
= NULL
;
111 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
112 int g_conf_replace_new_len
= 0;
113 int g_conf_replace_new_len_align
= 0;
115 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
116 grub_uint64_t g_ventoy_disk_size
= 0;
117 grub_uint64_t g_ventoy_disk_part_size
[2];
119 static char *g_tree_script_buf
= NULL
;
120 static int g_tree_script_pos
= 0;
122 static char *g_list_script_buf
= NULL
;
123 static int g_list_script_pos
= 0;
125 static char *g_part_list_buf
= NULL
;
126 static int g_part_list_pos
= 0;
128 static int g_video_mode_max
= 0;
129 static int g_video_mode_num
= 0;
130 static ventoy_video_mode
*g_video_mode_list
= NULL
;
132 static int g_enumerate_time_checked
= 0;
133 static grub_uint64_t g_enumerate_start_time_ms
;
134 static grub_uint64_t g_enumerate_finish_time_ms
;
135 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
137 static int g_pager_flag
= 0;
138 static char g_old_pager
[32];
140 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
142 static const char *g_menu_class
[] =
144 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
147 const char *g_menu_prefix
[img_type_max
] =
149 "iso", "wim", "efi", "img", "vhd", "vtoy"
152 static int g_vtoy_load_prompt
= 0;
153 static char g_vtoy_prompt_msg
[64];
155 static char g_json_case_mis_path
[32];
157 static int ventoy_get_fs_type(const char *fs
)
161 return ventoy_fs_max
;
163 else if (grub_strncmp(fs
, "exfat", 5) == 0)
165 return ventoy_fs_exfat
;
167 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
169 return ventoy_fs_ntfs
;
171 else if (grub_strncmp(fs
, "ext", 3) == 0)
173 return ventoy_fs_ext
;
175 else if (grub_strncmp(fs
, "xfs", 3) == 0)
177 return ventoy_fs_xfs
;
179 else if (grub_strncmp(fs
, "udf", 3) == 0)
181 return ventoy_fs_udf
;
183 else if (grub_strncmp(fs
, "fat", 3) == 0)
185 return ventoy_fs_fat
;
188 return ventoy_fs_max
;
191 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
210 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
212 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
216 static int ventoy_control_get_flag(const char *key
)
218 const char *val
= ventoy_get_env(key
);
220 if (val
&& val
[0] == '1' && val
[1] == 0)
227 static grub_err_t
ventoy_fs_close(grub_file_t file
)
229 grub_file_close(g_old_file
);
230 grub_free(file
->data
);
238 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
244 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
249 for (i
= 0; i
< g_video_mode_num
; i
++)
251 if (g_video_mode_list
[i
].width
== info
->width
&&
252 g_video_mode_list
[i
].height
== info
->height
&&
253 g_video_mode_list
[i
].bpp
== info
->bpp
)
259 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
260 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
261 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
264 if (g_video_mode_num
== g_video_mode_max
)
266 g_video_mode_max
*= 2;
267 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
273 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
275 if (v1
->bpp
== v2
->bpp
)
277 if (v1
->width
== v2
->width
)
279 if (v1
->height
== v2
->height
)
285 return (v1
->height
< v2
->height
) ? -1 : 1;
290 return (v1
->width
< v2
->width
) ? -1 : 1;
295 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
299 static int ventoy_enum_video_mode(void)
302 grub_video_adapter_t adapter
;
303 grub_video_driver_id_t id
;
304 ventoy_video_mode mode
;
306 g_video_mode_num
= 0;
307 g_video_mode_max
= 1024;
308 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
309 if (!g_video_mode_list
)
314 #ifdef GRUB_MACHINE_PCBIOS
315 grub_dl_load ("vbe");
318 id
= grub_video_get_driver_id ();
320 FOR_VIDEO_ADAPTERS (adapter
)
322 if (!adapter
->iterate
||
323 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
324 adapter
->init() != GRUB_ERR_NONE
)))
329 adapter
->iterate(ventoy_video_hook
, NULL
);
331 if (adapter
->id
!= id
)
337 /* sort video mode */
338 for (i
= 0; i
< g_video_mode_num
; i
++)
339 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
341 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
343 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
344 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
345 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
349 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
352 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
356 static struct grub_fs vtoy_fs
=
361 .fs_read
= ventoy_fs_read
,
362 .fs_close
= ventoy_fs_close
,
372 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
378 file
->data
= grub_malloc(rawFile
->size
+ 4096);
384 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
385 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
387 g_old_file
= rawFile
;
389 file
->size
= rawFile
->size
+ len
;
390 file
->device
= rawFile
->device
;
392 file
->not_easily_seekable
= 1;
397 static int ventoy_check_decimal_var(const char *name
, long *value
)
399 const char *value_str
= NULL
;
401 value_str
= grub_env_get(name
);
402 if (NULL
== value_str
)
404 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
407 if (!ventoy_is_decimal(value_str
))
409 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
412 *value
= grub_strtol(value_str
, NULL
, 10);
414 return GRUB_ERR_NONE
;
417 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
419 grub_uint64_t sectors
;
421 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
423 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
427 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
430 return sectors
* 512;
433 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
439 grub_uint32_t offset
;
441 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
444 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
448 len
= (int)file
->size
;
450 data
= (char *)grub_malloc(file
->size
);
456 grub_file_read(file
, data
, file
->size
);
457 grub_file_close(file
);
459 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
460 grub_script_execute_sourcecode(exec
);
462 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
463 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
464 grub_file_close(file
);
466 grub_script_execute_sourcecode("loopback -d efiboot");
470 *direntoff
= offset
+ 2;
475 static int ventoy_set_check_result(int ret
)
479 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
480 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
481 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
485 grub_printf(VTOY_WARNING
"\n");
486 grub_printf(VTOY_WARNING
"\n");
487 grub_printf(VTOY_WARNING
"\n\n\n");
489 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
490 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
492 grub_printf("\n\nWill exit after 10 seconds ...... ");
500 static int ventoy_check_official_device(grub_device_t dev
)
504 grub_uint64_t offset
;
507 grub_uint8_t mbr
[512];
511 struct grub_partition
*partition
;
513 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
515 return ventoy_set_check_result(1 | 0x1000);
518 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
519 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
520 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
522 #ifndef GRUB_MACHINE_EFI
523 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
524 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
525 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
527 return ventoy_set_check_result(2 | 0x1000);
536 /* We must have partition 2 */
539 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
543 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
547 return ventoy_set_check_result(3 | 0x1000);
550 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
552 grub_file_close(file
);
553 return ventoy_set_check_result(4 | 0x1000);
556 partition
= dev
->disk
->partition
;
557 if (partition
->number
!= 0 || partition
->start
!= 2048)
559 return ventoy_set_check_result(5);
564 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
566 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
567 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
568 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
570 grub_file_close(file
);
571 return ventoy_set_check_result(6);
576 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
577 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
578 PartTbl
[1].SectorCount
!= 65536)
580 grub_file_close(file
);
581 return ventoy_set_check_result(6);
587 offset
= partition
->start
+ partition
->len
;
588 partition
= file
->device
->disk
->partition
;
589 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
591 grub_file_close(file
);
592 return ventoy_set_check_result(7);
596 grub_file_close(file
);
600 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
601 dev2
= grub_device_open(devname
);
604 return ventoy_set_check_result(8);
607 fs
= grub_fs_probe(dev2
);
610 grub_device_close(dev2
);
611 return ventoy_set_check_result(9);
614 fs
->fs_label(dev2
, &label
);
615 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
617 grub_device_close(dev2
);
618 return ventoy_set_check_result(10);
621 grub_device_close(dev2
);
625 disk
= grub_disk_open(dev
->disk
->name
);
628 return ventoy_set_check_result(11);
631 grub_memset(mbr
, 0, 512);
632 grub_disk_read(disk
, 0, 0, 512, mbr
);
633 grub_disk_close(disk
);
635 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
637 return ventoy_set_check_result(12);
640 return ventoy_set_check_result(0);
643 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
647 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
657 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
659 grub_uint64_t size
= 0;
662 char fullpath
[256] = {0};
665 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
668 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
671 debug("grub_file_open failed <%s>\n", fullpath
);
677 grub_file_close(file
);
681 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
685 char fullpath
[256] = {0};
688 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
691 file
= grub_file_open(fullpath
, type
);
694 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
701 int ventoy_is_file_exist(const char *fmt
, ...)
708 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
712 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
715 grub_strncpy(pos
+ len
, "\" ]", 3);
717 debug("script exec %s\n", buf
);
719 if (0 == grub_script_execute_sourcecode(buf
))
727 int ventoy_is_dir_exist(const char *fmt
, ...)
734 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
738 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
741 grub_strncpy(pos
+ len
, "\" ]", 3);
743 debug("script exec %s\n", buf
);
745 if (0 == grub_script_execute_sourcecode(buf
))
753 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
756 grub_uint8_t
*outbuf
;
757 grub_uint8_t gzHdr
[10] =
759 0x1F, 0x8B, /* magic */
767 grub_memset(&s
, 0, sizeof(mz_stream
));
769 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
771 outbuf
= (grub_uint8_t
*)mem_out
;
773 mem_out_len
-= sizeof(gzHdr
) + 8;
774 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
775 outbuf
+= sizeof(gzHdr
);
777 s
.avail_in
= mem_in_len
;
780 s
.avail_out
= mem_out_len
;
783 mz_deflate(&s
, MZ_FINISH
);
787 outbuf
+= s
.total_out
;
788 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
789 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
791 return s
.total_out
+ sizeof(gzHdr
) + 8;
799 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
803 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
806 if (0 == grub_strcmp(args
[0], "on"))
809 grub_env_set("vtdebug_flag", "debug");
814 grub_env_set("vtdebug_flag", "");
817 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
820 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
824 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
826 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
827 grub_printf(" level:\r\n");
828 grub_printf(" 01/11: busybox / (+cat log)\r\n");
829 grub_printf(" 02/12: initrd / (+cat log)\r\n");
830 grub_printf(" 03/13: hook / (+cat log)\r\n");
832 grub_printf(" debug:\r\n");
833 grub_printf(" 0: debug is off\r\n");
834 grub_printf(" 1: debug is on\r\n");
836 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
839 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
841 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
843 g_ventoy_debug_level
= 1;
846 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
849 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
858 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
861 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
893 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
909 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
925 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
930 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
932 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
935 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
940 value_long
+= grub_strtol(args
[1], NULL
, 10);
942 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
943 grub_env_set(args
[0], buf
);
945 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
948 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
950 ulonglong value1
= 0;
951 ulonglong value2
= 0;
956 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
959 value1
= grub_strtoull(args
[0], NULL
, 10);
960 value2
= grub_strtoull(args
[1], NULL
, 10);
962 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
963 grub_env_set(args
[2], buf
);
965 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
968 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
983 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
986 debug("failed to open file <%s> for udf check\n", args
[0]);
990 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
992 grub_env_set(args
[1], buf
);
994 grub_file_close(file
);
1000 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1008 g_wimboot_enable
= 0;
1009 grub_check_free(g_wimiso_path
);
1010 grub_check_free(g_wimiso_chunk_list
.chunk
);
1012 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1018 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1019 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1020 if (NULL
== g_wimiso_chunk_list
.chunk
)
1022 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1025 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1026 g_wimiso_chunk_list
.cur_chunk
= 0;
1028 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1030 g_wimboot_enable
= 1;
1031 g_wimiso_path
= grub_strdup(args
[0]);
1033 grub_file_close(file
);
1038 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1048 ventoy_iso9660_override
*dirent
;
1057 totlen
= sizeof(ventoy_chain_head
);
1059 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1061 debug("failed to load efiboot template %d\n", len
);
1067 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1069 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1072 debug("failed to open file <%s>\n", args
[0]);
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
);
1151 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1157 grub_file_read(file
, cur
, left
);
1160 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1166 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1173 enum grub_file_type type
;
1184 if (grub_strcmp(args
[0], "nodecompress") == 0)
1186 type
= VENTOY_FILE_TYPE
;
1190 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1193 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1196 debug("failed to open file <%s>\n", args
[1]);
1200 #ifdef GRUB_MACHINE_EFI
1201 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1203 buf
= (char *)grub_malloc(file
->size
);
1208 grub_file_close(file
);
1212 if (g_vtoy_load_prompt
)
1214 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1218 grub_file_read(file
, buf
, file
->size
);
1221 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1222 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1223 grub_env_set(name
, value
);
1225 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1226 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1227 grub_env_set(name
, value
);
1229 grub_file_close(file
);
1235 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1253 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1256 debug("failed to open file <%s> for udf check\n", args
[0]);
1260 headlen
= sizeof(ventoy_chain_head
);
1262 #ifdef GRUB_MACHINE_EFI
1263 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1265 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1268 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1270 grub_file_read(file
, buf
+ headlen
, file
->size
);
1272 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1273 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1274 grub_env_set(name
, value
);
1276 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1277 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1278 grub_env_set(name
, value
);
1280 grub_file_close(file
);
1286 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1292 if (grub_iso9660_is_joliet())
1294 debug("This time has joliet process\n");
1303 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1312 if (args
[0][0] == '1')
1314 grub_iso9660_set_nojoliet(1);
1318 grub_iso9660_set_nojoliet(0);
1324 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1329 grub_uint8_t buf
[32];
1340 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1343 debug("failed to open file <%s> for udf check\n", args
[0]);
1347 for (i
= 16; i
< 32; i
++)
1349 grub_file_seek(file
, i
* 2048);
1350 grub_file_read(file
, buf
, sizeof(buf
));
1358 grub_file_seek(file
, i
* 2048);
1359 grub_file_read(file
, buf
, sizeof(buf
));
1361 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1364 grub_file_seek(file
, i
* 2048);
1365 grub_file_read(file
, buf
, sizeof(buf
));
1367 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1368 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1374 grub_file_close(file
);
1376 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1381 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1383 long value_long1
= 0;
1384 long value_long2
= 0;
1386 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1388 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1391 value_long1
= grub_strtol(args
[0], NULL
, 10);
1392 value_long2
= grub_strtol(args
[2], NULL
, 10);
1394 if (0 == grub_strcmp(args
[1], "eq"))
1396 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1398 else if (0 == grub_strcmp(args
[1], "ne"))
1400 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1402 else if (0 == grub_strcmp(args
[1], "gt"))
1404 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1406 else if (0 == grub_strcmp(args
[1], "lt"))
1408 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1410 else if (0 == grub_strcmp(args
[1], "ge"))
1412 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1414 else if (0 == grub_strcmp(args
[1], "le"))
1416 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1420 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1426 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1429 char buf
[128] = {0};
1433 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1436 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1437 pos
= grub_strstr(buf
, ",");
1443 grub_env_set(args
[1], buf
);
1445 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1448 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1454 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1460 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1463 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1465 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1466 if (0 == grub_script_execute_sourcecode(buf
))
1468 debug("file %s exist, ventoy_compatible YES\n", buf
);
1469 grub_env_set("ventoy_compatible", "YES");
1470 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1474 debug("file %s NOT exist\n", buf
);
1478 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1479 pos
= grub_strstr(buf
, ")");
1485 disk
= grub_disk_open(buf
);
1488 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1489 grub_disk_close(disk
);
1491 g_img_swap_tmp_buf
[703] = 0;
1492 for (i
= 318; i
< 703; i
++)
1494 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1495 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1497 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1498 grub_env_set("ventoy_compatible", "YES");
1499 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1505 debug("failed to open disk <%s>\n", buf
);
1508 grub_env_set("ventoy_compatible", "NO");
1509 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1512 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1518 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1520 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1523 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1528 if (0 == g_sort_case_sensitive
)
1530 if (grub_islower(c1
))
1532 c1
= c1
- 'a' + 'A';
1535 if (grub_islower(c2
))
1537 c2
= c2
- 'a' + 'A';
1550 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1556 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1558 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1561 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1566 if (0 == g_sort_case_sensitive
)
1568 if (grub_islower(c1
))
1570 c1
= c1
- 'a' + 'A';
1573 if (grub_islower(c2
))
1575 c2
= c2
- 'a' + 'A';
1588 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1590 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1592 grub_memcpy(img1
, img2
, sizeof(img_info
));
1593 img1
->next
= g_img_swap_tmp
.next
;
1594 img1
->prev
= g_img_swap_tmp
.prev
;
1596 g_img_swap_tmp
.next
= img2
->next
;
1597 g_img_swap_tmp
.prev
= img2
->prev
;
1598 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1601 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1605 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1613 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1622 const menu_tip
*tip
;
1623 img_iterator_node
*tmp
;
1624 img_iterator_node
*new_node
;
1625 img_iterator_node
*node
= (img_iterator_node
*)data
;
1627 if (g_enumerate_time_checked
== 0)
1629 g_enumerate_finish_time_ms
= grub_get_time_ms();
1630 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1633 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1635 g_enumerate_time_checked
= 1;
1639 len
= grub_strlen(filename
);
1643 if (node
->level
+ 1 > g_img_max_search_level
)
1648 if ((len
== 1 && filename
[0] == '.') ||
1649 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1654 if (!ventoy_img_name_valid(filename
, len
))
1659 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1664 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1666 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1667 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1670 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1675 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1678 new_node
->level
= node
->level
+ 1;
1679 new_node
->plugin_list_index
= index
;
1680 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1682 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1685 debug("Directory %s ignored...\n", new_node
->dir
);
1686 grub_free(new_node
);
1690 new_node
->tail
= node
->tail
;
1692 new_node
->parent
= node
;
1693 if (!node
->firstchild
)
1695 node
->firstchild
= new_node
;
1698 if (g_img_iterator_tail
)
1700 g_img_iterator_tail
->next
= new_node
;
1701 g_img_iterator_tail
= new_node
;
1705 g_img_iterator_head
.next
= new_node
;
1706 g_img_iterator_tail
= new_node
;
1712 debug("Find a file %s\n", filename
);
1718 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1720 type
= img_type_iso
;
1722 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1724 type
= img_type_wim
;
1726 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1727 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1729 type
= img_type_vhd
;
1731 #ifdef GRUB_MACHINE_EFI
1732 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1734 type
= img_type_efi
;
1737 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1739 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1741 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1742 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1747 type
= img_type_img
;
1749 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1751 type
= img_type_vtoy
;
1753 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1755 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1757 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1758 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1767 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1772 if (g_plugin_image_list
)
1774 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1775 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1776 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1778 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1781 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1783 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1788 img
= grub_zalloc(sizeof(img_info
));
1792 img
->plugin_list_index
= index
;
1793 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1795 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1797 img
->size
= info
->size
;
1800 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1803 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1805 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1810 if (g_ventoy_img_list
)
1812 tail
= *(node
->tail
);
1818 g_ventoy_img_list
= img
;
1821 img
->id
= g_ventoy_img_count
;
1823 if (node
&& NULL
== node
->firstiso
)
1825 node
->firstiso
= img
;
1836 *((img_info
**)(node
->tail
)) = img
;
1837 g_ventoy_img_count
++;
1839 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1841 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
1844 img
->tip1
= tip
->tip1
;
1845 img
->tip2
= tip
->tip2
;
1848 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1851 img
->class = g_menu_class
[type
];
1853 img
->menu_prefix
= g_menu_prefix
[type
];
1855 if (img_type_iso
== type
)
1857 if (ventoy_plugin_check_memdisk(img
->path
))
1859 img
->menu_prefix
= "miso";
1863 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1870 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1872 int len
= GRUB_UINT_MAX
;
1873 const char *value
= NULL
;
1874 char name
[32] = {0};
1875 char plat
[32] = {0};
1876 char guidstr
[32] = {0};
1877 ventoy_guid guid
= VENTOY_GUID
;
1878 const char *fmt1
= NULL
;
1879 const char *fmt2
= NULL
;
1880 const char *fmt3
= NULL
;
1881 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1882 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1883 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1884 const char fmtcode
[]={
1885 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1886 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1887 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1888 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1889 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1890 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1893 grub_memset(name
, 0, sizeof(name
));
1894 puint
[0] = grub_swap_bytes32(0x56454e54);
1895 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1896 puint
[2] = grub_swap_bytes32(0x45525349);
1897 puint
[1] = grub_swap_bytes32(0x4f595f56);
1898 value
= ventoy_get_env(name
);
1900 grub_memset(name
, 0, sizeof(name
));
1901 puint
[1] = grub_swap_bytes32(0x5f544f50);
1902 puint
[0] = grub_swap_bytes32(0x56544c45);
1903 fmt1
= ventoy_get_env(name
);
1909 grub_memset(name
, 0, sizeof(name
));
1910 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1911 puint
[0] = grub_swap_bytes32(0x56544c45);
1912 fmt2
= ventoy_get_env(name
);
1914 grub_memset(name
, 0, sizeof(name
));
1915 puint
[1] = grub_swap_bytes32(0x5f434c52);
1916 puint
[0] = grub_swap_bytes32(0x56544c45);
1917 fmt3
= ventoy_get_env(name
);
1919 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1921 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1923 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1924 #pragma GCC diagnostic push
1925 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1926 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1927 fmt1
? fmt1
: fmtdata
,
1928 fmt2
? fmt2
: fmtdata
+ 4,
1929 value
? value
: "", plat
, guidstr
,
1930 fmt3
? fmt3
: fmtdata
+ 6);
1931 #pragma GCC diagnostic pop
1933 grub_memset(name
, 0, sizeof(name
));
1934 puint
[0] = grub_swap_bytes32(0x76746f79);
1935 puint
[2] = grub_swap_bytes32(0x656e7365);
1936 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1937 ventoy_set_env(name
, guidstr
);
1942 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1946 grub_uint8_t md5
[16];
1950 grub_memset(input
, 0, sizeof(input
));
1952 grub_printf("Enter password: ");
1955 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1957 grub_password_get(input
, 128);
1958 if (grub_strcmp(pwd
->text
, input
) == 0)
1963 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1965 grub_password_get(input
, 128);
1966 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1967 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1972 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1974 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1975 grub_password_get(input
+ offset
, 128);
1977 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1978 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1984 grub_printf("Invalid password!\n\n");
1991 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1993 img_info
*minimg
= NULL
;
1994 img_info
*img
= (img_info
*)(node
->firstiso
);
1996 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1998 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2013 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2015 img_iterator_node
*Minchild
= NULL
;
2016 img_iterator_node
*child
= node
->firstchild
;
2018 while (child
&& child
->parent
== node
)
2020 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2024 child
= child
->next
;
2029 Minchild
->select
= 1;
2035 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2038 img_info
*img
= NULL
;
2039 const char *dir_class
= NULL
;
2040 const char *dir_alias
= NULL
;
2041 img_iterator_node
*child
= NULL
;
2042 const menu_tip
*tip
= NULL
;
2044 if (node
->isocnt
== 0 || node
->done
== 1)
2049 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2051 offset
= node
->parent
->dirlen
;
2054 if (node
== &g_img_iterator_head
)
2056 if (g_default_menu_mode
== 0)
2058 if (g_tree_view_menu_style
== 0)
2060 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2061 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2062 " echo 'return ...' \n"
2067 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2068 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2076 node
->dir
[node
->dirlen
- 1] = 0;
2077 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2080 dir_class
= "vtoydir";
2083 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2085 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2088 if (g_tree_view_menu_style
== 0)
2090 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2091 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2092 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2096 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2097 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2098 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2103 dir_alias
= node
->dir
+ offset
;
2105 if (g_tree_view_menu_style
== 0)
2107 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2108 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2109 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2113 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2114 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2115 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2119 if (g_tree_view_menu_style
== 0)
2121 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2122 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2123 " echo 'return ...' \n"
2128 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2129 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2135 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2137 ventoy_dynamic_tree_menu(child
);
2140 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2142 if (g_tree_view_menu_style
== 0)
2144 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2145 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2148 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2149 img
->unsupport
? "[***********] " : "",
2150 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2152 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2156 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2157 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2160 img
->unsupport
? "[***********] " : "",
2161 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2163 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2167 if (node
!= &g_img_iterator_head
)
2169 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2176 static int ventoy_set_default_menu(void)
2182 const char *strdata
= NULL
;
2183 img_info
*cur
= NULL
;
2184 img_info
*default_node
= NULL
;
2185 const char *default_image
= NULL
;
2187 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2188 if (default_image
&& default_image
[0] == '/')
2190 img_len
= grub_strlen(default_image
);
2192 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2194 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2206 if (0 == g_default_menu_mode
)
2208 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2212 def
= grub_strdup(default_image
);
2218 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2220 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2221 if (strdata
&& strdata
[0] == '/')
2223 pos
= def
+ grub_strlen(strdata
);
2234 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2237 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2241 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2249 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2251 img_info
*next
= NULL
;
2252 img_info
*cur
= g_ventoy_img_list
;
2265 g_ventoy_img_list
= NULL
;
2266 g_ventoy_img_count
= 0;
2268 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2271 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2274 img_info
*cur
= g_ventoy_img_list
;
2278 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2280 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2283 img_id
= grub_strtol(args
[0], NULL
, 10);
2284 if (img_id
>= g_ventoy_img_count
)
2286 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2289 debug("Find image %ld name \n", img_id
);
2291 while (cur
&& img_id
> 0)
2299 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2302 debug("image name is %s\n", cur
->name
);
2304 grub_env_set(args
[1], cur
->name
);
2306 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2309 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2313 img_info
*cur
= g_ventoy_img_list
;
2319 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2322 len
= (int)grub_strlen(args
[0]);
2326 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2335 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2338 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2339 grub_env_set("chosen", id
);
2340 grub_env_export("chosen");
2342 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2345 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2349 const char *id
= NULL
;
2350 img_info
*cur
= NULL
;
2354 if (argc
< 1 || argc
> 2)
2356 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2359 id
= grub_env_get("chosen");
2361 pos
= grub_strstr(id
, "VID_");
2364 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2368 cur
= g_ventoy_img_list
;
2373 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2376 grub_env_set(args
[0], cur
->path
);
2380 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2381 grub_env_set(args
[1], value
);
2384 g_svd_replace_offset
= 0;
2386 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2390 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2394 grub_device_t dev
= NULL
;
2395 img_info
*cur
= NULL
;
2396 img_info
*tail
= NULL
;
2397 img_info
*min
= NULL
;
2398 img_info
*head
= NULL
;
2399 const char *strdata
= NULL
;
2400 char *device_name
= NULL
;
2402 img_iterator_node
*node
= NULL
;
2403 img_iterator_node
*tmp
= NULL
;
2409 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2412 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2414 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2419 g_enumerate_time_checked
= 0;
2420 g_enumerate_start_time_ms
= grub_get_time_ms();
2422 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2423 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2425 g_filt_dot_underscore_file
= 1;
2428 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2429 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2431 g_sort_case_sensitive
= 1;
2434 device_name
= grub_file_get_device_name(args
[0]);
2440 g_enum_dev
= dev
= grub_device_open(device_name
);
2446 g_enum_fs
= fs
= grub_fs_probe(dev
);
2452 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2454 debug("unsupported fs:<%s>\n", fs
->name
);
2455 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2459 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2461 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2462 if (strdata
&& strdata
[0] == '1')
2464 g_default_menu_mode
= 1;
2467 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2469 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2471 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2472 if (strdata
&& strdata
[0] == '/')
2474 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2475 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2477 g_img_iterator_head
.dir
[len
++] = '/';
2479 g_img_iterator_head
.dirlen
= len
;
2483 g_img_iterator_head
.dirlen
= 1;
2484 grub_strcpy(g_img_iterator_head
.dir
, "/");
2487 g_img_iterator_head
.tail
= &tail
;
2489 if (g_img_max_search_level
< 0)
2491 g_img_max_search_level
= GRUB_INT_MAX
;
2492 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2493 if (strdata
&& ventoy_is_decimal(strdata
))
2495 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2499 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2500 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2501 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2502 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2503 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2504 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2506 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2508 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2511 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2512 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2514 g_tree_view_menu_style
= 1;
2517 ventoy_set_default_menu();
2519 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2521 ventoy_dynamic_tree_menu(node
);
2525 node
= g_img_iterator_head
.next
;
2533 /* sort image list by image name */
2534 while (g_ventoy_img_list
)
2536 min
= g_ventoy_img_list
;
2537 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2539 if (ventoy_cmp_img(min
, cur
) > 0)
2547 min
->prev
->next
= min
->next
;
2552 min
->next
->prev
= min
->prev
;
2555 if (min
== g_ventoy_img_list
)
2557 g_ventoy_img_list
= min
->next
;
2575 g_ventoy_img_list
= head
;
2577 if (g_default_menu_mode
== 1)
2579 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2580 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2581 " echo 'return ...' \n"
2585 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2587 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2588 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2591 cur
->unsupport
? "[***********] " : "",
2592 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2594 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2597 g_tree_script_buf
[g_tree_script_pos
] = 0;
2598 g_list_script_buf
[g_list_script_pos
] = 0;
2600 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2601 grub_env_set(args
[1], buf
);
2605 check_free(device_name
, grub_free
);
2606 check_free(dev
, grub_device_close
);
2608 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2611 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2618 device_name
= grub_file_get_device_name(filename
);
2630 pos2
= grub_strstr(pos
, ",");
2633 pos2
= grub_strstr(pos
, ")");
2641 disk
= grub_disk_open(pos
);
2644 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2645 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2646 grub_disk_close(disk
);
2653 grub_free(device_name
);
2657 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2659 eltorito_descriptor desc
;
2661 grub_memset(&desc
, 0, sizeof(desc
));
2662 grub_file_seek(file
, 17 * 2048);
2663 grub_file_read(file
, &desc
, sizeof(desc
));
2665 if (desc
.type
!= 0 || desc
.version
!= 1)
2670 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2671 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2679 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2681 grub_uint8_t buf
[512];
2683 grub_file_seek(file
, sector
* 2048);
2684 grub_file_read(file
, buf
, sizeof(buf
));
2686 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2687 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2689 return *((grub_uint32_t
*)(buf
+ 40));
2695 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2699 grub_uint8_t buf
[512];
2700 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2702 grub_file_seek(file
, sector
* 2048);
2703 grub_file_read(file
, buf
, sizeof(buf
));
2705 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2707 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2711 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2716 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2718 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2720 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2724 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2726 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2731 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2733 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2735 if (buf
[36] == parttype
[i
])
2737 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2743 debug("%s does not contain efi eltorito\n", file
->name
);
2747 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2750 const char *fs
= NULL
;
2751 const char *val
= NULL
;
2752 const char *cdprompt
= NULL
;
2754 grub_uint8_t chksum
= 0;
2757 disk
= file
->device
->disk
;
2758 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2760 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2761 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2762 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2764 pos
= grub_strstr(file
->name
, "/");
2770 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2772 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2774 param
->vtoy_img_size
= file
->size
;
2776 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2777 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2779 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2781 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2782 param
->vtoy_reserved
[4] = 0;
2783 if (g_ventoy_chain_type
== 1) /* Windows */
2785 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2786 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2788 param
->vtoy_reserved
[4] = 1;
2792 fs
= ventoy_get_env("ventoy_fs_probe");
2793 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2795 param
->vtoy_reserved
[3] = 1;
2798 param
->vtoy_reserved
[5] = 0;
2799 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
2800 if (val
&& val
[0] == '1' && val
[1] == 0)
2802 param
->vtoy_reserved
[5] = 1;
2805 /* calculate checksum */
2806 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2808 chksum
+= *((grub_uint8_t
*)param
+ i
);
2810 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2815 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2817 grub_uint32_t i
= 0;
2818 grub_uint64_t total
= 0;
2819 grub_uint64_t fileblk
= 0;
2820 ventoy_img_chunk
*chunk
= NULL
;
2822 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2824 chunk
= chunklist
->chunk
+ i
;
2826 if (chunk
->disk_start_sector
<= start
)
2828 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2832 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2835 fileblk
= (file
->size
+ 511) / 512;
2837 if (total
!= fileblk
)
2839 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2840 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2842 debug("maybe img file to be processed.\n");
2852 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2856 grub_uint32_t i
= 0;
2857 grub_uint32_t sector
= 0;
2858 grub_uint32_t count
= 0;
2859 grub_off_t size
= 0;
2860 grub_off_t read
= 0;
2862 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2863 if (fs_type
== ventoy_fs_exfat
)
2865 grub_fat_get_file_chunk(start
, file
, chunklist
);
2867 else if (fs_type
== ventoy_fs_ext
)
2869 grub_ext_get_file_chunk(start
, file
, chunklist
);
2873 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2874 file
->read_hook_data
= chunklist
;
2876 for (size
= file
->size
; size
> 0; size
-= read
)
2878 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2879 grub_file_read(file
, NULL
, read
);
2882 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2884 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2885 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2888 if (ventoy_fs_udf
== fs_type
)
2890 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2892 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2893 chunklist
->chunk
[i
].img_start_sector
= sector
;
2894 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2900 len
= (int)grub_strlen(file
->name
);
2901 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2902 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2903 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2904 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2906 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2908 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2918 chunklist
->chunk
[i
].img_start_sector
= sector
;
2919 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2927 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2931 grub_disk_addr_t start
;
2936 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2939 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2942 g_conf_replace_node
= NULL
;
2943 g_conf_replace_offset
= 0;
2945 if (g_img_chunk_list
.chunk
)
2947 grub_free(g_img_chunk_list
.chunk
);
2950 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2952 grub_file_close(file
);
2953 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2956 /* get image chunk data */
2957 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2958 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2959 if (NULL
== g_img_chunk_list
.chunk
)
2961 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2964 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2965 g_img_chunk_list
.cur_chunk
= 0;
2967 start
= file
->device
->disk
->partition
->start
;
2969 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2971 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2972 grub_file_close(file
);
2976 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2979 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2980 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
2981 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2984 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2986 grub_uint64_t offset
= 0;
2987 grub_uint32_t align
= 0;
2988 grub_file_t file
= NULL
;
2989 conf_replace
*node
= NULL
;
2995 debug("select conf replace argc:%d\n", argc
);
3002 node
= ventoy_plugin_find_conf_replace(args
[1]);
3005 debug("Conf replace not found for %s\n", args
[1]);
3009 debug("Find conf replace for %s\n", args
[1]);
3011 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3014 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3015 grub_file_close(file
);
3017 else if (node
->img
> 0)
3023 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3027 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3030 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3034 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3036 if (align
> vtoy_max_replace_file_size
)
3038 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3042 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3043 g_conf_replace_new_len
= (int)file
->size
;
3044 g_conf_replace_new_len_align
= align
;
3046 g_conf_replace_node
= node
;
3047 g_conf_replace_offset
= offset
+ 2;
3051 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3052 g_grub_param
->img_replace
.old_name_cnt
= 1;
3053 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3056 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3061 grub_file_close(file
);
3063 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3066 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3072 char configfile
[128];
3073 install_template
*node
= NULL
;
3079 debug("select auto installation argc:%d\n", argc
);
3086 node
= ventoy_plugin_find_install_template(args
[0]);
3089 debug("Auto install template not found for %s\n", args
[0]);
3093 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3095 defidx
= node
->autosel
;
3096 if (node
->timeout
< 0)
3098 node
->cursel
= node
->autosel
- 1;
3099 debug("Auto install template auto select %d\n", node
->autosel
);
3104 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3110 if (node
->timeout
> 0)
3112 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3115 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3116 " echo %s\n}\n", "");
3118 for (i
= 0; i
< node
->templatenum
; i
++)
3120 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3122 node
->templatepath
[i
].path
);
3125 g_ventoy_menu_esc
= 1;
3126 g_ventoy_suppress_esc
= 1;
3127 g_ventoy_suppress_esc_default
= defidx
;
3129 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3130 grub_script_execute_sourcecode(configfile
);
3132 g_ventoy_menu_esc
= 0;
3133 g_ventoy_suppress_esc
= 0;
3134 g_ventoy_suppress_esc_default
= 1;
3138 node
->cursel
= g_ventoy_last_entry
- 1;
3140 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3143 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3149 char configfile
[128];
3150 persistence_config
*node
;
3156 debug("select persistence argc:%d\n", argc
);
3163 node
= ventoy_plugin_find_persistent(args
[0]);
3166 debug("Persistence image not found for %s\n", args
[0]);
3170 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3172 defidx
= node
->autosel
;
3173 if (node
->timeout
< 0)
3175 node
->cursel
= node
->autosel
- 1;
3176 debug("Persistence image auto select %d\n", node
->autosel
);
3181 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3187 if (node
->timeout
> 0)
3189 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3192 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3193 " echo %s\n}\n", "");
3195 for (i
= 0; i
< node
->backendnum
; i
++)
3197 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3199 node
->backendpath
[i
].path
);
3203 g_ventoy_menu_esc
= 1;
3204 g_ventoy_suppress_esc
= 1;
3205 g_ventoy_suppress_esc_default
= defidx
;
3207 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3208 grub_script_execute_sourcecode(configfile
);
3210 g_ventoy_menu_esc
= 0;
3211 g_ventoy_suppress_esc
= 0;
3212 g_ventoy_suppress_esc_default
= 1;
3216 node
->cursel
= g_ventoy_last_entry
- 1;
3218 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3221 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3224 ventoy_img_chunk
*cur
;
3230 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3232 cur
= g_img_chunk_list
.chunk
+ i
;
3233 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3234 cur
->img_start_sector
, cur
->img_end_sector
,
3235 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3239 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3242 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3246 ventoy_img_chunk_list chunklist
;
3251 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3254 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3257 /* get image chunk data */
3258 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3259 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3260 if (NULL
== chunklist
.chunk
)
3262 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3265 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3266 chunklist
.cur_chunk
= 0;
3268 ventoy_get_block_list(file
, &chunklist
, 0);
3270 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3272 grub_printf("########## UNSUPPORTED ###############\n");
3275 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3277 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3279 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3280 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3283 grub_printf("\n==================================\n");
3285 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3287 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3288 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3289 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3290 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3291 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3295 grub_free(chunklist
.chunk
);
3296 grub_file_close(file
);
3298 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3301 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3304 ventoy_grub_param_file_replace
*replace
= NULL
;
3312 replace
= &(g_grub_param
->file_replace
);
3313 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3315 replace
->old_name_cnt
= 0;
3316 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3318 replace
->old_name_cnt
++;
3319 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3322 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3325 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3328 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3331 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3337 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3338 grub_env_set(args
[0], buf
);
3341 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3344 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3352 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3353 grub_printf("%s", g_list_script_buf
);
3357 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3358 grub_printf("%s", g_tree_script_buf
);
3364 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3366 img_info
*cur
= g_ventoy_img_list
;
3374 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3375 grub_printf("name:<%s>\n\n", cur
->name
);
3382 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3388 ventoy_plugin_dump_injection();
3393 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3399 ventoy_plugin_dump_auto_install();
3404 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3410 ventoy_plugin_dump_persistence();
3415 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3426 if (args
[0][0] == '0')
3428 return g_ventoy_memdisk_mode
? 0 : 1;
3430 else if (args
[0][0] == '1')
3432 return g_ventoy_iso_raw
? 0 : 1;
3434 else if (args
[0][0] == '2')
3436 return g_ventoy_iso_uefi_drv
? 0 : 1;
3438 else if (args
[0][0] == '3')
3440 return g_ventoy_grub2_mode
? 0 : 1;
3442 else if (args
[0][0] == '4')
3444 return g_ventoy_wimboot_mode
? 0 : 1;
3450 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3452 static int configfile_mode
= 0;
3453 char memfile
[128] = {0};
3460 * args[0]: 0:normal 1:configfile
3461 * args[1]: 0:list_buf 1:tree_buf
3466 debug("Invalid argc %d\n", argc
);
3472 if (args
[0][0] == '0')
3474 if (args
[1][0] == '0')
3476 grub_script_execute_sourcecode(g_list_script_buf
);
3480 grub_script_execute_sourcecode(g_tree_script_buf
);
3485 if (configfile_mode
)
3487 debug("Now already in F3 mode %d\n", configfile_mode
);
3491 if (args
[1][0] == '0')
3493 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3494 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3498 g_ventoy_last_entry
= -1;
3499 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3500 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3503 configfile_mode
= 1;
3504 grub_script_execute_sourcecode(memfile
);
3505 configfile_mode
= 0;
3511 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3522 g_ventoy_case_insensitive
= 1;
3523 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3524 g_ventoy_case_insensitive
= 0;
3530 grub_file_close(file
);
3536 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3541 const char *isopath
= NULL
;
3543 ventoy_mbr_head mbr
;
3550 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3553 isopath
= grub_env_get("vtoy_iso_part");
3556 debug("isopath is null %p\n", isopath
);
3560 debug("isopath is %s\n", isopath
);
3562 for (id
= 0; id
< 30 && (find
== 0); id
++)
3564 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3565 if (grub_strstr(isopath
, hdname
))
3567 debug("skip %s ...\n", hdname
);
3571 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3573 disk
= grub_disk_open(hdname
);
3576 debug("%s not exist\n", hdname
);
3580 grub_memset(&mbr
, 0, sizeof(mbr
));
3581 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3583 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3585 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3586 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3589 grub_env_set(args
[0], hdname
);
3593 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3597 debug("read %s failed\n", hdname
);
3600 grub_disk_close(disk
);
3606 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3617 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3620 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3623 debug("failed to open file %s\n", args
[0]);
3627 buf
= grub_malloc(len
);
3634 grub_file_read(file
, buf
, len
- 1);
3636 ventoy_get_line(buf
);
3637 ventoy_set_env(args
[1], buf
);
3641 grub_check_free(buf
);
3642 grub_file_close(file
);
3647 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3649 int *pCnt
= (int *)data
;
3654 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3655 "0 %llu linear /dev/ventoy %llu\n",
3656 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3661 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3664 char *device_name
= NULL
;
3665 grub_device_t dev
= NULL
;
3670 g_part_list_pos
= 0;
3671 grub_env_unset("vtoy_img_part_file");
3678 device_name
= grub_file_get_device_name(args
[0]);
3681 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3685 dev
= grub_device_open(device_name
);
3688 debug("grub_device_open failed, %s\n", device_name
);
3692 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3694 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3695 grub_env_set("vtoy_img_part_file", buf
);
3697 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3698 grub_env_set("vtoy_img_part_cnt", buf
);
3702 check_free(device_name
, grub_free
);
3703 check_free(dev
, grub_device_close
);
3709 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3720 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3723 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3726 debug("failed to open file %s\n", args
[0]);
3730 buf
= grub_malloc(file
->size
+ 1);
3736 buf
[file
->size
] = 0;
3737 grub_file_read(file
, buf
, file
->size
);
3739 if (grub_strstr(buf
, args
[1]))
3746 grub_check_free(buf
);
3747 grub_file_close(file
);
3752 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3758 ventoy_iso9660_vd pvd
;
3765 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3768 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3771 debug("failed to open file %s\n", args
[0]);
3775 grub_file_seek(file
, 16 * 2048);
3776 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3777 if (len
!= sizeof(pvd
))
3779 debug("failed to read pvd %d\n", len
);
3783 grub_memset(buf
, 0, sizeof(buf
));
3784 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3785 ventoy_set_env(args
[1], buf
);
3787 grub_memset(buf
, 0, sizeof(buf
));
3788 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3789 ventoy_set_env(args
[2], buf
);
3793 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3794 ventoy_set_env(args
[3], buf
);
3797 grub_file_close(file
);
3802 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3813 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3816 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3819 debug("failed to open file %s\n", args
[0]);
3823 grub_memset(buf
, 0, sizeof(buf
));
3824 grub_file_seek(file
, 16 * 2048 + 813);
3825 len
= (int)grub_file_read(file
, buf
, 17);
3828 debug("failed to read create date %d\n", len
);
3832 ventoy_set_env(args
[1], buf
);
3835 grub_file_close(file
);
3840 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3846 ventoy_env_hook_root(1);
3851 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3857 ventoy_env_hook_root(0);
3862 #ifdef GRUB_MACHINE_EFI
3863 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3868 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3874 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3875 if (var
&& *var
== 1)
3883 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3892 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3897 grub_uint64_t FileSectors
= 0;
3898 ventoy_gpt_info
*gpt
= NULL
;
3899 ventoy_part_table
*pt
= NULL
;
3900 grub_uint8_t zeroguid
[16] = {0};
3905 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3908 debug("failed to open file %s\n", args
[0]);
3912 if (file
->size
% 512)
3914 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3918 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3924 FileSectors
= file
->size
/ 512;
3926 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3927 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3929 debug("This is EFI partition table\n");
3931 for (i
= 0; i
< 128; i
++)
3933 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3935 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3937 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3938 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3946 debug("This is MBR partition table\n");
3948 for (i
= 0; i
< 4; i
++)
3950 pt
= gpt
->MBR
.PartTbl
+ i
;
3951 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3953 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3954 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3955 (ulonglong
)FileSectors
);
3964 grub_file_close(file
);
3965 grub_check_free(gpt
);
3966 grub_errno
= GRUB_ERR_NONE
;
3970 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3979 for (i
= 0; i
< 500; i
++)
3981 ret
= grub_getkey_noblock();
3982 if (ret
== GRUB_TERM_NO_KEY
)
3991 grub_printf("\n\n Still have key input after clear.\n");
3999 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4006 int image_sector_size
;
4008 ventoy_chain_head
*chain
;
4009 ventoy_img_chunk
*chunk
;
4010 ventoy_os_param
*osparam
;
4011 ventoy_image_location
*location
;
4012 ventoy_image_disk_region
*region
;
4013 struct grub_acpi_table_header
*acpi
;
4022 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4024 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4030 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4032 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4034 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4038 img_chunk_num
= chain
->img_chunk_num
;
4040 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4041 datalen
= sizeof(ventoy_os_param
) + loclen
;
4043 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4044 acpi
= grub_zalloc(buflen
);
4050 /* Step1: Fill acpi table header */
4051 grub_memcpy(acpi
->signature
, "VTOY", 4);
4052 acpi
->length
= buflen
;
4054 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4055 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4057 acpi
->creator_id
[0] = 1;
4058 acpi
->creator_rev
= 1;
4060 /* Step2: Fill data */
4061 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4062 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4063 osparam
->vtoy_img_location_addr
= 0;
4064 osparam
->vtoy_img_location_len
= loclen
;
4065 osparam
->chksum
= 0;
4066 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4068 location
= (ventoy_image_location
*)(osparam
+ 1);
4069 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4070 location
->image_sector_size
= image_sector_size
;
4071 location
->disk_sector_size
= chain
->disk_sector_size
;
4072 location
->region_count
= img_chunk_num
;
4074 region
= location
->regions
;
4075 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4076 if (512 == image_sector_size
)
4078 for (i
= 0; i
< img_chunk_num
; i
++)
4080 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4081 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4082 region
->disk_start_sector
= chunk
->disk_start_sector
;
4089 for (i
= 0; i
< img_chunk_num
; i
++)
4091 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4092 region
->image_start_sector
= chunk
->img_start_sector
;
4093 region
->disk_start_sector
= chunk
->disk_start_sector
;
4099 /* Step3: Fill acpi checksum */
4101 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4103 /* load acpi table */
4104 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4105 grub_script_execute_sourcecode(cmd
);
4109 VENTOY_CMD_RETURN(0);
4112 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4118 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4119 g_ventoy_last_entry
= -1;
4124 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4130 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4135 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4137 const char *pos
= filename
+ 1;
4145 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4147 grub_strncpy((char *)data
, filename
, 128);
4158 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4161 char *device_name
= NULL
;
4162 grub_device_t dev
= NULL
;
4163 grub_fs_t fs
= NULL
;
4164 char buf
[128] = {0};
4170 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4174 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4176 device_name
= grub_file_get_device_name(args
[0]);
4179 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4183 dev
= grub_device_open(device_name
);
4186 debug("grub_device_open failed, %s\n", device_name
);
4190 fs
= grub_fs_probe(dev
);
4193 debug("grub_fs_probe failed, %s\n", device_name
);
4197 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4201 ventoy_set_env(args
[2], buf
);
4208 check_free(device_name
, grub_free
);
4209 check_free(dev
, grub_device_close
);
4214 int ventoy_load_part_table(const char *diskname
)
4221 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4222 if (!g_ventoy_part_info
)
4227 disk
= grub_disk_open(diskname
);
4230 debug("Failed to open disk %s\n", diskname
);
4234 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4236 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4237 grub_disk_close(disk
);
4239 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4240 dev
= grub_device_open(name
);
4243 /* Check for official Ventoy device */
4244 ret
= ventoy_check_official_device(dev
);
4245 grub_device_close(dev
);
4253 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4254 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4259 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4266 ret
= ventoy_load_part_table(args
[0]);
4272 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4273 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4278 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4281 const char *vcfg
= NULL
;
4286 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4289 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4290 grub_env_set(args
[1], vcfg
);
4295 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4303 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4306 grub_uint8_t zeroguid
[16] = {0};
4311 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4314 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4316 if (id
>= 1 && id
<= 128)
4318 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4326 if (id
>= 1 && id
<= 4)
4328 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4338 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4341 char *device_name
= NULL
;
4342 grub_device_t dev
= NULL
;
4343 grub_fs_t fs
= NULL
;
4348 debug("get fs label for %s\n", args
[0]);
4352 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4356 device_name
= grub_file_get_device_name(args
[0]);
4359 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4363 dev
= grub_device_open(device_name
);
4366 debug("grub_device_open failed, %s\n", device_name
);
4370 fs
= grub_fs_probe(dev
);
4371 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4373 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4377 fs
->fs_label(dev
, &label
);
4380 debug("label=<%s>\n", label
);
4381 ventoy_set_env(args
[1], label
);
4389 check_free(device_name
, grub_free
);
4390 check_free(dev
, grub_device_close
);
4395 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4399 grub_snprintf((char *)data
, 256, "%s", filename
);
4406 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4408 if (info
->dir
&& filename
&& filename
[0] != '.')
4410 grub_snprintf((char *)data
, 256, "%s", filename
);
4417 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4420 char *device_name
= NULL
;
4421 grub_device_t dev
= NULL
;
4422 grub_fs_t fs
= NULL
;
4423 char name
[256] ={0};
4427 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4431 device_name
= grub_file_get_device_name(args
[0]);
4434 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4438 dev
= grub_device_open(device_name
);
4441 debug("grub_device_open failed, %s\n", device_name
);
4445 fs
= grub_fs_probe(dev
);
4448 debug("grub_fs_probe failed, %s\n", device_name
);
4452 fs
->fs_dir(dev
, args
[1], hook
, name
);
4455 ventoy_set_env(args
[2], name
);
4462 check_free(device_name
, grub_free
);
4463 check_free(dev
, grub_device_close
);
4468 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4471 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4474 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4477 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4480 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4490 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4494 for (pos
= args
[0]; *pos
; pos
++)
4508 grub_env_set(args
[1], args
[0]);
4518 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4528 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4533 len
= (int)grub_strlen(buf
);
4534 for (i
= len
; i
> 0; i
--)
4536 if (buf
[i
- 1] == '/')
4538 grub_env_set(args
[1], buf
+ i
);
4543 grub_env_set(args
[1], buf
);
4548 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4550 struct grub_video_mode_info info
;
4557 if (!g_video_mode_list
)
4559 ventoy_enum_video_mode();
4562 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4564 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4568 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4571 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4573 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4574 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4576 VENTOY_CMD_RETURN(0);
4579 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4581 struct grub_video_mode_info info
;
4588 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4590 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4594 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4597 grub_env_set(args
[0], buf
);
4599 VENTOY_CMD_RETURN(0);
4602 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4610 if (!g_video_mode_list
)
4615 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4616 if (id
< g_video_mode_num
)
4618 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4619 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4622 grub_env_set(args
[1], buf
);
4624 VENTOY_CMD_RETURN(0);
4627 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4630 grub_uint32_t loadsector
= 0;
4633 grub_uint32_t boot_catlog
= 0;
4634 grub_uint8_t buf
[512];
4640 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4644 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4647 debug("failed to open %s\n", args
[0]);
4651 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4652 if (boot_catlog
== 0)
4654 debug("No bootcatlog found\n");
4655 grub_file_close(file
);
4659 grub_memset(buf
, 0, sizeof(buf
));
4660 grub_file_seek(file
, boot_catlog
* 2048);
4661 grub_file_read(file
, buf
, sizeof(buf
));
4662 grub_file_close(file
);
4664 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4666 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4668 if (buf
[i
+ 32] == 0x88)
4670 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4671 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4677 if (loadsector
== 0)
4679 debug("No EFI eltorito info found\n");
4683 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4684 grub_env_set(args
[1], value
);
4685 VENTOY_CMD_RETURN(0);
4688 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4693 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4695 if (pfsdir
->initrd
[0])
4700 curpos
= pfsdir
->curpos
;
4701 len
= grub_strlen(filename
);
4705 if ((len
== 1 && filename
[0] == '.') ||
4706 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4711 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4714 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4715 pfsdir
->curpos
= curpos
+ printlen
;
4716 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4717 pfsdir
->curpos
= curpos
;
4718 pfsdir
->fullpath
[curpos
] = 0;
4722 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4725 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4726 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4728 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4730 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4739 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4743 char *device_name
= NULL
;
4744 grub_device_t dev
= NULL
;
4745 grub_fs_t fs
= NULL
;
4746 replace_fs_dir
*pfsdir
= NULL
;
4752 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4756 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4762 device_name
= grub_file_get_device_name(args
[0]);
4768 dev
= grub_device_open(device_name
);
4774 fs
= grub_fs_probe(dev
);
4783 pfsdir
->fullpath
[0] = '/';
4784 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4786 if (pfsdir
->initrd
[0])
4788 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4790 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4792 if (pfsdir
->initrd
[i
] == '/')
4794 pfsdir
->initrd
[i
] = '\\';
4798 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4799 grub_env_set(args
[1], pos
);
4803 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4808 grub_check_free(pfsdir
);
4809 grub_check_free(device_name
);
4810 check_free(dev
, grub_device_close
);
4812 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4815 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4817 const char *pager
= NULL
;
4823 pager
= grub_env_get("pager");
4827 grub_env_set("pager", "1");
4829 else if (pager
[0] == '1')
4835 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4837 grub_env_set("pager", "1");
4840 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4843 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4849 if (g_pager_flag
== 1)
4851 grub_env_unset("pager");
4853 else if (g_pager_flag
== 2)
4855 grub_env_set("pager", g_old_pager
);
4858 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4861 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4863 if (g_json_case_mis_path
[0])
4868 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
4870 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4876 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4879 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4881 if (g_json_case_mis_path
[0])
4886 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4888 if (grub_strcasecmp(filename
, "ventoy") == 0)
4890 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4891 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4892 if (g_json_case_mis_path
[0])
4902 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4905 char *device_name
= NULL
;
4906 grub_device_t dev
= NULL
;
4907 grub_fs_t fs
= NULL
;
4908 chk_case_fs_dir fs_dir
;
4914 device_name
= grub_file_get_device_name(args
[0]);
4920 dev
= grub_device_open(device_name
);
4926 fs
= grub_fs_probe(dev
);
4932 fstype
= ventoy_get_fs_type(fs
->name
);
4933 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4938 g_json_case_mis_path
[0] = 0;
4941 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4943 if (g_json_case_mis_path
[0])
4945 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4950 grub_check_free(device_name
);
4951 check_free(dev
, grub_device_close
);
4953 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4956 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4959 grub_partition_t part
;
4960 char priority_str
[3]; /* Maximum value 15 */
4964 if (argc
< 2 || argc
> 3)
4965 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4966 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4968 /* Open the disk if it exists */
4969 disk
= grub_disk_open (args
[0]);
4972 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4976 part
= grub_partition_probe (disk
, args
[1]);
4979 grub_disk_close (disk
);
4980 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4981 "No such partition");
4984 if (grub_strcmp (part
->partmap
->name
, "gpt"))
4986 grub_disk_close (disk
);
4987 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
4988 "Not a GPT partition");
4991 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
4992 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
4996 grub_env_set (args
[2], priority_str
);
4997 grub_env_export (args
[2]);
5001 grub_printf ("Priority is %s\n", priority_str
);
5004 grub_disk_close (disk
);
5005 return GRUB_ERR_NONE
;
5009 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5013 grub_file_t file
= NULL
;
5014 grub_uint32_t loadrba
= 0;
5015 grub_uint32_t boot_catlog
= 0;
5016 grub_uint8_t sector
[512];
5017 boot_info_table
*info
= NULL
;
5022 /* This also trigger a iso9660 fs parse */
5023 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5028 joliet
= grub_iso9660_is_joliet();
5034 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5037 debug("failed to open %s\n", args
[0]);
5041 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5042 if (boot_catlog
== 0)
5044 debug("no bootcatlog found %u\n", boot_catlog
);
5048 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5051 debug("no bios eltorito rba found %u\n", loadrba
);
5055 grub_file_seek(file
, loadrba
* 2048);
5056 grub_file_read(file
, sector
, 512);
5058 info
= (boot_info_table
*)sector
;
5059 if (info
->bi_data0
== 0x7c6ceafa &&
5060 info
->bi_data1
== 0x90900000 &&
5061 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5062 info
->bi_BootFileLocation
== loadrba
)
5064 debug("bootloader is syslinux, %u.\n", loadrba
);
5070 grub_file_close(file
);
5071 grub_errno
= GRUB_ERR_NONE
;
5075 int ventoy_env_init(void)
5079 grub_env_set("vtdebug_flag", "");
5081 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5082 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5083 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5084 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5086 ventoy_filt_register(0, ventoy_wrapper_open
);
5088 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5091 g_grub_param
->grub_env_get
= grub_env_get
;
5092 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5093 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5094 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5095 grub_env_set("env_param", buf
);
5096 grub_env_set("ventoy_env_param", buf
);
5098 grub_env_export("env_param");
5099 grub_env_export("ventoy_env_param");
5102 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5103 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5105 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5106 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5108 grub_env_export("vtoy_winpeshl_ini_addr");
5109 grub_env_export("vtoy_winpeshl_ini_size");
5111 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5112 grub_env_set("vtoy_chain_file_size", buf
);
5113 grub_env_export("vtoy_chain_file_size");
5115 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5116 grub_env_set("vtoy_chain_file_read", buf
);
5117 grub_env_export("vtoy_chain_file_read");
5124 static cmd_para ventoy_cmds
[] =
5126 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5127 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5128 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5129 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5130 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5131 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5132 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5133 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5134 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5135 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5136 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5137 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5138 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5139 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5140 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5141 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5142 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5143 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5144 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5145 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5146 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5147 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5148 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5149 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5150 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5152 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5153 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5154 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5155 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5156 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5157 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5158 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5160 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5161 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5162 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5163 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5164 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5165 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5166 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5167 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5168 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5169 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5172 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5173 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5174 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5175 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5176 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5177 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5178 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5179 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5180 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5181 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5182 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5184 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5185 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5186 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5187 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5188 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5189 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5190 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5192 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5193 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5194 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5195 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5196 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5197 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5198 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5199 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5200 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5201 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5203 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5204 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5205 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5206 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5207 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5208 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5209 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5210 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5211 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5213 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5214 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5215 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5216 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5219 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5220 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5221 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5223 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5224 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5225 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5228 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5229 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5230 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5231 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5232 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5233 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5234 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5235 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5236 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5237 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5238 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5239 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5241 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5242 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5243 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5244 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5245 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5246 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5247 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5248 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5249 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5250 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5251 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5252 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5254 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5255 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5256 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5257 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5258 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5259 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5260 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5261 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5264 int ventoy_register_all_cmd(void)
5267 cmd_para
*cur
= NULL
;
5269 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5271 cur
= ventoy_cmds
+ i
;
5272 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5273 cur
->summary
, cur
->description
, cur
->parser
);
5279 int ventoy_unregister_all_cmd(void)
5283 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5285 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);