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 initrd_info
*g_initrd_img_list
= NULL
;
55 initrd_info
*g_initrd_img_tail
= NULL
;
56 int g_initrd_img_count
= 0;
57 int g_valid_initrd_count
= 0;
58 int g_default_menu_mode
= 0;
59 int g_filt_dot_underscore_file
= 0;
60 int g_sort_case_sensitive
= 0;
61 int g_tree_view_menu_style
= 0;
62 static grub_file_t g_old_file
;
63 static int g_ventoy_last_entry_back
;
66 char g_img_swap_tmp_buf
[1024];
67 img_info g_img_swap_tmp
;
68 img_info
*g_ventoy_img_list
= NULL
;
70 int g_ventoy_img_count
= 0;
72 grub_device_t g_enum_dev
= NULL
;
73 grub_fs_t g_enum_fs
= NULL
;
74 int g_img_max_search_level
= -1;
75 img_iterator_node g_img_iterator_head
;
76 img_iterator_node
*g_img_iterator_tail
= NULL
;
78 grub_uint8_t g_ventoy_break_level
= 0;
79 grub_uint8_t g_ventoy_debug_level
= 0;
80 grub_uint8_t g_ventoy_chain_type
= 0;
82 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
83 grub_uint32_t g_ventoy_cpio_size
= 0;
84 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
85 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
87 int g_plugin_image_list
= 0;
89 ventoy_grub_param
*g_grub_param
= NULL
;
91 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
93 ventoy_img_chunk_list g_img_chunk_list
;
95 int g_wimboot_enable
= 0;
96 ventoy_img_chunk_list g_wimiso_chunk_list
;
97 char *g_wimiso_path
= NULL
;
99 int g_vhdboot_enable
= 0;
101 grub_uint64_t g_conf_replace_offset
= 0;
102 grub_uint64_t g_svd_replace_offset
= 0;
103 conf_replace
*g_conf_replace_node
= NULL
;
104 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
105 int g_conf_replace_new_len
= 0;
106 int g_conf_replace_new_len_align
= 0;
108 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
109 grub_uint64_t g_ventoy_disk_size
= 0;
110 grub_uint64_t g_ventoy_disk_part_size
[2];
112 static char *g_tree_script_buf
= NULL
;
113 static int g_tree_script_pos
= 0;
115 static char *g_list_script_buf
= NULL
;
116 static int g_list_script_pos
= 0;
118 static char *g_part_list_buf
= NULL
;
119 static int g_part_list_pos
= 0;
121 static int g_video_mode_max
= 0;
122 static int g_video_mode_num
= 0;
123 static ventoy_video_mode
*g_video_mode_list
= NULL
;
125 static int g_enumerate_time_checked
= 0;
126 static grub_uint64_t g_enumerate_start_time_ms
;
127 static grub_uint64_t g_enumerate_finish_time_ms
;
128 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
130 static int g_pager_flag
= 0;
131 static char g_old_pager
[32];
133 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
135 static const char *g_menu_class
[] =
137 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
140 const char *g_menu_prefix
[img_type_max
] =
142 "iso", "wim", "efi", "img", "vhd", "vtoy"
145 static int g_vtoy_load_prompt
= 0;
146 static char g_vtoy_prompt_msg
[64];
148 static char g_json_case_mis_path
[32];
150 static int ventoy_get_fs_type(const char *fs
)
154 return ventoy_fs_max
;
156 else if (grub_strncmp(fs
, "exfat", 5) == 0)
158 return ventoy_fs_exfat
;
160 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
162 return ventoy_fs_ntfs
;
164 else if (grub_strncmp(fs
, "ext", 3) == 0)
166 return ventoy_fs_ext
;
168 else if (grub_strncmp(fs
, "xfs", 3) == 0)
170 return ventoy_fs_xfs
;
172 else if (grub_strncmp(fs
, "udf", 3) == 0)
174 return ventoy_fs_udf
;
176 else if (grub_strncmp(fs
, "fat", 3) == 0)
178 return ventoy_fs_fat
;
181 return ventoy_fs_max
;
184 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
203 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
205 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
209 static int ventoy_control_get_flag(const char *key
)
211 const char *val
= ventoy_get_env(key
);
213 if (val
&& val
[0] == '1' && val
[1] == 0)
220 static grub_err_t
ventoy_fs_close(grub_file_t file
)
222 grub_file_close(g_old_file
);
223 grub_free(file
->data
);
231 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
237 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
242 for (i
= 0; i
< g_video_mode_num
; i
++)
244 if (g_video_mode_list
[i
].width
== info
->width
&&
245 g_video_mode_list
[i
].height
== info
->height
&&
246 g_video_mode_list
[i
].bpp
== info
->bpp
)
252 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
253 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
254 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
257 if (g_video_mode_num
== g_video_mode_max
)
259 g_video_mode_max
*= 2;
260 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
266 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
268 if (v1
->bpp
== v2
->bpp
)
270 if (v1
->width
== v2
->width
)
272 if (v1
->height
== v2
->height
)
278 return (v1
->height
< v2
->height
) ? -1 : 1;
283 return (v1
->width
< v2
->width
) ? -1 : 1;
288 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
292 static int ventoy_enum_video_mode(void)
295 grub_video_adapter_t adapter
;
296 grub_video_driver_id_t id
;
297 ventoy_video_mode mode
;
299 g_video_mode_num
= 0;
300 g_video_mode_max
= 1024;
301 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
302 if (!g_video_mode_list
)
307 #ifdef GRUB_MACHINE_PCBIOS
308 grub_dl_load ("vbe");
311 id
= grub_video_get_driver_id ();
313 FOR_VIDEO_ADAPTERS (adapter
)
315 if (!adapter
->iterate
||
316 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
317 adapter
->init() != GRUB_ERR_NONE
)))
322 adapter
->iterate(ventoy_video_hook
, NULL
);
324 if (adapter
->id
!= id
)
330 /* sort video mode */
331 for (i
= 0; i
< g_video_mode_num
; i
++)
332 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
334 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
336 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
337 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
338 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
342 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
345 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
349 static struct grub_fs vtoy_fs
=
354 .fs_read
= ventoy_fs_read
,
355 .fs_close
= ventoy_fs_close
,
365 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
371 file
->data
= grub_malloc(rawFile
->size
+ 4096);
377 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
378 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
380 g_old_file
= rawFile
;
382 file
->size
= rawFile
->size
+ len
;
383 file
->device
= rawFile
->device
;
385 file
->not_easily_seekable
= 1;
390 static int ventoy_check_decimal_var(const char *name
, long *value
)
392 const char *value_str
= NULL
;
394 value_str
= grub_env_get(name
);
395 if (NULL
== value_str
)
397 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
400 if (!ventoy_is_decimal(value_str
))
402 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
405 *value
= grub_strtol(value_str
, NULL
, 10);
407 return GRUB_ERR_NONE
;
410 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
412 grub_uint64_t sectors
;
414 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
416 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
420 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
423 return sectors
* 512;
426 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
432 grub_uint32_t offset
;
434 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
437 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
441 len
= (int)file
->size
;
443 data
= (char *)grub_malloc(file
->size
);
449 grub_file_read(file
, data
, file
->size
);
450 grub_file_close(file
);
452 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
453 grub_script_execute_sourcecode(exec
);
455 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
456 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
457 grub_file_close(file
);
459 grub_script_execute_sourcecode("loopback -d efiboot");
463 *direntoff
= offset
+ 2;
468 static int ventoy_set_check_result(int ret
)
472 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
473 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
474 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
478 grub_printf(VTOY_WARNING
"\n");
479 grub_printf(VTOY_WARNING
"\n");
480 grub_printf(VTOY_WARNING
"\n\n\n");
482 grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret
);
483 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
485 grub_printf("\n\nWill exit after 10 seconds ...... ");
493 static int ventoy_check_official_device(grub_device_t dev
)
497 grub_uint64_t offset
;
502 struct grub_partition
*partition
;
504 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
506 return ventoy_set_check_result(1 | 0x1000);
509 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
510 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
511 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
513 #ifndef GRUB_MACHINE_EFI
514 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
515 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
516 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
518 return ventoy_set_check_result(2 | 0x1000);
527 /* We must have partition 2 */
530 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
534 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
538 return ventoy_set_check_result(3 | 0x1000);
541 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
543 grub_file_close(file
);
544 return ventoy_set_check_result(4 | 0x1000);
547 partition
= dev
->disk
->partition
;
548 if (partition
->number
!= 0 || partition
->start
!= 2048)
550 return ventoy_set_check_result(5);
555 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
557 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
558 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
559 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
561 grub_file_close(file
);
562 return ventoy_set_check_result(6);
567 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
568 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
569 PartTbl
[1].SectorCount
!= 65536)
571 grub_file_close(file
);
572 return ventoy_set_check_result(6);
578 offset
= partition
->start
+ partition
->len
;
579 partition
= file
->device
->disk
->partition
;
580 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
582 grub_file_close(file
);
583 return ventoy_set_check_result(7);
587 grub_file_close(file
);
591 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
592 dev2
= grub_device_open(devname
);
595 return ventoy_set_check_result(8);
598 fs
= grub_fs_probe(dev2
);
601 grub_device_close(dev2
);
602 return ventoy_set_check_result(9);
605 fs
->fs_label(dev2
, &label
);
606 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
608 grub_device_close(dev2
);
609 return ventoy_set_check_result(10);
612 grub_device_close(dev2
);
615 return ventoy_set_check_result(0);
618 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
622 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
632 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
634 grub_uint64_t size
= 0;
637 char fullpath
[256] = {0};
640 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
643 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
646 debug("grub_file_open failed <%s>\n", fullpath
);
652 grub_file_close(file
);
656 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
660 char fullpath
[256] = {0};
663 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
666 file
= grub_file_open(fullpath
, type
);
669 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
676 int ventoy_is_file_exist(const char *fmt
, ...)
683 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
687 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
690 grub_strncpy(pos
+ len
, "\" ]", 3);
692 debug("script exec %s\n", buf
);
694 if (0 == grub_script_execute_sourcecode(buf
))
702 int ventoy_is_dir_exist(const char *fmt
, ...)
709 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
713 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
716 grub_strncpy(pos
+ len
, "\" ]", 3);
718 debug("script exec %s\n", buf
);
720 if (0 == grub_script_execute_sourcecode(buf
))
728 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
731 grub_uint8_t
*outbuf
;
732 grub_uint8_t gzHdr
[10] =
734 0x1F, 0x8B, /* magic */
742 grub_memset(&s
, 0, sizeof(mz_stream
));
744 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
746 outbuf
= (grub_uint8_t
*)mem_out
;
748 mem_out_len
-= sizeof(gzHdr
) + 8;
749 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
750 outbuf
+= sizeof(gzHdr
);
752 s
.avail_in
= mem_in_len
;
755 s
.avail_out
= mem_out_len
;
758 mz_deflate(&s
, MZ_FINISH
);
762 outbuf
+= s
.total_out
;
763 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
764 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
766 return s
.total_out
+ sizeof(gzHdr
) + 8;
774 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
778 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
781 if (0 == grub_strcmp(args
[0], "on"))
784 grub_env_set("vtdebug_flag", "debug");
789 grub_env_set("vtdebug_flag", "");
792 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
795 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
799 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
801 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
802 grub_printf(" level:\r\n");
803 grub_printf(" 01/11: busybox / (+cat log)\r\n");
804 grub_printf(" 02/12: initrd / (+cat log)\r\n");
805 grub_printf(" 03/13: hook / (+cat log)\r\n");
807 grub_printf(" debug:\r\n");
808 grub_printf(" 0: debug is off\r\n");
809 grub_printf(" 1: debug is on\r\n");
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
814 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
816 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
818 g_ventoy_debug_level
= 1;
821 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
824 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
833 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
836 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
868 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
873 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
875 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
878 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
883 value_long
+= grub_strtol(args
[1], NULL
, 10);
885 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
886 grub_env_set(args
[0], buf
);
888 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
891 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
893 ulonglong value1
= 0;
894 ulonglong value2
= 0;
899 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
902 value1
= grub_strtoull(args
[0], NULL
, 10);
903 value2
= grub_strtoull(args
[1], NULL
, 10);
905 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
906 grub_env_set(args
[2], buf
);
908 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
911 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
926 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
929 debug("failed to open file <%s> for udf check\n", args
[0]);
933 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
935 grub_env_set(args
[1], buf
);
937 grub_file_close(file
);
943 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
951 g_wimboot_enable
= 0;
952 grub_check_free(g_wimiso_path
);
953 grub_check_free(g_wimiso_chunk_list
.chunk
);
955 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
961 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
962 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
963 if (NULL
== g_wimiso_chunk_list
.chunk
)
965 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
968 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
969 g_wimiso_chunk_list
.cur_chunk
= 0;
971 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
973 g_wimboot_enable
= 1;
974 g_wimiso_path
= grub_strdup(args
[0]);
976 grub_file_close(file
);
981 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
991 ventoy_iso9660_override
*dirent
;
1000 totlen
= sizeof(ventoy_chain_head
);
1002 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1004 debug("failed to load efiboot template %d\n", len
);
1010 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1012 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1015 debug("failed to open file <%s>\n", args
[0]);
1019 totlen
+= ventoy_align_2k(file
->size
);
1021 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1022 dirent
->first_sector
= len
/ 2048;
1023 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1024 dirent
->size
= (grub_uint32_t
)file
->size
;
1025 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1027 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1029 #ifdef GRUB_MACHINE_EFI
1030 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1032 data
= (char *)grub_malloc(totlen
);
1035 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1037 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1038 grub_check_free(buf
);
1040 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1041 grub_file_close(file
);
1043 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1044 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1045 grub_env_set(name
, value
);
1047 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1048 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1049 grub_env_set(name
, value
);
1054 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1060 g_vtoy_load_prompt
= 0;
1061 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1063 if (argc
== 2 && args
[0][0] == '1')
1065 g_vtoy_load_prompt
= 1;
1066 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1069 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1072 int ventoy_need_prompt_load_file(void)
1074 return g_vtoy_load_prompt
;
1077 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1079 grub_uint64_t ro
= 0;
1080 grub_uint64_t div
= 0;
1081 grub_ssize_t left
= size
;
1082 char *cur
= (char *)buf
;
1084 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1087 while (left
>= VTOY_SIZE_2MB
)
1089 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1090 cur
+= VTOY_SIZE_2MB
;
1091 left
-= VTOY_SIZE_2MB
;
1093 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1094 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1100 grub_file_read(file
, cur
, left
);
1103 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1109 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1116 enum grub_file_type type
;
1127 if (grub_strcmp(args
[0], "nodecompress") == 0)
1129 type
= VENTOY_FILE_TYPE
;
1133 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1136 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1139 debug("failed to open file <%s>\n", args
[1]);
1143 #ifdef GRUB_MACHINE_EFI
1144 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1146 buf
= (char *)grub_malloc(file
->size
);
1151 grub_file_close(file
);
1155 if (g_vtoy_load_prompt
)
1157 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1161 grub_file_read(file
, buf
, file
->size
);
1164 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1165 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1166 grub_env_set(name
, value
);
1168 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1169 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1170 grub_env_set(name
, value
);
1172 grub_file_close(file
);
1178 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1196 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1199 debug("failed to open file <%s> for udf check\n", args
[0]);
1203 headlen
= sizeof(ventoy_chain_head
);
1205 #ifdef GRUB_MACHINE_EFI
1206 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1208 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1211 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1213 grub_file_read(file
, buf
+ headlen
, file
->size
);
1215 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1216 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1217 grub_env_set(name
, value
);
1219 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1220 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1221 grub_env_set(name
, value
);
1223 grub_file_close(file
);
1229 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1235 if (grub_iso9660_is_joliet())
1237 debug("This time has joliet process\n");
1246 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1255 if (args
[0][0] == '1')
1257 grub_iso9660_set_nojoliet(1);
1261 grub_iso9660_set_nojoliet(0);
1267 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1272 grub_uint8_t buf
[32];
1283 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1286 debug("failed to open file <%s> for udf check\n", args
[0]);
1290 for (i
= 16; i
< 32; i
++)
1292 grub_file_seek(file
, i
* 2048);
1293 grub_file_read(file
, buf
, sizeof(buf
));
1301 grub_file_seek(file
, i
* 2048);
1302 grub_file_read(file
, buf
, sizeof(buf
));
1304 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1307 grub_file_seek(file
, i
* 2048);
1308 grub_file_read(file
, buf
, sizeof(buf
));
1310 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1311 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1317 grub_file_close(file
);
1319 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1324 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1326 long value_long1
= 0;
1327 long value_long2
= 0;
1329 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1331 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1334 value_long1
= grub_strtol(args
[0], NULL
, 10);
1335 value_long2
= grub_strtol(args
[2], NULL
, 10);
1337 if (0 == grub_strcmp(args
[1], "eq"))
1339 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1341 else if (0 == grub_strcmp(args
[1], "ne"))
1343 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1345 else if (0 == grub_strcmp(args
[1], "gt"))
1347 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1349 else if (0 == grub_strcmp(args
[1], "lt"))
1351 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1353 else if (0 == grub_strcmp(args
[1], "ge"))
1355 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1357 else if (0 == grub_strcmp(args
[1], "le"))
1359 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1363 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1369 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1372 char buf
[128] = {0};
1376 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1379 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1380 pos
= grub_strstr(buf
, ",");
1386 grub_env_set(args
[1], buf
);
1388 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1391 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1397 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1403 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1406 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1408 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1409 if (0 == grub_script_execute_sourcecode(buf
))
1411 debug("file %s exist, ventoy_compatible YES\n", buf
);
1412 grub_env_set("ventoy_compatible", "YES");
1413 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1417 debug("file %s NOT exist\n", buf
);
1421 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1422 pos
= grub_strstr(buf
, ")");
1428 disk
= grub_disk_open(buf
);
1431 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1432 grub_disk_close(disk
);
1434 g_img_swap_tmp_buf
[703] = 0;
1435 for (i
= 318; i
< 703; i
++)
1437 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1438 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1440 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1441 grub_env_set("ventoy_compatible", "YES");
1442 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1448 debug("failed to open disk <%s>\n", buf
);
1451 grub_env_set("ventoy_compatible", "NO");
1452 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1455 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1461 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1463 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1466 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1471 if (0 == g_sort_case_sensitive
)
1473 if (grub_islower(c1
))
1475 c1
= c1
- 'a' + 'A';
1478 if (grub_islower(c2
))
1480 c2
= c2
- 'a' + 'A';
1493 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1499 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1501 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1504 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1509 if (0 == g_sort_case_sensitive
)
1511 if (grub_islower(c1
))
1513 c1
= c1
- 'a' + 'A';
1516 if (grub_islower(c2
))
1518 c2
= c2
- 'a' + 'A';
1531 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1533 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1535 grub_memcpy(img1
, img2
, sizeof(img_info
));
1536 img1
->next
= g_img_swap_tmp
.next
;
1537 img1
->prev
= g_img_swap_tmp
.prev
;
1539 g_img_swap_tmp
.next
= img2
->next
;
1540 g_img_swap_tmp
.prev
= img2
->prev
;
1541 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1544 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1548 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1556 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1565 img_iterator_node
*tmp
;
1566 img_iterator_node
*new_node
;
1567 img_iterator_node
*node
= (img_iterator_node
*)data
;
1569 if (g_enumerate_time_checked
== 0)
1571 g_enumerate_finish_time_ms
= grub_get_time_ms();
1572 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1575 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1577 g_enumerate_time_checked
= 1;
1581 len
= grub_strlen(filename
);
1585 if (node
->level
+ 1 > g_img_max_search_level
)
1590 if ((len
== 1 && filename
[0] == '.') ||
1591 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1596 if (!ventoy_img_name_valid(filename
, len
))
1601 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1606 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1608 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1609 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1612 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1617 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1620 new_node
->level
= node
->level
+ 1;
1621 new_node
->plugin_list_index
= index
;
1622 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1624 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1627 debug("Directory %s ignored...\n", new_node
->dir
);
1628 grub_free(new_node
);
1632 new_node
->tail
= node
->tail
;
1634 new_node
->parent
= node
;
1635 if (!node
->firstchild
)
1637 node
->firstchild
= new_node
;
1640 if (g_img_iterator_tail
)
1642 g_img_iterator_tail
->next
= new_node
;
1643 g_img_iterator_tail
= new_node
;
1647 g_img_iterator_head
.next
= new_node
;
1648 g_img_iterator_tail
= new_node
;
1654 debug("Find a file %s\n", filename
);
1660 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1662 type
= img_type_iso
;
1664 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1666 type
= img_type_wim
;
1668 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1669 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1671 type
= img_type_vhd
;
1673 #ifdef GRUB_MACHINE_EFI
1674 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1676 type
= img_type_efi
;
1679 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1681 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1683 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1684 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1689 type
= img_type_img
;
1691 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1693 type
= img_type_vtoy
;
1695 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1697 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1699 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1700 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1709 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1714 if (g_plugin_image_list
)
1716 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1717 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1718 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1720 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1723 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1725 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1730 img
= grub_zalloc(sizeof(img_info
));
1734 img
->plugin_list_index
= index
;
1735 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1737 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1739 img
->size
= info
->size
;
1742 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1745 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1747 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1752 if (g_ventoy_img_list
)
1754 tail
= *(node
->tail
);
1760 g_ventoy_img_list
= img
;
1763 img
->id
= g_ventoy_img_count
;
1765 if (node
&& NULL
== node
->firstiso
)
1767 node
->firstiso
= img
;
1778 *((img_info
**)(node
->tail
)) = img
;
1779 g_ventoy_img_count
++;
1781 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1782 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1785 img
->class = g_menu_class
[type
];
1787 img
->menu_prefix
= g_menu_prefix
[type
];
1789 if (img_type_iso
== type
)
1791 if (ventoy_plugin_check_memdisk(img
->path
))
1793 img
->menu_prefix
= "miso";
1797 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1804 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1806 int len
= GRUB_UINT_MAX
;
1807 const char *value
= NULL
;
1808 char name
[32] = {0};
1809 char plat
[32] = {0};
1810 char guidstr
[32] = {0};
1811 ventoy_guid guid
= VENTOY_GUID
;
1812 const char *fmt1
= NULL
;
1813 const char *fmt2
= NULL
;
1814 const char *fmt3
= NULL
;
1815 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1816 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1817 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1818 const char fmtcode
[]={
1819 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1820 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1821 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1822 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1823 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1824 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1827 grub_memset(name
, 0, sizeof(name
));
1828 puint
[0] = grub_swap_bytes32(0x56454e54);
1829 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1830 puint
[2] = grub_swap_bytes32(0x45525349);
1831 puint
[1] = grub_swap_bytes32(0x4f595f56);
1832 value
= ventoy_get_env(name
);
1834 grub_memset(name
, 0, sizeof(name
));
1835 puint
[1] = grub_swap_bytes32(0x5f544f50);
1836 puint
[0] = grub_swap_bytes32(0x56544c45);
1837 fmt1
= ventoy_get_env(name
);
1843 grub_memset(name
, 0, sizeof(name
));
1844 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1845 puint
[0] = grub_swap_bytes32(0x56544c45);
1846 fmt2
= ventoy_get_env(name
);
1848 grub_memset(name
, 0, sizeof(name
));
1849 puint
[1] = grub_swap_bytes32(0x5f434c52);
1850 puint
[0] = grub_swap_bytes32(0x56544c45);
1851 fmt3
= ventoy_get_env(name
);
1853 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1855 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1857 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1858 #pragma GCC diagnostic push
1859 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1860 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1861 fmt1
? fmt1
: fmtdata
,
1862 fmt2
? fmt2
: fmtdata
+ 4,
1863 value
? value
: "", plat
, guidstr
,
1864 fmt3
? fmt3
: fmtdata
+ 6);
1865 #pragma GCC diagnostic pop
1867 grub_memset(name
, 0, sizeof(name
));
1868 puint
[0] = grub_swap_bytes32(0x76746f79);
1869 puint
[2] = grub_swap_bytes32(0x656e7365);
1870 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1871 ventoy_set_env(name
, guidstr
);
1876 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1880 grub_uint8_t md5
[16];
1884 grub_memset(input
, 0, sizeof(input
));
1886 grub_printf("Enter password: ");
1889 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1891 grub_password_get(input
, 128);
1892 if (grub_strcmp(pwd
->text
, input
) == 0)
1897 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1899 grub_password_get(input
, 128);
1900 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1901 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1906 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1908 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1909 grub_password_get(input
+ offset
, 128);
1911 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1912 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1918 grub_printf("Invalid password!\n\n");
1925 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1927 img_info
*minimg
= NULL
;
1928 img_info
*img
= (img_info
*)(node
->firstiso
);
1930 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1932 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1947 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1949 img_iterator_node
*Minchild
= NULL
;
1950 img_iterator_node
*child
= node
->firstchild
;
1952 while (child
&& child
->parent
== node
)
1954 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1958 child
= child
->next
;
1963 Minchild
->select
= 1;
1969 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1972 img_info
*img
= NULL
;
1973 const char *dir_class
= NULL
;
1974 const char *dir_alias
= NULL
;
1975 img_iterator_node
*child
= NULL
;
1977 if (node
->isocnt
== 0 || node
->done
== 1)
1982 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1984 offset
= node
->parent
->dirlen
;
1987 if (node
== &g_img_iterator_head
)
1989 if (g_default_menu_mode
== 0)
1991 if (g_tree_view_menu_style
== 0)
1993 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1994 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1995 " echo 'return ...' \n"
2000 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2001 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2009 node
->dir
[node
->dirlen
- 1] = 0;
2010 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2013 dir_class
= "vtoydir";
2016 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2019 if (g_tree_view_menu_style
== 0)
2021 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2022 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2023 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2027 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2028 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2029 dir_alias
, dir_class
, node
->dir
+ offset
);
2034 dir_alias
= node
->dir
+ offset
;
2036 if (g_tree_view_menu_style
== 0)
2038 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2039 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2040 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2044 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2045 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2046 dir_alias
, dir_class
, node
->dir
+ offset
);
2050 if (g_tree_view_menu_style
== 0)
2052 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2053 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2054 " echo 'return ...' \n"
2059 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2060 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2066 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2068 ventoy_dynamic_tree_menu(child
);
2071 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2073 if (g_tree_view_menu_style
== 0)
2075 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2076 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2079 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2080 img
->unsupport
? "[***********] " : "",
2081 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2083 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2087 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2088 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2091 img
->unsupport
? "[***********] " : "",
2092 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2094 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2098 if (node
!= &g_img_iterator_head
)
2100 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2107 static int ventoy_set_default_menu(void)
2113 const char *strdata
= NULL
;
2114 img_info
*cur
= NULL
;
2115 img_info
*default_node
= NULL
;
2116 const char *default_image
= NULL
;
2118 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2119 if (default_image
&& default_image
[0] == '/')
2121 img_len
= grub_strlen(default_image
);
2123 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2125 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2137 if (0 == g_default_menu_mode
)
2139 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
2143 def
= grub_strdup(default_image
);
2149 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2151 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2152 if (strdata
&& strdata
[0] == '/')
2154 pos
= def
+ grub_strlen(strdata
);
2165 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2168 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2172 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
2180 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2182 img_info
*next
= NULL
;
2183 img_info
*cur
= g_ventoy_img_list
;
2196 g_ventoy_img_list
= NULL
;
2197 g_ventoy_img_count
= 0;
2199 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2202 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2205 img_info
*cur
= g_ventoy_img_list
;
2209 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2211 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2214 img_id
= grub_strtol(args
[0], NULL
, 10);
2215 if (img_id
>= g_ventoy_img_count
)
2217 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2220 debug("Find image %ld name \n", img_id
);
2222 while (cur
&& img_id
> 0)
2230 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2233 debug("image name is %s\n", cur
->name
);
2235 grub_env_set(args
[1], cur
->name
);
2237 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2240 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2244 img_info
*cur
= g_ventoy_img_list
;
2250 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2253 len
= (int)grub_strlen(args
[0]);
2257 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2266 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2269 grub_snprintf(id
, sizeof(id
), "VID_%d", cur
->id
);
2270 grub_env_set("chosen", id
);
2271 grub_env_export("chosen");
2273 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2276 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2281 const char *id
= NULL
;
2282 img_info
*cur
= g_ventoy_img_list
;
2286 if (argc
< 1 || argc
> 2)
2288 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2291 id
= grub_env_get("chosen");
2293 pos
= grub_strstr(id
, "VID_");
2296 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2300 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2305 if (img_id
== cur
->id
)
2314 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2317 grub_env_set(args
[0], cur
->path
);
2321 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2322 grub_env_set(args
[1], value
);
2325 g_svd_replace_offset
= 0;
2327 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2331 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2335 grub_device_t dev
= NULL
;
2336 img_info
*cur
= NULL
;
2337 img_info
*tail
= NULL
;
2338 const char *strdata
= NULL
;
2339 char *device_name
= NULL
;
2341 img_iterator_node
*node
= NULL
;
2342 img_iterator_node
*tmp
= NULL
;
2348 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2351 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2353 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2358 g_enumerate_time_checked
= 0;
2359 g_enumerate_start_time_ms
= grub_get_time_ms();
2361 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2362 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2364 g_filt_dot_underscore_file
= 1;
2367 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2368 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2370 g_sort_case_sensitive
= 1;
2373 device_name
= grub_file_get_device_name(args
[0]);
2379 g_enum_dev
= dev
= grub_device_open(device_name
);
2385 g_enum_fs
= fs
= grub_fs_probe(dev
);
2391 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2393 debug("unsupported fs:<%s>\n", fs
->name
);
2394 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2398 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2400 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2401 if (strdata
&& strdata
[0] == '1')
2403 g_default_menu_mode
= 1;
2406 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2408 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2410 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2411 if (strdata
&& strdata
[0] == '/')
2413 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2414 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2416 g_img_iterator_head
.dir
[len
++] = '/';
2418 g_img_iterator_head
.dirlen
= len
;
2422 g_img_iterator_head
.dirlen
= 1;
2423 grub_strcpy(g_img_iterator_head
.dir
, "/");
2426 g_img_iterator_head
.tail
= &tail
;
2428 if (g_img_max_search_level
< 0)
2430 g_img_max_search_level
= GRUB_INT_MAX
;
2431 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2432 if (strdata
&& ventoy_is_decimal(strdata
))
2434 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2438 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2439 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2440 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2441 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2442 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2443 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2445 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2447 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2450 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2451 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2453 g_tree_view_menu_style
= 1;
2456 ventoy_set_default_menu();
2458 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2460 ventoy_dynamic_tree_menu(node
);
2464 node
= g_img_iterator_head
.next
;
2472 /* sort image list by image name */
2473 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2475 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2477 if (ventoy_cmp_img(cur
, tail
) > 0)
2479 ventoy_swap_img(cur
, tail
);
2484 if (g_default_menu_mode
== 1)
2486 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2487 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2488 " echo 'return ...' \n"
2492 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2494 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2495 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2498 cur
->unsupport
? "[***********] " : "",
2499 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2501 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2504 g_tree_script_buf
[g_tree_script_pos
] = 0;
2505 g_list_script_buf
[g_list_script_pos
] = 0;
2507 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2508 grub_env_set(args
[1], buf
);
2512 check_free(device_name
, grub_free
);
2513 check_free(dev
, grub_device_close
);
2515 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2518 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2525 device_name
= grub_file_get_device_name(filename
);
2537 pos2
= grub_strstr(pos
, ",");
2540 pos2
= grub_strstr(pos
, ")");
2548 disk
= grub_disk_open(pos
);
2551 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2552 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2553 grub_disk_close(disk
);
2560 grub_free(device_name
);
2564 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2566 eltorito_descriptor desc
;
2568 grub_memset(&desc
, 0, sizeof(desc
));
2569 grub_file_seek(file
, 17 * 2048);
2570 grub_file_read(file
, &desc
, sizeof(desc
));
2572 if (desc
.type
!= 0 || desc
.version
!= 1)
2577 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2578 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2586 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2590 grub_uint8_t buf
[512];
2591 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2593 grub_file_seek(file
, sector
* 2048);
2594 grub_file_read(file
, buf
, sizeof(buf
));
2596 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2598 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2602 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2607 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2609 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2611 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2615 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2617 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2622 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2624 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2626 if (buf
[36] == parttype
[i
])
2628 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2634 debug("%s does not contain efi eltorito\n", file
->name
);
2638 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2641 const char *fs
= NULL
;
2642 const char *cdprompt
= NULL
;
2644 grub_uint8_t chksum
= 0;
2647 disk
= file
->device
->disk
;
2648 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2650 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2651 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2652 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2654 pos
= grub_strstr(file
->name
, "/");
2660 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2662 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2664 param
->vtoy_img_size
= file
->size
;
2666 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2667 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2669 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2671 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2672 param
->vtoy_reserved
[4] = 0;
2673 if (g_ventoy_chain_type
== 1) /* Windows */
2675 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2676 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2678 param
->vtoy_reserved
[4] = 1;
2682 fs
= ventoy_get_env("ventoy_fs_probe");
2683 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2685 param
->vtoy_reserved
[3] = 1;
2688 /* calculate checksum */
2689 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2691 chksum
+= *((grub_uint8_t
*)param
+ i
);
2693 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2698 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2700 grub_uint32_t i
= 0;
2701 grub_uint64_t total
= 0;
2702 grub_uint64_t fileblk
= 0;
2703 ventoy_img_chunk
*chunk
= NULL
;
2705 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2707 chunk
= chunklist
->chunk
+ i
;
2709 if (chunk
->disk_start_sector
<= start
)
2711 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2715 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2718 fileblk
= (file
->size
+ 511) / 512;
2720 if (total
!= fileblk
)
2722 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2723 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2725 debug("maybe img file to be processed.\n");
2735 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2739 grub_uint32_t i
= 0;
2740 grub_uint32_t sector
= 0;
2741 grub_uint32_t count
= 0;
2742 grub_off_t size
= 0;
2743 grub_off_t read
= 0;
2745 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2746 if (fs_type
== ventoy_fs_exfat
)
2748 grub_fat_get_file_chunk(start
, file
, chunklist
);
2750 else if (fs_type
== ventoy_fs_ext
)
2752 grub_ext_get_file_chunk(start
, file
, chunklist
);
2756 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2757 file
->read_hook_data
= chunklist
;
2759 for (size
= file
->size
; size
> 0; size
-= read
)
2761 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2762 grub_file_read(file
, NULL
, read
);
2765 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2767 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2768 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2771 if (ventoy_fs_udf
== fs_type
)
2773 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2775 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2776 chunklist
->chunk
[i
].img_start_sector
= sector
;
2777 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2783 len
= (int)grub_strlen(file
->name
);
2784 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2785 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2786 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2787 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2789 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2791 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2801 chunklist
->chunk
[i
].img_start_sector
= sector
;
2802 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2810 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2814 grub_disk_addr_t start
;
2819 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2822 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2825 g_conf_replace_node
= NULL
;
2826 g_conf_replace_offset
= 0;
2828 if (g_img_chunk_list
.chunk
)
2830 grub_free(g_img_chunk_list
.chunk
);
2833 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2835 grub_file_close(file
);
2836 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2839 /* get image chunk data */
2840 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2841 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2842 if (NULL
== g_img_chunk_list
.chunk
)
2844 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2847 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2848 g_img_chunk_list
.cur_chunk
= 0;
2850 start
= file
->device
->disk
->partition
->start
;
2852 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2854 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2855 grub_file_close(file
);
2859 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2862 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2863 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2866 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2868 grub_uint64_t offset
= 0;
2869 grub_uint32_t align
= 0;
2870 grub_file_t file
= NULL
;
2871 conf_replace
*node
= NULL
;
2877 debug("select conf replace argc:%d\n", argc
);
2884 node
= ventoy_plugin_find_conf_replace(args
[1]);
2887 debug("Conf replace not found for %s\n", args
[1]);
2891 debug("Find conf replace for %s\n", args
[1]);
2893 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2896 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2900 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2901 grub_file_close(file
);
2903 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2906 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2910 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2912 if (align
> vtoy_max_replace_file_size
)
2914 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2918 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2919 g_conf_replace_new_len
= (int)file
->size
;
2920 g_conf_replace_new_len_align
= align
;
2922 g_conf_replace_node
= node
;
2923 g_conf_replace_offset
= offset
+ 2;
2925 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2930 grub_file_close(file
);
2932 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2935 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2940 char configfile
[128];
2941 install_template
*node
= NULL
;
2947 debug("select auto installation argc:%d\n", argc
);
2954 node
= ventoy_plugin_find_install_template(args
[0]);
2957 debug("Auto install template not found for %s\n", args
[0]);
2961 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2963 node
->cursel
= node
->autosel
- 1;
2964 debug("Auto install template auto select %d\n", node
->autosel
);
2968 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2974 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2975 " echo %s\n}\n", "123");
2977 for (i
= 0; i
< node
->templatenum
; i
++)
2979 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2981 node
->templatepath
[i
].path
);
2984 g_ventoy_menu_esc
= 1;
2985 g_ventoy_suppress_esc
= 1;
2987 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2988 grub_script_execute_sourcecode(configfile
);
2990 g_ventoy_menu_esc
= 0;
2991 g_ventoy_suppress_esc
= 0;
2995 node
->cursel
= g_ventoy_last_entry
- 1;
2997 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3000 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3005 char configfile
[128];
3006 persistence_config
*node
;
3012 debug("select persistence argc:%d\n", argc
);
3019 node
= ventoy_plugin_find_persistent(args
[0]);
3022 debug("Persistence image not found for %s\n", args
[0]);
3026 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3028 node
->cursel
= node
->autosel
- 1;
3029 debug("Persistence image auto select %d\n", node
->autosel
);
3033 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3039 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3040 " echo %s\n}\n", "123");
3042 for (i
= 0; i
< node
->backendnum
; i
++)
3044 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3046 node
->backendpath
[i
].path
);
3050 g_ventoy_menu_esc
= 1;
3051 g_ventoy_suppress_esc
= 1;
3053 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3054 grub_script_execute_sourcecode(configfile
);
3056 g_ventoy_menu_esc
= 0;
3057 g_ventoy_suppress_esc
= 0;
3061 node
->cursel
= g_ventoy_last_entry
- 1;
3063 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3066 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3069 ventoy_img_chunk
*cur
;
3075 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3077 cur
= g_img_chunk_list
.chunk
+ i
;
3078 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3079 cur
->img_start_sector
, cur
->img_end_sector
,
3080 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3084 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3087 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3091 ventoy_img_chunk_list chunklist
;
3096 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3099 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3102 /* get image chunk data */
3103 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3104 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3105 if (NULL
== chunklist
.chunk
)
3107 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3110 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3111 chunklist
.cur_chunk
= 0;
3113 ventoy_get_block_list(file
, &chunklist
, 0);
3115 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3117 grub_printf("########## UNSUPPORTED ###############\n");
3120 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3122 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3124 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3125 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3128 grub_printf("\n==================================\n");
3130 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3132 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3133 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3134 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3135 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3136 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3140 grub_free(chunklist
.chunk
);
3141 grub_file_close(file
);
3143 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3146 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3149 ventoy_grub_param_file_replace
*replace
= NULL
;
3157 replace
= &(g_grub_param
->file_replace
);
3158 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3160 replace
->old_name_cnt
= 0;
3161 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3163 replace
->old_name_cnt
++;
3164 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3167 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3170 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3173 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3176 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3182 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3183 grub_env_set(args
[0], buf
);
3186 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3189 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3197 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3198 grub_printf("%s", g_list_script_buf
);
3202 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3203 grub_printf("%s", g_tree_script_buf
);
3209 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3211 img_info
*cur
= g_ventoy_img_list
;
3219 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3220 grub_printf("name:<%s>\n\n", cur
->name
);
3227 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3233 ventoy_plugin_dump_injection();
3238 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3244 ventoy_plugin_dump_auto_install();
3249 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3255 ventoy_plugin_dump_persistence();
3260 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3271 if (args
[0][0] == '0')
3273 return g_ventoy_memdisk_mode
? 0 : 1;
3275 else if (args
[0][0] == '1')
3277 return g_ventoy_iso_raw
? 0 : 1;
3279 else if (args
[0][0] == '2')
3281 return g_ventoy_iso_uefi_drv
? 0 : 1;
3283 else if (args
[0][0] == '3')
3285 return g_ventoy_grub2_mode
? 0 : 1;
3287 else if (args
[0][0] == '4')
3289 return g_ventoy_wimboot_mode
? 0 : 1;
3295 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3297 static int configfile_mode
= 0;
3298 char memfile
[128] = {0};
3305 * args[0]: 0:normal 1:configfile
3306 * args[1]: 0:list_buf 1:tree_buf
3311 debug("Invalid argc %d\n", argc
);
3317 if (args
[0][0] == '0')
3319 if (args
[1][0] == '0')
3321 grub_script_execute_sourcecode(g_list_script_buf
);
3325 grub_script_execute_sourcecode(g_tree_script_buf
);
3330 if (configfile_mode
)
3332 debug("Now already in F3 mode %d\n", configfile_mode
);
3336 if (args
[1][0] == '0')
3338 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3339 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3343 g_ventoy_last_entry
= -1;
3344 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3345 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3348 configfile_mode
= 1;
3349 grub_script_execute_sourcecode(memfile
);
3350 configfile_mode
= 0;
3356 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3367 g_ventoy_case_insensitive
= 1;
3368 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3369 g_ventoy_case_insensitive
= 0;
3375 grub_file_close(file
);
3381 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3386 const char *isopath
= NULL
;
3388 ventoy_mbr_head mbr
;
3395 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3398 isopath
= grub_env_get("vtoy_iso_part");
3401 debug("isopath is null %p\n", isopath
);
3405 debug("isopath is %s\n", isopath
);
3407 for (id
= 0; id
< 30 && (find
== 0); id
++)
3409 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3410 if (grub_strstr(isopath
, hdname
))
3412 debug("skip %s ...\n", hdname
);
3416 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3418 disk
= grub_disk_open(hdname
);
3421 debug("%s not exist\n", hdname
);
3425 grub_memset(&mbr
, 0, sizeof(mbr
));
3426 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3428 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3430 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3431 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3434 grub_env_set(args
[0], hdname
);
3438 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3442 debug("read %s failed\n", hdname
);
3445 grub_disk_close(disk
);
3451 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3462 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3465 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3468 debug("failed to open file %s\n", args
[0]);
3472 buf
= grub_malloc(len
);
3479 grub_file_read(file
, buf
, len
- 1);
3481 ventoy_get_line(buf
);
3482 ventoy_set_env(args
[1], buf
);
3486 grub_check_free(buf
);
3487 grub_file_close(file
);
3492 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3497 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3498 "0 %llu linear /dev/ventoy %llu\n",
3499 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3504 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3506 char *device_name
= NULL
;
3507 grub_device_t dev
= NULL
;
3512 g_part_list_pos
= 0;
3513 grub_env_unset("vtoy_img_part_file");
3520 device_name
= grub_file_get_device_name(args
[0]);
3523 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3527 dev
= grub_device_open(device_name
);
3530 debug("grub_device_open failed, %s\n", device_name
);
3534 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, NULL
);
3536 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3537 grub_env_set("vtoy_img_part_file", buf
);
3541 check_free(device_name
, grub_free
);
3542 check_free(dev
, grub_device_close
);
3548 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3559 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3562 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3565 debug("failed to open file %s\n", args
[0]);
3569 buf
= grub_malloc(file
->size
+ 1);
3575 buf
[file
->size
] = 0;
3576 grub_file_read(file
, buf
, file
->size
);
3578 if (grub_strstr(buf
, args
[1]))
3585 grub_check_free(buf
);
3586 grub_file_close(file
);
3591 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3597 ventoy_iso9660_vd pvd
;
3604 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3607 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3610 debug("failed to open file %s\n", args
[0]);
3614 grub_file_seek(file
, 16 * 2048);
3615 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3616 if (len
!= sizeof(pvd
))
3618 debug("failed to read pvd %d\n", len
);
3622 grub_memset(buf
, 0, sizeof(buf
));
3623 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3624 ventoy_set_env(args
[1], buf
);
3626 grub_memset(buf
, 0, sizeof(buf
));
3627 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3628 ventoy_set_env(args
[2], buf
);
3632 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3633 ventoy_set_env(args
[3], buf
);
3636 grub_file_close(file
);
3641 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3652 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3655 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3658 debug("failed to open file %s\n", args
[0]);
3662 grub_memset(buf
, 0, sizeof(buf
));
3663 grub_file_seek(file
, 16 * 2048 + 813);
3664 len
= (int)grub_file_read(file
, buf
, 17);
3667 debug("failed to read create date %d\n", len
);
3671 ventoy_set_env(args
[1], buf
);
3674 grub_file_close(file
);
3679 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3685 ventoy_env_hook_root(1);
3690 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3696 ventoy_env_hook_root(0);
3701 #ifdef GRUB_MACHINE_EFI
3702 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3707 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3713 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3714 if (var
&& *var
== 1)
3722 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3731 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3736 grub_uint64_t FileSectors
= 0;
3737 ventoy_gpt_info
*gpt
= NULL
;
3738 ventoy_part_table
*pt
= NULL
;
3739 grub_uint8_t zeroguid
[16] = {0};
3744 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3747 debug("failed to open file %s\n", args
[0]);
3751 if (file
->size
% 512)
3753 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3757 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3763 FileSectors
= file
->size
/ 512;
3765 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3766 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3768 debug("This is EFI partition table\n");
3770 for (i
= 0; i
< 128; i
++)
3772 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3774 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3776 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3777 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3785 debug("This is MBR partition table\n");
3787 for (i
= 0; i
< 4; i
++)
3789 pt
= gpt
->MBR
.PartTbl
+ i
;
3790 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3792 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3793 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3794 (ulonglong
)FileSectors
);
3803 grub_file_close(file
);
3804 grub_check_free(gpt
);
3805 grub_errno
= GRUB_ERR_NONE
;
3809 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3818 for (i
= 0; i
< 500; i
++)
3820 ret
= grub_getkey_noblock();
3821 if (ret
== GRUB_TERM_NO_KEY
)
3830 grub_printf("\n\n Still have key input after clear.\n");
3838 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3845 int image_sector_size
;
3847 ventoy_chain_head
*chain
;
3848 ventoy_img_chunk
*chunk
;
3849 ventoy_os_param
*osparam
;
3850 ventoy_image_location
*location
;
3851 ventoy_image_disk_region
*region
;
3852 struct grub_acpi_table_header
*acpi
;
3861 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3863 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3869 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3871 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3873 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3877 img_chunk_num
= chain
->img_chunk_num
;
3879 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3880 datalen
= sizeof(ventoy_os_param
) + loclen
;
3882 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3883 acpi
= grub_zalloc(buflen
);
3889 /* Step1: Fill acpi table header */
3890 grub_memcpy(acpi
->signature
, "VTOY", 4);
3891 acpi
->length
= buflen
;
3893 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3894 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3896 acpi
->creator_id
[0] = 1;
3897 acpi
->creator_rev
= 1;
3899 /* Step2: Fill data */
3900 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3901 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3902 osparam
->vtoy_img_location_addr
= 0;
3903 osparam
->vtoy_img_location_len
= loclen
;
3904 osparam
->chksum
= 0;
3905 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3907 location
= (ventoy_image_location
*)(osparam
+ 1);
3908 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3909 location
->image_sector_size
= image_sector_size
;
3910 location
->disk_sector_size
= chain
->disk_sector_size
;
3911 location
->region_count
= img_chunk_num
;
3913 region
= location
->regions
;
3914 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3915 if (512 == image_sector_size
)
3917 for (i
= 0; i
< img_chunk_num
; i
++)
3919 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3920 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3921 region
->disk_start_sector
= chunk
->disk_start_sector
;
3928 for (i
= 0; i
< img_chunk_num
; i
++)
3930 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3931 region
->image_start_sector
= chunk
->img_start_sector
;
3932 region
->disk_start_sector
= chunk
->disk_start_sector
;
3938 /* Step3: Fill acpi checksum */
3940 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3942 /* load acpi table */
3943 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3944 grub_script_execute_sourcecode(cmd
);
3948 VENTOY_CMD_RETURN(0);
3951 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3957 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3958 g_ventoy_last_entry
= -1;
3963 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3969 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3974 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3976 const char *pos
= filename
+ 1;
3984 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3986 grub_strncpy((char *)data
, filename
, 128);
3997 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4000 char *device_name
= NULL
;
4001 grub_device_t dev
= NULL
;
4002 grub_fs_t fs
= NULL
;
4003 char buf
[128] = {0};
4009 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4013 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4015 device_name
= grub_file_get_device_name(args
[0]);
4018 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4022 dev
= grub_device_open(device_name
);
4025 debug("grub_device_open failed, %s\n", device_name
);
4029 fs
= grub_fs_probe(dev
);
4032 debug("grub_fs_probe failed, %s\n", device_name
);
4036 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4040 ventoy_set_env(args
[2], buf
);
4047 check_free(device_name
, grub_free
);
4048 check_free(dev
, grub_device_close
);
4053 int ventoy_load_part_table(const char *diskname
)
4060 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4061 if (!g_ventoy_part_info
)
4066 disk
= grub_disk_open(diskname
);
4069 debug("Failed to open disk %s\n", diskname
);
4073 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4075 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4076 grub_disk_close(disk
);
4078 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4079 dev
= grub_device_open(name
);
4082 /* Check for official Ventoy device */
4083 ret
= ventoy_check_official_device(dev
);
4084 grub_device_close(dev
);
4092 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4093 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4098 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4105 ret
= ventoy_load_part_table(args
[0]);
4111 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4112 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4117 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4120 const char *vcfg
= NULL
;
4125 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4128 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4129 grub_env_set(args
[1], vcfg
);
4134 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4142 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4145 grub_uint8_t zeroguid
[16] = {0};
4150 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4153 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4155 if (id
>= 1 && id
<= 128)
4157 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4165 if (id
>= 1 && id
<= 4)
4167 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4177 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4180 char *device_name
= NULL
;
4181 grub_device_t dev
= NULL
;
4182 grub_fs_t fs
= NULL
;
4187 debug("get fs label for %s\n", args
[0]);
4191 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4195 device_name
= grub_file_get_device_name(args
[0]);
4198 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4202 dev
= grub_device_open(device_name
);
4205 debug("grub_device_open failed, %s\n", device_name
);
4209 fs
= grub_fs_probe(dev
);
4210 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4212 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4216 fs
->fs_label(dev
, &label
);
4219 debug("label=<%s>\n", label
);
4220 ventoy_set_env(args
[1], label
);
4228 check_free(device_name
, grub_free
);
4229 check_free(dev
, grub_device_close
);
4234 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4238 grub_snprintf((char *)data
, 256, "%s", filename
);
4245 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4247 if (info
->dir
&& filename
&& filename
[0] != '.')
4249 grub_snprintf((char *)data
, 256, "%s", filename
);
4256 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4259 char *device_name
= NULL
;
4260 grub_device_t dev
= NULL
;
4261 grub_fs_t fs
= NULL
;
4262 char name
[256] ={0};
4266 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4270 device_name
= grub_file_get_device_name(args
[0]);
4273 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4277 dev
= grub_device_open(device_name
);
4280 debug("grub_device_open failed, %s\n", device_name
);
4284 fs
= grub_fs_probe(dev
);
4287 debug("grub_fs_probe failed, %s\n", device_name
);
4291 fs
->fs_dir(dev
, args
[1], hook
, name
);
4294 ventoy_set_env(args
[2], name
);
4301 check_free(device_name
, grub_free
);
4302 check_free(dev
, grub_device_close
);
4307 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4310 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4313 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4316 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4319 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4329 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4333 for (pos
= args
[0]; *pos
; pos
++)
4347 grub_env_set(args
[1], args
[0]);
4357 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4367 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4372 len
= (int)grub_strlen(buf
);
4373 for (i
= len
; i
> 0; i
--)
4375 if (buf
[i
- 1] == '/')
4377 grub_env_set(args
[1], buf
+ i
);
4382 grub_env_set(args
[1], buf
);
4387 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4389 struct grub_video_mode_info info
;
4396 if (!g_video_mode_list
)
4398 ventoy_enum_video_mode();
4401 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4403 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4407 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4410 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4412 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4413 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4415 VENTOY_CMD_RETURN(0);
4418 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4420 struct grub_video_mode_info info
;
4427 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4429 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4433 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4436 grub_env_set(args
[0], buf
);
4438 VENTOY_CMD_RETURN(0);
4441 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4449 if (!g_video_mode_list
)
4454 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4455 if (id
< g_video_mode_num
)
4457 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4458 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4461 grub_env_set(args
[1], buf
);
4463 VENTOY_CMD_RETURN(0);
4466 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4469 grub_uint32_t loadsector
= 0;
4472 grub_uint32_t boot_catlog
= 0;
4473 grub_uint8_t buf
[512];
4479 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4483 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4486 debug("failed to open %s\n", args
[0]);
4490 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4491 if (boot_catlog
== 0)
4493 debug("No bootcatlog found\n");
4494 grub_file_close(file
);
4498 grub_memset(buf
, 0, sizeof(buf
));
4499 grub_file_seek(file
, boot_catlog
* 2048);
4500 grub_file_read(file
, buf
, sizeof(buf
));
4501 grub_file_close(file
);
4503 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4505 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4507 if (buf
[i
+ 32] == 0x88)
4509 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4510 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4516 if (loadsector
== 0)
4518 debug("No EFI eltorito info found\n");
4522 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4523 grub_env_set(args
[1], value
);
4524 VENTOY_CMD_RETURN(0);
4527 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4532 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4534 if (pfsdir
->initrd
[0])
4539 curpos
= pfsdir
->curpos
;
4540 len
= grub_strlen(filename
);
4544 if ((len
== 1 && filename
[0] == '.') ||
4545 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4550 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4553 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4554 pfsdir
->curpos
= curpos
+ printlen
;
4555 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4556 pfsdir
->curpos
= curpos
;
4557 pfsdir
->fullpath
[curpos
] = 0;
4561 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4564 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4565 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4567 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4569 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4578 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4582 char *device_name
= NULL
;
4583 grub_device_t dev
= NULL
;
4584 grub_fs_t fs
= NULL
;
4585 replace_fs_dir
*pfsdir
= NULL
;
4591 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4595 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4601 device_name
= grub_file_get_device_name(args
[0]);
4607 dev
= grub_device_open(device_name
);
4613 fs
= grub_fs_probe(dev
);
4622 pfsdir
->fullpath
[0] = '/';
4623 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4625 if (pfsdir
->initrd
[0])
4627 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4629 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4631 if (pfsdir
->initrd
[i
] == '/')
4633 pfsdir
->initrd
[i
] = '\\';
4637 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4638 grub_env_set(args
[1], pos
);
4642 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4647 grub_check_free(pfsdir
);
4648 grub_check_free(device_name
);
4649 check_free(dev
, grub_device_close
);
4651 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4654 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4656 const char *pager
= NULL
;
4662 pager
= grub_env_get("pager");
4666 grub_env_set("pager", "1");
4668 else if (pager
[0] == '1')
4674 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4676 grub_env_set("pager", "1");
4679 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4682 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4688 if (g_pager_flag
== 1)
4690 grub_env_unset("pager");
4692 else if (g_pager_flag
== 2)
4694 grub_env_set("pager", g_old_pager
);
4697 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4700 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4702 if (g_json_case_mis_path
[0])
4707 if (0 == info
->dir
&& grub_strncasecmp(filename
, "ventoy.json", 11) == 0)
4709 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4715 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4718 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4720 if (g_json_case_mis_path
[0])
4725 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4727 if (grub_strncasecmp(filename
, "ventoy", 6) == 0)
4729 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4730 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4731 if (g_json_case_mis_path
[0])
4741 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4744 char *device_name
= NULL
;
4745 grub_device_t dev
= NULL
;
4746 grub_fs_t fs
= NULL
;
4747 chk_case_fs_dir fs_dir
;
4753 device_name
= grub_file_get_device_name(args
[0]);
4759 dev
= grub_device_open(device_name
);
4765 fs
= grub_fs_probe(dev
);
4771 fstype
= ventoy_get_fs_type(fs
->name
);
4772 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4777 g_json_case_mis_path
[0] = 0;
4780 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4782 if (g_json_case_mis_path
[0])
4784 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4789 grub_check_free(device_name
);
4790 check_free(dev
, grub_device_close
);
4792 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4795 int ventoy_env_init(void)
4799 grub_env_set("vtdebug_flag", "");
4801 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4802 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4803 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4804 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4806 ventoy_filt_register(0, ventoy_wrapper_open
);
4808 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4811 g_grub_param
->grub_env_get
= grub_env_get
;
4812 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4813 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4814 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4815 grub_env_set("env_param", buf
);
4816 grub_env_set("ventoy_env_param", buf
);
4818 grub_env_export("env_param");
4819 grub_env_export("ventoy_env_param");
4822 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
4823 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
4825 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
4826 grub_env_set("vtoy_winpeshl_ini_size", buf
);
4828 grub_env_export("vtoy_winpeshl_ini_addr");
4829 grub_env_export("vtoy_winpeshl_ini_size");
4831 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
4832 grub_env_set("vtoy_chain_file_size", buf
);
4833 grub_env_export("vtoy_chain_file_size");
4835 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
4836 grub_env_set("vtoy_chain_file_read", buf
);
4837 grub_env_export("vtoy_chain_file_read");
4842 static cmd_para ventoy_cmds
[] =
4844 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4845 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4846 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4847 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4848 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4849 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4850 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4851 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4852 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4853 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4854 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4855 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4856 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4857 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4858 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4859 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4860 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4861 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4862 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4863 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4864 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4865 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4866 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4867 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4869 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4870 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4871 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4872 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4873 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4874 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4875 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4877 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4878 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4879 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4880 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4881 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
4882 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4883 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4884 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4885 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4886 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4889 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4890 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4891 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4892 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4893 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4894 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4895 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4896 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4897 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4898 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4899 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4901 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4902 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
4903 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4904 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4905 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4906 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4907 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4909 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4910 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4911 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4912 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4913 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4914 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4915 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4916 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4917 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4918 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4920 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4921 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4922 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
4923 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4924 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4925 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4926 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4927 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4928 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4930 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4931 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
4932 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4933 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4936 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4937 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4938 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
4940 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
4941 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
4942 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
4945 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
4946 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
4947 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
4948 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
4949 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
4950 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
4951 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
4952 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
4953 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
4954 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
4955 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
4957 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
4958 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
4959 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
4960 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
4961 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
4962 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
4963 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
4964 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
4965 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
4966 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
4968 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
4969 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
4970 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
4971 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
4972 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
4973 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
4976 int ventoy_register_all_cmd(void)
4979 cmd_para
*cur
= NULL
;
4981 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4983 cur
= ventoy_cmds
+ i
;
4984 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
4985 cur
->summary
, cur
->description
, cur
->parser
);
4991 int ventoy_unregister_all_cmd(void)
4995 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
4997 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);