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/random.h>
49 #include <grub/ventoy.h>
50 #include "ventoy_def.h"
53 GRUB_MOD_LICENSE ("GPLv3+");
55 static grub_uint8_t g_check_mbr_data
[] = {
56 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
62 initrd_info
*g_initrd_img_list
= NULL
;
63 initrd_info
*g_initrd_img_tail
= NULL
;
64 int g_initrd_img_count
= 0;
65 int g_valid_initrd_count
= 0;
66 int g_default_menu_mode
= 0;
67 int g_filt_dot_underscore_file
= 0;
68 int g_sort_case_sensitive
= 0;
69 int g_tree_view_menu_style
= 0;
70 static grub_file_t g_old_file
;
71 static int g_ventoy_last_entry_back
;
74 char g_img_swap_tmp_buf
[1024];
75 img_info g_img_swap_tmp
;
76 img_info
*g_ventoy_img_list
= NULL
;
78 int g_ventoy_img_count
= 0;
80 grub_device_t g_enum_dev
= NULL
;
81 grub_fs_t g_enum_fs
= NULL
;
82 int g_img_max_search_level
= -1;
83 img_iterator_node g_img_iterator_head
;
84 img_iterator_node
*g_img_iterator_tail
= NULL
;
86 grub_uint8_t g_ventoy_break_level
= 0;
87 grub_uint8_t g_ventoy_debug_level
= 0;
88 grub_uint8_t g_ventoy_chain_type
= 0;
90 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
91 grub_uint32_t g_ventoy_cpio_size
= 0;
92 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
93 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
95 int g_plugin_image_list
= 0;
97 ventoy_grub_param
*g_grub_param
= NULL
;
99 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
101 ventoy_img_chunk_list g_img_chunk_list
;
103 int g_wimboot_enable
= 0;
104 ventoy_img_chunk_list g_wimiso_chunk_list
;
105 char *g_wimiso_path
= NULL
;
106 grub_uint32_t g_wimiso_size
= 0;
108 int g_vhdboot_enable
= 0;
110 grub_uint64_t g_svd_replace_offset
= 0;
112 int g_conf_replace_count
= 0;
113 grub_uint64_t g_conf_replace_offset
[VTOY_MAX_CONF_REPLACE
] = { 0 };
114 conf_replace
*g_conf_replace_node
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
115 grub_uint8_t
*g_conf_replace_new_buf
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
116 int g_conf_replace_new_len
[VTOY_MAX_CONF_REPLACE
] = { 0 };
117 int g_conf_replace_new_len_align
[VTOY_MAX_CONF_REPLACE
] = { 0 };
119 int g_ventoy_disk_bios_id
= 0;
120 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
121 grub_uint64_t g_ventoy_disk_size
= 0;
122 grub_uint64_t g_ventoy_disk_part_size
[2];
124 char *g_tree_script_buf
= NULL
;
125 int g_tree_script_pos
= 0;
126 int g_tree_script_pre
= 0;
128 static char *g_list_script_buf
= NULL
;
129 static int g_list_script_pos
= 0;
131 static char *g_part_list_buf
= NULL
;
132 static int g_part_list_pos
= 0;
133 static grub_uint64_t g_part_end_max
= 0;
135 static int g_video_mode_max
= 0;
136 static int g_video_mode_num
= 0;
137 static ventoy_video_mode
*g_video_mode_list
= NULL
;
139 static int g_enumerate_time_checked
= 0;
140 static grub_uint64_t g_enumerate_start_time_ms
;
141 static grub_uint64_t g_enumerate_finish_time_ms
;
142 int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
144 static char g_iso_vd_id_publisher
[130];
145 static char g_iso_vd_id_prepare
[130];
146 static char g_iso_vd_id_application
[130];
148 static int g_pager_flag
= 0;
149 static char g_old_pager
[32];
151 const char *g_menu_class
[img_type_max
] =
153 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
156 const char *g_menu_prefix
[img_type_max
] =
158 "iso", "wim", "efi", "img", "vhd", "vtoy"
161 static int g_vtoy_secondary_need_recover
= 0;
163 static int g_vtoy_load_prompt
= 0;
164 static char g_vtoy_prompt_msg
[64];
166 static char g_json_case_mis_path
[32];
168 static ventoy_vlnk_part
*g_vlnk_part_list
= NULL
;
170 int ventoy_get_fs_type(const char *fs
)
174 return ventoy_fs_max
;
176 else if (grub_strncmp(fs
, "exfat", 5) == 0)
178 return ventoy_fs_exfat
;
180 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
182 return ventoy_fs_ntfs
;
184 else if (grub_strncmp(fs
, "ext", 3) == 0)
186 return ventoy_fs_ext
;
188 else if (grub_strncmp(fs
, "xfs", 3) == 0)
190 return ventoy_fs_xfs
;
192 else if (grub_strncmp(fs
, "udf", 3) == 0)
194 return ventoy_fs_udf
;
196 else if (grub_strncmp(fs
, "fat", 3) == 0)
198 return ventoy_fs_fat
;
201 return ventoy_fs_max
;
204 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
223 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
225 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
229 static int ventoy_control_get_flag(const char *key
)
231 const char *val
= ventoy_get_env(key
);
233 if (val
&& val
[0] == '1' && val
[1] == 0)
240 static grub_err_t
ventoy_fs_close(grub_file_t file
)
242 grub_file_close(g_old_file
);
243 grub_free(file
->data
);
251 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
257 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
262 for (i
= 0; i
< g_video_mode_num
; i
++)
264 if (g_video_mode_list
[i
].width
== info
->width
&&
265 g_video_mode_list
[i
].height
== info
->height
&&
266 g_video_mode_list
[i
].bpp
== info
->bpp
)
272 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
273 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
274 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
277 if (g_video_mode_num
== g_video_mode_max
)
279 g_video_mode_max
*= 2;
280 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
286 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
288 if (v1
->bpp
== v2
->bpp
)
290 if (v1
->width
== v2
->width
)
292 if (v1
->height
== v2
->height
)
298 return (v1
->height
< v2
->height
) ? -1 : 1;
303 return (v1
->width
< v2
->width
) ? -1 : 1;
308 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
312 static int ventoy_enum_video_mode(void)
315 grub_video_adapter_t adapter
;
316 grub_video_driver_id_t id
;
317 ventoy_video_mode mode
;
319 g_video_mode_num
= 0;
320 g_video_mode_max
= 1024;
321 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
322 if (!g_video_mode_list
)
327 #ifdef GRUB_MACHINE_PCBIOS
328 grub_dl_load ("vbe");
331 id
= grub_video_get_driver_id ();
333 FOR_VIDEO_ADAPTERS (adapter
)
335 if (!adapter
->iterate
||
336 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
337 adapter
->init() != GRUB_ERR_NONE
)))
342 adapter
->iterate(ventoy_video_hook
, NULL
);
344 if (adapter
->id
!= id
)
350 /* sort video mode */
351 for (i
= 0; i
< g_video_mode_num
; i
++)
352 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
354 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
356 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
357 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
358 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
362 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
365 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
369 static struct grub_fs vtoy_fs
=
374 .fs_read
= ventoy_fs_read
,
375 .fs_close
= ventoy_fs_close
,
385 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
391 file
->data
= grub_malloc(rawFile
->size
+ 4096);
397 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
398 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
400 g_old_file
= rawFile
;
402 file
->size
= rawFile
->size
+ len
;
403 file
->device
= rawFile
->device
;
405 file
->not_easily_seekable
= 1;
410 static int ventoy_check_decimal_var(const char *name
, long *value
)
412 const char *value_str
= NULL
;
414 value_str
= grub_env_get(name
);
415 if (NULL
== value_str
)
417 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
420 if (!ventoy_is_decimal(value_str
))
422 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
425 *value
= grub_strtol(value_str
, NULL
, 10);
427 return GRUB_ERR_NONE
;
430 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
432 grub_uint64_t sectors
;
434 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
436 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
440 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
443 return sectors
* 512;
446 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
452 grub_uint32_t offset
;
454 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
457 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
461 len
= (int)file
->size
;
463 data
= (char *)grub_malloc(file
->size
);
469 grub_file_read(file
, data
, file
->size
);
470 grub_file_close(file
);
472 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
473 grub_script_execute_sourcecode(exec
);
475 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
476 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
477 grub_file_close(file
);
479 grub_script_execute_sourcecode("loopback -d efiboot");
483 *direntoff
= offset
+ 2;
488 static int ventoy_set_check_result(int ret
, const char *msg
)
492 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
493 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
494 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
498 grub_printf(VTOY_WARNING
"\n");
499 grub_printf(VTOY_WARNING
"\n");
500 grub_printf(VTOY_WARNING
"\n\n\n");
502 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret
);
503 grub_printf("Error message: <%s>\n\n", msg
);
504 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
506 grub_printf("\n\nWill exit after 10 seconds ...... ");
514 static int ventoy_check_official_device(grub_device_t dev
)
518 grub_uint64_t offset
;
521 grub_uint8_t mbr
[512];
525 struct grub_partition
*partition
;
527 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
529 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
532 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
533 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
534 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
536 #ifndef GRUB_MACHINE_EFI
537 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
))
539 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
541 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
))
543 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
545 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
547 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
556 /* We must have partition 2 */
559 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
563 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
567 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
570 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
572 grub_file_close(file
);
573 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
576 partition
= dev
->disk
->partition
;
577 if (partition
->number
!= 0 || partition
->start
!= 2048)
579 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
584 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
586 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
587 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
588 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
590 grub_file_close(file
);
591 return ventoy_set_check_result(6, "Disk partition layout check failed.");
596 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
597 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
598 PartTbl
[1].SectorCount
!= 65536)
600 grub_file_close(file
);
601 return ventoy_set_check_result(6, "Disk partition layout check failed.");
607 offset
= partition
->start
+ partition
->len
;
608 partition
= file
->device
->disk
->partition
;
609 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
611 grub_file_close(file
);
612 return ventoy_set_check_result(7, "Disk partition layout check failed.");
616 grub_file_close(file
);
620 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
621 dev2
= grub_device_open(devname
);
624 return ventoy_set_check_result(8, "Disk open failed");
627 fs
= grub_fs_probe(dev2
);
630 grub_device_close(dev2
);
631 return ventoy_set_check_result(9, "FS probe failed");
634 fs
->fs_label(dev2
, &label
);
635 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
637 grub_device_close(dev2
);
638 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
641 grub_device_close(dev2
);
645 disk
= grub_disk_open(dev
->disk
->name
);
648 return ventoy_set_check_result(11, "Disk open failed");
651 grub_memset(mbr
, 0, 512);
652 grub_disk_read(disk
, 0, 0, 512, mbr
);
653 grub_disk_close(disk
);
655 if (grub_memcmp(g_check_mbr_data
, mbr
, 0x30) || grub_memcmp(g_check_mbr_data
+ 0x30, mbr
+ 0x190, 16))
657 return ventoy_set_check_result(12, "MBR check failed");
660 return ventoy_set_check_result(0, NULL
);
663 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
667 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
677 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
679 grub_uint64_t size
= 0;
682 char fullpath
[256] = {0};
685 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
688 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
691 debug("grub_file_open failed <%s>\n", fullpath
);
697 grub_file_close(file
);
701 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
705 char fullpath
[512] = {0};
708 grub_vsnprintf(fullpath
, 511, fmt
, ap
);
711 file
= grub_file_open(fullpath
, type
);
714 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
721 int ventoy_is_dir_exist(const char *fmt
, ...)
728 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
732 len
= grub_vsnprintf(pos
, 511, fmt
, ap
);
735 grub_strncpy(pos
+ len
, "\" ]", 3);
737 debug("script exec %s\n", buf
);
739 if (0 == grub_script_execute_sourcecode(buf
))
747 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
750 grub_uint8_t
*outbuf
;
751 grub_uint8_t gzHdr
[10] =
753 0x1F, 0x8B, /* magic */
761 grub_memset(&s
, 0, sizeof(mz_stream
));
763 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
765 outbuf
= (grub_uint8_t
*)mem_out
;
767 mem_out_len
-= sizeof(gzHdr
) + 8;
768 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
769 outbuf
+= sizeof(gzHdr
);
771 s
.avail_in
= mem_in_len
;
774 s
.avail_out
= mem_out_len
;
777 mz_deflate(&s
, MZ_FINISH
);
781 outbuf
+= s
.total_out
;
782 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
783 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
785 return s
.total_out
+ sizeof(gzHdr
) + 8;
793 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
797 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
800 if (0 == grub_strcmp(args
[0], "on"))
803 grub_env_set("vtdebug_flag", "debug");
808 grub_env_set("vtdebug_flag", "");
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
814 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
818 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
820 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
821 grub_printf(" level:\r\n");
822 grub_printf(" 01/11: busybox / (+cat log)\r\n");
823 grub_printf(" 02/12: initrd / (+cat log)\r\n");
824 grub_printf(" 03/13: hook / (+cat log)\r\n");
826 grub_printf(" debug:\r\n");
827 grub_printf(" 0: debug is off\r\n");
828 grub_printf(" 1: debug is on\r\n");
830 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
833 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
835 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
837 g_ventoy_debug_level
= 1;
840 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
843 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
852 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
855 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
887 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
903 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
919 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
924 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
926 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
929 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
934 value_long
+= grub_strtol(args
[1], NULL
, 10);
936 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
937 grub_env_set(args
[0], buf
);
939 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
942 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
944 ulonglong value1
= 0;
945 ulonglong value2
= 0;
950 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
953 value1
= grub_strtoull(args
[0], NULL
, 10);
954 value2
= grub_strtoull(args
[1], NULL
, 10);
956 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
957 grub_env_set(args
[2], buf
);
959 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
962 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
977 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
980 debug("failed to open file <%s> for udf check\n", args
[0]);
984 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
986 grub_env_set(args
[1], buf
);
988 grub_file_close(file
);
994 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1002 g_wimboot_enable
= 0;
1004 grub_check_free(g_wimiso_path
);
1005 grub_check_free(g_wimiso_chunk_list
.chunk
);
1007 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1013 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1014 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1015 if (NULL
== g_wimiso_chunk_list
.chunk
)
1017 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1020 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1021 g_wimiso_chunk_list
.cur_chunk
= 0;
1023 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1025 g_wimboot_enable
= 1;
1026 g_wimiso_path
= grub_strdup(args
[0]);
1027 g_wimiso_size
= (grub_uint32_t
)(file
->size
);
1028 grub_file_close(file
);
1033 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1043 ventoy_iso9660_override
*dirent
;
1052 totlen
= sizeof(ventoy_chain_head
);
1054 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1056 debug("failed to load efiboot template %d\n", len
);
1062 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1064 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1067 debug("failed to open file <%s>\n", args
[0]);
1071 if (grub_strncmp(args
[0], g_iso_path
, grub_strlen(g_iso_path
)))
1076 totlen
+= ventoy_align_2k(file
->size
);
1078 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1079 dirent
->first_sector
= len
/ 2048;
1080 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1081 dirent
->size
= (grub_uint32_t
)file
->size
;
1082 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1084 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1086 #ifdef GRUB_MACHINE_EFI
1087 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1089 data
= (char *)grub_malloc(totlen
);
1092 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1094 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1095 grub_check_free(buf
);
1097 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1098 grub_file_close(file
);
1100 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1101 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1102 grub_env_set(name
, value
);
1104 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1105 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1106 grub_env_set(name
, value
);
1111 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1117 g_vtoy_load_prompt
= 0;
1118 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1120 if (argc
== 2 && args
[0][0] == '1')
1122 g_vtoy_load_prompt
= 1;
1123 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1126 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1129 int ventoy_need_prompt_load_file(void)
1131 return g_vtoy_load_prompt
;
1134 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1136 grub_uint64_t ro
= 0;
1137 grub_uint64_t div
= 0;
1138 grub_ssize_t left
= size
;
1139 char *cur
= (char *)buf
;
1141 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1144 while (left
>= VTOY_SIZE_2MB
)
1146 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1147 cur
+= VTOY_SIZE_2MB
;
1148 left
-= VTOY_SIZE_2MB
;
1150 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1155 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1161 grub_file_read(file
, cur
, left
);
1164 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1170 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1177 enum grub_file_type type
;
1188 if (grub_strcmp(args
[0], "nodecompress") == 0)
1190 type
= VENTOY_FILE_TYPE
;
1194 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1197 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1200 debug("failed to open file <%s>\n", args
[1]);
1204 #ifdef GRUB_MACHINE_EFI
1205 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1207 buf
= (char *)grub_malloc(file
->size
);
1212 grub_file_close(file
);
1216 if (g_vtoy_load_prompt
)
1218 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1222 grub_file_read(file
, buf
, file
->size
);
1225 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1226 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1227 grub_env_set(name
, value
);
1229 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1230 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1231 grub_env_set(name
, value
);
1233 grub_file_close(file
);
1239 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1257 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1260 debug("failed to open file <%s> for udf check\n", args
[0]);
1264 headlen
= sizeof(ventoy_chain_head
);
1266 #ifdef GRUB_MACHINE_EFI
1267 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1269 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1272 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1274 grub_file_read(file
, buf
+ headlen
, file
->size
);
1276 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1277 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1278 grub_env_set(name
, value
);
1280 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1281 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1282 grub_env_set(name
, value
);
1284 grub_file_close(file
);
1290 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1296 if (grub_iso9660_is_joliet())
1298 debug("This time has joliet process\n");
1307 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1316 if (args
[0][0] == '1')
1318 grub_iso9660_set_nojoliet(1);
1322 grub_iso9660_set_nojoliet(0);
1328 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1333 grub_uint8_t buf
[32];
1344 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1347 debug("failed to open file <%s> for udf check\n", args
[0]);
1351 for (i
= 16; i
< 32; i
++)
1353 grub_file_seek(file
, i
* 2048);
1354 grub_file_read(file
, buf
, sizeof(buf
));
1362 grub_file_seek(file
, i
* 2048);
1363 grub_file_read(file
, buf
, sizeof(buf
));
1365 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1368 grub_file_seek(file
, i
* 2048);
1369 grub_file_read(file
, buf
, sizeof(buf
));
1371 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1372 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1378 grub_file_close(file
);
1380 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1385 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1387 long value_long1
= 0;
1388 long value_long2
= 0;
1390 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1392 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1395 value_long1
= grub_strtol(args
[0], NULL
, 10);
1396 value_long2
= grub_strtol(args
[2], NULL
, 10);
1398 if (0 == grub_strcmp(args
[1], "eq"))
1400 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1402 else if (0 == grub_strcmp(args
[1], "ne"))
1404 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1406 else if (0 == grub_strcmp(args
[1], "gt"))
1408 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1410 else if (0 == grub_strcmp(args
[1], "lt"))
1412 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1414 else if (0 == grub_strcmp(args
[1], "ge"))
1416 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1418 else if (0 == grub_strcmp(args
[1], "le"))
1420 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1424 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1430 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1433 char buf
[128] = {0};
1437 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1440 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1441 pos
= grub_strstr(buf
, ",");
1447 grub_env_set(args
[1], buf
);
1449 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1452 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1458 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1464 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1467 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1469 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1470 if (0 == grub_script_execute_sourcecode(buf
))
1472 debug("file %s exist, ventoy_compatible YES\n", buf
);
1473 grub_env_set("ventoy_compatible", "YES");
1474 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1478 debug("file %s NOT exist\n", buf
);
1482 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1483 pos
= grub_strstr(buf
, ")");
1489 disk
= grub_disk_open(buf
);
1492 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1493 grub_disk_close(disk
);
1495 g_img_swap_tmp_buf
[703] = 0;
1496 for (i
= 318; i
< 703; i
++)
1498 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1499 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1501 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1502 grub_env_set("ventoy_compatible", "YES");
1503 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1509 debug("failed to open disk <%s>\n", buf
);
1512 grub_env_set("ventoy_compatible", "NO");
1513 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1516 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1522 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1524 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1527 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1532 if (0 == g_sort_case_sensitive
)
1534 if (grub_islower(c1
))
1536 c1
= c1
- 'a' + 'A';
1539 if (grub_islower(c2
))
1541 c2
= c2
- 'a' + 'A';
1554 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1560 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1562 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1565 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1570 if (0 == g_sort_case_sensitive
)
1572 if (grub_islower(c1
))
1574 c1
= c1
- 'a' + 'A';
1577 if (grub_islower(c2
))
1579 c2
= c2
- 'a' + 'A';
1592 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1594 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1596 grub_memcpy(img1
, img2
, sizeof(img_info
));
1597 img1
->next
= g_img_swap_tmp
.next
;
1598 img1
->prev
= g_img_swap_tmp
.prev
;
1600 g_img_swap_tmp
.next
= img2
->next
;
1601 g_img_swap_tmp
.prev
= img2
->prev
;
1602 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1605 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1609 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1617 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1619 ventoy_vlnk_part
*node
= NULL
;
1620 grub_uint32_t SelfSig
;
1621 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1623 /* skip Ventoy partition 1/2 */
1624 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1625 if (partition
->number
< 2 && SelfSig
== *pSig
)
1630 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1633 node
->disksig
= *pSig
;
1634 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1635 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1636 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1638 node
->next
= g_vlnk_part_list
;
1639 g_vlnk_part_list
= node
;
1645 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1652 disk
= grub_disk_open(name
);
1655 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1656 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1657 grub_disk_close(disk
);
1663 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1665 const char *fs
[ventoy_fs_max
+ 1] =
1667 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1672 cur
->dev
= grub_device_open(cur
->device
);
1677 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1683 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1688 char *disk
, *device
;
1689 grub_uint32_t readcrc
, calccrc
;
1690 ventoy_vlnk_part
*cur
;
1691 grub_fs_t fs
= NULL
;
1693 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1697 grub_printf("VLNK invalid guid\n");
1703 readcrc
= vlnk
->crc32
;
1705 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1706 if (readcrc
!= calccrc
)
1710 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1716 if (!g_vlnk_part_list
)
1718 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1721 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1723 if (cur
->disksig
== vlnk
->disk_signature
)
1727 if (cur
->partoffset
== vlnk
->part_offset
)
1730 device
= cur
->device
;
1732 if (cur
->probe
== 0)
1735 ventoy_vlnk_probe_fs(cur
);
1745 struct grub_file file
;
1747 grub_memset(&file
, 0, sizeof(file
));
1748 file
.device
= cur
->dev
;
1749 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1752 cur
->fs
->fs_close(&file
);
1753 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1762 grub_printf("\n==== VLNK Information ====\n"
1763 "Disk Signature: %08x\n"
1764 "Partition Offset: %llu\n"
1765 "File Path: <%s>\n\n",
1766 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1770 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1774 grub_printf("Disk Find: [ NO ]\n");
1779 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1783 grub_printf("Part Find: [ NO ]\n");
1785 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1788 grub_printf("VLNK File: <%s>\n", dst
);
1795 return (1 - filefind
);
1798 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1803 grub_file_t file
= NULL
;
1808 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1810 else if (dir
[0] == '/')
1812 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1816 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1819 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1825 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1826 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1827 grub_file_close(file
);
1829 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1831 rc
= grub_file_add_vlnk(src
, dst
);
1837 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1847 const menu_tip
*tip
;
1848 img_iterator_node
*tmp
;
1849 img_iterator_node
*new_node
;
1850 img_iterator_node
*node
= (img_iterator_node
*)data
;
1852 if (g_enumerate_time_checked
== 0)
1854 g_enumerate_finish_time_ms
= grub_get_time_ms();
1855 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1858 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1860 g_enumerate_time_checked
= 1;
1864 len
= grub_strlen(filename
);
1868 if (node
->level
+ 1 > g_img_max_search_level
)
1873 if ((len
== 1 && filename
[0] == '.') ||
1874 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1879 if (!ventoy_img_name_valid(filename
, len
))
1884 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1889 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1891 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1892 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1895 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1900 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1903 new_node
->level
= node
->level
+ 1;
1904 new_node
->plugin_list_index
= index
;
1905 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1907 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1910 debug("Directory %s ignored...\n", new_node
->dir
);
1911 grub_free(new_node
);
1915 new_node
->tail
= node
->tail
;
1917 new_node
->parent
= node
;
1918 if (!node
->firstchild
)
1920 node
->firstchild
= new_node
;
1923 if (g_img_iterator_tail
)
1925 g_img_iterator_tail
->next
= new_node
;
1926 g_img_iterator_tail
= new_node
;
1930 g_img_iterator_head
.next
= new_node
;
1931 g_img_iterator_tail
= new_node
;
1937 debug("Find a file %s\n", filename
);
1943 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1945 type
= img_type_iso
;
1947 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1949 type
= img_type_wim
;
1951 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1952 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1954 type
= img_type_vhd
;
1956 #ifdef GRUB_MACHINE_EFI
1957 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1959 type
= img_type_efi
;
1962 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1964 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1966 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1967 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1972 type
= img_type_img
;
1974 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1976 type
= img_type_vtoy
;
1978 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1980 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1982 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1983 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1992 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1997 if (g_plugin_image_list
)
1999 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
2000 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
2001 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
2003 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2006 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2008 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2013 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2015 if (grub_file_is_vlnk_suffix(filename
, len
))
2018 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2025 img
= grub_zalloc(sizeof(img_info
));
2029 img
->plugin_list_index
= index
;
2030 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2032 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2034 img
->size
= info
->size
;
2035 if (vlnk
|| 0 == img
->size
)
2037 if (node
->dir
[0] == '/')
2039 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2043 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2047 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2049 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2054 if (g_ventoy_img_list
)
2056 tail
= *(node
->tail
);
2062 g_ventoy_img_list
= img
;
2065 img
->id
= g_ventoy_img_count
;
2067 if (node
&& NULL
== node
->firstiso
)
2069 node
->firstiso
= img
;
2080 *((img_info
**)(node
->tail
)) = img
;
2081 g_ventoy_img_count
++;
2083 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2085 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2088 img
->tip1
= tip
->tip1
;
2089 img
->tip2
= tip
->tip2
;
2092 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2095 img
->class = g_menu_class
[type
];
2097 img
->menu_prefix
= g_menu_prefix
[type
];
2099 if (img_type_iso
== type
)
2101 if (ventoy_plugin_check_memdisk(img
->path
))
2103 img
->menu_prefix
= "miso";
2107 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2114 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2116 int len
= GRUB_UINT_MAX
;
2117 const char *value
= NULL
;
2118 char name
[32] = {0};
2119 char plat
[32] = {0};
2120 char guidstr
[32] = {0};
2121 ventoy_guid guid
= VENTOY_GUID
;
2122 const char *fmt1
= NULL
;
2123 const char *fmt2
= NULL
;
2124 const char *fmt3
= NULL
;
2125 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2126 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2127 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2128 const char fmtcode
[]={
2129 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2130 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2131 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2132 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2133 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2134 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2137 grub_memset(name
, 0, sizeof(name
));
2138 puint
[0] = grub_swap_bytes32(0x56454e54);
2139 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2140 puint
[2] = grub_swap_bytes32(0x45525349);
2141 puint
[1] = grub_swap_bytes32(0x4f595f56);
2142 value
= ventoy_get_env(name
);
2144 grub_memset(name
, 0, sizeof(name
));
2145 puint
[1] = grub_swap_bytes32(0x5f544f50);
2146 puint
[0] = grub_swap_bytes32(0x56544c45);
2147 fmt1
= ventoy_get_env(name
);
2153 grub_memset(name
, 0, sizeof(name
));
2154 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2155 puint
[0] = grub_swap_bytes32(0x56544c45);
2156 fmt2
= ventoy_get_env(name
);
2158 grub_memset(name
, 0, sizeof(name
));
2159 puint
[1] = grub_swap_bytes32(0x5f434c52);
2160 puint
[0] = grub_swap_bytes32(0x56544c45);
2161 fmt3
= ventoy_get_env(name
);
2163 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2165 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2167 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2168 #pragma GCC diagnostic push
2169 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2170 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2171 fmt1
? fmt1
: fmtdata
,
2172 fmt2
? fmt2
: fmtdata
+ 4,
2173 value
? value
: "", plat
, guidstr
,
2174 fmt3
? fmt3
: fmtdata
+ 6);
2175 #pragma GCC diagnostic pop
2177 grub_memset(name
, 0, sizeof(name
));
2178 puint
[0] = grub_swap_bytes32(0x76746f79);
2179 puint
[2] = grub_swap_bytes32(0x656e7365);
2180 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2181 ventoy_set_env(name
, guidstr
);
2186 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2190 grub_uint8_t md5
[16];
2194 grub_memset(input
, 0, sizeof(input
));
2196 grub_printf("Enter password: ");
2199 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2201 grub_password_get(input
, 128);
2202 if (grub_strcmp(pwd
->text
, input
) == 0)
2207 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2209 grub_password_get(input
, 128);
2210 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2211 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2216 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2218 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2219 grub_password_get(input
+ offset
, 128);
2221 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2222 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2228 grub_printf("Invalid password!\n\n");
2235 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2237 img_info
*minimg
= NULL
;
2238 img_info
*img
= (img_info
*)(node
->firstiso
);
2240 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2242 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2257 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2259 img_iterator_node
*Minchild
= NULL
;
2260 img_iterator_node
*child
= node
->firstchild
;
2262 while (child
&& child
->parent
== node
)
2264 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2268 child
= child
->next
;
2273 Minchild
->select
= 1;
2279 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2282 img_info
*img
= NULL
;
2283 const char *dir_class
= NULL
;
2284 const char *dir_alias
= NULL
;
2285 img_iterator_node
*child
= NULL
;
2286 const menu_tip
*tip
= NULL
;
2288 if (node
->isocnt
== 0 || node
->done
== 1)
2293 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2295 offset
= node
->parent
->dirlen
;
2298 if (node
== &g_img_iterator_head
)
2300 if (g_default_menu_mode
== 0)
2302 if (g_tree_view_menu_style
== 0)
2304 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2305 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2306 " echo 'return ...' \n"
2311 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2312 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2313 " echo 'return ...' \n"
2318 g_tree_script_pre
= g_tree_script_pos
;
2322 node
->dir
[node
->dirlen
- 1] = 0;
2323 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2326 dir_class
= "vtoydir";
2329 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2331 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2334 if (g_tree_view_menu_style
== 0)
2336 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2337 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2338 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2342 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2343 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2344 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2349 dir_alias
= node
->dir
+ offset
;
2351 if (g_tree_view_menu_style
== 0)
2353 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2354 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2355 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2359 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2360 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2361 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2365 if (g_tree_view_menu_style
== 0)
2367 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2368 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2369 " echo 'return ...' \n"
2370 "}\n", "<--", node
->dir
);
2374 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2375 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2376 " echo 'return ...' \n"
2381 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2383 ventoy_dynamic_tree_menu(child
);
2386 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2388 if (g_tree_view_menu_style
== 0)
2390 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2391 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2394 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2395 img
->unsupport
? "[***********] " : "",
2396 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2398 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2402 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2403 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2406 img
->unsupport
? "[***********] " : "",
2407 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2409 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2413 if (node
!= &g_img_iterator_head
)
2415 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2422 static int ventoy_set_default_menu(void)
2428 const char *strdata
= NULL
;
2429 img_info
*cur
= NULL
;
2430 img_info
*default_node
= NULL
;
2431 const char *default_image
= NULL
;
2433 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2434 if (default_image
&& default_image
[0] == '/')
2436 img_len
= grub_strlen(default_image
);
2438 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2440 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2452 if (0 == g_default_menu_mode
)
2454 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2458 def
= grub_strdup(default_image
);
2464 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2466 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2467 if (strdata
&& strdata
[0] == '/')
2469 pos
= def
+ grub_strlen(strdata
);
2480 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2483 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2487 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2495 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2497 img_info
*next
= NULL
;
2498 img_info
*cur
= g_ventoy_img_list
;
2511 g_ventoy_img_list
= NULL
;
2512 g_ventoy_img_count
= 0;
2514 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2517 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2520 img_info
*cur
= g_ventoy_img_list
;
2524 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2526 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2529 img_id
= grub_strtol(args
[0], NULL
, 10);
2530 if (img_id
>= g_ventoy_img_count
)
2532 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2535 debug("Find image %ld name \n", img_id
);
2537 while (cur
&& img_id
> 0)
2545 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2548 debug("image name is %s\n", cur
->name
);
2550 grub_env_set(args
[1], cur
->name
);
2552 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2555 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2559 img_info
*cur
= g_ventoy_img_list
;
2565 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2568 len
= (int)grub_strlen(args
[0]);
2572 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2581 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2584 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2585 grub_env_set("chosen", id
);
2586 grub_env_export("chosen");
2588 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2591 static char g_fake_vlnk_src
[512];
2592 static char g_fake_vlnk_dst
[512];
2593 static grub_uint64_t g_fake_vlnk_size
;
2594 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2600 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2602 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2603 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2605 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2607 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2610 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2616 g_fake_vlnk_src
[0] = 0;
2617 g_fake_vlnk_dst
[0] = 0;
2618 g_fake_vlnk_size
= 0;
2619 grub_file_vtoy_vlnk(NULL
, NULL
);
2621 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2625 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2630 const char *id
= NULL
;
2631 img_info
*cur
= NULL
;
2635 if (argc
< 1 || argc
> 3)
2637 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2640 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2642 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2643 grub_env_set(args
[0], pos
);
2646 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2647 grub_env_set(args
[1], value
);
2652 for (last
= pos
; *pos
; pos
++)
2659 grub_env_set(args
[2], last
+ 1);
2665 id
= grub_env_get("chosen");
2667 pos
= grub_strstr(id
, "VID_");
2670 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2674 cur
= g_ventoy_img_list
;
2679 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2682 grub_env_set(args
[0], cur
->path
);
2686 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2687 grub_env_set(args
[1], value
);
2692 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2693 grub_env_set(args
[2], cur
->name
);
2697 g_svd_replace_offset
= 0;
2699 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2703 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2707 grub_device_t dev
= NULL
;
2708 img_info
*cur
= NULL
;
2709 img_info
*tail
= NULL
;
2710 img_info
*min
= NULL
;
2711 img_info
*head
= NULL
;
2712 const char *strdata
= NULL
;
2713 char *device_name
= NULL
;
2715 img_iterator_node
*node
= NULL
;
2716 img_iterator_node
*tmp
= NULL
;
2722 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2725 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2727 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2732 g_enumerate_time_checked
= 0;
2733 g_enumerate_start_time_ms
= grub_get_time_ms();
2735 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2736 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2738 g_filt_dot_underscore_file
= 1;
2741 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2742 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2744 g_sort_case_sensitive
= 1;
2747 device_name
= grub_file_get_device_name(args
[0]);
2753 g_enum_dev
= dev
= grub_device_open(device_name
);
2759 g_enum_fs
= fs
= grub_fs_probe(dev
);
2765 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2767 debug("unsupported fs:<%s>\n", fs
->name
);
2768 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2772 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2774 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2775 if (strdata
&& strdata
[0] == '1')
2777 g_default_menu_mode
= 1;
2780 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2782 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2784 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2785 if (strdata
&& strdata
[0] == '/')
2787 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2788 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2790 g_img_iterator_head
.dir
[len
++] = '/';
2792 g_img_iterator_head
.dirlen
= len
;
2796 g_img_iterator_head
.dirlen
= 1;
2797 grub_strcpy(g_img_iterator_head
.dir
, "/");
2800 g_img_iterator_head
.tail
= &tail
;
2802 if (g_img_max_search_level
< 0)
2804 g_img_max_search_level
= GRUB_INT_MAX
;
2805 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2806 if (strdata
&& ventoy_is_decimal(strdata
))
2808 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2812 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2813 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2814 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2815 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2816 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2817 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2819 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2821 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2824 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2825 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2827 g_tree_view_menu_style
= 1;
2830 ventoy_set_default_menu();
2832 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2834 ventoy_dynamic_tree_menu(node
);
2838 node
= g_img_iterator_head
.next
;
2846 /* sort image list by image name */
2847 while (g_ventoy_img_list
)
2849 min
= g_ventoy_img_list
;
2850 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2852 if (ventoy_cmp_img(min
, cur
) > 0)
2860 min
->prev
->next
= min
->next
;
2865 min
->next
->prev
= min
->prev
;
2868 if (min
== g_ventoy_img_list
)
2870 g_ventoy_img_list
= min
->next
;
2888 g_ventoy_img_list
= head
;
2890 if (g_default_menu_mode
== 1)
2892 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2893 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2894 " echo 'return ...' \n"
2898 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2900 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2901 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2904 cur
->unsupport
? "[***********] " : "",
2905 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2907 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2910 g_tree_script_buf
[g_tree_script_pos
] = 0;
2911 g_list_script_buf
[g_list_script_pos
] = 0;
2913 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2914 grub_env_set(args
[1], buf
);
2918 check_free(device_name
, grub_free
);
2919 check_free(dev
, grub_device_close
);
2921 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2924 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2931 device_name
= grub_file_get_device_name(filename
);
2943 pos2
= grub_strstr(pos
, ",");
2946 pos2
= grub_strstr(pos
, ")");
2954 disk
= grub_disk_open(pos
);
2957 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2958 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2959 grub_disk_close(disk
);
2966 grub_free(device_name
);
2970 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2972 eltorito_descriptor desc
;
2974 grub_memset(&desc
, 0, sizeof(desc
));
2975 grub_file_seek(file
, 17 * 2048);
2976 grub_file_read(file
, &desc
, sizeof(desc
));
2978 if (desc
.type
!= 0 || desc
.version
!= 1)
2983 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2984 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2992 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2994 grub_uint8_t buf
[512];
2996 grub_file_seek(file
, sector
* 2048);
2997 grub_file_read(file
, buf
, sizeof(buf
));
2999 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
3000 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
3002 return *((grub_uint32_t
*)(buf
+ 40));
3008 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3012 grub_uint8_t buf
[512];
3013 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3015 grub_file_seek(file
, sector
* 2048);
3016 grub_file_read(file
, buf
, sizeof(buf
));
3018 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3020 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3024 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3029 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3031 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3033 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3037 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3039 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3044 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3046 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3048 if (buf
[36] == parttype
[i
])
3050 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3056 debug("%s does not contain efi eltorito\n", file
->name
);
3060 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3063 const char *fs
= NULL
;
3064 const char *val
= NULL
;
3065 const char *cdprompt
= NULL
;
3067 grub_uint8_t chksum
= 0;
3070 disk
= file
->device
->disk
;
3071 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3073 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3074 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3075 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3077 pos
= grub_strstr(file
->name
, "/");
3083 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3085 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3087 param
->vtoy_img_size
= file
->size
;
3089 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3090 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3092 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3094 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3095 param
->vtoy_reserved
[4] = 0;
3096 if (g_ventoy_chain_type
== 1) /* Windows */
3098 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3099 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3101 param
->vtoy_reserved
[4] = 1;
3105 fs
= ventoy_get_env("ventoy_fs_probe");
3106 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3108 param
->vtoy_reserved
[3] = 1;
3111 param
->vtoy_reserved
[5] = 0;
3112 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3113 if (val
&& val
[0] == '1' && val
[1] == 0)
3115 param
->vtoy_reserved
[5] = 1;
3118 /* ventoy_disk_signature used for vlnk */
3119 param
->vtoy_reserved
[6] = file
->vlnk
;
3120 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3122 /* calculate checksum */
3123 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3125 chksum
+= *((grub_uint8_t
*)param
+ i
);
3127 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3132 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3134 grub_uint32_t i
= 0;
3135 grub_uint64_t total
= 0;
3136 grub_uint64_t fileblk
= 0;
3137 ventoy_img_chunk
*chunk
= NULL
;
3139 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3141 chunk
= chunklist
->chunk
+ i
;
3143 if (chunk
->disk_start_sector
<= start
)
3145 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3149 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3152 fileblk
= (file
->size
+ 511) / 512;
3154 if (total
!= fileblk
)
3156 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3157 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3159 debug("maybe img file to be processed.\n");
3169 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3173 grub_uint32_t i
= 0;
3174 grub_uint32_t sector
= 0;
3175 grub_uint32_t count
= 0;
3176 grub_off_t size
= 0;
3177 grub_off_t read
= 0;
3179 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3180 if (fs_type
== ventoy_fs_exfat
)
3182 grub_fat_get_file_chunk(start
, file
, chunklist
);
3184 else if (fs_type
== ventoy_fs_ext
)
3186 grub_ext_get_file_chunk(start
, file
, chunklist
);
3190 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3191 file
->read_hook_data
= chunklist
;
3193 for (size
= file
->size
; size
> 0; size
-= read
)
3195 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3196 grub_file_read(file
, NULL
, read
);
3199 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3201 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3202 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3205 if (ventoy_fs_udf
== fs_type
)
3207 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3209 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3210 chunklist
->chunk
[i
].img_start_sector
= sector
;
3211 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3217 len
= (int)grub_strlen(file
->name
);
3218 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3219 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3220 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3221 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3223 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3225 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3235 chunklist
->chunk
[i
].img_start_sector
= sector
;
3236 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3244 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3248 grub_disk_addr_t start
;
3253 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3256 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3259 g_conf_replace_count
= 0;
3260 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3261 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3263 if (g_img_chunk_list
.chunk
)
3265 grub_free(g_img_chunk_list
.chunk
);
3268 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3270 grub_file_close(file
);
3271 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3274 /* get image chunk data */
3275 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3276 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3277 if (NULL
== g_img_chunk_list
.chunk
)
3279 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3282 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3283 g_img_chunk_list
.cur_chunk
= 0;
3285 start
= file
->device
->disk
->partition
->start
;
3287 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3289 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3290 grub_file_close(file
);
3294 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3297 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3298 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3299 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3302 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3306 grub_uint64_t offset
= 0;
3307 grub_uint32_t align
= 0;
3308 grub_file_t file
= NULL
;
3309 conf_replace
*node
= NULL
;
3310 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3311 ventoy_grub_param_file_replace
*replace
= NULL
;
3317 debug("select conf replace argc:%d\n", argc
);
3324 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3327 debug("Conf replace not found for %s\n", args
[1]);
3331 debug("Find %d conf replace for %s\n", n
, args
[1]);
3333 g_conf_replace_count
= n
;
3334 for (i
= 0; i
< n
; i
++)
3338 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3341 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3342 grub_file_close(file
);
3344 else if (node
->img
> 0)
3350 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3354 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3357 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3361 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3363 if (align
> vtoy_max_replace_file_size
)
3365 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3366 grub_file_close(file
);
3370 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3371 grub_file_close(file
);
3372 g_conf_replace_new_len
[i
] = (int)file
->size
;
3373 g_conf_replace_new_len_align
[i
] = align
;
3375 g_conf_replace_node
[i
] = node
;
3376 g_conf_replace_offset
[i
] = offset
+ 2;
3380 replace
= &(g_grub_param
->img_replace
[i
]);
3381 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3382 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3383 replace
->old_name_cnt
++;
3386 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3390 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3393 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3398 const char *ch
= var
;
3405 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3412 debug("Invalid variable letter <%c>\n", *ch
);
3419 debug("Invalid variable length:%d <%s>\n", n
, var
);
3423 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3432 grub_printf("\n=================== Variables Expansion ===================\n\n");
3435 grub_printf("<%s>: ", var
);
3438 while (i
< (len
- 1))
3441 if ((c
== '\n') || (c
== '\r'))
3451 else if (grub_isprint(c
))
3453 if (i
+ 1 < (len
- 1))
3455 grub_printf("%c", c
);
3465 expand
[i
- 1] = ' ';
3466 grub_printf("\r<%s>: %s", var
, expand
);
3469 grub_printf("\r<%s>: %s", var
, expand
);
3481 grub_snprintf(expand
, len
, "$$%s$$", var
);
3487 static int ventoy_auto_install_var_expand(install_template
*node
)
3495 char *newbuf
= NULL
;
3496 char *curline
= NULL
;
3497 char *nextline
= NULL
;
3498 grub_uint8_t
*code
= NULL
;
3500 var_node
*CurNode
= NULL
;
3501 var_node
*pVarList
= NULL
;
3503 code
= (grub_uint8_t
*)node
->filebuf
;
3505 if (node
->filelen
>= VTOY_SIZE_1MB
)
3507 debug("auto install script too long %d\n", node
->filelen
);
3511 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3513 debug("UCS-2 encoding NOT supported\n");
3517 start
= grub_strstr(node
->filebuf
, "$$");
3520 debug("no need to expand variable, no start.\n");
3524 end
= grub_strstr(start
+ 2, "$$");
3527 debug("no need to expand variable, no end.\n");
3531 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3532 newbuf
= grub_malloc(newlen
);
3535 debug("Failed to alloc newbuf %d\n", newlen
);
3539 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3541 nextline
= ventoy_get_line(curline
);
3543 start
= grub_strstr(curline
, "$$");
3546 end
= grub_strstr(start
+ 2, "$$");
3552 VTOY_APPEND_NEWBUF(curline
);
3554 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3556 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3558 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3565 value
[sizeof(value
) - 1] = 0;
3566 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3570 CurNode
= grub_zalloc(sizeof(var_node
));
3573 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3574 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3575 CurNode
->next
= pVarList
;
3581 VTOY_APPEND_NEWBUF(value
);
3583 VTOY_APPEND_NEWBUF(end
+ 2);
3587 VTOY_APPEND_NEWBUF(curline
);
3590 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3592 newbuf
[pos
- 1] = '\n';
3596 newbuf
[pos
++] = '\n';
3600 grub_free(node
->filebuf
);
3601 node
->filebuf
= newbuf
;
3602 node
->filelen
= pos
;
3606 CurNode
= pVarList
->next
;
3607 grub_free(pVarList
);
3614 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3620 grub_file_t file
= NULL
;
3621 char configfile
[128];
3622 install_template
*node
= NULL
;
3628 debug("select auto installation argc:%d\n", argc
);
3635 node
= ventoy_plugin_find_install_template(args
[0]);
3638 debug("Auto install template not found for %s\n", args
[0]);
3642 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3644 defidx
= node
->autosel
;
3645 if (node
->timeout
< 0)
3647 node
->cursel
= node
->autosel
- 1;
3648 debug("Auto install template auto select %d\n", node
->autosel
);
3653 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3659 if (node
->timeout
> 0)
3661 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3664 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" --class=\"sel_auto_install\" {\n"
3665 " echo %s\n}\n", "");
3667 for (i
= 0; i
< node
->templatenum
; i
++)
3669 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" --class=\"sel_auto_install\" {\n"
3671 node
->templatepath
[i
].path
);
3674 g_ventoy_menu_esc
= 1;
3675 g_ventoy_suppress_esc
= 1;
3676 g_ventoy_suppress_esc_default
= defidx
;
3678 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3679 grub_script_execute_sourcecode(configfile
);
3681 g_ventoy_menu_esc
= 0;
3682 g_ventoy_suppress_esc
= 0;
3683 g_ventoy_suppress_esc_default
= 1;
3687 node
->cursel
= g_ventoy_last_entry
- 1;
3690 grub_check_free(node
->filebuf
);
3693 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3695 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3696 node
->templatepath
[node
->cursel
].path
);
3699 node
->filebuf
= grub_malloc(file
->size
+ 8);
3702 grub_file_read(file
, node
->filebuf
, file
->size
);
3703 grub_file_close(file
);
3705 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3706 node
->filelen
= (int)file
->size
;
3708 ventoy_auto_install_var_expand(node
);
3713 debug("Failed to open auto install script <%s%s>\n",
3714 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3718 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3721 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3727 char configfile
[128];
3728 persistence_config
*node
;
3734 debug("select persistence argc:%d\n", argc
);
3741 node
= ventoy_plugin_find_persistent(args
[0]);
3744 debug("Persistence image not found for %s\n", args
[0]);
3748 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3750 defidx
= node
->autosel
;
3751 if (node
->timeout
< 0)
3753 node
->cursel
= node
->autosel
- 1;
3754 debug("Persistence image auto select %d\n", node
->autosel
);
3759 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3765 if (node
->timeout
> 0)
3767 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3770 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" --class=\"sel_persistence\" {\n"
3771 " echo %s\n}\n", "");
3773 for (i
= 0; i
< node
->backendnum
; i
++)
3775 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" --class=\"sel_persistence\" {\n"
3777 node
->backendpath
[i
].path
);
3781 g_ventoy_menu_esc
= 1;
3782 g_ventoy_suppress_esc
= 1;
3783 g_ventoy_suppress_esc_default
= defidx
;
3785 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3786 grub_script_execute_sourcecode(configfile
);
3788 g_ventoy_menu_esc
= 0;
3789 g_ventoy_suppress_esc
= 0;
3790 g_ventoy_suppress_esc_default
= 1;
3794 node
->cursel
= g_ventoy_last_entry
- 1;
3796 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3799 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3802 ventoy_img_chunk
*cur
;
3808 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3810 cur
= g_img_chunk_list
.chunk
+ i
;
3811 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3812 cur
->img_start_sector
, cur
->img_end_sector
,
3813 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3817 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3820 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3824 ventoy_img_chunk_list chunklist
;
3829 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3832 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3835 /* get image chunk data */
3836 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3837 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3838 if (NULL
== chunklist
.chunk
)
3840 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3843 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3844 chunklist
.cur_chunk
= 0;
3846 ventoy_get_block_list(file
, &chunklist
, 0);
3848 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3850 grub_printf("########## UNSUPPORTED ###############\n");
3853 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3855 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3857 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3858 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3861 grub_printf("\n==================================\n");
3863 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3865 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3866 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3867 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3868 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3869 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3873 grub_free(chunklist
.chunk
);
3874 grub_file_close(file
);
3876 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3879 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3882 ventoy_grub_param_file_replace
*replace
= NULL
;
3890 replace
= &(g_grub_param
->file_replace
);
3891 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3893 replace
->old_name_cnt
= 0;
3894 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3896 replace
->old_name_cnt
++;
3897 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3900 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3903 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3906 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3909 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3915 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3916 grub_env_set(args
[0], buf
);
3919 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3922 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3930 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3931 grub_printf("%s", g_list_script_buf
);
3935 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3936 grub_printf("%s", g_tree_script_buf
);
3942 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3944 img_info
*cur
= g_ventoy_img_list
;
3952 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3953 grub_printf("name:<%s>\n\n", cur
->name
);
3960 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3966 ventoy_plugin_dump_injection();
3971 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3977 ventoy_plugin_dump_auto_install();
3982 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3988 ventoy_plugin_dump_persistence();
3993 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
3999 len1
= (int)grub_strlen(filename
);
4000 len2
= (int)grub_strlen(suffix
);
4007 for (i
= len1
- 1; i
>= 0; i
--)
4009 if (filename
[i
] == '.')
4020 if (filename
[i
- len2
- 1] != '_')
4025 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4033 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4039 if (argc
!= 1 && argc
!= 2)
4044 if (args
[0][0] == '0')
4046 if (g_ventoy_memdisk_mode
)
4051 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4058 else if (args
[0][0] == '1')
4060 return g_ventoy_iso_raw
? 0 : 1;
4062 else if (args
[0][0] == '2')
4064 return g_ventoy_iso_uefi_drv
? 0 : 1;
4066 else if (args
[0][0] == '3')
4068 if (g_ventoy_grub2_mode
)
4073 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4080 else if (args
[0][0] == '4')
4082 if (g_ventoy_wimboot_mode
)
4087 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4098 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4100 static int configfile_mode
= 0;
4101 char memfile
[128] = {0};
4108 * args[0]: 0:normal 1:configfile
4109 * args[1]: 0:list_buf 1:tree_buf
4114 debug("Invalid argc %d\n", argc
);
4120 if (args
[0][0] == '0')
4122 if (args
[1][0] == '0')
4124 grub_script_execute_sourcecode(g_list_script_buf
);
4128 grub_script_execute_sourcecode(g_tree_script_buf
);
4133 if (configfile_mode
)
4135 debug("Now already in F3 mode %d\n", configfile_mode
);
4139 if (args
[1][0] == '0')
4141 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4142 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4146 g_ventoy_last_entry
= -1;
4147 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4148 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4151 configfile_mode
= 1;
4152 grub_script_execute_sourcecode(memfile
);
4153 configfile_mode
= 0;
4159 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4170 g_ventoy_case_insensitive
= 1;
4171 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4172 g_ventoy_case_insensitive
= 0;
4178 grub_file_close(file
);
4184 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4189 const char *isopath
= NULL
;
4191 ventoy_mbr_head mbr
;
4198 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4201 isopath
= grub_env_get("vtoy_iso_part");
4204 debug("isopath is null %p\n", isopath
);
4208 debug("isopath is %s\n", isopath
);
4210 for (id
= 0; id
< 30 && (find
== 0); id
++)
4212 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4213 if (grub_strstr(isopath
, hdname
))
4215 debug("skip %s ...\n", hdname
);
4219 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4221 disk
= grub_disk_open(hdname
);
4224 debug("%s not exist\n", hdname
);
4228 grub_memset(&mbr
, 0, sizeof(mbr
));
4229 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4231 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4233 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4234 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4237 grub_env_set(args
[0], hdname
);
4241 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4245 debug("read %s failed\n", hdname
);
4248 grub_disk_close(disk
);
4254 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4265 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4268 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4271 debug("failed to open file %s\n", args
[0]);
4275 buf
= grub_malloc(len
);
4282 grub_file_read(file
, buf
, len
- 1);
4284 ventoy_get_line(buf
);
4285 ventoy_set_env(args
[1], buf
);
4289 grub_check_free(buf
);
4290 grub_file_close(file
);
4295 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4297 grub_uint64_t end_max
= 0;
4298 int *pCnt
= (int *)data
;
4303 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4304 "0 %llu linear /dev/ventoy %llu\n",
4305 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4307 end_max
= (partition
->len
+ partition
->start
) * 512;
4308 if (end_max
> g_part_end_max
)
4310 g_part_end_max
= end_max
;
4316 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4319 char *device_name
= NULL
;
4320 grub_device_t dev
= NULL
;
4325 g_part_list_pos
= 0;
4327 grub_env_unset("vtoy_img_part_file");
4334 device_name
= grub_file_get_device_name(args
[0]);
4337 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4341 dev
= grub_device_open(device_name
);
4344 debug("grub_device_open failed, %s\n", device_name
);
4348 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4350 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4351 grub_env_set("vtoy_img_part_file", buf
);
4353 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4354 grub_env_set("vtoy_img_part_cnt", buf
);
4356 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4357 grub_env_set("vtoy_img_max_part_end", buf
);
4361 check_free(device_name
, grub_free
);
4362 check_free(dev
, grub_device_close
);
4368 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4379 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4382 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4385 debug("failed to open file %s\n", args
[0]);
4389 buf
= grub_malloc(file
->size
+ 1);
4395 buf
[file
->size
] = 0;
4396 grub_file_read(file
, buf
, file
->size
);
4398 if (grub_strstr(buf
, args
[1]))
4405 grub_check_free(buf
);
4406 grub_file_close(file
);
4411 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4417 ventoy_iso9660_vd pvd
;
4424 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4427 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4430 debug("failed to open file %s\n", args
[0]);
4434 grub_file_seek(file
, 16 * 2048);
4435 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4436 if (len
!= sizeof(pvd
))
4438 debug("failed to read pvd %d\n", len
);
4442 grub_memset(buf
, 0, sizeof(buf
));
4443 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4444 ventoy_set_env(args
[1], buf
);
4446 grub_memset(buf
, 0, sizeof(buf
));
4447 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4448 ventoy_set_env(args
[2], buf
);
4452 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4453 ventoy_set_env(args
[3], buf
);
4456 grub_file_close(file
);
4461 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4472 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4475 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4478 debug("failed to open file %s\n", args
[0]);
4482 grub_memset(buf
, 0, sizeof(buf
));
4483 grub_file_seek(file
, 16 * 2048 + 813);
4484 len
= (int)grub_file_read(file
, buf
, 17);
4487 debug("failed to read create date %d\n", len
);
4491 ventoy_set_env(args
[1], buf
);
4494 grub_file_close(file
);
4499 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4505 ventoy_env_hook_root(1);
4510 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4516 ventoy_env_hook_root(0);
4521 #ifdef GRUB_MACHINE_EFI
4522 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4527 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4533 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4534 if (var
&& *var
== 1)
4542 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4551 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4556 grub_uint64_t FileSectors
= 0;
4557 ventoy_gpt_info
*gpt
= NULL
;
4558 ventoy_part_table
*pt
= NULL
;
4559 grub_uint8_t zeroguid
[16] = {0};
4564 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4567 debug("failed to open file %s\n", args
[0]);
4571 if (file
->size
% 512)
4573 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4577 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4583 FileSectors
= file
->size
/ 512;
4585 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4586 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4588 debug("This is EFI partition table\n");
4590 for (i
= 0; i
< 128; i
++)
4592 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4594 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4596 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4597 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4605 debug("This is MBR partition table\n");
4607 for (i
= 0; i
< 4; i
++)
4609 pt
= gpt
->MBR
.PartTbl
+ i
;
4610 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4612 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4613 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4614 (ulonglong
)FileSectors
);
4623 grub_file_close(file
);
4624 grub_check_free(gpt
);
4625 grub_errno
= GRUB_ERR_NONE
;
4629 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4638 for (i
= 0; i
< 500; i
++)
4640 ret
= grub_getkey_noblock();
4641 if (ret
== GRUB_TERM_NO_KEY
)
4650 grub_printf("\n\n Still have key input after clear.\n");
4658 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4665 int image_sector_size
;
4667 ventoy_chain_head
*chain
;
4668 ventoy_img_chunk
*chunk
;
4669 ventoy_os_param
*osparam
;
4670 ventoy_image_location
*location
;
4671 ventoy_image_disk_region
*region
;
4672 struct grub_acpi_table_header
*acpi
;
4681 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4683 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4689 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4691 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4693 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4697 img_chunk_num
= chain
->img_chunk_num
;
4699 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4700 datalen
= sizeof(ventoy_os_param
) + loclen
;
4702 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4703 acpi
= grub_zalloc(buflen
);
4709 /* Step1: Fill acpi table header */
4710 grub_memcpy(acpi
->signature
, "VTOY", 4);
4711 acpi
->length
= buflen
;
4713 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4714 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4716 acpi
->creator_id
[0] = 1;
4717 acpi
->creator_rev
= 1;
4719 /* Step2: Fill data */
4720 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4721 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4722 osparam
->vtoy_img_location_addr
= 0;
4723 osparam
->vtoy_img_location_len
= loclen
;
4724 osparam
->chksum
= 0;
4725 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4727 location
= (ventoy_image_location
*)(osparam
+ 1);
4728 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4729 location
->image_sector_size
= image_sector_size
;
4730 location
->disk_sector_size
= chain
->disk_sector_size
;
4731 location
->region_count
= img_chunk_num
;
4733 region
= location
->regions
;
4734 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4735 if (512 == image_sector_size
)
4737 for (i
= 0; i
< img_chunk_num
; i
++)
4739 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4740 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4741 region
->disk_start_sector
= chunk
->disk_start_sector
;
4748 for (i
= 0; i
< img_chunk_num
; i
++)
4750 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4751 region
->image_start_sector
= chunk
->img_start_sector
;
4752 region
->disk_start_sector
= chunk
->disk_start_sector
;
4758 /* Step3: Fill acpi checksum */
4760 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4762 /* load acpi table */
4763 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4764 grub_script_execute_sourcecode(cmd
);
4768 VENTOY_CMD_RETURN(0);
4771 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4777 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4778 g_ventoy_last_entry
= -1;
4783 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4789 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4794 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4796 const char *pos
= filename
+ 1;
4804 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4806 grub_strncpy((char *)data
, filename
, 128);
4817 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4820 char *device_name
= NULL
;
4821 grub_device_t dev
= NULL
;
4822 grub_fs_t fs
= NULL
;
4823 char buf
[128] = {0};
4829 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4833 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4835 device_name
= grub_file_get_device_name(args
[0]);
4838 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4842 dev
= grub_device_open(device_name
);
4845 debug("grub_device_open failed, %s\n", device_name
);
4849 fs
= grub_fs_probe(dev
);
4852 debug("grub_fs_probe failed, %s\n", device_name
);
4856 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4860 ventoy_set_env(args
[2], buf
);
4867 check_free(device_name
, grub_free
);
4868 check_free(dev
, grub_device_close
);
4873 int ventoy_load_part_table(const char *diskname
)
4880 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4881 if (!g_ventoy_part_info
)
4886 disk
= grub_disk_open(diskname
);
4889 debug("Failed to open disk %s\n", diskname
);
4893 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4895 g_ventoy_disk_bios_id
= disk
->id
;
4897 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4898 grub_disk_close(disk
);
4900 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4901 dev
= grub_device_open(name
);
4904 /* Check for official Ventoy device */
4905 ret
= ventoy_check_official_device(dev
);
4906 grub_device_close(dev
);
4914 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4915 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4920 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4927 ret
= ventoy_load_part_table(args
[0]);
4933 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4934 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4939 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4942 const char *vcfg
= NULL
;
4947 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4950 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4951 grub_env_set(args
[1], vcfg
);
4956 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4964 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4967 grub_uint8_t zeroguid
[16] = {0};
4972 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4975 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4977 if (id
>= 1 && id
<= 128)
4979 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4987 if (id
>= 1 && id
<= 4)
4989 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4999 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5002 char *device_name
= NULL
;
5003 grub_device_t dev
= NULL
;
5004 grub_fs_t fs
= NULL
;
5009 debug("get fs label for %s\n", args
[0]);
5013 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5017 device_name
= grub_file_get_device_name(args
[0]);
5020 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5024 dev
= grub_device_open(device_name
);
5027 debug("grub_device_open failed, %s\n", device_name
);
5031 fs
= grub_fs_probe(dev
);
5032 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5034 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5038 fs
->fs_label(dev
, &label
);
5041 debug("label=<%s>\n", label
);
5042 ventoy_set_env(args
[1], label
);
5050 check_free(device_name
, grub_free
);
5051 check_free(dev
, grub_device_close
);
5056 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5060 grub_snprintf((char *)data
, 256, "%s", filename
);
5067 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5069 if (info
->dir
&& filename
&& filename
[0] != '.')
5071 grub_snprintf((char *)data
, 256, "%s", filename
);
5078 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5081 char *device_name
= NULL
;
5082 grub_device_t dev
= NULL
;
5083 grub_fs_t fs
= NULL
;
5084 char name
[256] ={0};
5088 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5092 device_name
= grub_file_get_device_name(args
[0]);
5095 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5099 dev
= grub_device_open(device_name
);
5102 debug("grub_device_open failed, %s\n", device_name
);
5106 fs
= grub_fs_probe(dev
);
5109 debug("grub_fs_probe failed, %s\n", device_name
);
5113 fs
->fs_dir(dev
, args
[1], hook
, name
);
5116 ventoy_set_env(args
[2], name
);
5123 check_free(device_name
, grub_free
);
5124 check_free(dev
, grub_device_close
);
5129 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5132 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5135 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5138 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5141 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5151 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5155 for (pos
= args
[0]; *pos
; pos
++)
5169 grub_env_set(args
[1], args
[0]);
5179 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5189 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5194 len
= (int)grub_strlen(buf
);
5195 for (i
= len
; i
> 0; i
--)
5197 if (buf
[i
- 1] == '/')
5199 grub_env_set(args
[1], buf
+ i
);
5204 grub_env_set(args
[1], buf
);
5209 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5211 struct grub_video_mode_info info
;
5218 if (!g_video_mode_list
)
5220 ventoy_enum_video_mode();
5223 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5225 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5229 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5232 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5234 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5235 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5237 VENTOY_CMD_RETURN(0);
5240 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5242 struct grub_video_mode_info info
;
5249 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5251 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5255 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5258 grub_env_set(args
[0], buf
);
5260 VENTOY_CMD_RETURN(0);
5263 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5271 if (!g_video_mode_list
)
5276 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5277 if (id
< g_video_mode_num
)
5279 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5280 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5283 grub_env_set(args
[1], buf
);
5285 VENTOY_CMD_RETURN(0);
5288 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5291 grub_uint32_t loadsector
= 0;
5294 grub_uint32_t boot_catlog
= 0;
5295 grub_uint8_t buf
[512];
5301 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5305 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5308 debug("failed to open %s\n", args
[0]);
5312 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5313 if (boot_catlog
== 0)
5315 debug("No bootcatlog found\n");
5316 grub_file_close(file
);
5320 grub_memset(buf
, 0, sizeof(buf
));
5321 grub_file_seek(file
, boot_catlog
* 2048);
5322 grub_file_read(file
, buf
, sizeof(buf
));
5323 grub_file_close(file
);
5325 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5327 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5329 if (buf
[i
+ 32] == 0x88)
5331 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5332 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5338 if (loadsector
== 0)
5340 debug("No EFI eltorito info found\n");
5344 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5345 grub_env_set(args
[1], value
);
5346 VENTOY_CMD_RETURN(0);
5349 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5354 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5356 if (pfsdir
->initrd
[0])
5361 curpos
= pfsdir
->curpos
;
5362 len
= grub_strlen(filename
);
5366 if ((len
== 1 && filename
[0] == '.') ||
5367 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5372 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5375 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5376 pfsdir
->curpos
= curpos
+ printlen
;
5377 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5378 pfsdir
->curpos
= curpos
;
5379 pfsdir
->fullpath
[curpos
] = 0;
5383 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5386 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5387 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5389 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5391 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5400 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5404 char *device_name
= NULL
;
5405 grub_device_t dev
= NULL
;
5406 grub_fs_t fs
= NULL
;
5407 replace_fs_dir
*pfsdir
= NULL
;
5413 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5417 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5423 device_name
= grub_file_get_device_name(args
[0]);
5429 dev
= grub_device_open(device_name
);
5435 fs
= grub_fs_probe(dev
);
5444 pfsdir
->fullpath
[0] = '/';
5445 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5447 if (pfsdir
->initrd
[0])
5449 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5451 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5453 if (pfsdir
->initrd
[i
] == '/')
5455 pfsdir
->initrd
[i
] = '\\';
5459 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5460 grub_env_set(args
[1], pos
);
5464 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5469 grub_check_free(pfsdir
);
5470 grub_check_free(device_name
);
5471 check_free(dev
, grub_device_close
);
5473 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5476 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5478 const char *pager
= NULL
;
5484 pager
= grub_env_get("pager");
5488 grub_env_set("pager", "1");
5490 else if (pager
[0] == '1')
5496 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5498 grub_env_set("pager", "1");
5501 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5504 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5510 if (g_pager_flag
== 1)
5512 grub_env_unset("pager");
5514 else if (g_pager_flag
== 2)
5516 grub_env_set("pager", g_old_pager
);
5519 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5522 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5524 if (g_json_case_mis_path
[0])
5529 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5531 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5537 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5540 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5542 if (g_json_case_mis_path
[0])
5547 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5549 if (grub_strcasecmp(filename
, "ventoy") == 0)
5551 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5552 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5553 if (g_json_case_mis_path
[0])
5563 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5566 char *device_name
= NULL
;
5567 grub_device_t dev
= NULL
;
5568 grub_fs_t fs
= NULL
;
5569 chk_case_fs_dir fs_dir
;
5575 device_name
= grub_file_get_device_name(args
[0]);
5581 dev
= grub_device_open(device_name
);
5587 fs
= grub_fs_probe(dev
);
5593 fstype
= ventoy_get_fs_type(fs
->name
);
5594 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5599 g_json_case_mis_path
[0] = 0;
5602 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5604 if (g_json_case_mis_path
[0])
5606 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5611 grub_check_free(device_name
);
5612 check_free(dev
, grub_device_close
);
5614 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5617 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5620 grub_partition_t part
;
5621 char priority_str
[3]; /* Maximum value 15 */
5625 if (argc
< 2 || argc
> 3)
5626 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5627 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5629 /* Open the disk if it exists */
5630 disk
= grub_disk_open (args
[0]);
5633 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5637 part
= grub_partition_probe (disk
, args
[1]);
5640 grub_disk_close (disk
);
5641 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5642 "No such partition");
5645 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5647 grub_disk_close (disk
);
5648 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5649 "Not a GPT partition");
5652 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5653 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5657 grub_env_set (args
[2], priority_str
);
5658 grub_env_export (args
[2]);
5662 grub_printf ("Priority is %s\n", priority_str
);
5665 grub_disk_close (disk
);
5666 return GRUB_ERR_NONE
;
5670 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5674 grub_file_t file
= NULL
;
5675 grub_uint32_t loadrba
= 0;
5676 grub_uint32_t boot_catlog
= 0;
5677 grub_uint8_t sector
[512];
5678 boot_info_table
*info
= NULL
;
5683 /* This also trigger a iso9660 fs parse */
5684 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5689 joliet
= grub_iso9660_is_joliet();
5695 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5698 debug("failed to open %s\n", args
[0]);
5702 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5703 if (boot_catlog
== 0)
5705 debug("no bootcatlog found %u\n", boot_catlog
);
5709 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5712 debug("no bios eltorito rba found %u\n", loadrba
);
5716 grub_file_seek(file
, loadrba
* 2048);
5717 grub_file_read(file
, sector
, 512);
5719 info
= (boot_info_table
*)sector
;
5720 if (info
->bi_data0
== 0x7c6ceafa &&
5721 info
->bi_data1
== 0x90900000 &&
5722 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5723 info
->bi_BootFileLocation
== loadrba
)
5725 debug("bootloader is syslinux, %u.\n", loadrba
);
5731 grub_file_close(file
);
5732 grub_errno
= GRUB_ERR_NONE
;
5736 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5739 ventoy_vlnk_part
*node
;
5745 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5747 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5748 ++n
, node
->device
, node
->disksig
,
5749 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5755 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5763 len
= (int)grub_strlen(args
[0]);
5764 if (grub_file_is_vlnk_suffix(args
[0], len
))
5773 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5776 const char *name
= NULL
;
5782 grub_env_unset(args
[1]);
5783 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5786 debug("VLNK SRC: <%s>\n", args
[0]);
5787 debug("VLNK DST: <%s>\n", name
);
5788 grub_env_set(args
[1], name
);
5796 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5800 grub_file_t file
= NULL
;
5811 len
= (int)grub_strlen(args
[0]);
5812 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5814 grub_printf("Invalid vlnk suffix\n");
5818 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5821 grub_printf("Failed to open %s\n", args
[0]);
5825 if (file
->size
!= 32768)
5827 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5831 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5832 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5834 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5839 check_free(file
, grub_file_close
);
5840 grub_errno
= GRUB_ERR_NONE
;
5844 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5850 g_iso_vd_id_publisher
[0] = 0;
5851 g_iso_vd_id_prepare
[0] = 0;
5852 g_iso_vd_id_application
[0] = 0;
5857 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5861 grub_file_t file
= NULL
;
5866 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5869 grub_printf("Failed to open %s\n", args
[0]);
5873 grub_file_seek(file
, 16 * 2048 + offset
);
5874 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5877 grub_file_seek(file
, 16 * 2048 + offset
);
5878 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5881 grub_file_seek(file
, 16 * 2048 + offset
);
5882 grub_file_read(file
, g_iso_vd_id_application
, 128);
5886 check_free(file
, grub_file_close
);
5887 grub_errno
= GRUB_ERR_NONE
;
5891 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5894 char *id
= g_iso_vd_id_publisher
;
5899 if (args
[0][0] == '1')
5901 id
= g_iso_vd_id_prepare
;
5903 else if (args
[0][0] == '2')
5905 id
= g_iso_vd_id_application
;
5908 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5913 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5918 grub_errno
= GRUB_ERR_NONE
;
5922 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5927 g_ventoy_fn_mutex
= 0;
5928 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5930 g_ventoy_fn_mutex
= 1;
5933 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5936 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5938 grub_uint64_t total
;
5939 grub_uint64_t org_required
;
5940 grub_uint64_t new_required
;
5946 #ifdef GRUB_MACHINE_EFI
5947 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
5948 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
5949 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
5950 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
5955 grub_printf("Non EFI mode!\n");
5960 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5963 static grub_err_t
ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5965 const char *env
= NULL
;
5970 if (g_ventoy_memdisk_mode
|| g_ventoy_grub2_mode
|| g_ventoy_wimboot_mode
|| g_ventoy_iso_raw
)
5975 if (ventoy_check_mode_by_name(args
[0], "vtmemdisk") ||
5976 ventoy_check_mode_by_name(args
[0], "vtgrub2") ||
5977 ventoy_check_mode_by_name(args
[0], "vtwimboot"))
5982 env
= grub_env_get("VTOY_SECONDARY_BOOT_MENU");
5983 if (env
&& env
[0] == '0' && env
[1] == 0)
5991 static grub_err_t
ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5999 const char *env
= NULL
;
6000 ulonglong fsize
= 0;
6002 int seldata
[16] = {0};
6007 len
= 8 * VTOY_SIZE_1KB
;
6008 cmd
= (char *)grub_malloc(len
);
6014 g_vtoy_secondary_need_recover
= 0;
6015 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6017 env
= grub_env_get("VTOY_SECONDARY_TIMEOUT");
6020 timeout
= (int)grub_strtol(env
, NULL
, 10);
6025 vtoy_len_ssprintf(cmd
, pos
, len
, "set timeout=%d\n", timeout
);
6028 fsize
= grub_strtoull(args
[2], NULL
, 10);
6030 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in normal mode", "second_normal"); seldata
[n
++] = 1;
6032 if (grub_strcmp(args
[1], "Unix") != 0)
6034 if (grub_strcmp(args
[1], "Windows") == 0)
6036 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in wimboot mode", "second_wimboot"); seldata
[n
++] = 2;
6040 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in grub2 mode", "second_grub2"); seldata
[n
++] = 3;
6043 if (fsize
<= VTOY_SIZE_1GB
)
6045 vtoy_dummy_menuentry(cmd
, pos
, len
, "Boot in memdisk mode", "second_memdisk"); seldata
[n
++] = 4;
6049 vtoy_dummy_menuentry(cmd
, pos
, len
, "File checksum", "second_checksum"); seldata
[n
++] = 5;
6052 g_ventoy_menu_esc
= 1;
6053 g_ventoy_suppress_esc
= 1;
6054 g_ventoy_suppress_esc_default
= 0;
6055 g_ventoy_secondary_menu_on
= 1;
6056 grub_snprintf(cfgfile
, sizeof(cfgfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)cmd
, pos
);
6057 grub_script_execute_sourcecode(cfgfile
);
6058 g_ventoy_menu_esc
= 0;
6059 g_ventoy_suppress_esc
= 0;
6060 g_ventoy_suppress_esc_default
= 1;
6061 g_ventoy_secondary_menu_on
= 0;
6063 select
= seldata
[g_ventoy_last_entry
];
6067 g_ventoy_wimboot_mode
= 1;
6068 g_vtoy_secondary_need_recover
= 1;
6070 else if (select
== 3)
6072 g_ventoy_grub2_mode
= 1;
6073 g_vtoy_secondary_need_recover
= 2;
6075 else if (select
== 4)
6077 g_ventoy_memdisk_mode
= 1;
6078 g_vtoy_secondary_need_recover
= 3;
6080 else if (select
== 5)
6082 grub_env_set("VTOY_CHKSUM_FILE_PATH", args
[0]);
6083 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6085 }while (select
== 5);
6091 static grub_err_t
ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6097 if (g_vtoy_secondary_need_recover
== 1)
6099 g_ventoy_wimboot_mode
= 0;
6101 else if (g_vtoy_secondary_need_recover
== 2)
6103 g_ventoy_grub2_mode
= 0;
6105 else if (g_vtoy_secondary_need_recover
== 3)
6107 g_ventoy_memdisk_mode
= 0;
6110 g_vtoy_secondary_need_recover
= 0;
6112 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
6115 static grub_err_t
ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt
, int argc
, char **args
)
6120 if (args
[0][0] == '0')
6122 g_ventoy_case_insensitive
= 0;
6126 g_ventoy_case_insensitive
= 1;
6132 int ventoy_env_init(void)
6137 grub_env_set("vtdebug_flag", "");
6139 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
6140 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6141 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
6142 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
6144 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
6147 ventoy_filt_register(0, ventoy_wrapper_open
);
6149 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
6152 g_grub_param
->grub_env_get
= grub_env_get
;
6153 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
6154 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
6155 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
6156 grub_env_set("env_param", buf
);
6157 grub_env_set("ventoy_env_param", buf
);
6159 grub_env_export("env_param");
6160 grub_env_export("ventoy_env_param");
6163 grub_env_export("vtoy_winpeshl_ini_addr");
6164 grub_env_export("vtoy_winpeshl_ini_size");
6166 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
6167 grub_env_set("vtoy_chain_file_size", buf
);
6168 grub_env_export("vtoy_chain_file_size");
6170 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6171 grub_env_set("vtoy_chain_file_read", buf
);
6172 grub_env_export("vtoy_chain_file_read");
6179 static cmd_para ventoy_cmds
[] =
6181 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6182 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6183 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6184 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6185 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6186 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6187 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6188 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6189 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6190 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6191 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6192 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6193 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6194 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6195 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6196 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6197 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6198 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6199 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6200 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6201 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6202 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6203 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6204 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6205 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6206 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6207 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6209 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6210 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6211 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6212 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6213 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6214 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6215 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6217 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6218 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6219 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6220 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6221 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6222 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6223 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6224 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6225 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6226 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6229 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6230 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6231 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6232 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6233 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6234 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6235 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6236 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6237 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6238 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6239 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6241 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6242 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6243 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6244 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6245 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6246 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6247 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6249 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6250 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6251 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6252 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6253 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6254 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6255 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6256 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6257 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6258 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6260 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6261 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6262 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6263 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6264 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6265 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6266 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6267 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6268 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6270 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6271 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6272 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6273 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6276 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6277 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6278 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6280 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6281 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6282 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6285 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6286 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6287 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6288 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6289 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6290 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6291 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6292 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6293 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6294 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6295 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6296 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6297 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6298 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6300 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6301 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6302 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6303 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6304 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6305 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6306 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6307 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6308 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6309 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6310 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6311 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6313 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6314 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6315 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6316 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6317 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6318 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6319 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6320 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6321 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6322 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6323 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6324 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6325 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6326 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6327 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6328 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6329 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6330 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6331 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6332 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso
, 0, NULL
, "", "", NULL
},
6333 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim
, 0, NULL
, "", "", NULL
},
6334 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu
, 0, NULL
, "", "", NULL
},
6335 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu
, 0, NULL
, "", "", NULL
},
6336 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case
, 0, NULL
, "", "", NULL
},
6337 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu
, 0, NULL
, "", "", NULL
},
6338 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode
, 0, NULL
, "", "", NULL
},
6341 int ventoy_register_all_cmd(void)
6344 cmd_para
*cur
= NULL
;
6346 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6348 cur
= ventoy_cmds
+ i
;
6349 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6350 cur
->summary
, cur
->description
, cur
->parser
);
6356 int ventoy_unregister_all_cmd(void)
6360 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6362 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);