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 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
153 const char *g_menu_class
[img_type_max
] =
155 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
158 const char *g_menu_prefix
[img_type_max
] =
160 "iso", "wim", "efi", "img", "vhd", "vtoy"
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
);
1151 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1157 grub_file_read(file
, cur
, left
);
1160 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1166 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1173 enum grub_file_type type
;
1184 if (grub_strcmp(args
[0], "nodecompress") == 0)
1186 type
= VENTOY_FILE_TYPE
;
1190 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1193 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1196 debug("failed to open file <%s>\n", args
[1]);
1200 #ifdef GRUB_MACHINE_EFI
1201 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1203 buf
= (char *)grub_malloc(file
->size
);
1208 grub_file_close(file
);
1212 if (g_vtoy_load_prompt
)
1214 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1218 grub_file_read(file
, buf
, file
->size
);
1221 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1222 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1223 grub_env_set(name
, value
);
1225 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1226 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1227 grub_env_set(name
, value
);
1229 grub_file_close(file
);
1235 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1253 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1256 debug("failed to open file <%s> for udf check\n", args
[0]);
1260 headlen
= sizeof(ventoy_chain_head
);
1262 #ifdef GRUB_MACHINE_EFI
1263 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1265 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1268 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1270 grub_file_read(file
, buf
+ headlen
, file
->size
);
1272 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1273 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1274 grub_env_set(name
, value
);
1276 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1277 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1278 grub_env_set(name
, value
);
1280 grub_file_close(file
);
1286 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1292 if (grub_iso9660_is_joliet())
1294 debug("This time has joliet process\n");
1303 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1312 if (args
[0][0] == '1')
1314 grub_iso9660_set_nojoliet(1);
1318 grub_iso9660_set_nojoliet(0);
1324 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1329 grub_uint8_t buf
[32];
1340 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1343 debug("failed to open file <%s> for udf check\n", args
[0]);
1347 for (i
= 16; i
< 32; i
++)
1349 grub_file_seek(file
, i
* 2048);
1350 grub_file_read(file
, buf
, sizeof(buf
));
1358 grub_file_seek(file
, i
* 2048);
1359 grub_file_read(file
, buf
, sizeof(buf
));
1361 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1364 grub_file_seek(file
, i
* 2048);
1365 grub_file_read(file
, buf
, sizeof(buf
));
1367 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1368 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1374 grub_file_close(file
);
1376 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1381 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1383 long value_long1
= 0;
1384 long value_long2
= 0;
1386 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1388 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1391 value_long1
= grub_strtol(args
[0], NULL
, 10);
1392 value_long2
= grub_strtol(args
[2], NULL
, 10);
1394 if (0 == grub_strcmp(args
[1], "eq"))
1396 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1398 else if (0 == grub_strcmp(args
[1], "ne"))
1400 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1402 else if (0 == grub_strcmp(args
[1], "gt"))
1404 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1406 else if (0 == grub_strcmp(args
[1], "lt"))
1408 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1410 else if (0 == grub_strcmp(args
[1], "ge"))
1412 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1414 else if (0 == grub_strcmp(args
[1], "le"))
1416 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1420 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1426 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1429 char buf
[128] = {0};
1433 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1436 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1437 pos
= grub_strstr(buf
, ",");
1443 grub_env_set(args
[1], buf
);
1445 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1448 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1454 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1460 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1463 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1465 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1466 if (0 == grub_script_execute_sourcecode(buf
))
1468 debug("file %s exist, ventoy_compatible YES\n", buf
);
1469 grub_env_set("ventoy_compatible", "YES");
1470 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1474 debug("file %s NOT exist\n", buf
);
1478 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1479 pos
= grub_strstr(buf
, ")");
1485 disk
= grub_disk_open(buf
);
1488 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1489 grub_disk_close(disk
);
1491 g_img_swap_tmp_buf
[703] = 0;
1492 for (i
= 318; i
< 703; i
++)
1494 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1495 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1497 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1498 grub_env_set("ventoy_compatible", "YES");
1499 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1505 debug("failed to open disk <%s>\n", buf
);
1508 grub_env_set("ventoy_compatible", "NO");
1509 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1512 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1518 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1520 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1523 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1528 if (0 == g_sort_case_sensitive
)
1530 if (grub_islower(c1
))
1532 c1
= c1
- 'a' + 'A';
1535 if (grub_islower(c2
))
1537 c2
= c2
- 'a' + 'A';
1550 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1556 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1558 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1561 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1566 if (0 == g_sort_case_sensitive
)
1568 if (grub_islower(c1
))
1570 c1
= c1
- 'a' + 'A';
1573 if (grub_islower(c2
))
1575 c2
= c2
- 'a' + 'A';
1588 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1590 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1592 grub_memcpy(img1
, img2
, sizeof(img_info
));
1593 img1
->next
= g_img_swap_tmp
.next
;
1594 img1
->prev
= g_img_swap_tmp
.prev
;
1596 g_img_swap_tmp
.next
= img2
->next
;
1597 g_img_swap_tmp
.prev
= img2
->prev
;
1598 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1601 int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1605 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1613 static int ventoy_vlnk_iterate_partition(struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
1615 ventoy_vlnk_part
*node
= NULL
;
1616 grub_uint32_t SelfSig
;
1617 grub_uint32_t
*pSig
= (grub_uint32_t
*)data
;
1619 /* skip Ventoy partition 1/2 */
1620 grub_memcpy(&SelfSig
, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
1621 if (partition
->number
< 2 && SelfSig
== *pSig
)
1626 node
= grub_zalloc(sizeof(ventoy_vlnk_part
));
1629 node
->disksig
= *pSig
;
1630 node
->partoffset
= (partition
->start
<< GRUB_DISK_SECTOR_BITS
);
1631 grub_snprintf(node
->disk
, sizeof(node
->disk
) - 1, "%s", disk
->name
);
1632 grub_snprintf(node
->device
, sizeof(node
->device
) - 1, "%s,%d", disk
->name
, partition
->number
+ 1);
1634 node
->next
= g_vlnk_part_list
;
1635 g_vlnk_part_list
= node
;
1641 static int ventoy_vlnk_iterate_disk(const char *name
, void *data
)
1648 disk
= grub_disk_open(name
);
1651 grub_disk_read(disk
, 0, 0x1b8, 4, &sig
);
1652 grub_partition_iterate(disk
, ventoy_vlnk_iterate_partition
, &sig
);
1653 grub_disk_close(disk
);
1659 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part
*cur
)
1661 const char *fs
[ventoy_fs_max
+ 1] =
1663 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1668 cur
->dev
= grub_device_open(cur
->device
);
1673 cur
->fs
= grub_fs_list_probe(cur
->dev
, fs
);
1679 static int ventoy_check_vlnk_data(ventoy_vlnk
*vlnk
, int print
, char *dst
, int size
)
1684 char *disk
, *device
;
1685 grub_uint32_t readcrc
, calccrc
;
1686 ventoy_vlnk_part
*cur
;
1687 grub_fs_t fs
= NULL
;
1689 if (grub_memcmp(&(vlnk
->guid
), &g_ventoy_guid
, sizeof(ventoy_guid
)))
1693 grub_printf("VLNK invalid guid\n");
1699 readcrc
= vlnk
->crc32
;
1701 calccrc
= grub_getcrc32c(0, vlnk
, sizeof(ventoy_vlnk
));
1702 if (readcrc
!= calccrc
)
1706 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc
, readcrc
);
1712 if (!g_vlnk_part_list
)
1714 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk
, NULL
);
1717 for (cur
= g_vlnk_part_list
; cur
&& filefind
== 0; cur
= cur
->next
)
1719 if (cur
->disksig
== vlnk
->disk_signature
)
1723 if (cur
->partoffset
== vlnk
->part_offset
)
1726 device
= cur
->device
;
1728 if (cur
->probe
== 0)
1731 ventoy_vlnk_probe_fs(cur
);
1741 struct grub_file file
;
1743 grub_memset(&file
, 0, sizeof(file
));
1744 file
.device
= cur
->dev
;
1745 if (cur
->fs
->fs_open(&file
, vlnk
->filepath
) == GRUB_ERR_NONE
)
1748 cur
->fs
->fs_close(&file
);
1749 grub_snprintf(dst
, size
- 1, "(%s)%s", cur
->device
, vlnk
->filepath
);
1758 grub_printf("\n==== VLNK Information ====\n"
1759 "Disk Signature: %08x\n"
1760 "Partition Offset: %llu\n"
1761 "File Path: <%s>\n\n",
1762 vlnk
->disk_signature
, (ulonglong
)vlnk
->part_offset
, vlnk
->filepath
);
1766 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk
);
1770 grub_printf("Disk Find: [ NO ]\n");
1775 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device
, fs
? fs
->name
: "N/A");
1779 grub_printf("Part Find: [ NO ]\n");
1781 grub_printf("File Find: [ %s ]\n", filefind
? "YES" : "NO");
1784 grub_printf("VLNK File: <%s>\n", dst
);
1791 return (1 - filefind
);
1794 int ventoy_add_vlnk_file(char *dir
, const char *name
)
1799 grub_file_t file
= NULL
;
1804 grub_snprintf(src
, sizeof(src
), "%s%s", g_iso_path
, name
);
1806 else if (dir
[0] == '/')
1808 grub_snprintf(src
, sizeof(src
), "%s%s%s", g_iso_path
, dir
, name
);
1812 grub_snprintf(src
, sizeof(src
), "%s/%s%s", g_iso_path
, dir
, name
);
1815 file
= grub_file_open(src
, VENTOY_FILE_TYPE
);
1821 grub_memset(&vlnk
, 0, sizeof(vlnk
));
1822 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
1823 grub_file_close(file
);
1825 if (ventoy_check_vlnk_data(&vlnk
, 0, dst
, sizeof(dst
)) == 0)
1827 rc
= grub_file_add_vlnk(src
, dst
);
1833 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1843 const menu_tip
*tip
;
1844 img_iterator_node
*tmp
;
1845 img_iterator_node
*new_node
;
1846 img_iterator_node
*node
= (img_iterator_node
*)data
;
1848 if (g_enumerate_time_checked
== 0)
1850 g_enumerate_finish_time_ms
= grub_get_time_ms();
1851 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1854 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1856 g_enumerate_time_checked
= 1;
1860 len
= grub_strlen(filename
);
1864 if (node
->level
+ 1 > g_img_max_search_level
)
1869 if ((len
== 1 && filename
[0] == '.') ||
1870 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1875 if (!ventoy_img_name_valid(filename
, len
))
1880 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1885 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1887 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1888 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1891 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1896 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1899 new_node
->level
= node
->level
+ 1;
1900 new_node
->plugin_list_index
= index
;
1901 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1903 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1906 debug("Directory %s ignored...\n", new_node
->dir
);
1907 grub_free(new_node
);
1911 new_node
->tail
= node
->tail
;
1913 new_node
->parent
= node
;
1914 if (!node
->firstchild
)
1916 node
->firstchild
= new_node
;
1919 if (g_img_iterator_tail
)
1921 g_img_iterator_tail
->next
= new_node
;
1922 g_img_iterator_tail
= new_node
;
1926 g_img_iterator_head
.next
= new_node
;
1927 g_img_iterator_tail
= new_node
;
1933 debug("Find a file %s\n", filename
);
1939 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1941 type
= img_type_iso
;
1943 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1945 type
= img_type_wim
;
1947 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1948 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1950 type
= img_type_vhd
;
1952 #ifdef GRUB_MACHINE_EFI
1953 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1955 type
= img_type_efi
;
1958 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1960 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1962 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1963 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1968 type
= img_type_img
;
1970 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1972 type
= img_type_vtoy
;
1974 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1976 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1978 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1979 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1988 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1993 if (g_plugin_image_list
)
1995 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1996 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1997 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1999 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
2002 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
2004 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
2009 if (info
->size
== VTOY_FILT_MIN_FILE_SIZE
|| info
->size
== 0)
2011 if (grub_file_is_vlnk_suffix(filename
, len
))
2014 if (ventoy_add_vlnk_file(node
->dir
, filename
) != 0)
2021 img
= grub_zalloc(sizeof(img_info
));
2025 img
->plugin_list_index
= index
;
2026 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
2028 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
2030 img
->size
= info
->size
;
2031 if (vlnk
|| 0 == img
->size
)
2033 if (node
->dir
[0] == '/')
2035 img
->size
= ventoy_grub_get_file_size("%s%s%s", g_iso_path
, node
->dir
, filename
);
2039 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
2043 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
2045 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
2050 if (g_ventoy_img_list
)
2052 tail
= *(node
->tail
);
2058 g_ventoy_img_list
= img
;
2061 img
->id
= g_ventoy_img_count
;
2063 if (node
&& NULL
== node
->firstiso
)
2065 node
->firstiso
= img
;
2076 *((img_info
**)(node
->tail
)) = img
;
2077 g_ventoy_img_count
++;
2079 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
2081 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_image_file
, img
->path
);
2084 img
->tip1
= tip
->tip1
;
2085 img
->tip2
= tip
->tip2
;
2088 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
2091 img
->class = g_menu_class
[type
];
2093 img
->menu_prefix
= g_menu_prefix
[type
];
2095 if (img_type_iso
== type
)
2097 if (ventoy_plugin_check_memdisk(img
->path
))
2099 img
->menu_prefix
= "miso";
2103 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
2110 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
2112 int len
= GRUB_UINT_MAX
;
2113 const char *value
= NULL
;
2114 char name
[32] = {0};
2115 char plat
[32] = {0};
2116 char guidstr
[32] = {0};
2117 ventoy_guid guid
= VENTOY_GUID
;
2118 const char *fmt1
= NULL
;
2119 const char *fmt2
= NULL
;
2120 const char *fmt3
= NULL
;
2121 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
2122 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
2123 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2124 const char fmtcode
[]={
2125 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2126 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2127 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2128 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2129 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2130 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2133 grub_memset(name
, 0, sizeof(name
));
2134 puint
[0] = grub_swap_bytes32(0x56454e54);
2135 puint
[3] = grub_swap_bytes32(0x4f4e0000);
2136 puint
[2] = grub_swap_bytes32(0x45525349);
2137 puint
[1] = grub_swap_bytes32(0x4f595f56);
2138 value
= ventoy_get_env(name
);
2140 grub_memset(name
, 0, sizeof(name
));
2141 puint
[1] = grub_swap_bytes32(0x5f544f50);
2142 puint
[0] = grub_swap_bytes32(0x56544c45);
2143 fmt1
= ventoy_get_env(name
);
2149 grub_memset(name
, 0, sizeof(name
));
2150 puint
[1] = grub_swap_bytes32(0x5f4c4654);
2151 puint
[0] = grub_swap_bytes32(0x56544c45);
2152 fmt2
= ventoy_get_env(name
);
2154 grub_memset(name
, 0, sizeof(name
));
2155 puint
[1] = grub_swap_bytes32(0x5f434c52);
2156 puint
[0] = grub_swap_bytes32(0x56544c45);
2157 fmt3
= ventoy_get_env(name
);
2159 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
2161 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
2163 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2164 #pragma GCC diagnostic push
2165 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2166 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
2167 fmt1
? fmt1
: fmtdata
,
2168 fmt2
? fmt2
: fmtdata
+ 4,
2169 value
? value
: "", plat
, guidstr
,
2170 fmt3
? fmt3
: fmtdata
+ 6);
2171 #pragma GCC diagnostic pop
2173 grub_memset(name
, 0, sizeof(name
));
2174 puint
[0] = grub_swap_bytes32(0x76746f79);
2175 puint
[2] = grub_swap_bytes32(0x656e7365);
2176 puint
[1] = grub_swap_bytes32(0x5f6c6963);
2177 ventoy_set_env(name
, guidstr
);
2182 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
2186 grub_uint8_t md5
[16];
2190 grub_memset(input
, 0, sizeof(input
));
2192 grub_printf("Enter password: ");
2195 if (pwd
->type
== VTOY_PASSWORD_TXT
)
2197 grub_password_get(input
, 128);
2198 if (grub_strcmp(pwd
->text
, input
) == 0)
2203 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
2205 grub_password_get(input
, 128);
2206 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2207 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2212 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2214 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2215 grub_password_get(input
+ offset
, 128);
2217 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2218 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2224 grub_printf("Invalid password!\n\n");
2231 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2233 img_info
*minimg
= NULL
;
2234 img_info
*img
= (img_info
*)(node
->firstiso
);
2236 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2238 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2253 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2255 img_iterator_node
*Minchild
= NULL
;
2256 img_iterator_node
*child
= node
->firstchild
;
2258 while (child
&& child
->parent
== node
)
2260 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2264 child
= child
->next
;
2269 Minchild
->select
= 1;
2275 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2278 img_info
*img
= NULL
;
2279 const char *dir_class
= NULL
;
2280 const char *dir_alias
= NULL
;
2281 img_iterator_node
*child
= NULL
;
2282 const menu_tip
*tip
= NULL
;
2284 if (node
->isocnt
== 0 || node
->done
== 1)
2289 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2291 offset
= node
->parent
->dirlen
;
2294 if (node
== &g_img_iterator_head
)
2296 if (g_default_menu_mode
== 0)
2298 if (g_tree_view_menu_style
== 0)
2300 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2301 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2302 " echo 'return ...' \n"
2307 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2308 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2309 " echo 'return ...' \n"
2314 g_tree_script_pre
= g_tree_script_pos
;
2318 node
->dir
[node
->dirlen
- 1] = 0;
2319 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2322 dir_class
= "vtoydir";
2325 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2327 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2330 if (g_tree_view_menu_style
== 0)
2332 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2333 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2334 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2338 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2339 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2340 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2345 dir_alias
= node
->dir
+ offset
;
2347 if (g_tree_view_menu_style
== 0)
2349 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2350 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2351 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2355 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2356 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2357 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2361 if (g_tree_view_menu_style
== 0)
2363 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2364 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2365 " echo 'return ...' \n"
2366 "}\n", "<--", node
->dir
);
2370 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2371 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2372 " echo 'return ...' \n"
2377 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2379 ventoy_dynamic_tree_menu(child
);
2382 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2384 if (g_tree_view_menu_style
== 0)
2386 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2387 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2390 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2391 img
->unsupport
? "[***********] " : "",
2392 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2394 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2398 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2399 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2402 img
->unsupport
? "[***********] " : "",
2403 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2405 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2409 if (node
!= &g_img_iterator_head
)
2411 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "}\n");
2418 static int ventoy_set_default_menu(void)
2424 const char *strdata
= NULL
;
2425 img_info
*cur
= NULL
;
2426 img_info
*default_node
= NULL
;
2427 const char *default_image
= NULL
;
2429 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2430 if (default_image
&& default_image
[0] == '/')
2432 img_len
= grub_strlen(default_image
);
2434 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2436 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2448 if (0 == g_default_menu_mode
)
2450 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2454 def
= grub_strdup(default_image
);
2460 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2462 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2463 if (strdata
&& strdata
[0] == '/')
2465 pos
= def
+ grub_strlen(strdata
);
2476 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2479 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2483 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2491 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2493 img_info
*next
= NULL
;
2494 img_info
*cur
= g_ventoy_img_list
;
2507 g_ventoy_img_list
= NULL
;
2508 g_ventoy_img_count
= 0;
2510 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2513 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2516 img_info
*cur
= g_ventoy_img_list
;
2520 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2522 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2525 img_id
= grub_strtol(args
[0], NULL
, 10);
2526 if (img_id
>= g_ventoy_img_count
)
2528 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2531 debug("Find image %ld name \n", img_id
);
2533 while (cur
&& img_id
> 0)
2541 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2544 debug("image name is %s\n", cur
->name
);
2546 grub_env_set(args
[1], cur
->name
);
2548 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2551 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2555 img_info
*cur
= g_ventoy_img_list
;
2561 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2564 len
= (int)grub_strlen(args
[0]);
2568 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2577 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2580 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2581 grub_env_set("chosen", id
);
2582 grub_env_export("chosen");
2584 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2587 static char g_fake_vlnk_src
[512];
2588 static char g_fake_vlnk_dst
[512];
2589 static grub_uint64_t g_fake_vlnk_size
;
2590 static grub_err_t
ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2596 g_fake_vlnk_size
= (grub_uint64_t
)grub_strtoull(args
[2], NULL
, 10);
2598 grub_strncpy(g_fake_vlnk_dst
, args
[0], sizeof(g_fake_vlnk_dst
));
2599 grub_snprintf(g_fake_vlnk_src
, sizeof(g_fake_vlnk_src
), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path
, args
[1]);
2601 grub_file_vtoy_vlnk(g_fake_vlnk_src
, g_fake_vlnk_dst
);
2603 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2606 static grub_err_t
ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2612 g_fake_vlnk_src
[0] = 0;
2613 g_fake_vlnk_dst
[0] = 0;
2614 g_fake_vlnk_size
= 0;
2615 grub_file_vtoy_vlnk(NULL
, NULL
);
2617 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2621 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2626 const char *id
= NULL
;
2627 img_info
*cur
= NULL
;
2631 if (argc
< 1 || argc
> 3)
2633 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2636 if (g_fake_vlnk_src
[0] && g_fake_vlnk_dst
[0])
2638 pos
= grub_strchr(g_fake_vlnk_src
, '/');
2639 grub_env_set(args
[0], pos
);
2642 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(g_fake_vlnk_size
));
2643 grub_env_set(args
[1], value
);
2648 for (last
= pos
; *pos
; pos
++)
2655 grub_env_set(args
[2], last
+ 1);
2661 id
= grub_env_get("chosen");
2663 pos
= grub_strstr(id
, "VID_");
2666 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2670 cur
= g_ventoy_img_list
;
2675 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2678 grub_env_set(args
[0], cur
->path
);
2682 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2683 grub_env_set(args
[1], value
);
2688 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2689 grub_env_set(args
[2], cur
->name
);
2693 g_svd_replace_offset
= 0;
2695 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2699 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2703 grub_device_t dev
= NULL
;
2704 img_info
*cur
= NULL
;
2705 img_info
*tail
= NULL
;
2706 img_info
*min
= NULL
;
2707 img_info
*head
= NULL
;
2708 const char *strdata
= NULL
;
2709 char *device_name
= NULL
;
2711 img_iterator_node
*node
= NULL
;
2712 img_iterator_node
*tmp
= NULL
;
2718 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2721 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2723 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2728 g_enumerate_time_checked
= 0;
2729 g_enumerate_start_time_ms
= grub_get_time_ms();
2731 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2732 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2734 g_filt_dot_underscore_file
= 1;
2737 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2738 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2740 g_sort_case_sensitive
= 1;
2743 device_name
= grub_file_get_device_name(args
[0]);
2749 g_enum_dev
= dev
= grub_device_open(device_name
);
2755 g_enum_fs
= fs
= grub_fs_probe(dev
);
2761 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2763 debug("unsupported fs:<%s>\n", fs
->name
);
2764 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2768 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2770 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2771 if (strdata
&& strdata
[0] == '1')
2773 g_default_menu_mode
= 1;
2776 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2778 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2780 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2781 if (strdata
&& strdata
[0] == '/')
2783 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2784 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2786 g_img_iterator_head
.dir
[len
++] = '/';
2788 g_img_iterator_head
.dirlen
= len
;
2792 g_img_iterator_head
.dirlen
= 1;
2793 grub_strcpy(g_img_iterator_head
.dir
, "/");
2796 g_img_iterator_head
.tail
= &tail
;
2798 if (g_img_max_search_level
< 0)
2800 g_img_max_search_level
= GRUB_INT_MAX
;
2801 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2802 if (strdata
&& ventoy_is_decimal(strdata
))
2804 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2808 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2809 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2810 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2811 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2812 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2813 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2815 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2817 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2820 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2821 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2823 g_tree_view_menu_style
= 1;
2826 ventoy_set_default_menu();
2828 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2830 ventoy_dynamic_tree_menu(node
);
2834 node
= g_img_iterator_head
.next
;
2842 /* sort image list by image name */
2843 while (g_ventoy_img_list
)
2845 min
= g_ventoy_img_list
;
2846 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2848 if (ventoy_cmp_img(min
, cur
) > 0)
2856 min
->prev
->next
= min
->next
;
2861 min
->next
->prev
= min
->prev
;
2864 if (min
== g_ventoy_img_list
)
2866 g_ventoy_img_list
= min
->next
;
2884 g_ventoy_img_list
= head
;
2886 if (g_default_menu_mode
== 1)
2888 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2889 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2890 " echo 'return ...' \n"
2894 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2896 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2897 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2900 cur
->unsupport
? "[***********] " : "",
2901 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2903 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2906 g_tree_script_buf
[g_tree_script_pos
] = 0;
2907 g_list_script_buf
[g_list_script_pos
] = 0;
2909 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2910 grub_env_set(args
[1], buf
);
2914 check_free(device_name
, grub_free
);
2915 check_free(dev
, grub_device_close
);
2917 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2920 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2927 device_name
= grub_file_get_device_name(filename
);
2939 pos2
= grub_strstr(pos
, ",");
2942 pos2
= grub_strstr(pos
, ")");
2950 disk
= grub_disk_open(pos
);
2953 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2954 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2955 grub_disk_close(disk
);
2962 grub_free(device_name
);
2966 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2968 eltorito_descriptor desc
;
2970 grub_memset(&desc
, 0, sizeof(desc
));
2971 grub_file_seek(file
, 17 * 2048);
2972 grub_file_read(file
, &desc
, sizeof(desc
));
2974 if (desc
.type
!= 0 || desc
.version
!= 1)
2979 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2980 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2988 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2990 grub_uint8_t buf
[512];
2992 grub_file_seek(file
, sector
* 2048);
2993 grub_file_read(file
, buf
, sizeof(buf
));
2995 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2996 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2998 return *((grub_uint32_t
*)(buf
+ 40));
3004 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
3008 grub_uint8_t buf
[512];
3009 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
3011 grub_file_seek(file
, sector
* 2048);
3012 grub_file_read(file
, buf
, sizeof(buf
));
3014 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
3016 debug("%s efi eltorito in Validation Entry\n", file
->name
);
3020 if (buf
[0] == 0x01 && buf
[1] == 0x00)
3025 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
3027 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
3029 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3033 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
3035 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
3040 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
3042 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
3044 if (buf
[36] == parttype
[i
])
3046 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
3052 debug("%s does not contain efi eltorito\n", file
->name
);
3056 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
3059 const char *fs
= NULL
;
3060 const char *val
= NULL
;
3061 const char *cdprompt
= NULL
;
3063 grub_uint8_t chksum
= 0;
3066 disk
= file
->device
->disk
;
3067 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
3069 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
3070 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
3071 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
3073 pos
= grub_strstr(file
->name
, "/");
3079 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
3081 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
3083 param
->vtoy_img_size
= file
->size
;
3085 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
3086 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
3088 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
3090 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3091 param
->vtoy_reserved
[4] = 0;
3092 if (g_ventoy_chain_type
== 1) /* Windows */
3094 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3095 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
3097 param
->vtoy_reserved
[4] = 1;
3101 fs
= ventoy_get_env("ventoy_fs_probe");
3102 if (fs
&& grub_strcmp(fs
, "udf") == 0)
3104 param
->vtoy_reserved
[3] = 1;
3107 param
->vtoy_reserved
[5] = 0;
3108 val
= ventoy_get_env("VTOY_LINUX_REMOUNT");
3109 if (val
&& val
[0] == '1' && val
[1] == 0)
3111 param
->vtoy_reserved
[5] = 1;
3114 /* ventoy_disk_signature used for vlnk */
3115 param
->vtoy_reserved
[6] = file
->vlnk
;
3116 grub_memcpy(param
->vtoy_reserved
+ 7, g_ventoy_part_info
->MBR
.BootCode
+ 0x1b8, 4);
3118 /* calculate checksum */
3119 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
3121 chksum
+= *((grub_uint8_t
*)param
+ i
);
3123 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
3128 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3130 grub_uint32_t i
= 0;
3131 grub_uint64_t total
= 0;
3132 grub_uint64_t fileblk
= 0;
3133 ventoy_img_chunk
*chunk
= NULL
;
3135 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3137 chunk
= chunklist
->chunk
+ i
;
3139 if (chunk
->disk_start_sector
<= start
)
3141 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
3145 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
3148 fileblk
= (file
->size
+ 511) / 512;
3150 if (total
!= fileblk
)
3152 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
3153 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
3155 debug("maybe img file to be processed.\n");
3165 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
3169 grub_uint32_t i
= 0;
3170 grub_uint32_t sector
= 0;
3171 grub_uint32_t count
= 0;
3172 grub_off_t size
= 0;
3173 grub_off_t read
= 0;
3175 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
3176 if (fs_type
== ventoy_fs_exfat
)
3178 grub_fat_get_file_chunk(start
, file
, chunklist
);
3180 else if (fs_type
== ventoy_fs_ext
)
3182 grub_ext_get_file_chunk(start
, file
, chunklist
);
3186 file
->read_hook
= (grub_disk_read_hook_t
)(void *)grub_disk_blocklist_read
;
3187 file
->read_hook_data
= chunklist
;
3189 for (size
= file
->size
; size
> 0; size
-= read
)
3191 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
3192 grub_file_read(file
, NULL
, read
);
3195 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
3197 chunklist
->chunk
[i
].disk_start_sector
+= start
;
3198 chunklist
->chunk
[i
].disk_end_sector
+= start
;
3201 if (ventoy_fs_udf
== fs_type
)
3203 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3205 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
3206 chunklist
->chunk
[i
].img_start_sector
= sector
;
3207 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3213 len
= (int)grub_strlen(file
->name
);
3214 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
3215 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
3216 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
3217 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
3219 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
3221 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
3231 chunklist
->chunk
[i
].img_start_sector
= sector
;
3232 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
3240 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3244 grub_disk_addr_t start
;
3249 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3252 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3255 g_conf_replace_count
= 0;
3256 grub_memset(g_conf_replace_node
, 0, sizeof(g_conf_replace_node
));
3257 grub_memset(g_conf_replace_offset
, 0, sizeof(g_conf_replace_offset
));
3259 if (g_img_chunk_list
.chunk
)
3261 grub_free(g_img_chunk_list
.chunk
);
3264 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
3266 grub_file_close(file
);
3267 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
3270 /* get image chunk data */
3271 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
3272 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3273 if (NULL
== g_img_chunk_list
.chunk
)
3275 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3278 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
3279 g_img_chunk_list
.cur_chunk
= 0;
3281 start
= file
->device
->disk
->partition
->start
;
3283 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
3285 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
3286 grub_file_close(file
);
3290 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
3293 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3294 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3295 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3298 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3302 grub_uint64_t offset
= 0;
3303 grub_uint32_t align
= 0;
3304 grub_file_t file
= NULL
;
3305 conf_replace
*node
= NULL
;
3306 conf_replace
*nodes
[VTOY_MAX_CONF_REPLACE
] = { NULL
};
3307 ventoy_grub_param_file_replace
*replace
= NULL
;
3313 debug("select conf replace argc:%d\n", argc
);
3320 n
= ventoy_plugin_find_conf_replace(args
[1], nodes
);
3323 debug("Conf replace not found for %s\n", args
[1]);
3327 debug("Find %d conf replace for %s\n", n
, args
[1]);
3329 g_conf_replace_count
= n
;
3330 for (i
= 0; i
< n
; i
++)
3334 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3337 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3338 grub_file_close(file
);
3340 else if (node
->img
> 0)
3346 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3350 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3353 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3357 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3359 if (align
> vtoy_max_replace_file_size
)
3361 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3362 grub_file_close(file
);
3366 grub_file_read(file
, g_conf_replace_new_buf
[i
], file
->size
);
3367 grub_file_close(file
);
3368 g_conf_replace_new_len
[i
] = (int)file
->size
;
3369 g_conf_replace_new_len_align
[i
] = align
;
3371 g_conf_replace_node
[i
] = node
;
3372 g_conf_replace_offset
[i
] = offset
+ 2;
3376 replace
= &(g_grub_param
->img_replace
[i
]);
3377 replace
->magic
= GRUB_IMG_REPLACE_MAGIC
;
3378 grub_snprintf(replace
->old_file_name
[replace
->old_name_cnt
], 256, "%s", node
->orgconf
);
3379 replace
->old_name_cnt
++;
3382 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i
, g_conf_replace_new_len
[i
], node
->img
);
3386 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3389 static int ventoy_var_expand(int *record
, int *flag
, const char *var
, char *expand
, int len
)
3394 const char *ch
= var
;
3401 if (*ch
== '_' || (*ch
>= '0' && *ch
<= '9') || (*ch
>= 'A' && *ch
<= 'Z') || (*ch
>= 'a' && *ch
<= 'z'))
3408 debug("Invalid variable letter <%c>\n", *ch
);
3415 debug("Invalid variable length:%d <%s>\n", n
, var
);
3419 if (grub_strncmp(var
, "VT_", 3) == 0) /* built-in variables */
3428 grub_printf("\n=================== Variables Expansion ===================\n\n");
3431 grub_printf("<%s>: ", var
);
3434 while (i
< (len
- 1))
3437 if ((c
== '\n') || (c
== '\r'))
3447 else if (grub_isprint(c
))
3449 if (i
+ 1 < (len
- 1))
3451 grub_printf("%c", c
);
3461 expand
[i
- 1] = ' ';
3462 grub_printf("\r<%s>: %s", var
, expand
);
3465 grub_printf("\r<%s>: %s", var
, expand
);
3477 grub_snprintf(expand
, len
, "$$%s$$", var
);
3483 static int ventoy_auto_install_var_expand(install_template
*node
)
3491 char *newbuf
= NULL
;
3492 char *curline
= NULL
;
3493 char *nextline
= NULL
;
3494 grub_uint8_t
*code
= NULL
;
3496 var_node
*CurNode
= NULL
;
3497 var_node
*pVarList
= NULL
;
3499 code
= (grub_uint8_t
*)node
->filebuf
;
3501 if (node
->filelen
>= VTOY_SIZE_1MB
)
3503 debug("auto install script too long %d\n", node
->filelen
);
3507 if ((code
[0] == 0xff && code
[1] == 0xfe) || (code
[0] == 0xfe && code
[1] == 0xff))
3509 debug("UCS-2 encoding NOT supported\n");
3513 start
= grub_strstr(node
->filebuf
, "$$");
3516 debug("no need to expand variable, no start.\n");
3520 end
= grub_strstr(start
+ 2, "$$");
3523 debug("no need to expand variable, no end.\n");
3527 newlen
= grub_max(node
->filelen
* 10, VTOY_SIZE_128KB
);
3528 newbuf
= grub_malloc(newlen
);
3531 debug("Failed to alloc newbuf %d\n", newlen
);
3535 for (curline
= node
->filebuf
; curline
; curline
= nextline
)
3537 nextline
= ventoy_get_line(curline
);
3539 start
= grub_strstr(curline
, "$$");
3542 end
= grub_strstr(start
+ 2, "$$");
3548 VTOY_APPEND_NEWBUF(curline
);
3550 for (CurNode
= pVarList
; CurNode
; CurNode
= CurNode
->next
)
3552 if (grub_strcmp(start
+ 2, CurNode
->var
) == 0)
3554 grub_snprintf(value
, sizeof(value
) - 1, "%s", CurNode
->val
);
3561 value
[sizeof(value
) - 1] = 0;
3562 ventoy_var_expand(&record
, &flag
, start
+ 2, value
, sizeof(value
) - 1);
3566 CurNode
= grub_zalloc(sizeof(var_node
));
3569 grub_snprintf(CurNode
->var
, sizeof(CurNode
->var
), "%s", start
+ 2);
3570 grub_snprintf(CurNode
->val
, sizeof(CurNode
->val
), "%s", value
);
3571 CurNode
->next
= pVarList
;
3577 VTOY_APPEND_NEWBUF(value
);
3579 VTOY_APPEND_NEWBUF(end
+ 2);
3583 VTOY_APPEND_NEWBUF(curline
);
3586 if (pos
> 0 && newbuf
[pos
- 1] == '\r')
3588 newbuf
[pos
- 1] = '\n';
3592 newbuf
[pos
++] = '\n';
3596 grub_free(node
->filebuf
);
3597 node
->filebuf
= newbuf
;
3598 node
->filelen
= pos
;
3602 CurNode
= pVarList
->next
;
3603 grub_free(pVarList
);
3610 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3616 grub_file_t file
= NULL
;
3617 char configfile
[128];
3618 install_template
*node
= NULL
;
3624 debug("select auto installation argc:%d\n", argc
);
3631 node
= ventoy_plugin_find_install_template(args
[0]);
3634 debug("Auto install template not found for %s\n", args
[0]);
3638 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3640 defidx
= node
->autosel
;
3641 if (node
->timeout
< 0)
3643 node
->cursel
= node
->autosel
- 1;
3644 debug("Auto install template auto select %d\n", node
->autosel
);
3649 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3655 if (node
->timeout
> 0)
3657 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3660 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3661 " echo %s\n}\n", "");
3663 for (i
= 0; i
< node
->templatenum
; i
++)
3665 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3667 node
->templatepath
[i
].path
);
3670 g_ventoy_menu_esc
= 1;
3671 g_ventoy_suppress_esc
= 1;
3672 g_ventoy_suppress_esc_default
= defidx
;
3674 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3675 grub_script_execute_sourcecode(configfile
);
3677 g_ventoy_menu_esc
= 0;
3678 g_ventoy_suppress_esc
= 0;
3679 g_ventoy_suppress_esc_default
= 1;
3683 node
->cursel
= g_ventoy_last_entry
- 1;
3685 grub_check_free(node
->filebuf
);
3688 if (node
->cursel
>= 0 && node
->cursel
< node
->templatenum
)
3690 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", ventoy_get_env("vtoy_iso_part"),
3691 node
->templatepath
[node
->cursel
].path
);
3694 node
->filebuf
= grub_malloc(file
->size
+ 8);
3697 grub_file_read(file
, node
->filebuf
, file
->size
);
3698 grub_file_close(file
);
3700 grub_memset(node
->filebuf
+ file
->size
, 0, 8);
3701 node
->filelen
= (int)file
->size
;
3703 ventoy_auto_install_var_expand(node
);
3708 debug("Failed to open auto install script <%s%s>\n",
3709 ventoy_get_env("vtoy_iso_part"), node
->templatepath
[node
->cursel
].path
);
3713 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3716 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3722 char configfile
[128];
3723 persistence_config
*node
;
3729 debug("select persistence argc:%d\n", argc
);
3736 node
= ventoy_plugin_find_persistent(args
[0]);
3739 debug("Persistence image not found for %s\n", args
[0]);
3743 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3745 defidx
= node
->autosel
;
3746 if (node
->timeout
< 0)
3748 node
->cursel
= node
->autosel
- 1;
3749 debug("Persistence image auto select %d\n", node
->autosel
);
3754 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3760 if (node
->timeout
> 0)
3762 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3765 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3766 " echo %s\n}\n", "");
3768 for (i
= 0; i
< node
->backendnum
; i
++)
3770 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3772 node
->backendpath
[i
].path
);
3776 g_ventoy_menu_esc
= 1;
3777 g_ventoy_suppress_esc
= 1;
3778 g_ventoy_suppress_esc_default
= defidx
;
3780 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3781 grub_script_execute_sourcecode(configfile
);
3783 g_ventoy_menu_esc
= 0;
3784 g_ventoy_suppress_esc
= 0;
3785 g_ventoy_suppress_esc_default
= 1;
3789 node
->cursel
= g_ventoy_last_entry
- 1;
3791 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3794 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3797 ventoy_img_chunk
*cur
;
3803 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3805 cur
= g_img_chunk_list
.chunk
+ i
;
3806 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3807 cur
->img_start_sector
, cur
->img_end_sector
,
3808 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3812 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3815 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3819 ventoy_img_chunk_list chunklist
;
3824 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3827 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3830 /* get image chunk data */
3831 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3832 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3833 if (NULL
== chunklist
.chunk
)
3835 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3838 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3839 chunklist
.cur_chunk
= 0;
3841 ventoy_get_block_list(file
, &chunklist
, 0);
3843 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3845 grub_printf("########## UNSUPPORTED ###############\n");
3848 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3850 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3852 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3853 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3856 grub_printf("\n==================================\n");
3858 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3860 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3861 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3862 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3863 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3864 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3868 grub_free(chunklist
.chunk
);
3869 grub_file_close(file
);
3871 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3874 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3877 ventoy_grub_param_file_replace
*replace
= NULL
;
3885 replace
= &(g_grub_param
->file_replace
);
3886 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3888 replace
->old_name_cnt
= 0;
3889 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3891 replace
->old_name_cnt
++;
3892 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3895 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3898 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3901 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3904 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3910 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3911 grub_env_set(args
[0], buf
);
3914 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3917 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3925 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3926 grub_printf("%s", g_list_script_buf
);
3930 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3931 grub_printf("%s", g_tree_script_buf
);
3937 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3939 img_info
*cur
= g_ventoy_img_list
;
3947 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3948 grub_printf("name:<%s>\n\n", cur
->name
);
3955 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3961 ventoy_plugin_dump_injection();
3966 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3972 ventoy_plugin_dump_auto_install();
3977 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3983 ventoy_plugin_dump_persistence();
3988 static int ventoy_check_mode_by_name(char *filename
, const char *suffix
)
3994 len1
= (int)grub_strlen(filename
);
3995 len2
= (int)grub_strlen(suffix
);
4002 for (i
= len1
- 1; i
>= 0; i
--)
4004 if (filename
[i
] == '.')
4015 if (filename
[i
- len2
- 1] != '_')
4020 if (grub_strncasecmp(filename
+ (i
- len2
), suffix
, len2
) == 0)
4028 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4034 if (argc
!= 1 && argc
!= 2)
4039 if (args
[0][0] == '0')
4041 if (g_ventoy_memdisk_mode
)
4046 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtmemdisk"))
4053 else if (args
[0][0] == '1')
4055 return g_ventoy_iso_raw
? 0 : 1;
4057 else if (args
[0][0] == '2')
4059 return g_ventoy_iso_uefi_drv
? 0 : 1;
4061 else if (args
[0][0] == '3')
4063 if (g_ventoy_grub2_mode
)
4068 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtgrub2"))
4075 else if (args
[0][0] == '4')
4077 if (g_ventoy_wimboot_mode
)
4082 if (argc
== 2 && ventoy_check_mode_by_name(args
[1], "vtwimboot"))
4093 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4095 static int configfile_mode
= 0;
4096 char memfile
[128] = {0};
4103 * args[0]: 0:normal 1:configfile
4104 * args[1]: 0:list_buf 1:tree_buf
4109 debug("Invalid argc %d\n", argc
);
4115 if (args
[0][0] == '0')
4117 if (args
[1][0] == '0')
4119 grub_script_execute_sourcecode(g_list_script_buf
);
4123 grub_script_execute_sourcecode(g_tree_script_buf
);
4128 if (configfile_mode
)
4130 debug("Now already in F3 mode %d\n", configfile_mode
);
4134 if (args
[1][0] == '0')
4136 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4137 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
4141 g_ventoy_last_entry
= -1;
4142 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
4143 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
4146 configfile_mode
= 1;
4147 grub_script_execute_sourcecode(memfile
);
4148 configfile_mode
= 0;
4154 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4165 g_ventoy_case_insensitive
= 1;
4166 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4167 g_ventoy_case_insensitive
= 0;
4173 grub_file_close(file
);
4179 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4184 const char *isopath
= NULL
;
4186 ventoy_mbr_head mbr
;
4193 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
4196 isopath
= grub_env_get("vtoy_iso_part");
4199 debug("isopath is null %p\n", isopath
);
4203 debug("isopath is %s\n", isopath
);
4205 for (id
= 0; id
< 30 && (find
== 0); id
++)
4207 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
4208 if (grub_strstr(isopath
, hdname
))
4210 debug("skip %s ...\n", hdname
);
4214 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
4216 disk
= grub_disk_open(hdname
);
4219 debug("%s not exist\n", hdname
);
4223 grub_memset(&mbr
, 0, sizeof(mbr
));
4224 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
4226 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
4228 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
4229 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
4232 grub_env_set(args
[0], hdname
);
4236 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
4240 debug("read %s failed\n", hdname
);
4243 grub_disk_close(disk
);
4249 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4260 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
4263 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4266 debug("failed to open file %s\n", args
[0]);
4270 buf
= grub_malloc(len
);
4277 grub_file_read(file
, buf
, len
- 1);
4279 ventoy_get_line(buf
);
4280 ventoy_set_env(args
[1], buf
);
4284 grub_check_free(buf
);
4285 grub_file_close(file
);
4290 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
4292 grub_uint64_t end_max
= 0;
4293 int *pCnt
= (int *)data
;
4298 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
4299 "0 %llu linear /dev/ventoy %llu\n",
4300 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
4302 end_max
= (partition
->len
+ partition
->start
) * 512;
4303 if (end_max
> g_part_end_max
)
4305 g_part_end_max
= end_max
;
4311 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4314 char *device_name
= NULL
;
4315 grub_device_t dev
= NULL
;
4320 g_part_list_pos
= 0;
4322 grub_env_unset("vtoy_img_part_file");
4329 device_name
= grub_file_get_device_name(args
[0]);
4332 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
4336 dev
= grub_device_open(device_name
);
4339 debug("grub_device_open failed, %s\n", device_name
);
4343 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
4345 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
4346 grub_env_set("vtoy_img_part_file", buf
);
4348 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
4349 grub_env_set("vtoy_img_part_cnt", buf
);
4351 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)g_part_end_max
);
4352 grub_env_set("vtoy_img_max_part_end", buf
);
4356 check_free(device_name
, grub_free
);
4357 check_free(dev
, grub_device_close
);
4363 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4374 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
4377 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4380 debug("failed to open file %s\n", args
[0]);
4384 buf
= grub_malloc(file
->size
+ 1);
4390 buf
[file
->size
] = 0;
4391 grub_file_read(file
, buf
, file
->size
);
4393 if (grub_strstr(buf
, args
[1]))
4400 grub_check_free(buf
);
4401 grub_file_close(file
);
4406 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4412 ventoy_iso9660_vd pvd
;
4419 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
4422 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4425 debug("failed to open file %s\n", args
[0]);
4429 grub_file_seek(file
, 16 * 2048);
4430 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
4431 if (len
!= sizeof(pvd
))
4433 debug("failed to read pvd %d\n", len
);
4437 grub_memset(buf
, 0, sizeof(buf
));
4438 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
4439 ventoy_set_env(args
[1], buf
);
4441 grub_memset(buf
, 0, sizeof(buf
));
4442 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
4443 ventoy_set_env(args
[2], buf
);
4447 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
4448 ventoy_set_env(args
[3], buf
);
4451 grub_file_close(file
);
4456 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4467 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
4470 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4473 debug("failed to open file %s\n", args
[0]);
4477 grub_memset(buf
, 0, sizeof(buf
));
4478 grub_file_seek(file
, 16 * 2048 + 813);
4479 len
= (int)grub_file_read(file
, buf
, 17);
4482 debug("failed to read create date %d\n", len
);
4486 ventoy_set_env(args
[1], buf
);
4489 grub_file_close(file
);
4494 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4500 ventoy_env_hook_root(1);
4505 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4511 ventoy_env_hook_root(0);
4516 #ifdef GRUB_MACHINE_EFI
4517 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4522 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
4528 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
4529 if (var
&& *var
== 1)
4537 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4546 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4551 grub_uint64_t FileSectors
= 0;
4552 ventoy_gpt_info
*gpt
= NULL
;
4553 ventoy_part_table
*pt
= NULL
;
4554 grub_uint8_t zeroguid
[16] = {0};
4559 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
4562 debug("failed to open file %s\n", args
[0]);
4566 if (file
->size
% 512)
4568 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
4572 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
4578 FileSectors
= file
->size
/ 512;
4580 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
4581 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
4583 debug("This is EFI partition table\n");
4585 for (i
= 0; i
< 128; i
++)
4587 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
4589 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
4591 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4592 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
4600 debug("This is MBR partition table\n");
4602 for (i
= 0; i
< 4; i
++)
4604 pt
= gpt
->MBR
.PartTbl
+ i
;
4605 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
4607 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
4608 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
4609 (ulonglong
)FileSectors
);
4618 grub_file_close(file
);
4619 grub_check_free(gpt
);
4620 grub_errno
= GRUB_ERR_NONE
;
4624 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4633 for (i
= 0; i
< 500; i
++)
4635 ret
= grub_getkey_noblock();
4636 if (ret
== GRUB_TERM_NO_KEY
)
4645 grub_printf("\n\n Still have key input after clear.\n");
4653 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4660 int image_sector_size
;
4662 ventoy_chain_head
*chain
;
4663 ventoy_img_chunk
*chunk
;
4664 ventoy_os_param
*osparam
;
4665 ventoy_image_location
*location
;
4666 ventoy_image_disk_region
*region
;
4667 struct grub_acpi_table_header
*acpi
;
4676 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4678 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4684 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4686 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4688 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4692 img_chunk_num
= chain
->img_chunk_num
;
4694 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4695 datalen
= sizeof(ventoy_os_param
) + loclen
;
4697 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4698 acpi
= grub_zalloc(buflen
);
4704 /* Step1: Fill acpi table header */
4705 grub_memcpy(acpi
->signature
, "VTOY", 4);
4706 acpi
->length
= buflen
;
4708 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4709 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4711 acpi
->creator_id
[0] = 1;
4712 acpi
->creator_rev
= 1;
4714 /* Step2: Fill data */
4715 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4716 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4717 osparam
->vtoy_img_location_addr
= 0;
4718 osparam
->vtoy_img_location_len
= loclen
;
4719 osparam
->chksum
= 0;
4720 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4722 location
= (ventoy_image_location
*)(osparam
+ 1);
4723 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4724 location
->image_sector_size
= image_sector_size
;
4725 location
->disk_sector_size
= chain
->disk_sector_size
;
4726 location
->region_count
= img_chunk_num
;
4728 region
= location
->regions
;
4729 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4730 if (512 == image_sector_size
)
4732 for (i
= 0; i
< img_chunk_num
; i
++)
4734 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4735 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4736 region
->disk_start_sector
= chunk
->disk_start_sector
;
4743 for (i
= 0; i
< img_chunk_num
; i
++)
4745 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4746 region
->image_start_sector
= chunk
->img_start_sector
;
4747 region
->disk_start_sector
= chunk
->disk_start_sector
;
4753 /* Step3: Fill acpi checksum */
4755 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4757 /* load acpi table */
4758 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4759 grub_script_execute_sourcecode(cmd
);
4763 VENTOY_CMD_RETURN(0);
4766 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4772 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4773 g_ventoy_last_entry
= -1;
4778 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4784 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4789 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4791 const char *pos
= filename
+ 1;
4799 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4801 grub_strncpy((char *)data
, filename
, 128);
4812 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4815 char *device_name
= NULL
;
4816 grub_device_t dev
= NULL
;
4817 grub_fs_t fs
= NULL
;
4818 char buf
[128] = {0};
4824 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4828 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4830 device_name
= grub_file_get_device_name(args
[0]);
4833 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4837 dev
= grub_device_open(device_name
);
4840 debug("grub_device_open failed, %s\n", device_name
);
4844 fs
= grub_fs_probe(dev
);
4847 debug("grub_fs_probe failed, %s\n", device_name
);
4851 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4855 ventoy_set_env(args
[2], buf
);
4862 check_free(device_name
, grub_free
);
4863 check_free(dev
, grub_device_close
);
4868 int ventoy_load_part_table(const char *diskname
)
4875 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4876 if (!g_ventoy_part_info
)
4881 disk
= grub_disk_open(diskname
);
4884 debug("Failed to open disk %s\n", diskname
);
4888 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4890 g_ventoy_disk_bios_id
= disk
->id
;
4892 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4893 grub_disk_close(disk
);
4895 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4896 dev
= grub_device_open(name
);
4899 /* Check for official Ventoy device */
4900 ret
= ventoy_check_official_device(dev
);
4901 grub_device_close(dev
);
4909 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4910 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4915 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4922 ret
= ventoy_load_part_table(args
[0]);
4928 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4929 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4934 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4937 const char *vcfg
= NULL
;
4942 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4945 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4946 grub_env_set(args
[1], vcfg
);
4951 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4959 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4962 grub_uint8_t zeroguid
[16] = {0};
4967 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4970 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4972 if (id
>= 1 && id
<= 128)
4974 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4982 if (id
>= 1 && id
<= 4)
4984 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4994 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4997 char *device_name
= NULL
;
4998 grub_device_t dev
= NULL
;
4999 grub_fs_t fs
= NULL
;
5004 debug("get fs label for %s\n", args
[0]);
5008 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
5012 device_name
= grub_file_get_device_name(args
[0]);
5015 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5019 dev
= grub_device_open(device_name
);
5022 debug("grub_device_open failed, %s\n", device_name
);
5026 fs
= grub_fs_probe(dev
);
5027 if (NULL
== fs
|| NULL
== fs
->fs_label
)
5029 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
5033 fs
->fs_label(dev
, &label
);
5036 debug("label=<%s>\n", label
);
5037 ventoy_set_env(args
[1], label
);
5045 check_free(device_name
, grub_free
);
5046 check_free(dev
, grub_device_close
);
5051 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5055 grub_snprintf((char *)data
, 256, "%s", filename
);
5062 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5064 if (info
->dir
&& filename
&& filename
[0] != '.')
5066 grub_snprintf((char *)data
, 256, "%s", filename
);
5073 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
5076 char *device_name
= NULL
;
5077 grub_device_t dev
= NULL
;
5078 grub_fs_t fs
= NULL
;
5079 char name
[256] ={0};
5083 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
5087 device_name
= grub_file_get_device_name(args
[0]);
5090 debug("grub_file_get_device_name failed, %s\n", args
[0]);
5094 dev
= grub_device_open(device_name
);
5097 debug("grub_device_open failed, %s\n", device_name
);
5101 fs
= grub_fs_probe(dev
);
5104 debug("grub_fs_probe failed, %s\n", device_name
);
5108 fs
->fs_dir(dev
, args
[1], hook
, name
);
5111 ventoy_set_env(args
[2], name
);
5118 check_free(device_name
, grub_free
);
5119 check_free(dev
, grub_device_close
);
5124 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5127 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
5130 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5133 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
5136 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5146 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
5150 for (pos
= args
[0]; *pos
; pos
++)
5164 grub_env_set(args
[1], args
[0]);
5174 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5184 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
5189 len
= (int)grub_strlen(buf
);
5190 for (i
= len
; i
> 0; i
--)
5192 if (buf
[i
- 1] == '/')
5194 grub_env_set(args
[1], buf
+ i
);
5199 grub_env_set(args
[1], buf
);
5204 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5206 struct grub_video_mode_info info
;
5213 if (!g_video_mode_list
)
5215 ventoy_enum_video_mode();
5218 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5220 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
5224 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
5227 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
5229 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
5230 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
5232 VENTOY_CMD_RETURN(0);
5235 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5237 struct grub_video_mode_info info
;
5244 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
5246 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
5250 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
5253 grub_env_set(args
[0], buf
);
5255 VENTOY_CMD_RETURN(0);
5258 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5266 if (!g_video_mode_list
)
5271 id
= (int)grub_strtoul(args
[0], NULL
, 10);
5272 if (id
< g_video_mode_num
)
5274 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
5275 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
5278 grub_env_set(args
[1], buf
);
5280 VENTOY_CMD_RETURN(0);
5283 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5286 grub_uint32_t loadsector
= 0;
5289 grub_uint32_t boot_catlog
= 0;
5290 grub_uint8_t buf
[512];
5296 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
5300 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5303 debug("failed to open %s\n", args
[0]);
5307 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5308 if (boot_catlog
== 0)
5310 debug("No bootcatlog found\n");
5311 grub_file_close(file
);
5315 grub_memset(buf
, 0, sizeof(buf
));
5316 grub_file_seek(file
, boot_catlog
* 2048);
5317 grub_file_read(file
, buf
, sizeof(buf
));
5318 grub_file_close(file
);
5320 for (i
= 0; i
< sizeof(buf
); i
+= 32)
5322 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
5324 if (buf
[i
+ 32] == 0x88)
5326 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
5327 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
5333 if (loadsector
== 0)
5335 debug("No EFI eltorito info found\n");
5339 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
5340 grub_env_set(args
[1], value
);
5341 VENTOY_CMD_RETURN(0);
5344 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5349 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
5351 if (pfsdir
->initrd
[0])
5356 curpos
= pfsdir
->curpos
;
5357 len
= grub_strlen(filename
);
5361 if ((len
== 1 && filename
[0] == '.') ||
5362 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
5367 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5370 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
5371 pfsdir
->curpos
= curpos
+ printlen
;
5372 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
5373 pfsdir
->curpos
= curpos
;
5374 pfsdir
->fullpath
[curpos
] = 0;
5378 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5381 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5382 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
5384 if (info
->size
> 32 * VTOY_SIZE_1MB
)
5386 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
5395 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5399 char *device_name
= NULL
;
5400 grub_device_t dev
= NULL
;
5401 grub_fs_t fs
= NULL
;
5402 replace_fs_dir
*pfsdir
= NULL
;
5408 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
5412 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
5418 device_name
= grub_file_get_device_name(args
[0]);
5424 dev
= grub_device_open(device_name
);
5430 fs
= grub_fs_probe(dev
);
5439 pfsdir
->fullpath
[0] = '/';
5440 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
5442 if (pfsdir
->initrd
[0])
5444 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
5446 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
5448 if (pfsdir
->initrd
[i
] == '/')
5450 pfsdir
->initrd
[i
] = '\\';
5454 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
5455 grub_env_set(args
[1], pos
);
5459 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
5464 grub_check_free(pfsdir
);
5465 grub_check_free(device_name
);
5466 check_free(dev
, grub_device_close
);
5468 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5471 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5473 const char *pager
= NULL
;
5479 pager
= grub_env_get("pager");
5483 grub_env_set("pager", "1");
5485 else if (pager
[0] == '1')
5491 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
5493 grub_env_set("pager", "1");
5496 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5499 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5505 if (g_pager_flag
== 1)
5507 grub_env_unset("pager");
5509 else if (g_pager_flag
== 2)
5511 grub_env_set("pager", g_old_pager
);
5514 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5517 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5519 if (g_json_case_mis_path
[0])
5524 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
5526 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
5532 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
5535 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
5537 if (g_json_case_mis_path
[0])
5542 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
5544 if (grub_strcasecmp(filename
, "ventoy") == 0)
5546 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
5547 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
5548 if (g_json_case_mis_path
[0])
5558 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5561 char *device_name
= NULL
;
5562 grub_device_t dev
= NULL
;
5563 grub_fs_t fs
= NULL
;
5564 chk_case_fs_dir fs_dir
;
5570 device_name
= grub_file_get_device_name(args
[0]);
5576 dev
= grub_device_open(device_name
);
5582 fs
= grub_fs_probe(dev
);
5588 fstype
= ventoy_get_fs_type(fs
->name
);
5589 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
5594 g_json_case_mis_path
[0] = 0;
5597 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
5599 if (g_json_case_mis_path
[0])
5601 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
5606 grub_check_free(device_name
);
5607 check_free(dev
, grub_device_close
);
5609 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5612 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5615 grub_partition_t part
;
5616 char priority_str
[3]; /* Maximum value 15 */
5620 if (argc
< 2 || argc
> 3)
5621 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5622 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5624 /* Open the disk if it exists */
5625 disk
= grub_disk_open (args
[0]);
5628 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5632 part
= grub_partition_probe (disk
, args
[1]);
5635 grub_disk_close (disk
);
5636 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5637 "No such partition");
5640 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5642 grub_disk_close (disk
);
5643 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5644 "Not a GPT partition");
5647 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5648 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5652 grub_env_set (args
[2], priority_str
);
5653 grub_env_export (args
[2]);
5657 grub_printf ("Priority is %s\n", priority_str
);
5660 grub_disk_close (disk
);
5661 return GRUB_ERR_NONE
;
5665 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5669 grub_file_t file
= NULL
;
5670 grub_uint32_t loadrba
= 0;
5671 grub_uint32_t boot_catlog
= 0;
5672 grub_uint8_t sector
[512];
5673 boot_info_table
*info
= NULL
;
5678 /* This also trigger a iso9660 fs parse */
5679 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5684 joliet
= grub_iso9660_is_joliet();
5690 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5693 debug("failed to open %s\n", args
[0]);
5697 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5698 if (boot_catlog
== 0)
5700 debug("no bootcatlog found %u\n", boot_catlog
);
5704 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5707 debug("no bios eltorito rba found %u\n", loadrba
);
5711 grub_file_seek(file
, loadrba
* 2048);
5712 grub_file_read(file
, sector
, 512);
5714 info
= (boot_info_table
*)sector
;
5715 if (info
->bi_data0
== 0x7c6ceafa &&
5716 info
->bi_data1
== 0x90900000 &&
5717 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5718 info
->bi_BootFileLocation
== loadrba
)
5720 debug("bootloader is syslinux, %u.\n", loadrba
);
5726 grub_file_close(file
);
5727 grub_errno
= GRUB_ERR_NONE
;
5731 static grub_err_t
grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5734 ventoy_vlnk_part
*node
;
5740 for (node
= g_vlnk_part_list
; node
; node
= node
->next
)
5742 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5743 ++n
, node
->device
, node
->disksig
,
5744 (ulonglong
)node
->partoffset
, (node
->fs
? node
->fs
->name
: "N/A"));
5750 static grub_err_t
grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5758 len
= (int)grub_strlen(args
[0]);
5759 if (grub_file_is_vlnk_suffix(args
[0], len
))
5768 static grub_err_t
grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5771 const char *name
= NULL
;
5777 grub_env_unset(args
[1]);
5778 name
= grub_file_get_vlnk(args
[0], &vlnk
);
5781 debug("VLNK SRC: <%s>\n", args
[0]);
5782 debug("VLNK DST: <%s>\n", name
);
5783 grub_env_set(args
[1], name
);
5791 static grub_err_t
grub_cmd_check_vlnk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5795 grub_file_t file
= NULL
;
5806 len
= (int)grub_strlen(args
[0]);
5807 if (!grub_file_is_vlnk_suffix(args
[0], len
))
5809 grub_printf("Invalid vlnk suffix\n");
5813 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
| GRUB_FILE_TYPE_NO_VLNK
);
5816 grub_printf("Failed to open %s\n", args
[0]);
5820 if (file
->size
!= 32768)
5822 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong
)file
->size
);
5826 grub_memset(&vlnk
, 0, sizeof(vlnk
));
5827 grub_file_read(file
, &vlnk
, sizeof(vlnk
));
5829 ret
= ventoy_check_vlnk_data(&vlnk
, 1, dst
, sizeof(dst
));
5834 check_free(file
, grub_file_close
);
5835 grub_errno
= GRUB_ERR_NONE
;
5839 static grub_err_t
ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5845 g_iso_vd_id_publisher
[0] = 0;
5846 g_iso_vd_id_prepare
[0] = 0;
5847 g_iso_vd_id_application
[0] = 0;
5852 static grub_err_t
ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5856 grub_file_t file
= NULL
;
5861 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5864 grub_printf("Failed to open %s\n", args
[0]);
5868 grub_file_seek(file
, 16 * 2048 + offset
);
5869 grub_file_read(file
, g_iso_vd_id_publisher
, 128);
5872 grub_file_seek(file
, 16 * 2048 + offset
);
5873 grub_file_read(file
, g_iso_vd_id_prepare
, 128);
5876 grub_file_seek(file
, 16 * 2048 + offset
);
5877 grub_file_read(file
, g_iso_vd_id_application
, 128);
5881 check_free(file
, grub_file_close
);
5882 grub_errno
= GRUB_ERR_NONE
;
5886 static grub_err_t
ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5889 char *id
= g_iso_vd_id_publisher
;
5894 if (args
[0][0] == '1')
5896 id
= g_iso_vd_id_prepare
;
5898 else if (args
[0][0] == '2')
5900 id
= g_iso_vd_id_application
;
5903 if (args
[1][0] == '0' && grub_strncasecmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5908 if (args
[1][0] == '1' && grub_strncmp(id
, args
[2], grub_strlen(args
[2])) == 0)
5913 grub_errno
= GRUB_ERR_NONE
;
5917 static grub_err_t
ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5922 g_ventoy_fn_mutex
= 0;
5923 if (argc
== 1 && args
[0][0] == '1' && args
[0][1] == 0)
5925 g_ventoy_fn_mutex
= 1;
5928 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5931 static grub_err_t
ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5933 grub_uint64_t total
;
5934 grub_uint64_t org_required
;
5935 grub_uint64_t new_required
;
5941 #ifdef GRUB_MACHINE_EFI
5942 grub_efi_get_reserved_page_num(&total
, &org_required
, &new_required
);
5943 grub_printf("Total pages: %llu\n", (unsigned long long)total
);
5944 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required
);
5945 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required
);
5950 grub_printf("Non EFI mode!\n");
5955 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
5958 int ventoy_env_init(void)
5963 grub_env_set("vtdebug_flag", "");
5965 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5966 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5967 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5968 for (i
= 0; i
< VTOY_MAX_CONF_REPLACE
; i
++)
5970 g_conf_replace_new_buf
[i
] = grub_malloc(vtoy_max_replace_file_size
);
5973 ventoy_filt_register(0, ventoy_wrapper_open
);
5975 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5978 g_grub_param
->grub_env_get
= grub_env_get
;
5979 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5980 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5981 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5982 grub_env_set("env_param", buf
);
5983 grub_env_set("ventoy_env_param", buf
);
5985 grub_env_export("env_param");
5986 grub_env_export("ventoy_env_param");
5989 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5990 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5992 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5993 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5995 grub_env_export("vtoy_winpeshl_ini_addr");
5996 grub_env_export("vtoy_winpeshl_ini_size");
5998 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5999 grub_env_set("vtoy_chain_file_size", buf
);
6000 grub_env_export("vtoy_chain_file_size");
6002 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
6003 grub_env_set("vtoy_chain_file_read", buf
);
6004 grub_env_export("vtoy_chain_file_read");
6011 static cmd_para ventoy_cmds
[] =
6013 { "vt_browser_disk", ventoy_cmd_browser_disk
, 0, NULL
, "", "", NULL
},
6014 { "vt_browser_dir", ventoy_cmd_browser_dir
, 0, NULL
, "", "", NULL
},
6015 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
6016 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
6017 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
6018 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
6019 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
6020 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6021 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
6022 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
6023 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
6024 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
6025 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
6026 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
6027 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
6028 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
6029 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
6030 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
6031 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
6032 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
6033 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
6034 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
6035 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
6036 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
6037 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
6038 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
6039 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
6041 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
6042 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
6043 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
6044 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
6045 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
6046 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
6047 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
6049 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
6050 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
6051 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
6052 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
6053 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
6054 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
6055 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
6056 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
6057 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
6058 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
6061 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
6062 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
6063 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
6064 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
6065 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
6066 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
6067 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
6068 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
6069 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
6070 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
6071 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
6073 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
6074 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
6075 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
6076 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
6077 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
6078 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
6079 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
6081 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6082 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
6083 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
6084 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
6085 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
6086 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
6087 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
6088 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
6089 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
6090 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
6092 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
6093 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
6094 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
6095 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
6096 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
6097 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
6098 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
6099 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
6100 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
6102 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
6103 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
6104 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
6105 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
6108 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
6109 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
6110 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
6112 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
6113 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
6114 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
6117 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
6118 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
6119 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
6120 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
6121 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
6122 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
6123 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk
, 0, NULL
, "", "", NULL
},
6124 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
6125 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf
, 0, NULL
, "", "", NULL
},
6126 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
6127 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap
, 0, NULL
, "", "", NULL
},
6128 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
6129 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
6130 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
6132 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
6133 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
6134 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
6135 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
6136 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
6137 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
6138 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
6139 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
6140 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
6141 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
6142 { "vt_set_theme_path", ventoy_cmd_set_theme_path
, 0, NULL
, "", "", NULL
},
6143 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg
, 0, NULL
, "", "", NULL
},
6145 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
6146 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
6147 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
6148 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
6149 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
6150 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
6151 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
6152 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
6153 { "vt_vlnk_check", grub_cmd_check_vlnk
, 0, NULL
, "", "", NULL
},
6154 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part
, 0, NULL
, "", "", NULL
},
6155 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name
, 0, NULL
, "", "", NULL
},
6156 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst
, 0, NULL
, "", "", NULL
},
6157 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk
, 0, NULL
, "", "", NULL
},
6158 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk
, 0, NULL
, "", "", NULL
},
6159 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse
, 0, NULL
, "", "", NULL
},
6160 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear
, 0, NULL
, "", "", NULL
},
6161 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin
, 0, NULL
, "", "", NULL
},
6162 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock
, 0, NULL
, "", "", NULL
},
6163 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page
, 0, NULL
, "", "", NULL
},
6166 int ventoy_register_all_cmd(void)
6169 cmd_para
*cur
= NULL
;
6171 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6173 cur
= ventoy_cmds
+ i
;
6174 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
6175 cur
->summary
, cur
->description
, cur
->parser
);
6181 int ventoy_unregister_all_cmd(void)
6185 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
6187 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);