1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 initrd_info
*g_initrd_img_list
= NULL
;
55 initrd_info
*g_initrd_img_tail
= NULL
;
56 int g_initrd_img_count
= 0;
57 int g_valid_initrd_count
= 0;
58 int g_default_menu_mode
= 0;
59 int g_filt_dot_underscore_file
= 0;
60 int g_sort_case_sensitive
= 0;
61 int g_tree_view_menu_style
= 0;
62 static grub_file_t g_old_file
;
63 static int g_ventoy_last_entry_back
;
66 char g_img_swap_tmp_buf
[1024];
67 img_info g_img_swap_tmp
;
68 img_info
*g_ventoy_img_list
= NULL
;
70 int g_ventoy_img_count
= 0;
72 grub_device_t g_enum_dev
= NULL
;
73 grub_fs_t g_enum_fs
= NULL
;
74 int g_img_max_search_level
= -1;
75 img_iterator_node g_img_iterator_head
;
76 img_iterator_node
*g_img_iterator_tail
= NULL
;
78 grub_uint8_t g_ventoy_break_level
= 0;
79 grub_uint8_t g_ventoy_debug_level
= 0;
80 grub_uint8_t g_ventoy_chain_type
= 0;
82 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
83 grub_uint32_t g_ventoy_cpio_size
= 0;
84 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
85 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
87 int g_plugin_image_list
= 0;
89 ventoy_grub_param
*g_grub_param
= NULL
;
91 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
93 ventoy_img_chunk_list g_img_chunk_list
;
95 int g_wimboot_enable
= 0;
96 ventoy_img_chunk_list g_wimiso_chunk_list
;
97 char *g_wimiso_path
= NULL
;
99 int g_vhdboot_enable
= 0;
101 grub_uint64_t g_conf_replace_offset
= 0;
102 grub_uint64_t g_svd_replace_offset
= 0;
103 conf_replace
*g_conf_replace_node
= NULL
;
104 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
105 int g_conf_replace_new_len
= 0;
106 int g_conf_replace_new_len_align
= 0;
108 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
109 grub_uint64_t g_ventoy_disk_size
= 0;
110 grub_uint64_t g_ventoy_disk_part_size
[2];
112 static char *g_tree_script_buf
= NULL
;
113 static int g_tree_script_pos
= 0;
115 static char *g_list_script_buf
= NULL
;
116 static int g_list_script_pos
= 0;
118 static char *g_part_list_buf
= NULL
;
119 static int g_part_list_pos
= 0;
121 static int g_video_mode_max
= 0;
122 static int g_video_mode_num
= 0;
123 static ventoy_video_mode
*g_video_mode_list
= NULL
;
125 static int g_enumerate_time_checked
= 0;
126 static grub_uint64_t g_enumerate_start_time_ms
;
127 static grub_uint64_t g_enumerate_finish_time_ms
;
128 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
130 static int g_pager_flag
= 0;
131 static char g_old_pager
[32];
133 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
135 static const char *g_menu_class
[] =
137 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
140 const char *g_menu_prefix
[img_type_max
] =
142 "iso", "wim", "efi", "img", "vhd", "vtoy"
145 static int g_vtoy_load_prompt
= 0;
146 static char g_vtoy_prompt_msg
[64];
148 static char g_json_case_mis_path
[32];
150 static int ventoy_get_fs_type(const char *fs
)
154 return ventoy_fs_max
;
156 else if (grub_strncmp(fs
, "exfat", 5) == 0)
158 return ventoy_fs_exfat
;
160 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
162 return ventoy_fs_ntfs
;
164 else if (grub_strncmp(fs
, "ext", 3) == 0)
166 return ventoy_fs_ext
;
168 else if (grub_strncmp(fs
, "xfs", 3) == 0)
170 return ventoy_fs_xfs
;
172 else if (grub_strncmp(fs
, "udf", 3) == 0)
174 return ventoy_fs_udf
;
176 else if (grub_strncmp(fs
, "fat", 3) == 0)
178 return ventoy_fs_fat
;
181 return ventoy_fs_max
;
184 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
203 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
205 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
209 static int ventoy_control_get_flag(const char *key
)
211 const char *val
= ventoy_get_env(key
);
213 if (val
&& val
[0] == '1' && val
[1] == 0)
220 static grub_err_t
ventoy_fs_close(grub_file_t file
)
222 grub_file_close(g_old_file
);
223 grub_free(file
->data
);
231 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
237 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
242 for (i
= 0; i
< g_video_mode_num
; i
++)
244 if (g_video_mode_list
[i
].width
== info
->width
&&
245 g_video_mode_list
[i
].height
== info
->height
&&
246 g_video_mode_list
[i
].bpp
== info
->bpp
)
252 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
253 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
254 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
257 if (g_video_mode_num
== g_video_mode_max
)
259 g_video_mode_max
*= 2;
260 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
266 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
268 if (v1
->bpp
== v2
->bpp
)
270 if (v1
->width
== v2
->width
)
272 if (v1
->height
== v2
->height
)
278 return (v1
->height
< v2
->height
) ? -1 : 1;
283 return (v1
->width
< v2
->width
) ? -1 : 1;
288 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
292 static int ventoy_enum_video_mode(void)
295 grub_video_adapter_t adapter
;
296 grub_video_driver_id_t id
;
297 ventoy_video_mode mode
;
299 g_video_mode_num
= 0;
300 g_video_mode_max
= 1024;
301 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
302 if (!g_video_mode_list
)
307 #ifdef GRUB_MACHINE_PCBIOS
308 grub_dl_load ("vbe");
311 id
= grub_video_get_driver_id ();
313 FOR_VIDEO_ADAPTERS (adapter
)
315 if (!adapter
->iterate
||
316 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
317 adapter
->init() != GRUB_ERR_NONE
)))
322 adapter
->iterate(ventoy_video_hook
, NULL
);
324 if (adapter
->id
!= id
)
330 /* sort video mode */
331 for (i
= 0; i
< g_video_mode_num
; i
++)
332 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
334 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
336 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
337 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
338 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
342 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
345 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
349 static struct grub_fs vtoy_fs
=
354 .fs_read
= ventoy_fs_read
,
355 .fs_close
= ventoy_fs_close
,
365 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
371 file
->data
= grub_malloc(rawFile
->size
+ 4096);
377 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
378 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
380 g_old_file
= rawFile
;
382 file
->size
= rawFile
->size
+ len
;
383 file
->device
= rawFile
->device
;
385 file
->not_easily_seekable
= 1;
390 static int ventoy_check_decimal_var(const char *name
, long *value
)
392 const char *value_str
= NULL
;
394 value_str
= grub_env_get(name
);
395 if (NULL
== value_str
)
397 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
400 if (!ventoy_is_decimal(value_str
))
402 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
405 *value
= grub_strtol(value_str
, NULL
, 10);
407 return GRUB_ERR_NONE
;
410 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
412 grub_uint64_t sectors
;
414 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
416 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
420 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
423 return sectors
* 512;
426 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
432 grub_uint32_t offset
;
434 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
437 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
441 len
= (int)file
->size
;
443 data
= (char *)grub_malloc(file
->size
);
449 grub_file_read(file
, data
, file
->size
);
450 grub_file_close(file
);
452 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
453 grub_script_execute_sourcecode(exec
);
455 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
456 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
457 grub_file_close(file
);
459 grub_script_execute_sourcecode("loopback -d efiboot");
463 *direntoff
= offset
+ 2;
468 static int ventoy_set_check_result(int ret
)
472 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
473 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
474 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
478 grub_printf(VTOY_WARNING
"\n");
479 grub_printf(VTOY_WARNING
"\n");
480 grub_printf(VTOY_WARNING
"\n\n\n");
482 grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret
);
483 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
485 grub_printf("\n\nWill exit after 10 seconds ...... ");
493 static int ventoy_check_official_device(grub_device_t dev
)
497 grub_uint64_t offset
;
502 struct grub_partition
*partition
;
504 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
506 return ventoy_set_check_result(1 | 0x1000);
509 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
510 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
511 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
513 #ifndef GRUB_MACHINE_EFI
514 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
515 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
516 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
518 return ventoy_set_check_result(2 | 0x1000);
527 /* We must have partition 2 */
530 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
534 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
538 return ventoy_set_check_result(3 | 0x1000);
541 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
543 grub_file_close(file
);
544 return ventoy_set_check_result(4 | 0x1000);
547 partition
= dev
->disk
->partition
;
548 if (partition
->number
!= 0 || partition
->start
!= 2048)
550 return ventoy_set_check_result(5);
555 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
557 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
558 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
559 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
561 grub_file_close(file
);
562 return ventoy_set_check_result(6);
567 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
568 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
569 PartTbl
[1].SectorCount
!= 65536)
571 grub_file_close(file
);
572 return ventoy_set_check_result(6);
578 offset
= partition
->start
+ partition
->len
;
579 partition
= file
->device
->disk
->partition
;
580 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
582 grub_file_close(file
);
583 return ventoy_set_check_result(7);
587 grub_file_close(file
);
591 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
592 dev2
= grub_device_open(devname
);
595 return ventoy_set_check_result(8);
598 fs
= grub_fs_probe(dev2
);
601 grub_device_close(dev2
);
602 return ventoy_set_check_result(9);
605 fs
->fs_label(dev2
, &label
);
606 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
608 grub_device_close(dev2
);
609 return ventoy_set_check_result(10);
612 grub_device_close(dev2
);
615 return ventoy_set_check_result(0);
618 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
622 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
632 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
634 grub_uint64_t size
= 0;
637 char fullpath
[256] = {0};
640 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
643 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
646 debug("grub_file_open failed <%s>\n", fullpath
);
652 grub_file_close(file
);
656 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
660 char fullpath
[256] = {0};
663 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
666 file
= grub_file_open(fullpath
, type
);
669 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
676 int ventoy_is_file_exist(const char *fmt
, ...)
683 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
687 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
690 grub_strncpy(pos
+ len
, "\" ]", 3);
692 debug("script exec %s\n", buf
);
694 if (0 == grub_script_execute_sourcecode(buf
))
702 int ventoy_is_dir_exist(const char *fmt
, ...)
709 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
713 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
716 grub_strncpy(pos
+ len
, "\" ]", 3);
718 debug("script exec %s\n", buf
);
720 if (0 == grub_script_execute_sourcecode(buf
))
728 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
731 grub_uint8_t
*outbuf
;
732 grub_uint8_t gzHdr
[10] =
734 0x1F, 0x8B, /* magic */
742 grub_memset(&s
, 0, sizeof(mz_stream
));
744 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
746 outbuf
= (grub_uint8_t
*)mem_out
;
748 mem_out_len
-= sizeof(gzHdr
) + 8;
749 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
750 outbuf
+= sizeof(gzHdr
);
752 s
.avail_in
= mem_in_len
;
755 s
.avail_out
= mem_out_len
;
758 mz_deflate(&s
, MZ_FINISH
);
762 outbuf
+= s
.total_out
;
763 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
764 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
766 return s
.total_out
+ sizeof(gzHdr
) + 8;
774 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
778 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
781 if (0 == grub_strcmp(args
[0], "on"))
784 grub_env_set("vtdebug_flag", "debug");
789 grub_env_set("vtdebug_flag", "");
792 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
795 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
799 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
801 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
802 grub_printf(" level:\r\n");
803 grub_printf(" 01/11: busybox / (+cat log)\r\n");
804 grub_printf(" 02/12: initrd / (+cat log)\r\n");
805 grub_printf(" 03/13: hook / (+cat log)\r\n");
807 grub_printf(" debug:\r\n");
808 grub_printf(" 0: debug is off\r\n");
809 grub_printf(" 1: debug is on\r\n");
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
814 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
816 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
818 g_ventoy_debug_level
= 1;
821 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
824 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
833 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
836 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
868 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
873 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
875 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
878 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
883 value_long
+= grub_strtol(args
[1], NULL
, 10);
885 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
886 grub_env_set(args
[0], buf
);
888 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
891 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
893 ulonglong value1
= 0;
894 ulonglong value2
= 0;
899 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
902 value1
= grub_strtoull(args
[0], NULL
, 10);
903 value2
= grub_strtoull(args
[1], NULL
, 10);
905 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
906 grub_env_set(args
[2], buf
);
908 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
911 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
926 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
929 debug("failed to open file <%s> for udf check\n", args
[0]);
933 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
935 grub_env_set(args
[1], buf
);
937 grub_file_close(file
);
943 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
951 g_wimboot_enable
= 0;
952 grub_check_free(g_wimiso_path
);
953 grub_check_free(g_wimiso_chunk_list
.chunk
);
955 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
961 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
962 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
963 if (NULL
== g_wimiso_chunk_list
.chunk
)
965 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
968 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
969 g_wimiso_chunk_list
.cur_chunk
= 0;
971 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
973 g_wimboot_enable
= 1;
974 g_wimiso_path
= grub_strdup(args
[0]);
976 grub_file_close(file
);
981 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
991 ventoy_iso9660_override
*dirent
;
1000 totlen
= sizeof(ventoy_chain_head
);
1002 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1004 debug("failed to load efiboot template %d\n", len
);
1010 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1012 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1015 debug("failed to open file <%s>\n", args
[0]);
1019 totlen
+= ventoy_align_2k(file
->size
);
1021 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1022 dirent
->first_sector
= len
/ 2048;
1023 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1024 dirent
->size
= (grub_uint32_t
)file
->size
;
1025 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1027 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1029 #ifdef GRUB_MACHINE_EFI
1030 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1032 data
= (char *)grub_malloc(totlen
);
1035 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1037 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1038 grub_check_free(buf
);
1040 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1041 grub_file_close(file
);
1043 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1044 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1045 grub_env_set(name
, value
);
1047 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1048 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1049 grub_env_set(name
, value
);
1054 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1060 g_vtoy_load_prompt
= 0;
1061 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1063 if (argc
== 2 && args
[0][0] == '1')
1065 g_vtoy_load_prompt
= 1;
1066 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1069 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1072 int ventoy_need_prompt_load_file(void)
1074 return g_vtoy_load_prompt
;
1077 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1079 grub_uint64_t ro
= 0;
1080 grub_uint64_t div
= 0;
1081 grub_ssize_t left
= size
;
1082 char *cur
= (char *)buf
;
1084 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1087 while (left
>= VTOY_SIZE_2MB
)
1089 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1090 cur
+= VTOY_SIZE_2MB
;
1091 left
-= VTOY_SIZE_2MB
;
1093 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1094 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1100 grub_file_read(file
, cur
, left
);
1103 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1109 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1116 enum grub_file_type type
;
1127 if (grub_strcmp(args
[0], "nodecompress") == 0)
1129 type
= VENTOY_FILE_TYPE
;
1133 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1136 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1139 debug("failed to open file <%s>\n", args
[1]);
1143 #ifdef GRUB_MACHINE_EFI
1144 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1146 buf
= (char *)grub_malloc(file
->size
);
1151 grub_file_close(file
);
1155 if (g_vtoy_load_prompt
)
1157 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1161 grub_file_read(file
, buf
, file
->size
);
1164 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1165 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1166 grub_env_set(name
, value
);
1168 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1169 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1170 grub_env_set(name
, value
);
1172 grub_file_close(file
);
1178 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1196 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1199 debug("failed to open file <%s> for udf check\n", args
[0]);
1203 headlen
= sizeof(ventoy_chain_head
);
1205 #ifdef GRUB_MACHINE_EFI
1206 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1208 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1211 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1213 grub_file_read(file
, buf
+ headlen
, file
->size
);
1215 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1216 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1217 grub_env_set(name
, value
);
1219 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1220 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1221 grub_env_set(name
, value
);
1223 grub_file_close(file
);
1229 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1235 if (grub_iso9660_is_joliet())
1237 debug("This time has joliet process\n");
1246 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1255 if (args
[0][0] == '1')
1257 grub_iso9660_set_nojoliet(1);
1261 grub_iso9660_set_nojoliet(0);
1267 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1272 grub_uint8_t buf
[32];
1283 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1286 debug("failed to open file <%s> for udf check\n", args
[0]);
1290 for (i
= 16; i
< 32; i
++)
1292 grub_file_seek(file
, i
* 2048);
1293 grub_file_read(file
, buf
, sizeof(buf
));
1301 grub_file_seek(file
, i
* 2048);
1302 grub_file_read(file
, buf
, sizeof(buf
));
1304 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1307 grub_file_seek(file
, i
* 2048);
1308 grub_file_read(file
, buf
, sizeof(buf
));
1310 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1311 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1317 grub_file_close(file
);
1319 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1324 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1326 long value_long1
= 0;
1327 long value_long2
= 0;
1329 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1331 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1334 value_long1
= grub_strtol(args
[0], NULL
, 10);
1335 value_long2
= grub_strtol(args
[2], NULL
, 10);
1337 if (0 == grub_strcmp(args
[1], "eq"))
1339 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1341 else if (0 == grub_strcmp(args
[1], "ne"))
1343 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1345 else if (0 == grub_strcmp(args
[1], "gt"))
1347 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1349 else if (0 == grub_strcmp(args
[1], "lt"))
1351 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1353 else if (0 == grub_strcmp(args
[1], "ge"))
1355 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1357 else if (0 == grub_strcmp(args
[1], "le"))
1359 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1363 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1369 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1372 char buf
[128] = {0};
1376 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1379 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1380 pos
= grub_strstr(buf
, ",");
1386 grub_env_set(args
[1], buf
);
1388 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1391 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1397 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1403 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1406 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1408 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1409 if (0 == grub_script_execute_sourcecode(buf
))
1411 debug("file %s exist, ventoy_compatible YES\n", buf
);
1412 grub_env_set("ventoy_compatible", "YES");
1413 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1417 debug("file %s NOT exist\n", buf
);
1421 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1422 pos
= grub_strstr(buf
, ")");
1428 disk
= grub_disk_open(buf
);
1431 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1432 grub_disk_close(disk
);
1434 g_img_swap_tmp_buf
[703] = 0;
1435 for (i
= 318; i
< 703; i
++)
1437 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1438 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1440 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1441 grub_env_set("ventoy_compatible", "YES");
1442 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1448 debug("failed to open disk <%s>\n", buf
);
1451 grub_env_set("ventoy_compatible", "NO");
1452 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1455 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1461 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1463 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1466 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1471 if (0 == g_sort_case_sensitive
)
1473 if (grub_islower(c1
))
1475 c1
= c1
- 'a' + 'A';
1478 if (grub_islower(c2
))
1480 c2
= c2
- 'a' + 'A';
1493 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1499 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1501 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1504 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1509 if (0 == g_sort_case_sensitive
)
1511 if (grub_islower(c1
))
1513 c1
= c1
- 'a' + 'A';
1516 if (grub_islower(c2
))
1518 c2
= c2
- 'a' + 'A';
1531 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1533 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1535 grub_memcpy(img1
, img2
, sizeof(img_info
));
1536 img1
->next
= g_img_swap_tmp
.next
;
1537 img1
->prev
= g_img_swap_tmp
.prev
;
1539 g_img_swap_tmp
.next
= img2
->next
;
1540 g_img_swap_tmp
.prev
= img2
->prev
;
1541 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1544 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1548 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1556 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1565 img_iterator_node
*tmp
;
1566 img_iterator_node
*new_node
;
1567 img_iterator_node
*node
= (img_iterator_node
*)data
;
1569 if (g_enumerate_time_checked
== 0)
1571 g_enumerate_finish_time_ms
= grub_get_time_ms();
1572 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1575 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1577 g_enumerate_time_checked
= 1;
1581 len
= grub_strlen(filename
);
1585 if (node
->level
+ 1 > g_img_max_search_level
)
1590 if ((len
== 1 && filename
[0] == '.') ||
1591 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1596 if (!ventoy_img_name_valid(filename
, len
))
1601 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1606 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1608 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1609 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1612 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1617 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1620 new_node
->level
= node
->level
+ 1;
1621 new_node
->plugin_list_index
= index
;
1622 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1624 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1627 debug("Directory %s ignored...\n", new_node
->dir
);
1628 grub_free(new_node
);
1632 new_node
->tail
= node
->tail
;
1634 new_node
->parent
= node
;
1635 if (!node
->firstchild
)
1637 node
->firstchild
= new_node
;
1640 if (g_img_iterator_tail
)
1642 g_img_iterator_tail
->next
= new_node
;
1643 g_img_iterator_tail
= new_node
;
1647 g_img_iterator_head
.next
= new_node
;
1648 g_img_iterator_tail
= new_node
;
1654 debug("Find a file %s\n", filename
);
1660 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1662 type
= img_type_iso
;
1664 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1666 type
= img_type_wim
;
1668 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1669 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1671 type
= img_type_vhd
;
1673 #ifdef GRUB_MACHINE_EFI
1674 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1676 type
= img_type_efi
;
1679 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1681 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1683 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1684 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1689 type
= img_type_img
;
1691 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1693 type
= img_type_vtoy
;
1695 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1697 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1699 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1700 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1709 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1714 if (g_plugin_image_list
)
1716 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1717 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1718 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1720 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1723 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1725 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1730 img
= grub_zalloc(sizeof(img_info
));
1734 img
->plugin_list_index
= index
;
1735 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1737 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1739 img
->size
= info
->size
;
1742 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1745 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1747 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1752 if (g_ventoy_img_list
)
1754 tail
= *(node
->tail
);
1760 g_ventoy_img_list
= img
;
1763 img
->id
= g_ventoy_img_count
;
1765 if (node
&& NULL
== node
->firstiso
)
1767 node
->firstiso
= img
;
1778 *((img_info
**)(node
->tail
)) = img
;
1779 g_ventoy_img_count
++;
1781 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1782 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1785 img
->class = g_menu_class
[type
];
1787 img
->menu_prefix
= g_menu_prefix
[type
];
1789 if (img_type_iso
== type
)
1791 if (ventoy_plugin_check_memdisk(img
->path
))
1793 img
->menu_prefix
= "miso";
1797 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1804 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1806 int len
= GRUB_UINT_MAX
;
1807 const char *value
= NULL
;
1808 char name
[32] = {0};
1809 char plat
[32] = {0};
1810 char guidstr
[32] = {0};
1811 ventoy_guid guid
= VENTOY_GUID
;
1812 const char *fmt1
= NULL
;
1813 const char *fmt2
= NULL
;
1814 const char *fmt3
= NULL
;
1815 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1816 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1817 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1818 const char fmtcode
[]={
1819 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1820 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1821 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1822 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1823 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1824 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1827 grub_memset(name
, 0, sizeof(name
));
1828 puint
[0] = grub_swap_bytes32(0x56454e54);
1829 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1830 puint
[2] = grub_swap_bytes32(0x45525349);
1831 puint
[1] = grub_swap_bytes32(0x4f595f56);
1832 value
= ventoy_get_env(name
);
1834 grub_memset(name
, 0, sizeof(name
));
1835 puint
[1] = grub_swap_bytes32(0x5f544f50);
1836 puint
[0] = grub_swap_bytes32(0x56544c45);
1837 fmt1
= ventoy_get_env(name
);
1843 grub_memset(name
, 0, sizeof(name
));
1844 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1845 puint
[0] = grub_swap_bytes32(0x56544c45);
1846 fmt2
= ventoy_get_env(name
);
1848 grub_memset(name
, 0, sizeof(name
));
1849 puint
[1] = grub_swap_bytes32(0x5f434c52);
1850 puint
[0] = grub_swap_bytes32(0x56544c45);
1851 fmt3
= ventoy_get_env(name
);
1853 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1855 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1857 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1858 #pragma GCC diagnostic push
1859 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1860 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1861 fmt1
? fmt1
: fmtdata
,
1862 fmt2
? fmt2
: fmtdata
+ 4,
1863 value
? value
: "", plat
, guidstr
,
1864 fmt3
? fmt3
: fmtdata
+ 6);
1865 #pragma GCC diagnostic pop
1867 grub_memset(name
, 0, sizeof(name
));
1868 puint
[0] = grub_swap_bytes32(0x76746f79);
1869 puint
[2] = grub_swap_bytes32(0x656e7365);
1870 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1871 ventoy_set_env(name
, guidstr
);
1876 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1880 grub_uint8_t md5
[16];
1884 grub_memset(input
, 0, sizeof(input
));
1886 grub_printf("Enter password: ");
1889 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1891 grub_password_get(input
, 128);
1892 if (grub_strcmp(pwd
->text
, input
) == 0)
1897 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1899 grub_password_get(input
, 128);
1900 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1901 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1906 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1908 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1909 grub_password_get(input
+ offset
, 128);
1911 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1912 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1918 grub_printf("Invalid password!\n\n");
1925 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1927 img_info
*minimg
= NULL
;
1928 img_info
*img
= (img_info
*)(node
->firstiso
);
1930 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1932 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
1947 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
1949 img_iterator_node
*Minchild
= NULL
;
1950 img_iterator_node
*child
= node
->firstchild
;
1952 while (child
&& child
->parent
== node
)
1954 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
1958 child
= child
->next
;
1963 Minchild
->select
= 1;
1969 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
1972 img_info
*img
= NULL
;
1973 const char *dir_class
= NULL
;
1974 const char *dir_alias
= NULL
;
1975 img_iterator_node
*child
= NULL
;
1977 if (node
->isocnt
== 0 || node
->done
== 1)
1982 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
1984 offset
= node
->parent
->dirlen
;
1987 if (node
== &g_img_iterator_head
)
1989 if (g_default_menu_mode
== 0)
1991 if (g_tree_view_menu_style
== 0)
1993 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
1994 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1995 " echo 'return ...' \n"
2000 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2001 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2009 node
->dir
[node
->dirlen
- 1] = 0;
2010 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2013 dir_class
= "vtoydir";
2016 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2019 if (g_tree_view_menu_style
== 0)
2021 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2022 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2023 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2027 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2028 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2029 dir_alias
, dir_class
, node
->dir
+ offset
);
2034 dir_alias
= node
->dir
+ offset
;
2036 if (g_tree_view_menu_style
== 0)
2038 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2039 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2040 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2044 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2045 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2046 dir_alias
, dir_class
, node
->dir
+ offset
);
2050 if (g_tree_view_menu_style
== 0)
2052 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2053 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2054 " echo 'return ...' \n"
2059 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2060 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2066 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2068 ventoy_dynamic_tree_menu(child
);
2071 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2073 if (g_tree_view_menu_style
== 0)
2075 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2076 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2079 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2080 img
->unsupport
? "[***********] " : "",
2081 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2083 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2087 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2088 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2091 img
->unsupport
? "[***********] " : "",
2092 img
->alias
? img
->alias
: img
->name
, img
->class, img
->id
,
2094 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2098 if (node
!= &g_img_iterator_head
)
2100 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2107 static int ventoy_set_default_menu(void)
2113 const char *strdata
= NULL
;
2114 img_info
*cur
= NULL
;
2115 img_info
*default_node
= NULL
;
2116 const char *default_image
= NULL
;
2118 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2119 if (default_image
&& default_image
[0] == '/')
2121 img_len
= grub_strlen(default_image
);
2123 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2125 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2137 if (0 == g_default_menu_mode
)
2139 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%d'\n", default_node
->id
);
2143 def
= grub_strdup(default_image
);
2149 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2151 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2152 if (strdata
&& strdata
[0] == '/')
2154 pos
= def
+ grub_strlen(strdata
);
2165 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2168 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2172 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%d'\n", default_node
->id
);
2180 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2182 img_info
*next
= NULL
;
2183 img_info
*cur
= g_ventoy_img_list
;
2196 g_ventoy_img_list
= NULL
;
2197 g_ventoy_img_count
= 0;
2199 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2202 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2205 img_info
*cur
= g_ventoy_img_list
;
2209 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2211 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2214 img_id
= grub_strtol(args
[0], NULL
, 10);
2215 if (img_id
>= g_ventoy_img_count
)
2217 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2220 debug("Find image %ld name \n", img_id
);
2222 while (cur
&& img_id
> 0)
2230 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2233 debug("image name is %s\n", cur
->name
);
2235 grub_env_set(args
[1], cur
->name
);
2237 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2240 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2244 img_info
*cur
= g_ventoy_img_list
;
2250 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2253 len
= (int)grub_strlen(args
[0]);
2257 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2266 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2269 grub_snprintf(id
, sizeof(id
), "VID_%d", cur
->id
);
2270 grub_env_set("chosen", id
);
2271 grub_env_export("chosen");
2273 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2276 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2281 const char *id
= NULL
;
2282 img_info
*cur
= g_ventoy_img_list
;
2286 if (argc
< 1 || argc
> 2)
2288 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2291 id
= grub_env_get("chosen");
2293 pos
= grub_strstr(id
, "VID_");
2296 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
2300 img_id
= (int)grub_strtoul(id
, NULL
, 10);
2305 if (img_id
== cur
->id
)
2314 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2317 grub_env_set(args
[0], cur
->path
);
2321 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2322 grub_env_set(args
[1], value
);
2325 g_svd_replace_offset
= 0;
2327 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2331 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2335 grub_device_t dev
= NULL
;
2336 img_info
*cur
= NULL
;
2337 img_info
*tail
= NULL
;
2338 const char *strdata
= NULL
;
2339 char *device_name
= NULL
;
2341 img_iterator_node
*node
= NULL
;
2342 img_iterator_node
*tmp
= NULL
;
2348 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2351 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2353 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2358 g_enumerate_time_checked
= 0;
2359 g_enumerate_start_time_ms
= grub_get_time_ms();
2361 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2362 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2364 g_filt_dot_underscore_file
= 1;
2367 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2368 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2370 g_sort_case_sensitive
= 1;
2373 device_name
= grub_file_get_device_name(args
[0]);
2379 g_enum_dev
= dev
= grub_device_open(device_name
);
2385 g_enum_fs
= fs
= grub_fs_probe(dev
);
2391 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2393 debug("unsupported fs:<%s>\n", fs
->name
);
2394 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2398 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2400 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2401 if (strdata
&& strdata
[0] == '1')
2403 g_default_menu_mode
= 1;
2406 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2408 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2410 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2411 if (strdata
&& strdata
[0] == '/')
2413 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2414 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2416 g_img_iterator_head
.dir
[len
++] = '/';
2418 g_img_iterator_head
.dirlen
= len
;
2422 g_img_iterator_head
.dirlen
= 1;
2423 grub_strcpy(g_img_iterator_head
.dir
, "/");
2426 g_img_iterator_head
.tail
= &tail
;
2428 if (g_img_max_search_level
< 0)
2430 g_img_max_search_level
= GRUB_INT_MAX
;
2431 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2432 if (strdata
&& ventoy_is_decimal(strdata
))
2434 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2438 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2439 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2440 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2441 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2442 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2443 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2445 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2447 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2450 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2451 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2453 g_tree_view_menu_style
= 1;
2456 ventoy_set_default_menu();
2458 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2460 ventoy_dynamic_tree_menu(node
);
2464 node
= g_img_iterator_head
.next
;
2472 /* sort image list by image name */
2473 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2475 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
2477 if (ventoy_cmp_img(cur
, tail
) > 0)
2479 ventoy_swap_img(cur
, tail
);
2484 if (g_default_menu_mode
== 1)
2486 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2487 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2488 " echo 'return ...' \n"
2492 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2494 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2495 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2498 cur
->unsupport
? "[***********] " : "",
2499 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
->id
,
2501 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2504 g_tree_script_buf
[g_tree_script_pos
] = 0;
2505 g_list_script_buf
[g_list_script_pos
] = 0;
2507 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2508 grub_env_set(args
[1], buf
);
2512 check_free(device_name
, grub_free
);
2513 check_free(dev
, grub_device_close
);
2515 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2518 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2525 device_name
= grub_file_get_device_name(filename
);
2537 pos2
= grub_strstr(pos
, ",");
2540 pos2
= grub_strstr(pos
, ")");
2548 disk
= grub_disk_open(pos
);
2551 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2552 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2553 grub_disk_close(disk
);
2560 grub_free(device_name
);
2564 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2566 eltorito_descriptor desc
;
2568 grub_memset(&desc
, 0, sizeof(desc
));
2569 grub_file_seek(file
, 17 * 2048);
2570 grub_file_read(file
, &desc
, sizeof(desc
));
2572 if (desc
.type
!= 0 || desc
.version
!= 1)
2577 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2578 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2586 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2590 grub_uint8_t buf
[512];
2591 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2593 grub_file_seek(file
, sector
* 2048);
2594 grub_file_read(file
, buf
, sizeof(buf
));
2596 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2598 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2602 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2607 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2609 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2611 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2615 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2617 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2622 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2624 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2626 if (buf
[36] == parttype
[i
])
2628 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2634 debug("%s does not contain efi eltorito\n", file
->name
);
2638 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2641 const char *fs
= NULL
;
2642 const char *cdprompt
= NULL
;
2644 grub_uint8_t chksum
= 0;
2647 disk
= file
->device
->disk
;
2648 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2650 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2651 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2652 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2654 pos
= grub_strstr(file
->name
, "/");
2660 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2662 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2664 param
->vtoy_img_size
= file
->size
;
2666 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2667 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2669 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2671 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2672 param
->vtoy_reserved
[4] = 0;
2673 if (g_ventoy_chain_type
== 1) /* Windows */
2675 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2676 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2678 param
->vtoy_reserved
[4] = 1;
2682 fs
= ventoy_get_env("ventoy_fs_probe");
2683 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2685 param
->vtoy_reserved
[3] = 1;
2688 /* calculate checksum */
2689 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2691 chksum
+= *((grub_uint8_t
*)param
+ i
);
2693 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2698 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2700 grub_uint32_t i
= 0;
2701 grub_uint64_t total
= 0;
2702 grub_uint64_t fileblk
= 0;
2703 ventoy_img_chunk
*chunk
= NULL
;
2705 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2707 chunk
= chunklist
->chunk
+ i
;
2709 if (chunk
->disk_start_sector
<= start
)
2711 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2715 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2718 fileblk
= (file
->size
+ 511) / 512;
2720 if (total
!= fileblk
)
2722 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2723 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2725 debug("maybe img file to be processed.\n");
2735 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2739 grub_uint32_t i
= 0;
2740 grub_uint32_t sector
= 0;
2741 grub_uint32_t count
= 0;
2742 grub_off_t size
= 0;
2743 grub_off_t read
= 0;
2745 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2746 if (fs_type
== ventoy_fs_exfat
)
2748 grub_fat_get_file_chunk(start
, file
, chunklist
);
2750 else if (fs_type
== ventoy_fs_ext
)
2752 grub_ext_get_file_chunk(start
, file
, chunklist
);
2756 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2757 file
->read_hook_data
= chunklist
;
2759 for (size
= file
->size
; size
> 0; size
-= read
)
2761 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2762 grub_file_read(file
, NULL
, read
);
2765 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2767 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2768 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2771 if (ventoy_fs_udf
== fs_type
)
2773 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2775 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2776 chunklist
->chunk
[i
].img_start_sector
= sector
;
2777 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2783 len
= (int)grub_strlen(file
->name
);
2784 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2785 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2786 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2787 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2789 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2791 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2801 chunklist
->chunk
[i
].img_start_sector
= sector
;
2802 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2810 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2814 grub_disk_addr_t start
;
2819 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2822 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2825 g_conf_replace_node
= NULL
;
2826 g_conf_replace_offset
= 0;
2828 if (g_img_chunk_list
.chunk
)
2830 grub_free(g_img_chunk_list
.chunk
);
2833 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2835 grub_file_close(file
);
2836 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2839 /* get image chunk data */
2840 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2841 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2842 if (NULL
== g_img_chunk_list
.chunk
)
2844 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2847 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2848 g_img_chunk_list
.cur_chunk
= 0;
2850 start
= file
->device
->disk
->partition
->start
;
2852 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2854 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2855 grub_file_close(file
);
2859 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2862 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2863 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2866 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2868 grub_uint64_t offset
= 0;
2869 grub_uint32_t align
= 0;
2870 grub_file_t file
= NULL
;
2871 conf_replace
*node
= NULL
;
2877 debug("select conf replace argc:%d\n", argc
);
2884 node
= ventoy_plugin_find_conf_replace(args
[1]);
2887 debug("Conf replace not found for %s\n", args
[1]);
2891 debug("Find conf replace for %s\n", args
[1]);
2893 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2896 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2900 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2901 grub_file_close(file
);
2903 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2906 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2910 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2912 if (align
> vtoy_max_replace_file_size
)
2914 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
2918 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
2919 g_conf_replace_new_len
= (int)file
->size
;
2920 g_conf_replace_new_len_align
= align
;
2922 g_conf_replace_node
= node
;
2923 g_conf_replace_offset
= offset
+ 2;
2925 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
2930 grub_file_close(file
);
2932 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2935 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2940 char configfile
[128];
2941 install_template
*node
= NULL
;
2947 debug("select auto installation argc:%d\n", argc
);
2954 node
= ventoy_plugin_find_install_template(args
[0]);
2957 debug("Auto install template not found for %s\n", args
[0]);
2961 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
2963 node
->cursel
= node
->autosel
- 1;
2964 debug("Auto install template auto select %d\n", node
->autosel
);
2968 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
2974 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
2975 " echo %s\n}\n", "123");
2977 for (i
= 0; i
< node
->templatenum
; i
++)
2979 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
2981 node
->templatepath
[i
].path
);
2984 g_ventoy_menu_esc
= 1;
2985 g_ventoy_suppress_esc
= 1;
2987 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
2988 grub_script_execute_sourcecode(configfile
);
2990 g_ventoy_menu_esc
= 0;
2991 g_ventoy_suppress_esc
= 0;
2995 node
->cursel
= g_ventoy_last_entry
- 1;
2997 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3000 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3005 char configfile
[128];
3006 persistence_config
*node
;
3012 debug("select persistence argc:%d\n", argc
);
3019 node
= ventoy_plugin_find_persistent(args
[0]);
3022 debug("Persistence image not found for %s\n", args
[0]);
3026 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3028 node
->cursel
= node
->autosel
- 1;
3029 debug("Persistence image auto select %d\n", node
->autosel
);
3033 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3039 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3040 " echo %s\n}\n", "123");
3042 for (i
= 0; i
< node
->backendnum
; i
++)
3044 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3046 node
->backendpath
[i
].path
);
3050 g_ventoy_menu_esc
= 1;
3051 g_ventoy_suppress_esc
= 1;
3053 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3054 grub_script_execute_sourcecode(configfile
);
3056 g_ventoy_menu_esc
= 0;
3057 g_ventoy_suppress_esc
= 0;
3061 node
->cursel
= g_ventoy_last_entry
- 1;
3063 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3066 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3069 ventoy_img_chunk
*cur
;
3075 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3077 cur
= g_img_chunk_list
.chunk
+ i
;
3078 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3079 cur
->img_start_sector
, cur
->img_end_sector
,
3080 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3084 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3087 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3091 ventoy_img_chunk_list chunklist
;
3096 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3099 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3102 /* get image chunk data */
3103 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3104 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3105 if (NULL
== chunklist
.chunk
)
3107 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3110 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3111 chunklist
.cur_chunk
= 0;
3113 ventoy_get_block_list(file
, &chunklist
, 0);
3115 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3117 grub_printf("########## UNSUPPORTED ###############\n");
3120 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3122 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3124 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3125 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3128 grub_printf("\n==================================\n");
3130 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3132 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3133 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3134 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3135 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3136 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3140 grub_free(chunklist
.chunk
);
3141 grub_file_close(file
);
3143 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3146 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3149 ventoy_grub_param_file_replace
*replace
= NULL
;
3157 replace
= &(g_grub_param
->file_replace
);
3158 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3160 replace
->old_name_cnt
= 0;
3161 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3163 replace
->old_name_cnt
++;
3164 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3167 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3170 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3173 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3176 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3182 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3183 grub_env_set(args
[0], buf
);
3186 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3189 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3197 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3198 grub_printf("%s", g_list_script_buf
);
3202 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3203 grub_printf("%s", g_tree_script_buf
);
3209 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3211 img_info
*cur
= g_ventoy_img_list
;
3219 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3220 grub_printf("name:<%s>\n\n", cur
->name
);
3227 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3233 ventoy_plugin_dump_injection();
3238 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3244 ventoy_plugin_dump_auto_install();
3249 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3255 ventoy_plugin_dump_persistence();
3260 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3271 if (args
[0][0] == '0')
3273 return g_ventoy_memdisk_mode
? 0 : 1;
3275 else if (args
[0][0] == '1')
3277 return g_ventoy_iso_raw
? 0 : 1;
3279 else if (args
[0][0] == '2')
3281 return g_ventoy_iso_uefi_drv
? 0 : 1;
3283 else if (args
[0][0] == '3')
3285 return g_ventoy_grub2_mode
? 0 : 1;
3287 else if (args
[0][0] == '4')
3289 return g_ventoy_wimboot_mode
? 0 : 1;
3295 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3297 static int configfile_mode
= 0;
3298 char memfile
[128] = {0};
3305 * args[0]: 0:normal 1:configfile
3306 * args[1]: 0:list_buf 1:tree_buf
3311 debug("Invalid argc %d\n", argc
);
3317 if (args
[0][0] == '0')
3319 if (args
[1][0] == '0')
3321 grub_script_execute_sourcecode(g_list_script_buf
);
3325 grub_script_execute_sourcecode(g_tree_script_buf
);
3330 if (configfile_mode
)
3332 debug("Now already in F3 mode %d\n", configfile_mode
);
3336 if (args
[1][0] == '0')
3338 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3339 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3343 g_ventoy_last_entry
= -1;
3344 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3345 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3348 configfile_mode
= 1;
3349 grub_script_execute_sourcecode(memfile
);
3350 configfile_mode
= 0;
3356 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3367 g_ventoy_case_insensitive
= 1;
3368 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3369 g_ventoy_case_insensitive
= 0;
3375 grub_file_close(file
);
3381 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3386 const char *isopath
= NULL
;
3388 ventoy_mbr_head mbr
;
3395 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3398 isopath
= grub_env_get("vtoy_iso_part");
3401 debug("isopath is null %p\n", isopath
);
3405 debug("isopath is %s\n", isopath
);
3407 for (id
= 0; id
< 30 && (find
== 0); id
++)
3409 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3410 if (grub_strstr(isopath
, hdname
))
3412 debug("skip %s ...\n", hdname
);
3416 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3418 disk
= grub_disk_open(hdname
);
3421 debug("%s not exist\n", hdname
);
3425 grub_memset(&mbr
, 0, sizeof(mbr
));
3426 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3428 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3430 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3431 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3434 grub_env_set(args
[0], hdname
);
3438 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3442 debug("read %s failed\n", hdname
);
3445 grub_disk_close(disk
);
3451 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3462 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3465 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3468 debug("failed to open file %s\n", args
[0]);
3472 buf
= grub_malloc(len
);
3479 grub_file_read(file
, buf
, len
- 1);
3481 ventoy_get_line(buf
);
3482 ventoy_set_env(args
[1], buf
);
3486 grub_check_free(buf
);
3487 grub_file_close(file
);
3492 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3494 int *pCnt
= (int *)data
;
3499 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3500 "0 %llu linear /dev/ventoy %llu\n",
3501 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3506 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3509 char *device_name
= NULL
;
3510 grub_device_t dev
= NULL
;
3515 g_part_list_pos
= 0;
3516 grub_env_unset("vtoy_img_part_file");
3523 device_name
= grub_file_get_device_name(args
[0]);
3526 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3530 dev
= grub_device_open(device_name
);
3533 debug("grub_device_open failed, %s\n", device_name
);
3537 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3539 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3540 grub_env_set("vtoy_img_part_file", buf
);
3542 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3543 grub_env_set("vtoy_img_part_cnt", buf
);
3547 check_free(device_name
, grub_free
);
3548 check_free(dev
, grub_device_close
);
3554 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3565 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3568 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3571 debug("failed to open file %s\n", args
[0]);
3575 buf
= grub_malloc(file
->size
+ 1);
3581 buf
[file
->size
] = 0;
3582 grub_file_read(file
, buf
, file
->size
);
3584 if (grub_strstr(buf
, args
[1]))
3591 grub_check_free(buf
);
3592 grub_file_close(file
);
3597 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3603 ventoy_iso9660_vd pvd
;
3610 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3613 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3616 debug("failed to open file %s\n", args
[0]);
3620 grub_file_seek(file
, 16 * 2048);
3621 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3622 if (len
!= sizeof(pvd
))
3624 debug("failed to read pvd %d\n", len
);
3628 grub_memset(buf
, 0, sizeof(buf
));
3629 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3630 ventoy_set_env(args
[1], buf
);
3632 grub_memset(buf
, 0, sizeof(buf
));
3633 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3634 ventoy_set_env(args
[2], buf
);
3638 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3639 ventoy_set_env(args
[3], buf
);
3642 grub_file_close(file
);
3647 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3658 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3661 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3664 debug("failed to open file %s\n", args
[0]);
3668 grub_memset(buf
, 0, sizeof(buf
));
3669 grub_file_seek(file
, 16 * 2048 + 813);
3670 len
= (int)grub_file_read(file
, buf
, 17);
3673 debug("failed to read create date %d\n", len
);
3677 ventoy_set_env(args
[1], buf
);
3680 grub_file_close(file
);
3685 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3691 ventoy_env_hook_root(1);
3696 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3702 ventoy_env_hook_root(0);
3707 #ifdef GRUB_MACHINE_EFI
3708 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3713 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3719 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3720 if (var
&& *var
== 1)
3728 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3737 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3742 grub_uint64_t FileSectors
= 0;
3743 ventoy_gpt_info
*gpt
= NULL
;
3744 ventoy_part_table
*pt
= NULL
;
3745 grub_uint8_t zeroguid
[16] = {0};
3750 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3753 debug("failed to open file %s\n", args
[0]);
3757 if (file
->size
% 512)
3759 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3763 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3769 FileSectors
= file
->size
/ 512;
3771 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3772 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3774 debug("This is EFI partition table\n");
3776 for (i
= 0; i
< 128; i
++)
3778 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3780 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3782 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3783 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3791 debug("This is MBR partition table\n");
3793 for (i
= 0; i
< 4; i
++)
3795 pt
= gpt
->MBR
.PartTbl
+ i
;
3796 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3798 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3799 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3800 (ulonglong
)FileSectors
);
3809 grub_file_close(file
);
3810 grub_check_free(gpt
);
3811 grub_errno
= GRUB_ERR_NONE
;
3815 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3824 for (i
= 0; i
< 500; i
++)
3826 ret
= grub_getkey_noblock();
3827 if (ret
== GRUB_TERM_NO_KEY
)
3836 grub_printf("\n\n Still have key input after clear.\n");
3844 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3851 int image_sector_size
;
3853 ventoy_chain_head
*chain
;
3854 ventoy_img_chunk
*chunk
;
3855 ventoy_os_param
*osparam
;
3856 ventoy_image_location
*location
;
3857 ventoy_image_disk_region
*region
;
3858 struct grub_acpi_table_header
*acpi
;
3867 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3869 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3875 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3877 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3879 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3883 img_chunk_num
= chain
->img_chunk_num
;
3885 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3886 datalen
= sizeof(ventoy_os_param
) + loclen
;
3888 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3889 acpi
= grub_zalloc(buflen
);
3895 /* Step1: Fill acpi table header */
3896 grub_memcpy(acpi
->signature
, "VTOY", 4);
3897 acpi
->length
= buflen
;
3899 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
3900 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
3902 acpi
->creator_id
[0] = 1;
3903 acpi
->creator_rev
= 1;
3905 /* Step2: Fill data */
3906 osparam
= (ventoy_os_param
*)(acpi
+ 1);
3907 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
3908 osparam
->vtoy_img_location_addr
= 0;
3909 osparam
->vtoy_img_location_len
= loclen
;
3910 osparam
->chksum
= 0;
3911 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
3913 location
= (ventoy_image_location
*)(osparam
+ 1);
3914 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
3915 location
->image_sector_size
= image_sector_size
;
3916 location
->disk_sector_size
= chain
->disk_sector_size
;
3917 location
->region_count
= img_chunk_num
;
3919 region
= location
->regions
;
3920 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
3921 if (512 == image_sector_size
)
3923 for (i
= 0; i
< img_chunk_num
; i
++)
3925 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
3926 region
->image_start_sector
= chunk
->img_start_sector
* 4;
3927 region
->disk_start_sector
= chunk
->disk_start_sector
;
3934 for (i
= 0; i
< img_chunk_num
; i
++)
3936 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
3937 region
->image_start_sector
= chunk
->img_start_sector
;
3938 region
->disk_start_sector
= chunk
->disk_start_sector
;
3944 /* Step3: Fill acpi checksum */
3946 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
3948 /* load acpi table */
3949 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
3950 grub_script_execute_sourcecode(cmd
);
3954 VENTOY_CMD_RETURN(0);
3957 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3963 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
3964 g_ventoy_last_entry
= -1;
3969 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3975 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
3980 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
3982 const char *pos
= filename
+ 1;
3990 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
3992 grub_strncpy((char *)data
, filename
, 128);
4003 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4006 char *device_name
= NULL
;
4007 grub_device_t dev
= NULL
;
4008 grub_fs_t fs
= NULL
;
4009 char buf
[128] = {0};
4015 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4019 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4021 device_name
= grub_file_get_device_name(args
[0]);
4024 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4028 dev
= grub_device_open(device_name
);
4031 debug("grub_device_open failed, %s\n", device_name
);
4035 fs
= grub_fs_probe(dev
);
4038 debug("grub_fs_probe failed, %s\n", device_name
);
4042 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4046 ventoy_set_env(args
[2], buf
);
4053 check_free(device_name
, grub_free
);
4054 check_free(dev
, grub_device_close
);
4059 int ventoy_load_part_table(const char *diskname
)
4066 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4067 if (!g_ventoy_part_info
)
4072 disk
= grub_disk_open(diskname
);
4075 debug("Failed to open disk %s\n", diskname
);
4079 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4081 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4082 grub_disk_close(disk
);
4084 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4085 dev
= grub_device_open(name
);
4088 /* Check for official Ventoy device */
4089 ret
= ventoy_check_official_device(dev
);
4090 grub_device_close(dev
);
4098 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4099 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4104 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4111 ret
= ventoy_load_part_table(args
[0]);
4117 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4118 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4123 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4126 const char *vcfg
= NULL
;
4131 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4134 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4135 grub_env_set(args
[1], vcfg
);
4140 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4148 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4151 grub_uint8_t zeroguid
[16] = {0};
4156 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4159 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4161 if (id
>= 1 && id
<= 128)
4163 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4171 if (id
>= 1 && id
<= 4)
4173 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4183 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4186 char *device_name
= NULL
;
4187 grub_device_t dev
= NULL
;
4188 grub_fs_t fs
= NULL
;
4193 debug("get fs label for %s\n", args
[0]);
4197 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4201 device_name
= grub_file_get_device_name(args
[0]);
4204 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4208 dev
= grub_device_open(device_name
);
4211 debug("grub_device_open failed, %s\n", device_name
);
4215 fs
= grub_fs_probe(dev
);
4216 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4218 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4222 fs
->fs_label(dev
, &label
);
4225 debug("label=<%s>\n", label
);
4226 ventoy_set_env(args
[1], label
);
4234 check_free(device_name
, grub_free
);
4235 check_free(dev
, grub_device_close
);
4240 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4244 grub_snprintf((char *)data
, 256, "%s", filename
);
4251 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4253 if (info
->dir
&& filename
&& filename
[0] != '.')
4255 grub_snprintf((char *)data
, 256, "%s", filename
);
4262 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4265 char *device_name
= NULL
;
4266 grub_device_t dev
= NULL
;
4267 grub_fs_t fs
= NULL
;
4268 char name
[256] ={0};
4272 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4276 device_name
= grub_file_get_device_name(args
[0]);
4279 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4283 dev
= grub_device_open(device_name
);
4286 debug("grub_device_open failed, %s\n", device_name
);
4290 fs
= grub_fs_probe(dev
);
4293 debug("grub_fs_probe failed, %s\n", device_name
);
4297 fs
->fs_dir(dev
, args
[1], hook
, name
);
4300 ventoy_set_env(args
[2], name
);
4307 check_free(device_name
, grub_free
);
4308 check_free(dev
, grub_device_close
);
4313 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4316 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4319 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4322 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4325 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4335 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4339 for (pos
= args
[0]; *pos
; pos
++)
4353 grub_env_set(args
[1], args
[0]);
4363 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4373 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4378 len
= (int)grub_strlen(buf
);
4379 for (i
= len
; i
> 0; i
--)
4381 if (buf
[i
- 1] == '/')
4383 grub_env_set(args
[1], buf
+ i
);
4388 grub_env_set(args
[1], buf
);
4393 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4395 struct grub_video_mode_info info
;
4402 if (!g_video_mode_list
)
4404 ventoy_enum_video_mode();
4407 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4409 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4413 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4416 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4418 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4419 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4421 VENTOY_CMD_RETURN(0);
4424 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4426 struct grub_video_mode_info info
;
4433 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4435 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4439 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4442 grub_env_set(args
[0], buf
);
4444 VENTOY_CMD_RETURN(0);
4447 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4455 if (!g_video_mode_list
)
4460 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4461 if (id
< g_video_mode_num
)
4463 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4464 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4467 grub_env_set(args
[1], buf
);
4469 VENTOY_CMD_RETURN(0);
4472 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4475 grub_uint32_t loadsector
= 0;
4478 grub_uint32_t boot_catlog
= 0;
4479 grub_uint8_t buf
[512];
4485 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4489 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4492 debug("failed to open %s\n", args
[0]);
4496 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4497 if (boot_catlog
== 0)
4499 debug("No bootcatlog found\n");
4500 grub_file_close(file
);
4504 grub_memset(buf
, 0, sizeof(buf
));
4505 grub_file_seek(file
, boot_catlog
* 2048);
4506 grub_file_read(file
, buf
, sizeof(buf
));
4507 grub_file_close(file
);
4509 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4511 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4513 if (buf
[i
+ 32] == 0x88)
4515 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4516 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4522 if (loadsector
== 0)
4524 debug("No EFI eltorito info found\n");
4528 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4529 grub_env_set(args
[1], value
);
4530 VENTOY_CMD_RETURN(0);
4533 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4538 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4540 if (pfsdir
->initrd
[0])
4545 curpos
= pfsdir
->curpos
;
4546 len
= grub_strlen(filename
);
4550 if ((len
== 1 && filename
[0] == '.') ||
4551 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4556 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4559 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4560 pfsdir
->curpos
= curpos
+ printlen
;
4561 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4562 pfsdir
->curpos
= curpos
;
4563 pfsdir
->fullpath
[curpos
] = 0;
4567 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4570 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4571 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4573 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4575 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4584 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4588 char *device_name
= NULL
;
4589 grub_device_t dev
= NULL
;
4590 grub_fs_t fs
= NULL
;
4591 replace_fs_dir
*pfsdir
= NULL
;
4597 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4601 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4607 device_name
= grub_file_get_device_name(args
[0]);
4613 dev
= grub_device_open(device_name
);
4619 fs
= grub_fs_probe(dev
);
4628 pfsdir
->fullpath
[0] = '/';
4629 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4631 if (pfsdir
->initrd
[0])
4633 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4635 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4637 if (pfsdir
->initrd
[i
] == '/')
4639 pfsdir
->initrd
[i
] = '\\';
4643 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4644 grub_env_set(args
[1], pos
);
4648 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4653 grub_check_free(pfsdir
);
4654 grub_check_free(device_name
);
4655 check_free(dev
, grub_device_close
);
4657 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4660 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4662 const char *pager
= NULL
;
4668 pager
= grub_env_get("pager");
4672 grub_env_set("pager", "1");
4674 else if (pager
[0] == '1')
4680 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4682 grub_env_set("pager", "1");
4685 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4688 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4694 if (g_pager_flag
== 1)
4696 grub_env_unset("pager");
4698 else if (g_pager_flag
== 2)
4700 grub_env_set("pager", g_old_pager
);
4703 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4706 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4708 if (g_json_case_mis_path
[0])
4713 if (0 == info
->dir
&& grub_strncasecmp(filename
, "ventoy.json", 11) == 0)
4715 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4721 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4724 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4726 if (g_json_case_mis_path
[0])
4731 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4733 if (grub_strncasecmp(filename
, "ventoy", 6) == 0)
4735 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4736 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4737 if (g_json_case_mis_path
[0])
4747 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4750 char *device_name
= NULL
;
4751 grub_device_t dev
= NULL
;
4752 grub_fs_t fs
= NULL
;
4753 chk_case_fs_dir fs_dir
;
4759 device_name
= grub_file_get_device_name(args
[0]);
4765 dev
= grub_device_open(device_name
);
4771 fs
= grub_fs_probe(dev
);
4777 fstype
= ventoy_get_fs_type(fs
->name
);
4778 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4783 g_json_case_mis_path
[0] = 0;
4786 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4788 if (g_json_case_mis_path
[0])
4790 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4795 grub_check_free(device_name
);
4796 check_free(dev
, grub_device_close
);
4798 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4801 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4804 grub_partition_t part
;
4805 char priority_str
[3]; /* Maximum value 15 */
4809 if (argc
< 2 || argc
> 3)
4810 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4811 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4813 /* Open the disk if it exists */
4814 disk
= grub_disk_open (args
[0]);
4817 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4821 part
= grub_partition_probe (disk
, args
[1]);
4824 grub_disk_close (disk
);
4825 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4826 "No such partition");
4829 if (grub_strcmp (part
->partmap
->name
, "gpt"))
4831 grub_disk_close (disk
);
4832 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
4833 "Not a GPT partition");
4836 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
4837 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
4841 grub_env_set (args
[2], priority_str
);
4842 grub_env_export (args
[2]);
4846 grub_printf ("Priority is %s\n", priority_str
);
4849 grub_disk_close (disk
);
4850 return GRUB_ERR_NONE
;
4854 int ventoy_env_init(void)
4858 grub_env_set("vtdebug_flag", "");
4860 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4861 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4862 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4863 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4865 ventoy_filt_register(0, ventoy_wrapper_open
);
4867 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
4870 g_grub_param
->grub_env_get
= grub_env_get
;
4871 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
4872 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
4873 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
4874 grub_env_set("env_param", buf
);
4875 grub_env_set("ventoy_env_param", buf
);
4877 grub_env_export("env_param");
4878 grub_env_export("ventoy_env_param");
4881 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
4882 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
4884 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
4885 grub_env_set("vtoy_winpeshl_ini_size", buf
);
4887 grub_env_export("vtoy_winpeshl_ini_addr");
4888 grub_env_export("vtoy_winpeshl_ini_size");
4890 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
4891 grub_env_set("vtoy_chain_file_size", buf
);
4892 grub_env_export("vtoy_chain_file_size");
4894 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
4895 grub_env_set("vtoy_chain_file_read", buf
);
4896 grub_env_export("vtoy_chain_file_read");
4903 static cmd_para ventoy_cmds
[] =
4905 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
4906 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
4907 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
4908 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
4909 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4910 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
4911 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
4912 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
4913 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
4914 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
4915 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
4916 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
4917 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
4918 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
4919 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
4920 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
4921 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
4922 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
4923 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
4924 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
4925 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
4926 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
4927 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
4928 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
4930 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
4931 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
4932 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
4933 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
4934 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
4935 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
4936 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
4938 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
4939 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
4940 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
4941 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
4942 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
4943 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
4944 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
4945 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
4946 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
4947 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
4950 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
4951 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
4952 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
4953 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
4954 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
4955 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
4956 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
4957 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
4958 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
4959 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
4960 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
4962 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
4963 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
4964 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
4965 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
4966 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
4967 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
4968 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
4970 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4971 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
4972 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
4973 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
4974 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
4975 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
4976 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
4977 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
4978 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
4979 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
4981 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
4982 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
4983 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
4984 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
4985 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
4986 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
4987 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
4988 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
4989 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
4991 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
4992 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
4993 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
4994 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
4997 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
4998 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
4999 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5001 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5002 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5003 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5006 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5007 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5008 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5009 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5010 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5011 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5012 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5013 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5014 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5015 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5016 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5018 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5019 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5020 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5021 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5022 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5023 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5024 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5025 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5026 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5027 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5029 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5030 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5031 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5032 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5033 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5034 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5035 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5038 int ventoy_register_all_cmd(void)
5041 cmd_para
*cur
= NULL
;
5043 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5045 cur
= ventoy_cmds
+ i
;
5046 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5047 cur
->summary
, cur
->description
, cur
->parser
);
5053 int ventoy_unregister_all_cmd(void)
5057 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5059 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);