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 const menu_tip
*tip
;
1566 img_iterator_node
*tmp
;
1567 img_iterator_node
*new_node
;
1568 img_iterator_node
*node
= (img_iterator_node
*)data
;
1570 if (g_enumerate_time_checked
== 0)
1572 g_enumerate_finish_time_ms
= grub_get_time_ms();
1573 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1576 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1578 g_enumerate_time_checked
= 1;
1582 len
= grub_strlen(filename
);
1586 if (node
->level
+ 1 > g_img_max_search_level
)
1591 if ((len
== 1 && filename
[0] == '.') ||
1592 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1597 if (!ventoy_img_name_valid(filename
, len
))
1602 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1607 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1609 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1610 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1613 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1618 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1621 new_node
->level
= node
->level
+ 1;
1622 new_node
->plugin_list_index
= index
;
1623 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1625 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1628 debug("Directory %s ignored...\n", new_node
->dir
);
1629 grub_free(new_node
);
1633 new_node
->tail
= node
->tail
;
1635 new_node
->parent
= node
;
1636 if (!node
->firstchild
)
1638 node
->firstchild
= new_node
;
1641 if (g_img_iterator_tail
)
1643 g_img_iterator_tail
->next
= new_node
;
1644 g_img_iterator_tail
= new_node
;
1648 g_img_iterator_head
.next
= new_node
;
1649 g_img_iterator_tail
= new_node
;
1655 debug("Find a file %s\n", filename
);
1661 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1663 type
= img_type_iso
;
1665 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1667 type
= img_type_wim
;
1669 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1670 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1672 type
= img_type_vhd
;
1674 #ifdef GRUB_MACHINE_EFI
1675 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1677 type
= img_type_efi
;
1680 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1682 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1684 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1685 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1690 type
= img_type_img
;
1692 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1694 type
= img_type_vtoy
;
1696 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1698 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1700 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1701 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1710 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1715 if (g_plugin_image_list
)
1717 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1718 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1719 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1721 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1724 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1726 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1731 img
= grub_zalloc(sizeof(img_info
));
1735 img
->plugin_list_index
= index
;
1736 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1738 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1740 img
->size
= info
->size
;
1743 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1746 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1748 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1753 if (g_ventoy_img_list
)
1755 tail
= *(node
->tail
);
1761 g_ventoy_img_list
= img
;
1764 img
->id
= g_ventoy_img_count
;
1766 if (node
&& NULL
== node
->firstiso
)
1768 node
->firstiso
= img
;
1779 *((img_info
**)(node
->tail
)) = img
;
1780 g_ventoy_img_count
++;
1782 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1784 tip
= ventoy_plugin_get_menu_tip(img
->path
);
1787 img
->tip1
= tip
->tip1
;
1788 img
->tip2
= tip
->tip2
;
1791 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1794 img
->class = g_menu_class
[type
];
1796 img
->menu_prefix
= g_menu_prefix
[type
];
1798 if (img_type_iso
== type
)
1800 if (ventoy_plugin_check_memdisk(img
->path
))
1802 img
->menu_prefix
= "miso";
1806 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1813 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1815 int len
= GRUB_UINT_MAX
;
1816 const char *value
= NULL
;
1817 char name
[32] = {0};
1818 char plat
[32] = {0};
1819 char guidstr
[32] = {0};
1820 ventoy_guid guid
= VENTOY_GUID
;
1821 const char *fmt1
= NULL
;
1822 const char *fmt2
= NULL
;
1823 const char *fmt3
= NULL
;
1824 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1825 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1826 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1827 const char fmtcode
[]={
1828 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1829 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1830 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1831 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1832 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1833 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1836 grub_memset(name
, 0, sizeof(name
));
1837 puint
[0] = grub_swap_bytes32(0x56454e54);
1838 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1839 puint
[2] = grub_swap_bytes32(0x45525349);
1840 puint
[1] = grub_swap_bytes32(0x4f595f56);
1841 value
= ventoy_get_env(name
);
1843 grub_memset(name
, 0, sizeof(name
));
1844 puint
[1] = grub_swap_bytes32(0x5f544f50);
1845 puint
[0] = grub_swap_bytes32(0x56544c45);
1846 fmt1
= ventoy_get_env(name
);
1852 grub_memset(name
, 0, sizeof(name
));
1853 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1854 puint
[0] = grub_swap_bytes32(0x56544c45);
1855 fmt2
= ventoy_get_env(name
);
1857 grub_memset(name
, 0, sizeof(name
));
1858 puint
[1] = grub_swap_bytes32(0x5f434c52);
1859 puint
[0] = grub_swap_bytes32(0x56544c45);
1860 fmt3
= ventoy_get_env(name
);
1862 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1864 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1866 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1867 #pragma GCC diagnostic push
1868 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1869 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1870 fmt1
? fmt1
: fmtdata
,
1871 fmt2
? fmt2
: fmtdata
+ 4,
1872 value
? value
: "", plat
, guidstr
,
1873 fmt3
? fmt3
: fmtdata
+ 6);
1874 #pragma GCC diagnostic pop
1876 grub_memset(name
, 0, sizeof(name
));
1877 puint
[0] = grub_swap_bytes32(0x76746f79);
1878 puint
[2] = grub_swap_bytes32(0x656e7365);
1879 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1880 ventoy_set_env(name
, guidstr
);
1885 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1889 grub_uint8_t md5
[16];
1893 grub_memset(input
, 0, sizeof(input
));
1895 grub_printf("Enter password: ");
1898 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1900 grub_password_get(input
, 128);
1901 if (grub_strcmp(pwd
->text
, input
) == 0)
1906 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1908 grub_password_get(input
, 128);
1909 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1910 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1915 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1917 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1918 grub_password_get(input
+ offset
, 128);
1920 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1921 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1927 grub_printf("Invalid password!\n\n");
1934 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1936 img_info
*minimg
= NULL
;
1937 img_info
*img
= (img_info
*)(node
->firstiso
);
1939 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1941 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1956 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1958 img_iterator_node
*Minchild
= NULL
;
1959 img_iterator_node
*child
= node
->firstchild
;
1961 while (child
&& child
->parent
== node
)
1963 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1967 child
= child
->next
;
1972 Minchild
->select
= 1;
1978 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1981 img_info
*img
= NULL
;
1982 const char *dir_class
= NULL
;
1983 const char *dir_alias
= NULL
;
1984 img_iterator_node
*child
= NULL
;
1986 if (node
->isocnt
== 0 || node
->done
== 1)
1991 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1993 offset
= node
->parent
->dirlen
;
1996 if (node
== &g_img_iterator_head
)
1998 if (g_default_menu_mode
== 0)
2000 if (g_tree_view_menu_style
== 0)
2002 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2003 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2004 " echo 'return ...' \n"
2009 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2010 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2018 node
->dir
[node
->dirlen
- 1] = 0;
2019 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2022 dir_class
= "vtoydir";
2025 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2028 if (g_tree_view_menu_style
== 0)
2030 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2031 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2032 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2036 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2037 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2038 dir_alias
, dir_class
, node
->dir
+ offset
);
2043 dir_alias
= node
->dir
+ offset
;
2045 if (g_tree_view_menu_style
== 0)
2047 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2048 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2049 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2053 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2054 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2055 dir_alias
, dir_class
, node
->dir
+ offset
);
2059 if (g_tree_view_menu_style
== 0)
2061 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2062 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2063 " echo 'return ...' \n"
2068 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2069 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2075 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2077 ventoy_dynamic_tree_menu(child
);
2080 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2082 if (g_tree_view_menu_style
== 0)
2084 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2085 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2088 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2089 img
->unsupport
? "[***********] " : "",
2090 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2092 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2096 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2097 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2100 img
->unsupport
? "[***********] " : "",
2101 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2103 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2107 if (node
!= &g_img_iterator_head
)
2109 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2116 static int ventoy_set_default_menu(void)
2122 const char *strdata
= NULL
;
2123 img_info
*cur
= NULL
;
2124 img_info
*default_node
= NULL
;
2125 const char *default_image
= NULL
;
2127 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2128 if (default_image
&& default_image
[0] == '/')
2130 img_len
= grub_strlen(default_image
);
2132 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2134 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2146 if (0 == g_default_menu_mode
)
2148 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2152 def
= grub_strdup(default_image
);
2158 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2160 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2161 if (strdata
&& strdata
[0] == '/')
2163 pos
= def
+ grub_strlen(strdata
);
2174 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2177 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2181 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2189 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2191 img_info
*next
= NULL
;
2192 img_info
*cur
= g_ventoy_img_list
;
2205 g_ventoy_img_list
= NULL
;
2206 g_ventoy_img_count
= 0;
2208 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2211 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2214 img_info
*cur
= g_ventoy_img_list
;
2218 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2220 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2223 img_id
= grub_strtol(args
[0], NULL
, 10);
2224 if (img_id
>= g_ventoy_img_count
)
2226 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2229 debug("Find image %ld name \n", img_id
);
2231 while (cur
&& img_id
> 0)
2239 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2242 debug("image name is %s\n", cur
->name
);
2244 grub_env_set(args
[1], cur
->name
);
2246 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2249 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2253 img_info
*cur
= g_ventoy_img_list
;
2259 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2262 len
= (int)grub_strlen(args
[0]);
2266 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2275 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2278 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2279 grub_env_set("chosen", id
);
2280 grub_env_export("chosen");
2282 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2285 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2289 const char *id
= NULL
;
2290 img_info
*cur
= NULL
;
2294 if (argc
< 1 || argc
> 2)
2296 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2299 id
= grub_env_get("chosen");
2301 pos
= grub_strstr(id
, "VID_");
2304 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2308 cur
= g_ventoy_img_list
;
2313 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2316 grub_env_set(args
[0], cur
->path
);
2320 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2321 grub_env_set(args
[1], value
);
2324 g_svd_replace_offset
= 0;
2326 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2330 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2334 grub_device_t dev
= NULL
;
2335 img_info
*cur
= NULL
;
2336 img_info
*tail
= NULL
;
2337 img_info
*min
= NULL
;
2338 img_info
*head
= NULL
;
2339 const char *strdata
= NULL
;
2340 char *device_name
= NULL
;
2342 img_iterator_node
*node
= NULL
;
2343 img_iterator_node
*tmp
= NULL
;
2349 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2352 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2354 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2359 g_enumerate_time_checked
= 0;
2360 g_enumerate_start_time_ms
= grub_get_time_ms();
2362 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2363 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2365 g_filt_dot_underscore_file
= 1;
2368 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2369 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2371 g_sort_case_sensitive
= 1;
2374 device_name
= grub_file_get_device_name(args
[0]);
2380 g_enum_dev
= dev
= grub_device_open(device_name
);
2386 g_enum_fs
= fs
= grub_fs_probe(dev
);
2392 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2394 debug("unsupported fs:<%s>\n", fs
->name
);
2395 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2399 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2401 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2402 if (strdata
&& strdata
[0] == '1')
2404 g_default_menu_mode
= 1;
2407 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2409 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2411 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2412 if (strdata
&& strdata
[0] == '/')
2414 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2415 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2417 g_img_iterator_head
.dir
[len
++] = '/';
2419 g_img_iterator_head
.dirlen
= len
;
2423 g_img_iterator_head
.dirlen
= 1;
2424 grub_strcpy(g_img_iterator_head
.dir
, "/");
2427 g_img_iterator_head
.tail
= &tail
;
2429 if (g_img_max_search_level
< 0)
2431 g_img_max_search_level
= GRUB_INT_MAX
;
2432 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2433 if (strdata
&& ventoy_is_decimal(strdata
))
2435 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2439 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2440 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2441 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2442 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2443 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2444 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2446 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2448 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2451 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2452 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2454 g_tree_view_menu_style
= 1;
2457 ventoy_set_default_menu();
2459 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2461 ventoy_dynamic_tree_menu(node
);
2465 node
= g_img_iterator_head
.next
;
2473 /* sort image list by image name */
2474 while (g_ventoy_img_list
)
2476 min
= g_ventoy_img_list
;
2477 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2479 if (ventoy_cmp_img(min
, cur
) > 0)
2487 min
->prev
->next
= min
->next
;
2492 min
->next
->prev
= min
->prev
;
2495 if (min
== g_ventoy_img_list
)
2497 g_ventoy_img_list
= min
->next
;
2515 g_ventoy_img_list
= head
;
2517 if (g_default_menu_mode
== 1)
2519 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2520 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2521 " echo 'return ...' \n"
2525 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2527 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2528 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2531 cur
->unsupport
? "[***********] " : "",
2532 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2534 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2537 g_tree_script_buf
[g_tree_script_pos
] = 0;
2538 g_list_script_buf
[g_list_script_pos
] = 0;
2540 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2541 grub_env_set(args
[1], buf
);
2545 check_free(device_name
, grub_free
);
2546 check_free(dev
, grub_device_close
);
2548 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2551 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2558 device_name
= grub_file_get_device_name(filename
);
2570 pos2
= grub_strstr(pos
, ",");
2573 pos2
= grub_strstr(pos
, ")");
2581 disk
= grub_disk_open(pos
);
2584 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2585 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2586 grub_disk_close(disk
);
2593 grub_free(device_name
);
2597 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2599 eltorito_descriptor desc
;
2601 grub_memset(&desc
, 0, sizeof(desc
));
2602 grub_file_seek(file
, 17 * 2048);
2603 grub_file_read(file
, &desc
, sizeof(desc
));
2605 if (desc
.type
!= 0 || desc
.version
!= 1)
2610 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2611 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2619 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2623 grub_uint8_t buf
[512];
2624 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2626 grub_file_seek(file
, sector
* 2048);
2627 grub_file_read(file
, buf
, sizeof(buf
));
2629 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2631 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2635 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2640 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2642 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2644 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2648 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2650 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2655 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2657 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2659 if (buf
[36] == parttype
[i
])
2661 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2667 debug("%s does not contain efi eltorito\n", file
->name
);
2671 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2674 const char *fs
= NULL
;
2675 const char *cdprompt
= NULL
;
2677 grub_uint8_t chksum
= 0;
2680 disk
= file
->device
->disk
;
2681 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2683 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2684 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2685 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2687 pos
= grub_strstr(file
->name
, "/");
2693 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2695 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2697 param
->vtoy_img_size
= file
->size
;
2699 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2700 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2702 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2704 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2705 param
->vtoy_reserved
[4] = 0;
2706 if (g_ventoy_chain_type
== 1) /* Windows */
2708 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2709 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2711 param
->vtoy_reserved
[4] = 1;
2715 fs
= ventoy_get_env("ventoy_fs_probe");
2716 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2718 param
->vtoy_reserved
[3] = 1;
2721 /* calculate checksum */
2722 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2724 chksum
+= *((grub_uint8_t
*)param
+ i
);
2726 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2731 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2733 grub_uint32_t i
= 0;
2734 grub_uint64_t total
= 0;
2735 grub_uint64_t fileblk
= 0;
2736 ventoy_img_chunk
*chunk
= NULL
;
2738 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2740 chunk
= chunklist
->chunk
+ i
;
2742 if (chunk
->disk_start_sector
<= start
)
2744 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2748 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2751 fileblk
= (file
->size
+ 511) / 512;
2753 if (total
!= fileblk
)
2755 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2756 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2758 debug("maybe img file to be processed.\n");
2768 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2772 grub_uint32_t i
= 0;
2773 grub_uint32_t sector
= 0;
2774 grub_uint32_t count
= 0;
2775 grub_off_t size
= 0;
2776 grub_off_t read
= 0;
2778 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2779 if (fs_type
== ventoy_fs_exfat
)
2781 grub_fat_get_file_chunk(start
, file
, chunklist
);
2783 else if (fs_type
== ventoy_fs_ext
)
2785 grub_ext_get_file_chunk(start
, file
, chunklist
);
2789 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2790 file
->read_hook_data
= chunklist
;
2792 for (size
= file
->size
; size
> 0; size
-= read
)
2794 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2795 grub_file_read(file
, NULL
, read
);
2798 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2800 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2801 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2804 if (ventoy_fs_udf
== fs_type
)
2806 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2808 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2809 chunklist
->chunk
[i
].img_start_sector
= sector
;
2810 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2816 len
= (int)grub_strlen(file
->name
);
2817 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2818 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2819 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2820 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2822 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2824 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2834 chunklist
->chunk
[i
].img_start_sector
= sector
;
2835 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2843 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2847 grub_disk_addr_t start
;
2852 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2855 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2858 g_conf_replace_node
= NULL
;
2859 g_conf_replace_offset
= 0;
2861 if (g_img_chunk_list
.chunk
)
2863 grub_free(g_img_chunk_list
.chunk
);
2866 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2868 grub_file_close(file
);
2869 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2872 /* get image chunk data */
2873 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2874 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2875 if (NULL
== g_img_chunk_list
.chunk
)
2877 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2880 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2881 g_img_chunk_list
.cur_chunk
= 0;
2883 start
= file
->device
->disk
->partition
->start
;
2885 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2887 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2888 grub_file_close(file
);
2892 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2895 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2896 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2899 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2901 grub_uint64_t offset
= 0;
2902 grub_uint32_t align
= 0;
2903 grub_file_t file
= NULL
;
2904 conf_replace
*node
= NULL
;
2910 debug("select conf replace argc:%d\n", argc
);
2917 node
= ventoy_plugin_find_conf_replace(args
[1]);
2920 debug("Conf replace not found for %s\n", args
[1]);
2924 debug("Find conf replace for %s\n", args
[1]);
2926 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2929 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2933 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2934 grub_file_close(file
);
2936 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2939 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2943 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2945 if (align
> vtoy_max_replace_file_size
)
2947 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2951 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2952 g_conf_replace_new_len
= (int)file
->size
;
2953 g_conf_replace_new_len_align
= align
;
2955 g_conf_replace_node
= node
;
2956 g_conf_replace_offset
= offset
+ 2;
2958 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2963 grub_file_close(file
);
2965 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2968 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2974 char configfile
[128];
2975 install_template
*node
= NULL
;
2981 debug("select auto installation argc:%d\n", argc
);
2988 node
= ventoy_plugin_find_install_template(args
[0]);
2991 debug("Auto install template not found for %s\n", args
[0]);
2995 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2997 defidx
= node
->autosel
;
2998 if (node
->timeout
< 0)
3000 node
->cursel
= node
->autosel
- 1;
3001 debug("Auto install template auto select %d\n", node
->autosel
);
3006 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3012 if (node
->timeout
> 0)
3014 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3017 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3018 " echo %s\n}\n", "");
3020 for (i
= 0; i
< node
->templatenum
; i
++)
3022 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3024 node
->templatepath
[i
].path
);
3027 g_ventoy_menu_esc
= 1;
3028 g_ventoy_suppress_esc
= 1;
3029 g_ventoy_suppress_esc_default
= defidx
;
3031 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3032 grub_script_execute_sourcecode(configfile
);
3034 g_ventoy_menu_esc
= 0;
3035 g_ventoy_suppress_esc
= 0;
3036 g_ventoy_suppress_esc_default
= 1;
3040 node
->cursel
= g_ventoy_last_entry
- 1;
3042 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3045 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3051 char configfile
[128];
3052 persistence_config
*node
;
3058 debug("select persistence argc:%d\n", argc
);
3065 node
= ventoy_plugin_find_persistent(args
[0]);
3068 debug("Persistence image not found for %s\n", args
[0]);
3072 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3074 defidx
= node
->autosel
;
3075 if (node
->timeout
< 0)
3077 node
->cursel
= node
->autosel
- 1;
3078 debug("Persistence image auto select %d\n", node
->autosel
);
3083 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3089 if (node
->timeout
> 0)
3091 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3094 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3095 " echo %s\n}\n", "");
3097 for (i
= 0; i
< node
->backendnum
; i
++)
3099 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3101 node
->backendpath
[i
].path
);
3105 g_ventoy_menu_esc
= 1;
3106 g_ventoy_suppress_esc
= 1;
3107 g_ventoy_suppress_esc_default
= defidx
;
3109 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3110 grub_script_execute_sourcecode(configfile
);
3112 g_ventoy_menu_esc
= 0;
3113 g_ventoy_suppress_esc
= 0;
3114 g_ventoy_suppress_esc_default
= 1;
3118 node
->cursel
= g_ventoy_last_entry
- 1;
3120 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3123 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3126 ventoy_img_chunk
*cur
;
3132 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3134 cur
= g_img_chunk_list
.chunk
+ i
;
3135 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3136 cur
->img_start_sector
, cur
->img_end_sector
,
3137 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3141 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3144 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3148 ventoy_img_chunk_list chunklist
;
3153 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3156 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3159 /* get image chunk data */
3160 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3161 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3162 if (NULL
== chunklist
.chunk
)
3164 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3167 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3168 chunklist
.cur_chunk
= 0;
3170 ventoy_get_block_list(file
, &chunklist
, 0);
3172 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3174 grub_printf("########## UNSUPPORTED ###############\n");
3177 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3179 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3181 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3182 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3185 grub_printf("\n==================================\n");
3187 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3189 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3190 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3191 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3192 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3193 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3197 grub_free(chunklist
.chunk
);
3198 grub_file_close(file
);
3200 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3203 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3206 ventoy_grub_param_file_replace
*replace
= NULL
;
3214 replace
= &(g_grub_param
->file_replace
);
3215 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3217 replace
->old_name_cnt
= 0;
3218 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3220 replace
->old_name_cnt
++;
3221 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3224 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3227 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3230 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3233 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3239 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3240 grub_env_set(args
[0], buf
);
3243 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3246 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3254 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3255 grub_printf("%s", g_list_script_buf
);
3259 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3260 grub_printf("%s", g_tree_script_buf
);
3266 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3268 img_info
*cur
= g_ventoy_img_list
;
3276 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3277 grub_printf("name:<%s>\n\n", cur
->name
);
3284 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3290 ventoy_plugin_dump_injection();
3295 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3301 ventoy_plugin_dump_auto_install();
3306 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3312 ventoy_plugin_dump_persistence();
3317 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3328 if (args
[0][0] == '0')
3330 return g_ventoy_memdisk_mode
? 0 : 1;
3332 else if (args
[0][0] == '1')
3334 return g_ventoy_iso_raw
? 0 : 1;
3336 else if (args
[0][0] == '2')
3338 return g_ventoy_iso_uefi_drv
? 0 : 1;
3340 else if (args
[0][0] == '3')
3342 return g_ventoy_grub2_mode
? 0 : 1;
3344 else if (args
[0][0] == '4')
3346 return g_ventoy_wimboot_mode
? 0 : 1;
3352 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3354 static int configfile_mode
= 0;
3355 char memfile
[128] = {0};
3362 * args[0]: 0:normal 1:configfile
3363 * args[1]: 0:list_buf 1:tree_buf
3368 debug("Invalid argc %d\n", argc
);
3374 if (args
[0][0] == '0')
3376 if (args
[1][0] == '0')
3378 grub_script_execute_sourcecode(g_list_script_buf
);
3382 grub_script_execute_sourcecode(g_tree_script_buf
);
3387 if (configfile_mode
)
3389 debug("Now already in F3 mode %d\n", configfile_mode
);
3393 if (args
[1][0] == '0')
3395 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3396 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3400 g_ventoy_last_entry
= -1;
3401 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3402 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3405 configfile_mode
= 1;
3406 grub_script_execute_sourcecode(memfile
);
3407 configfile_mode
= 0;
3413 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3424 g_ventoy_case_insensitive
= 1;
3425 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3426 g_ventoy_case_insensitive
= 0;
3432 grub_file_close(file
);
3438 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3443 const char *isopath
= NULL
;
3445 ventoy_mbr_head mbr
;
3452 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3455 isopath
= grub_env_get("vtoy_iso_part");
3458 debug("isopath is null %p\n", isopath
);
3462 debug("isopath is %s\n", isopath
);
3464 for (id
= 0; id
< 30 && (find
== 0); id
++)
3466 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3467 if (grub_strstr(isopath
, hdname
))
3469 debug("skip %s ...\n", hdname
);
3473 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3475 disk
= grub_disk_open(hdname
);
3478 debug("%s not exist\n", hdname
);
3482 grub_memset(&mbr
, 0, sizeof(mbr
));
3483 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3485 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3487 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3488 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3491 grub_env_set(args
[0], hdname
);
3495 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3499 debug("read %s failed\n", hdname
);
3502 grub_disk_close(disk
);
3508 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3519 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3522 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3525 debug("failed to open file %s\n", args
[0]);
3529 buf
= grub_malloc(len
);
3536 grub_file_read(file
, buf
, len
- 1);
3538 ventoy_get_line(buf
);
3539 ventoy_set_env(args
[1], buf
);
3543 grub_check_free(buf
);
3544 grub_file_close(file
);
3549 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3551 int *pCnt
= (int *)data
;
3556 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3557 "0 %llu linear /dev/ventoy %llu\n",
3558 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3563 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3566 char *device_name
= NULL
;
3567 grub_device_t dev
= NULL
;
3572 g_part_list_pos
= 0;
3573 grub_env_unset("vtoy_img_part_file");
3580 device_name
= grub_file_get_device_name(args
[0]);
3583 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3587 dev
= grub_device_open(device_name
);
3590 debug("grub_device_open failed, %s\n", device_name
);
3594 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3596 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3597 grub_env_set("vtoy_img_part_file", buf
);
3599 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3600 grub_env_set("vtoy_img_part_cnt", buf
);
3604 check_free(device_name
, grub_free
);
3605 check_free(dev
, grub_device_close
);
3611 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3622 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3625 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3628 debug("failed to open file %s\n", args
[0]);
3632 buf
= grub_malloc(file
->size
+ 1);
3638 buf
[file
->size
] = 0;
3639 grub_file_read(file
, buf
, file
->size
);
3641 if (grub_strstr(buf
, args
[1]))
3648 grub_check_free(buf
);
3649 grub_file_close(file
);
3654 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3660 ventoy_iso9660_vd pvd
;
3667 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3670 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3673 debug("failed to open file %s\n", args
[0]);
3677 grub_file_seek(file
, 16 * 2048);
3678 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3679 if (len
!= sizeof(pvd
))
3681 debug("failed to read pvd %d\n", len
);
3685 grub_memset(buf
, 0, sizeof(buf
));
3686 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3687 ventoy_set_env(args
[1], buf
);
3689 grub_memset(buf
, 0, sizeof(buf
));
3690 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3691 ventoy_set_env(args
[2], buf
);
3695 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3696 ventoy_set_env(args
[3], buf
);
3699 grub_file_close(file
);
3704 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3715 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3718 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3721 debug("failed to open file %s\n", args
[0]);
3725 grub_memset(buf
, 0, sizeof(buf
));
3726 grub_file_seek(file
, 16 * 2048 + 813);
3727 len
= (int)grub_file_read(file
, buf
, 17);
3730 debug("failed to read create date %d\n", len
);
3734 ventoy_set_env(args
[1], buf
);
3737 grub_file_close(file
);
3742 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3748 ventoy_env_hook_root(1);
3753 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3759 ventoy_env_hook_root(0);
3764 #ifdef GRUB_MACHINE_EFI
3765 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3770 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3776 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3777 if (var
&& *var
== 1)
3785 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3794 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3799 grub_uint64_t FileSectors
= 0;
3800 ventoy_gpt_info
*gpt
= NULL
;
3801 ventoy_part_table
*pt
= NULL
;
3802 grub_uint8_t zeroguid
[16] = {0};
3807 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3810 debug("failed to open file %s\n", args
[0]);
3814 if (file
->size
% 512)
3816 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3820 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3826 FileSectors
= file
->size
/ 512;
3828 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3829 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3831 debug("This is EFI partition table\n");
3833 for (i
= 0; i
< 128; i
++)
3835 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3837 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3839 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3840 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3848 debug("This is MBR partition table\n");
3850 for (i
= 0; i
< 4; i
++)
3852 pt
= gpt
->MBR
.PartTbl
+ i
;
3853 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3855 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3856 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3857 (ulonglong
)FileSectors
);
3866 grub_file_close(file
);
3867 grub_check_free(gpt
);
3868 grub_errno
= GRUB_ERR_NONE
;
3872 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3881 for (i
= 0; i
< 500; i
++)
3883 ret
= grub_getkey_noblock();
3884 if (ret
== GRUB_TERM_NO_KEY
)
3893 grub_printf("\n\n Still have key input after clear.\n");
3901 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3908 int image_sector_size
;
3910 ventoy_chain_head
*chain
;
3911 ventoy_img_chunk
*chunk
;
3912 ventoy_os_param
*osparam
;
3913 ventoy_image_location
*location
;
3914 ventoy_image_disk_region
*region
;
3915 struct grub_acpi_table_header
*acpi
;
3924 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3926 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3932 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3934 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3936 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3940 img_chunk_num
= chain
->img_chunk_num
;
3942 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3943 datalen
= sizeof(ventoy_os_param
) + loclen
;
3945 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3946 acpi
= grub_zalloc(buflen
);
3952 /* Step1: Fill acpi table header */
3953 grub_memcpy(acpi
->signature
, "VTOY", 4);
3954 acpi
->length
= buflen
;
3956 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3957 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3959 acpi
->creator_id
[0] = 1;
3960 acpi
->creator_rev
= 1;
3962 /* Step2: Fill data */
3963 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3964 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3965 osparam
->vtoy_img_location_addr
= 0;
3966 osparam
->vtoy_img_location_len
= loclen
;
3967 osparam
->chksum
= 0;
3968 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3970 location
= (ventoy_image_location
*)(osparam
+ 1);
3971 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3972 location
->image_sector_size
= image_sector_size
;
3973 location
->disk_sector_size
= chain
->disk_sector_size
;
3974 location
->region_count
= img_chunk_num
;
3976 region
= location
->regions
;
3977 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3978 if (512 == image_sector_size
)
3980 for (i
= 0; i
< img_chunk_num
; i
++)
3982 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3983 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3984 region
->disk_start_sector
= chunk
->disk_start_sector
;
3991 for (i
= 0; i
< img_chunk_num
; i
++)
3993 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3994 region
->image_start_sector
= chunk
->img_start_sector
;
3995 region
->disk_start_sector
= chunk
->disk_start_sector
;
4001 /* Step3: Fill acpi checksum */
4003 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4005 /* load acpi table */
4006 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4007 grub_script_execute_sourcecode(cmd
);
4011 VENTOY_CMD_RETURN(0);
4014 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4020 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4021 g_ventoy_last_entry
= -1;
4026 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4032 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4037 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4039 const char *pos
= filename
+ 1;
4047 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4049 grub_strncpy((char *)data
, filename
, 128);
4060 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4063 char *device_name
= NULL
;
4064 grub_device_t dev
= NULL
;
4065 grub_fs_t fs
= NULL
;
4066 char buf
[128] = {0};
4072 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4076 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4078 device_name
= grub_file_get_device_name(args
[0]);
4081 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4085 dev
= grub_device_open(device_name
);
4088 debug("grub_device_open failed, %s\n", device_name
);
4092 fs
= grub_fs_probe(dev
);
4095 debug("grub_fs_probe failed, %s\n", device_name
);
4099 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4103 ventoy_set_env(args
[2], buf
);
4110 check_free(device_name
, grub_free
);
4111 check_free(dev
, grub_device_close
);
4116 int ventoy_load_part_table(const char *diskname
)
4123 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4124 if (!g_ventoy_part_info
)
4129 disk
= grub_disk_open(diskname
);
4132 debug("Failed to open disk %s\n", diskname
);
4136 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4138 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4139 grub_disk_close(disk
);
4141 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4142 dev
= grub_device_open(name
);
4145 /* Check for official Ventoy device */
4146 ret
= ventoy_check_official_device(dev
);
4147 grub_device_close(dev
);
4155 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4156 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4161 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4168 ret
= ventoy_load_part_table(args
[0]);
4174 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4175 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4180 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4183 const char *vcfg
= NULL
;
4188 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4191 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4192 grub_env_set(args
[1], vcfg
);
4197 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4205 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4208 grub_uint8_t zeroguid
[16] = {0};
4213 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4216 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4218 if (id
>= 1 && id
<= 128)
4220 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4228 if (id
>= 1 && id
<= 4)
4230 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4240 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4243 char *device_name
= NULL
;
4244 grub_device_t dev
= NULL
;
4245 grub_fs_t fs
= NULL
;
4250 debug("get fs label for %s\n", args
[0]);
4254 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4258 device_name
= grub_file_get_device_name(args
[0]);
4261 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4265 dev
= grub_device_open(device_name
);
4268 debug("grub_device_open failed, %s\n", device_name
);
4272 fs
= grub_fs_probe(dev
);
4273 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4275 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4279 fs
->fs_label(dev
, &label
);
4282 debug("label=<%s>\n", label
);
4283 ventoy_set_env(args
[1], label
);
4291 check_free(device_name
, grub_free
);
4292 check_free(dev
, grub_device_close
);
4297 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4301 grub_snprintf((char *)data
, 256, "%s", filename
);
4308 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4310 if (info
->dir
&& filename
&& filename
[0] != '.')
4312 grub_snprintf((char *)data
, 256, "%s", filename
);
4319 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4322 char *device_name
= NULL
;
4323 grub_device_t dev
= NULL
;
4324 grub_fs_t fs
= NULL
;
4325 char name
[256] ={0};
4329 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4333 device_name
= grub_file_get_device_name(args
[0]);
4336 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4340 dev
= grub_device_open(device_name
);
4343 debug("grub_device_open failed, %s\n", device_name
);
4347 fs
= grub_fs_probe(dev
);
4350 debug("grub_fs_probe failed, %s\n", device_name
);
4354 fs
->fs_dir(dev
, args
[1], hook
, name
);
4357 ventoy_set_env(args
[2], name
);
4364 check_free(device_name
, grub_free
);
4365 check_free(dev
, grub_device_close
);
4370 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4373 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4376 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4379 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4382 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4392 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4396 for (pos
= args
[0]; *pos
; pos
++)
4410 grub_env_set(args
[1], args
[0]);
4420 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4430 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4435 len
= (int)grub_strlen(buf
);
4436 for (i
= len
; i
> 0; i
--)
4438 if (buf
[i
- 1] == '/')
4440 grub_env_set(args
[1], buf
+ i
);
4445 grub_env_set(args
[1], buf
);
4450 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4452 struct grub_video_mode_info info
;
4459 if (!g_video_mode_list
)
4461 ventoy_enum_video_mode();
4464 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4466 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4470 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4473 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4475 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4476 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4478 VENTOY_CMD_RETURN(0);
4481 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4483 struct grub_video_mode_info info
;
4490 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4492 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4496 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4499 grub_env_set(args
[0], buf
);
4501 VENTOY_CMD_RETURN(0);
4504 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4512 if (!g_video_mode_list
)
4517 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4518 if (id
< g_video_mode_num
)
4520 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4521 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4524 grub_env_set(args
[1], buf
);
4526 VENTOY_CMD_RETURN(0);
4529 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4532 grub_uint32_t loadsector
= 0;
4535 grub_uint32_t boot_catlog
= 0;
4536 grub_uint8_t buf
[512];
4542 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4546 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4549 debug("failed to open %s\n", args
[0]);
4553 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4554 if (boot_catlog
== 0)
4556 debug("No bootcatlog found\n");
4557 grub_file_close(file
);
4561 grub_memset(buf
, 0, sizeof(buf
));
4562 grub_file_seek(file
, boot_catlog
* 2048);
4563 grub_file_read(file
, buf
, sizeof(buf
));
4564 grub_file_close(file
);
4566 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4568 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4570 if (buf
[i
+ 32] == 0x88)
4572 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4573 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4579 if (loadsector
== 0)
4581 debug("No EFI eltorito info found\n");
4585 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4586 grub_env_set(args
[1], value
);
4587 VENTOY_CMD_RETURN(0);
4590 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4595 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4597 if (pfsdir
->initrd
[0])
4602 curpos
= pfsdir
->curpos
;
4603 len
= grub_strlen(filename
);
4607 if ((len
== 1 && filename
[0] == '.') ||
4608 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4613 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4616 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4617 pfsdir
->curpos
= curpos
+ printlen
;
4618 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4619 pfsdir
->curpos
= curpos
;
4620 pfsdir
->fullpath
[curpos
] = 0;
4624 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4627 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4628 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4630 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4632 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4641 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4645 char *device_name
= NULL
;
4646 grub_device_t dev
= NULL
;
4647 grub_fs_t fs
= NULL
;
4648 replace_fs_dir
*pfsdir
= NULL
;
4654 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4658 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4664 device_name
= grub_file_get_device_name(args
[0]);
4670 dev
= grub_device_open(device_name
);
4676 fs
= grub_fs_probe(dev
);
4685 pfsdir
->fullpath
[0] = '/';
4686 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4688 if (pfsdir
->initrd
[0])
4690 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4692 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4694 if (pfsdir
->initrd
[i
] == '/')
4696 pfsdir
->initrd
[i
] = '\\';
4700 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4701 grub_env_set(args
[1], pos
);
4705 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4710 grub_check_free(pfsdir
);
4711 grub_check_free(device_name
);
4712 check_free(dev
, grub_device_close
);
4714 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4717 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4719 const char *pager
= NULL
;
4725 pager
= grub_env_get("pager");
4729 grub_env_set("pager", "1");
4731 else if (pager
[0] == '1')
4737 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4739 grub_env_set("pager", "1");
4742 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4745 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4751 if (g_pager_flag
== 1)
4753 grub_env_unset("pager");
4755 else if (g_pager_flag
== 2)
4757 grub_env_set("pager", g_old_pager
);
4760 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4763 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4765 if (g_json_case_mis_path
[0])
4770 if (0 == info
->dir
&& grub_strncasecmp(filename
, "ventoy.json", 11) == 0)
4772 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4778 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4781 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4783 if (g_json_case_mis_path
[0])
4788 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4790 if (grub_strncasecmp(filename
, "ventoy", 6) == 0)
4792 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4793 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4794 if (g_json_case_mis_path
[0])
4804 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4807 char *device_name
= NULL
;
4808 grub_device_t dev
= NULL
;
4809 grub_fs_t fs
= NULL
;
4810 chk_case_fs_dir fs_dir
;
4816 device_name
= grub_file_get_device_name(args
[0]);
4822 dev
= grub_device_open(device_name
);
4828 fs
= grub_fs_probe(dev
);
4834 fstype
= ventoy_get_fs_type(fs
->name
);
4835 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4840 g_json_case_mis_path
[0] = 0;
4843 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4845 if (g_json_case_mis_path
[0])
4847 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4852 grub_check_free(device_name
);
4853 check_free(dev
, grub_device_close
);
4855 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4858 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4861 grub_partition_t part
;
4862 char priority_str
[3]; /* Maximum value 15 */
4866 if (argc
< 2 || argc
> 3)
4867 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4868 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4870 /* Open the disk if it exists */
4871 disk
= grub_disk_open (args
[0]);
4874 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4878 part
= grub_partition_probe (disk
, args
[1]);
4881 grub_disk_close (disk
);
4882 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4883 "No such partition");
4886 if (grub_strcmp (part
->partmap
->name
, "gpt"))
4888 grub_disk_close (disk
);
4889 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
4890 "Not a GPT partition");
4893 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
4894 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
4898 grub_env_set (args
[2], priority_str
);
4899 grub_env_export (args
[2]);
4903 grub_printf ("Priority is %s\n", priority_str
);
4906 grub_disk_close (disk
);
4907 return GRUB_ERR_NONE
;
4912 /* <BEGIN>: Deleted by longpanda, 20210916 PN:XX LABEL:XX */
4914 void ventoy_tip_set_menu_label(const char *vid
)
4918 g_ventoy_tip_msg1
= g_ventoy_tip_msg2
= NULL
;
4921 node
= (img_info
*)(void *)grub_strtoul(vid
+ 4, NULL
, 16);
4924 g_ventoy_tip_msg1
= node
->tip1
;
4925 g_ventoy_tip_msg2
= node
->tip2
;
4930 /* <END> : Deleted by longpanda, 20210916 PN:XX LABEL:XX */
4932 int ventoy_env_init(void)
4936 grub_env_set("vtdebug_flag", "");
4938 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4939 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4940 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4941 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4943 ventoy_filt_register(0, ventoy_wrapper_open
);
4945 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4948 g_grub_param
->grub_env_get
= grub_env_get
;
4949 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4950 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4951 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4952 grub_env_set("env_param", buf
);
4953 grub_env_set("ventoy_env_param", buf
);
4955 grub_env_export("env_param");
4956 grub_env_export("ventoy_env_param");
4959 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
4960 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
4962 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
4963 grub_env_set("vtoy_winpeshl_ini_size", buf
);
4965 grub_env_export("vtoy_winpeshl_ini_addr");
4966 grub_env_export("vtoy_winpeshl_ini_size");
4968 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
4969 grub_env_set("vtoy_chain_file_size", buf
);
4970 grub_env_export("vtoy_chain_file_size");
4972 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
4973 grub_env_set("vtoy_chain_file_read", buf
);
4974 grub_env_export("vtoy_chain_file_read");
4981 static cmd_para ventoy_cmds
[] =
4983 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4984 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4985 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4986 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4987 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4988 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4989 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4990 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4991 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4992 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4993 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4994 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4995 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4996 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4997 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4998 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4999 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5000 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5001 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5002 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5003 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5004 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5005 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5006 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5008 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5009 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5010 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5011 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5012 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5013 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5014 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5016 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5017 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5018 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5019 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5020 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5021 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5022 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5023 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5024 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5025 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5028 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5029 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5030 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5031 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5032 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5033 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5034 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5035 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5036 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5037 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5038 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5040 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5041 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5042 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5043 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5044 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5045 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5046 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5048 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5049 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5050 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5051 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5052 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5053 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5054 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5055 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5056 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5057 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5059 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5060 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5061 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5062 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5063 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5064 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5065 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5066 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5067 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5069 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5070 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5071 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5072 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5075 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5076 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5077 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5079 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5080 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5081 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5084 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5085 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5086 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5087 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5088 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5089 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5090 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5091 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5092 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5093 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5094 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5096 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5097 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5098 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5099 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5100 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5101 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5102 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5103 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5104 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5105 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5107 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5108 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5109 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5110 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5111 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5112 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5113 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5116 int ventoy_register_all_cmd(void)
5119 cmd_para
*cur
= NULL
;
5121 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5123 cur
= ventoy_cmds
+ i
;
5124 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5125 cur
->summary
, cur
->description
, cur
->parser
);
5131 int ventoy_unregister_all_cmd(void)
5135 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5137 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);