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 *cdprompt
= NULL
;
2753 grub_uint8_t chksum
= 0;
2756 disk
= file
->device
->disk
;
2757 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2759 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2760 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2761 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2763 pos
= grub_strstr(file
->name
, "/");
2769 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2771 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2773 param
->vtoy_img_size
= file
->size
;
2775 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2776 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2778 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2780 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2781 param
->vtoy_reserved
[4] = 0;
2782 if (g_ventoy_chain_type
== 1) /* Windows */
2784 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2785 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2787 param
->vtoy_reserved
[4] = 1;
2791 fs
= ventoy_get_env("ventoy_fs_probe");
2792 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2794 param
->vtoy_reserved
[3] = 1;
2797 /* calculate checksum */
2798 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2800 chksum
+= *((grub_uint8_t
*)param
+ i
);
2802 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2807 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2809 grub_uint32_t i
= 0;
2810 grub_uint64_t total
= 0;
2811 grub_uint64_t fileblk
= 0;
2812 ventoy_img_chunk
*chunk
= NULL
;
2814 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2816 chunk
= chunklist
->chunk
+ i
;
2818 if (chunk
->disk_start_sector
<= start
)
2820 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2824 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2827 fileblk
= (file
->size
+ 511) / 512;
2829 if (total
!= fileblk
)
2831 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2832 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2834 debug("maybe img file to be processed.\n");
2844 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2848 grub_uint32_t i
= 0;
2849 grub_uint32_t sector
= 0;
2850 grub_uint32_t count
= 0;
2851 grub_off_t size
= 0;
2852 grub_off_t read
= 0;
2854 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2855 if (fs_type
== ventoy_fs_exfat
)
2857 grub_fat_get_file_chunk(start
, file
, chunklist
);
2859 else if (fs_type
== ventoy_fs_ext
)
2861 grub_ext_get_file_chunk(start
, file
, chunklist
);
2865 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2866 file
->read_hook_data
= chunklist
;
2868 for (size
= file
->size
; size
> 0; size
-= read
)
2870 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2871 grub_file_read(file
, NULL
, read
);
2874 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2876 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2877 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2880 if (ventoy_fs_udf
== fs_type
)
2882 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2884 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2885 chunklist
->chunk
[i
].img_start_sector
= sector
;
2886 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2892 len
= (int)grub_strlen(file
->name
);
2893 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2894 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2895 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2896 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2898 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2900 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2910 chunklist
->chunk
[i
].img_start_sector
= sector
;
2911 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2919 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2923 grub_disk_addr_t start
;
2928 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2931 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2934 g_conf_replace_node
= NULL
;
2935 g_conf_replace_offset
= 0;
2937 if (g_img_chunk_list
.chunk
)
2939 grub_free(g_img_chunk_list
.chunk
);
2942 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2944 grub_file_close(file
);
2945 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2948 /* get image chunk data */
2949 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2950 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2951 if (NULL
== g_img_chunk_list
.chunk
)
2953 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2956 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2957 g_img_chunk_list
.cur_chunk
= 0;
2959 start
= file
->device
->disk
->partition
->start
;
2961 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2963 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2964 grub_file_close(file
);
2968 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2971 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2972 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
2973 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2976 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2978 grub_uint64_t offset
= 0;
2979 grub_uint32_t align
= 0;
2980 grub_file_t file
= NULL
;
2981 conf_replace
*node
= NULL
;
2987 debug("select conf replace argc:%d\n", argc
);
2994 node
= ventoy_plugin_find_conf_replace(args
[1]);
2997 debug("Conf replace not found for %s\n", args
[1]);
3001 debug("Find conf replace for %s\n", args
[1]);
3003 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3006 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3007 grub_file_close(file
);
3009 else if (node
->img
> 0)
3015 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3019 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3022 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3026 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3028 if (align
> vtoy_max_replace_file_size
)
3030 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3034 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3035 g_conf_replace_new_len
= (int)file
->size
;
3036 g_conf_replace_new_len_align
= align
;
3038 g_conf_replace_node
= node
;
3039 g_conf_replace_offset
= offset
+ 2;
3043 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3044 g_grub_param
->img_replace
.old_name_cnt
= 1;
3045 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3048 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3053 grub_file_close(file
);
3055 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3058 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3064 char configfile
[128];
3065 install_template
*node
= NULL
;
3071 debug("select auto installation argc:%d\n", argc
);
3078 node
= ventoy_plugin_find_install_template(args
[0]);
3081 debug("Auto install template not found for %s\n", args
[0]);
3085 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3087 defidx
= node
->autosel
;
3088 if (node
->timeout
< 0)
3090 node
->cursel
= node
->autosel
- 1;
3091 debug("Auto install template auto select %d\n", node
->autosel
);
3096 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3102 if (node
->timeout
> 0)
3104 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3107 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3108 " echo %s\n}\n", "");
3110 for (i
= 0; i
< node
->templatenum
; i
++)
3112 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3114 node
->templatepath
[i
].path
);
3117 g_ventoy_menu_esc
= 1;
3118 g_ventoy_suppress_esc
= 1;
3119 g_ventoy_suppress_esc_default
= defidx
;
3121 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3122 grub_script_execute_sourcecode(configfile
);
3124 g_ventoy_menu_esc
= 0;
3125 g_ventoy_suppress_esc
= 0;
3126 g_ventoy_suppress_esc_default
= 1;
3130 node
->cursel
= g_ventoy_last_entry
- 1;
3132 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3135 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3141 char configfile
[128];
3142 persistence_config
*node
;
3148 debug("select persistence argc:%d\n", argc
);
3155 node
= ventoy_plugin_find_persistent(args
[0]);
3158 debug("Persistence image not found for %s\n", args
[0]);
3162 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3164 defidx
= node
->autosel
;
3165 if (node
->timeout
< 0)
3167 node
->cursel
= node
->autosel
- 1;
3168 debug("Persistence image auto select %d\n", node
->autosel
);
3173 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3179 if (node
->timeout
> 0)
3181 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3184 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3185 " echo %s\n}\n", "");
3187 for (i
= 0; i
< node
->backendnum
; i
++)
3189 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3191 node
->backendpath
[i
].path
);
3195 g_ventoy_menu_esc
= 1;
3196 g_ventoy_suppress_esc
= 1;
3197 g_ventoy_suppress_esc_default
= defidx
;
3199 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3200 grub_script_execute_sourcecode(configfile
);
3202 g_ventoy_menu_esc
= 0;
3203 g_ventoy_suppress_esc
= 0;
3204 g_ventoy_suppress_esc_default
= 1;
3208 node
->cursel
= g_ventoy_last_entry
- 1;
3210 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3213 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3216 ventoy_img_chunk
*cur
;
3222 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3224 cur
= g_img_chunk_list
.chunk
+ i
;
3225 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3226 cur
->img_start_sector
, cur
->img_end_sector
,
3227 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3231 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3234 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3238 ventoy_img_chunk_list chunklist
;
3243 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3246 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3249 /* get image chunk data */
3250 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3251 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3252 if (NULL
== chunklist
.chunk
)
3254 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3257 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3258 chunklist
.cur_chunk
= 0;
3260 ventoy_get_block_list(file
, &chunklist
, 0);
3262 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3264 grub_printf("########## UNSUPPORTED ###############\n");
3267 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3269 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3271 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3272 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3275 grub_printf("\n==================================\n");
3277 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3279 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3280 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3281 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3282 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3283 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3287 grub_free(chunklist
.chunk
);
3288 grub_file_close(file
);
3290 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3293 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3296 ventoy_grub_param_file_replace
*replace
= NULL
;
3304 replace
= &(g_grub_param
->file_replace
);
3305 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3307 replace
->old_name_cnt
= 0;
3308 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3310 replace
->old_name_cnt
++;
3311 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3314 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3317 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3320 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3323 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3329 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3330 grub_env_set(args
[0], buf
);
3333 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3336 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3344 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3345 grub_printf("%s", g_list_script_buf
);
3349 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3350 grub_printf("%s", g_tree_script_buf
);
3356 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3358 img_info
*cur
= g_ventoy_img_list
;
3366 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3367 grub_printf("name:<%s>\n\n", cur
->name
);
3374 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3380 ventoy_plugin_dump_injection();
3385 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3391 ventoy_plugin_dump_auto_install();
3396 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3402 ventoy_plugin_dump_persistence();
3407 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3418 if (args
[0][0] == '0')
3420 return g_ventoy_memdisk_mode
? 0 : 1;
3422 else if (args
[0][0] == '1')
3424 return g_ventoy_iso_raw
? 0 : 1;
3426 else if (args
[0][0] == '2')
3428 return g_ventoy_iso_uefi_drv
? 0 : 1;
3430 else if (args
[0][0] == '3')
3432 return g_ventoy_grub2_mode
? 0 : 1;
3434 else if (args
[0][0] == '4')
3436 return g_ventoy_wimboot_mode
? 0 : 1;
3442 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3444 static int configfile_mode
= 0;
3445 char memfile
[128] = {0};
3452 * args[0]: 0:normal 1:configfile
3453 * args[1]: 0:list_buf 1:tree_buf
3458 debug("Invalid argc %d\n", argc
);
3464 if (args
[0][0] == '0')
3466 if (args
[1][0] == '0')
3468 grub_script_execute_sourcecode(g_list_script_buf
);
3472 grub_script_execute_sourcecode(g_tree_script_buf
);
3477 if (configfile_mode
)
3479 debug("Now already in F3 mode %d\n", configfile_mode
);
3483 if (args
[1][0] == '0')
3485 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3486 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3490 g_ventoy_last_entry
= -1;
3491 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3492 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3495 configfile_mode
= 1;
3496 grub_script_execute_sourcecode(memfile
);
3497 configfile_mode
= 0;
3503 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3514 g_ventoy_case_insensitive
= 1;
3515 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3516 g_ventoy_case_insensitive
= 0;
3522 grub_file_close(file
);
3528 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3533 const char *isopath
= NULL
;
3535 ventoy_mbr_head mbr
;
3542 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3545 isopath
= grub_env_get("vtoy_iso_part");
3548 debug("isopath is null %p\n", isopath
);
3552 debug("isopath is %s\n", isopath
);
3554 for (id
= 0; id
< 30 && (find
== 0); id
++)
3556 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3557 if (grub_strstr(isopath
, hdname
))
3559 debug("skip %s ...\n", hdname
);
3563 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3565 disk
= grub_disk_open(hdname
);
3568 debug("%s not exist\n", hdname
);
3572 grub_memset(&mbr
, 0, sizeof(mbr
));
3573 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3575 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3577 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3578 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3581 grub_env_set(args
[0], hdname
);
3585 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3589 debug("read %s failed\n", hdname
);
3592 grub_disk_close(disk
);
3598 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3609 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3612 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3615 debug("failed to open file %s\n", args
[0]);
3619 buf
= grub_malloc(len
);
3626 grub_file_read(file
, buf
, len
- 1);
3628 ventoy_get_line(buf
);
3629 ventoy_set_env(args
[1], buf
);
3633 grub_check_free(buf
);
3634 grub_file_close(file
);
3639 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3641 int *pCnt
= (int *)data
;
3646 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3647 "0 %llu linear /dev/ventoy %llu\n",
3648 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3653 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3656 char *device_name
= NULL
;
3657 grub_device_t dev
= NULL
;
3662 g_part_list_pos
= 0;
3663 grub_env_unset("vtoy_img_part_file");
3670 device_name
= grub_file_get_device_name(args
[0]);
3673 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3677 dev
= grub_device_open(device_name
);
3680 debug("grub_device_open failed, %s\n", device_name
);
3684 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3686 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3687 grub_env_set("vtoy_img_part_file", buf
);
3689 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3690 grub_env_set("vtoy_img_part_cnt", buf
);
3694 check_free(device_name
, grub_free
);
3695 check_free(dev
, grub_device_close
);
3701 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3712 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3715 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3718 debug("failed to open file %s\n", args
[0]);
3722 buf
= grub_malloc(file
->size
+ 1);
3728 buf
[file
->size
] = 0;
3729 grub_file_read(file
, buf
, file
->size
);
3731 if (grub_strstr(buf
, args
[1]))
3738 grub_check_free(buf
);
3739 grub_file_close(file
);
3744 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3750 ventoy_iso9660_vd pvd
;
3757 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3760 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3763 debug("failed to open file %s\n", args
[0]);
3767 grub_file_seek(file
, 16 * 2048);
3768 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3769 if (len
!= sizeof(pvd
))
3771 debug("failed to read pvd %d\n", len
);
3775 grub_memset(buf
, 0, sizeof(buf
));
3776 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3777 ventoy_set_env(args
[1], buf
);
3779 grub_memset(buf
, 0, sizeof(buf
));
3780 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3781 ventoy_set_env(args
[2], buf
);
3785 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3786 ventoy_set_env(args
[3], buf
);
3789 grub_file_close(file
);
3794 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3805 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3808 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3811 debug("failed to open file %s\n", args
[0]);
3815 grub_memset(buf
, 0, sizeof(buf
));
3816 grub_file_seek(file
, 16 * 2048 + 813);
3817 len
= (int)grub_file_read(file
, buf
, 17);
3820 debug("failed to read create date %d\n", len
);
3824 ventoy_set_env(args
[1], buf
);
3827 grub_file_close(file
);
3832 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3838 ventoy_env_hook_root(1);
3843 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3849 ventoy_env_hook_root(0);
3854 #ifdef GRUB_MACHINE_EFI
3855 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3860 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3866 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3867 if (var
&& *var
== 1)
3875 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3884 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3889 grub_uint64_t FileSectors
= 0;
3890 ventoy_gpt_info
*gpt
= NULL
;
3891 ventoy_part_table
*pt
= NULL
;
3892 grub_uint8_t zeroguid
[16] = {0};
3897 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3900 debug("failed to open file %s\n", args
[0]);
3904 if (file
->size
% 512)
3906 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3910 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3916 FileSectors
= file
->size
/ 512;
3918 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3919 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3921 debug("This is EFI partition table\n");
3923 for (i
= 0; i
< 128; i
++)
3925 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3927 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3929 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3930 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3938 debug("This is MBR partition table\n");
3940 for (i
= 0; i
< 4; i
++)
3942 pt
= gpt
->MBR
.PartTbl
+ i
;
3943 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3945 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3946 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3947 (ulonglong
)FileSectors
);
3956 grub_file_close(file
);
3957 grub_check_free(gpt
);
3958 grub_errno
= GRUB_ERR_NONE
;
3962 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3971 for (i
= 0; i
< 500; i
++)
3973 ret
= grub_getkey_noblock();
3974 if (ret
== GRUB_TERM_NO_KEY
)
3983 grub_printf("\n\n Still have key input after clear.\n");
3991 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3998 int image_sector_size
;
4000 ventoy_chain_head
*chain
;
4001 ventoy_img_chunk
*chunk
;
4002 ventoy_os_param
*osparam
;
4003 ventoy_image_location
*location
;
4004 ventoy_image_disk_region
*region
;
4005 struct grub_acpi_table_header
*acpi
;
4014 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4016 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4022 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4024 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4026 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4030 img_chunk_num
= chain
->img_chunk_num
;
4032 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4033 datalen
= sizeof(ventoy_os_param
) + loclen
;
4035 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4036 acpi
= grub_zalloc(buflen
);
4042 /* Step1: Fill acpi table header */
4043 grub_memcpy(acpi
->signature
, "VTOY", 4);
4044 acpi
->length
= buflen
;
4046 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4047 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4049 acpi
->creator_id
[0] = 1;
4050 acpi
->creator_rev
= 1;
4052 /* Step2: Fill data */
4053 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4054 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4055 osparam
->vtoy_img_location_addr
= 0;
4056 osparam
->vtoy_img_location_len
= loclen
;
4057 osparam
->chksum
= 0;
4058 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4060 location
= (ventoy_image_location
*)(osparam
+ 1);
4061 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4062 location
->image_sector_size
= image_sector_size
;
4063 location
->disk_sector_size
= chain
->disk_sector_size
;
4064 location
->region_count
= img_chunk_num
;
4066 region
= location
->regions
;
4067 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4068 if (512 == image_sector_size
)
4070 for (i
= 0; i
< img_chunk_num
; i
++)
4072 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4073 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4074 region
->disk_start_sector
= chunk
->disk_start_sector
;
4081 for (i
= 0; i
< img_chunk_num
; i
++)
4083 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4084 region
->image_start_sector
= chunk
->img_start_sector
;
4085 region
->disk_start_sector
= chunk
->disk_start_sector
;
4091 /* Step3: Fill acpi checksum */
4093 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4095 /* load acpi table */
4096 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4097 grub_script_execute_sourcecode(cmd
);
4101 VENTOY_CMD_RETURN(0);
4104 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4110 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4111 g_ventoy_last_entry
= -1;
4116 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4122 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4127 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4129 const char *pos
= filename
+ 1;
4137 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4139 grub_strncpy((char *)data
, filename
, 128);
4150 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4153 char *device_name
= NULL
;
4154 grub_device_t dev
= NULL
;
4155 grub_fs_t fs
= NULL
;
4156 char buf
[128] = {0};
4162 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4166 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4168 device_name
= grub_file_get_device_name(args
[0]);
4171 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4175 dev
= grub_device_open(device_name
);
4178 debug("grub_device_open failed, %s\n", device_name
);
4182 fs
= grub_fs_probe(dev
);
4185 debug("grub_fs_probe failed, %s\n", device_name
);
4189 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4193 ventoy_set_env(args
[2], buf
);
4200 check_free(device_name
, grub_free
);
4201 check_free(dev
, grub_device_close
);
4206 int ventoy_load_part_table(const char *diskname
)
4213 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4214 if (!g_ventoy_part_info
)
4219 disk
= grub_disk_open(diskname
);
4222 debug("Failed to open disk %s\n", diskname
);
4226 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4228 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4229 grub_disk_close(disk
);
4231 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4232 dev
= grub_device_open(name
);
4235 /* Check for official Ventoy device */
4236 ret
= ventoy_check_official_device(dev
);
4237 grub_device_close(dev
);
4245 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4246 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4251 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4258 ret
= ventoy_load_part_table(args
[0]);
4264 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4265 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4270 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4273 const char *vcfg
= NULL
;
4278 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4281 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4282 grub_env_set(args
[1], vcfg
);
4287 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4295 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4298 grub_uint8_t zeroguid
[16] = {0};
4303 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4306 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4308 if (id
>= 1 && id
<= 128)
4310 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4318 if (id
>= 1 && id
<= 4)
4320 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4330 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4333 char *device_name
= NULL
;
4334 grub_device_t dev
= NULL
;
4335 grub_fs_t fs
= NULL
;
4340 debug("get fs label for %s\n", args
[0]);
4344 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4348 device_name
= grub_file_get_device_name(args
[0]);
4351 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4355 dev
= grub_device_open(device_name
);
4358 debug("grub_device_open failed, %s\n", device_name
);
4362 fs
= grub_fs_probe(dev
);
4363 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4365 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4369 fs
->fs_label(dev
, &label
);
4372 debug("label=<%s>\n", label
);
4373 ventoy_set_env(args
[1], label
);
4381 check_free(device_name
, grub_free
);
4382 check_free(dev
, grub_device_close
);
4387 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4391 grub_snprintf((char *)data
, 256, "%s", filename
);
4398 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4400 if (info
->dir
&& filename
&& filename
[0] != '.')
4402 grub_snprintf((char *)data
, 256, "%s", filename
);
4409 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4412 char *device_name
= NULL
;
4413 grub_device_t dev
= NULL
;
4414 grub_fs_t fs
= NULL
;
4415 char name
[256] ={0};
4419 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4423 device_name
= grub_file_get_device_name(args
[0]);
4426 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4430 dev
= grub_device_open(device_name
);
4433 debug("grub_device_open failed, %s\n", device_name
);
4437 fs
= grub_fs_probe(dev
);
4440 debug("grub_fs_probe failed, %s\n", device_name
);
4444 fs
->fs_dir(dev
, args
[1], hook
, name
);
4447 ventoy_set_env(args
[2], name
);
4454 check_free(device_name
, grub_free
);
4455 check_free(dev
, grub_device_close
);
4460 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4463 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4466 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4469 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4472 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4482 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4486 for (pos
= args
[0]; *pos
; pos
++)
4500 grub_env_set(args
[1], args
[0]);
4510 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4520 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4525 len
= (int)grub_strlen(buf
);
4526 for (i
= len
; i
> 0; i
--)
4528 if (buf
[i
- 1] == '/')
4530 grub_env_set(args
[1], buf
+ i
);
4535 grub_env_set(args
[1], buf
);
4540 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4542 struct grub_video_mode_info info
;
4549 if (!g_video_mode_list
)
4551 ventoy_enum_video_mode();
4554 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4556 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4560 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4563 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4565 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4566 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4568 VENTOY_CMD_RETURN(0);
4571 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4573 struct grub_video_mode_info info
;
4580 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4582 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4586 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4589 grub_env_set(args
[0], buf
);
4591 VENTOY_CMD_RETURN(0);
4594 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4602 if (!g_video_mode_list
)
4607 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4608 if (id
< g_video_mode_num
)
4610 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4611 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4614 grub_env_set(args
[1], buf
);
4616 VENTOY_CMD_RETURN(0);
4619 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4622 grub_uint32_t loadsector
= 0;
4625 grub_uint32_t boot_catlog
= 0;
4626 grub_uint8_t buf
[512];
4632 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4636 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4639 debug("failed to open %s\n", args
[0]);
4643 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4644 if (boot_catlog
== 0)
4646 debug("No bootcatlog found\n");
4647 grub_file_close(file
);
4651 grub_memset(buf
, 0, sizeof(buf
));
4652 grub_file_seek(file
, boot_catlog
* 2048);
4653 grub_file_read(file
, buf
, sizeof(buf
));
4654 grub_file_close(file
);
4656 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4658 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4660 if (buf
[i
+ 32] == 0x88)
4662 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4663 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4669 if (loadsector
== 0)
4671 debug("No EFI eltorito info found\n");
4675 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4676 grub_env_set(args
[1], value
);
4677 VENTOY_CMD_RETURN(0);
4680 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4685 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4687 if (pfsdir
->initrd
[0])
4692 curpos
= pfsdir
->curpos
;
4693 len
= grub_strlen(filename
);
4697 if ((len
== 1 && filename
[0] == '.') ||
4698 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4703 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4706 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4707 pfsdir
->curpos
= curpos
+ printlen
;
4708 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4709 pfsdir
->curpos
= curpos
;
4710 pfsdir
->fullpath
[curpos
] = 0;
4714 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4717 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4718 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4720 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4722 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4731 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4735 char *device_name
= NULL
;
4736 grub_device_t dev
= NULL
;
4737 grub_fs_t fs
= NULL
;
4738 replace_fs_dir
*pfsdir
= NULL
;
4744 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4748 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4754 device_name
= grub_file_get_device_name(args
[0]);
4760 dev
= grub_device_open(device_name
);
4766 fs
= grub_fs_probe(dev
);
4775 pfsdir
->fullpath
[0] = '/';
4776 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4778 if (pfsdir
->initrd
[0])
4780 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4782 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4784 if (pfsdir
->initrd
[i
] == '/')
4786 pfsdir
->initrd
[i
] = '\\';
4790 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4791 grub_env_set(args
[1], pos
);
4795 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4800 grub_check_free(pfsdir
);
4801 grub_check_free(device_name
);
4802 check_free(dev
, grub_device_close
);
4804 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4807 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4809 const char *pager
= NULL
;
4815 pager
= grub_env_get("pager");
4819 grub_env_set("pager", "1");
4821 else if (pager
[0] == '1')
4827 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4829 grub_env_set("pager", "1");
4832 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4835 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4841 if (g_pager_flag
== 1)
4843 grub_env_unset("pager");
4845 else if (g_pager_flag
== 2)
4847 grub_env_set("pager", g_old_pager
);
4850 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4853 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4855 if (g_json_case_mis_path
[0])
4860 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
4862 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4868 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4871 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4873 if (g_json_case_mis_path
[0])
4878 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4880 if (grub_strcasecmp(filename
, "ventoy") == 0)
4882 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4883 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4884 if (g_json_case_mis_path
[0])
4894 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4897 char *device_name
= NULL
;
4898 grub_device_t dev
= NULL
;
4899 grub_fs_t fs
= NULL
;
4900 chk_case_fs_dir fs_dir
;
4906 device_name
= grub_file_get_device_name(args
[0]);
4912 dev
= grub_device_open(device_name
);
4918 fs
= grub_fs_probe(dev
);
4924 fstype
= ventoy_get_fs_type(fs
->name
);
4925 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4930 g_json_case_mis_path
[0] = 0;
4933 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4935 if (g_json_case_mis_path
[0])
4937 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4942 grub_check_free(device_name
);
4943 check_free(dev
, grub_device_close
);
4945 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4948 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4951 grub_partition_t part
;
4952 char priority_str
[3]; /* Maximum value 15 */
4956 if (argc
< 2 || argc
> 3)
4957 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4958 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4960 /* Open the disk if it exists */
4961 disk
= grub_disk_open (args
[0]);
4964 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4968 part
= grub_partition_probe (disk
, args
[1]);
4971 grub_disk_close (disk
);
4972 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4973 "No such partition");
4976 if (grub_strcmp (part
->partmap
->name
, "gpt"))
4978 grub_disk_close (disk
);
4979 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
4980 "Not a GPT partition");
4983 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
4984 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
4988 grub_env_set (args
[2], priority_str
);
4989 grub_env_export (args
[2]);
4993 grub_printf ("Priority is %s\n", priority_str
);
4996 grub_disk_close (disk
);
4997 return GRUB_ERR_NONE
;
5001 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5005 grub_file_t file
= NULL
;
5006 grub_uint32_t loadrba
= 0;
5007 grub_uint32_t boot_catlog
= 0;
5008 grub_uint8_t sector
[512];
5009 boot_info_table
*info
= NULL
;
5014 /* This also trigger a iso9660 fs parse */
5015 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5020 joliet
= grub_iso9660_is_joliet();
5026 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5029 debug("failed to open %s\n", args
[0]);
5033 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5034 if (boot_catlog
== 0)
5036 debug("no bootcatlog found %u\n", boot_catlog
);
5040 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5043 debug("no bios eltorito rba found %u\n", loadrba
);
5047 grub_file_seek(file
, loadrba
* 2048);
5048 grub_file_read(file
, sector
, 512);
5050 info
= (boot_info_table
*)sector
;
5051 if (info
->bi_data0
== 0x7c6ceafa &&
5052 info
->bi_data1
== 0x90900000 &&
5053 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5054 info
->bi_BootFileLocation
== loadrba
)
5056 debug("bootloader is syslinux, %u.\n", loadrba
);
5062 grub_file_close(file
);
5063 grub_errno
= GRUB_ERR_NONE
;
5067 int ventoy_env_init(void)
5071 grub_env_set("vtdebug_flag", "");
5073 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5074 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5075 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5076 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5078 ventoy_filt_register(0, ventoy_wrapper_open
);
5080 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5083 g_grub_param
->grub_env_get
= grub_env_get
;
5084 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5085 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5086 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5087 grub_env_set("env_param", buf
);
5088 grub_env_set("ventoy_env_param", buf
);
5090 grub_env_export("env_param");
5091 grub_env_export("ventoy_env_param");
5094 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5095 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5097 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5098 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5100 grub_env_export("vtoy_winpeshl_ini_addr");
5101 grub_env_export("vtoy_winpeshl_ini_size");
5103 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5104 grub_env_set("vtoy_chain_file_size", buf
);
5105 grub_env_export("vtoy_chain_file_size");
5107 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5108 grub_env_set("vtoy_chain_file_read", buf
);
5109 grub_env_export("vtoy_chain_file_read");
5116 static cmd_para ventoy_cmds
[] =
5118 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5119 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5120 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5121 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5122 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5123 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5124 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5125 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5126 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5127 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5128 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5129 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5130 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5131 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5132 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5133 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5134 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5135 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5136 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5137 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5138 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5139 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5140 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5141 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5142 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5144 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5145 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5146 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5147 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5148 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5149 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5150 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5152 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5153 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5154 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5155 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5156 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5157 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5158 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5159 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5160 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5161 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5164 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5165 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5166 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5167 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5168 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5169 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5170 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5171 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5172 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5173 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5174 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5176 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5177 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5178 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5179 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5180 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5181 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5182 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5184 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5185 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5186 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5187 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5188 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5189 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5190 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5191 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5192 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5193 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5195 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5196 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5197 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5198 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5199 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5200 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5201 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5202 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5203 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5205 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5206 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5207 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5208 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5211 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5212 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5213 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5215 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5216 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5217 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5220 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5221 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5222 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5223 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5224 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5225 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5226 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5227 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5228 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
5229 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5230 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5231 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5233 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5234 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5235 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5236 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5237 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5238 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5239 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5240 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5241 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5242 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5243 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
5244 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
5246 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5247 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5248 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5249 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5250 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5251 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5252 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5253 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5256 int ventoy_register_all_cmd(void)
5259 cmd_para
*cur
= NULL
;
5261 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5263 cur
= ventoy_cmds
+ i
;
5264 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5265 cur
->summary
, cur
->description
, cur
->parser
);
5271 int ventoy_unregister_all_cmd(void)
5275 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5277 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);