1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 static grub_uint8_t g_check_mbr_data
[440] = {
55 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFA, 0x90, 0x90, 0xF6, 0xC2, 0x80, 0x74, 0x05, 0xF6, 0xC2, 0x70,
62 0x74, 0x02, 0xB2, 0x80, 0xEA, 0x79, 0x7C, 0x00, 0x00, 0x31, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC,
63 0x00, 0x20, 0xFB, 0xA0, 0x64, 0x7C, 0x3C, 0xFF, 0x74, 0x02, 0x88, 0xC2, 0x52, 0xBE, 0x90, 0x7D,
64 0xE8, 0x16, 0x01, 0xBE, 0x05, 0x7C, 0xB4, 0x41, 0xBB, 0xAA, 0x55, 0xCD, 0x13, 0x5A, 0x52, 0x72,
65 0x3D, 0x81, 0xFB, 0x55, 0xAA, 0x75, 0x37, 0x83, 0xE1, 0x01, 0x74, 0x32, 0x31, 0xC0, 0x89, 0x44,
66 0x04, 0x40, 0x88, 0x44, 0xFF, 0x89, 0x44, 0x02, 0xC7, 0x04, 0x10, 0x00, 0x66, 0x8B, 0x1E, 0x5C,
67 0x7C, 0x66, 0x89, 0x5C, 0x08, 0x66, 0x8B, 0x1E, 0x60, 0x7C, 0x66, 0x89, 0x5C, 0x0C, 0xC7, 0x44,
68 0x06, 0x00, 0x70, 0xB4, 0x42, 0xCD, 0x13, 0x72, 0x05, 0xBB, 0x00, 0x70, 0xEB, 0x76, 0xB4, 0x08,
69 0xCD, 0x13, 0x73, 0x0D, 0x5A, 0x84, 0xD2, 0x0F, 0x83, 0xD8, 0x00, 0xBE, 0x96, 0x7D, 0xE9, 0x82,
70 0x00, 0x66, 0x0F, 0xB6, 0xC6, 0x88, 0x64, 0xFF, 0x40, 0x66, 0x89, 0x44, 0x04, 0x0F, 0xB6, 0xD1,
71 0xC1, 0xE2, 0x02, 0x88, 0xE8, 0x88, 0xF4, 0x40, 0x89, 0x44, 0x08, 0x0F, 0xB6, 0xC2, 0xC0, 0xE8,
72 0x02, 0x66, 0x89, 0x04, 0x66, 0xA1, 0x60, 0x7C, 0x66, 0x09, 0xC0, 0x75, 0x4E, 0x66, 0xA1, 0x5C,
73 0x7C, 0x66, 0x31, 0xD2, 0x66, 0xF7, 0x34, 0x88, 0xD1, 0x31, 0xD2, 0x66, 0xF7, 0x74, 0x04, 0x3B,
74 0x44, 0x08, 0x7D, 0x37, 0xFE, 0xC1, 0x88, 0xC5, 0x30, 0xC0, 0xC1, 0xE8, 0x02, 0x08, 0xC1, 0x88,
75 0xD0, 0x5A, 0x88, 0xC6, 0xBB, 0x00, 0x70, 0x8E, 0xC3, 0x31, 0xDB, 0xB8, 0x01, 0x02, 0xCD, 0x13,
76 0x72, 0x1E, 0x8C, 0xC3, 0x60, 0x1E, 0xB9, 0x00, 0x01, 0x8E, 0xDB, 0x31, 0xF6, 0xBF, 0x00, 0x80,
77 0x8E, 0xC6, 0xFC, 0xF3, 0xA5, 0x1F, 0x61, 0xFF, 0x26, 0x5A, 0x7C, 0xBE, 0x93, 0x7D, 0xEB, 0x03,
78 0xBE, 0x99, 0x7D, 0xE8, 0x33, 0x00, 0xBE, 0x9C, 0x7D, 0xE8, 0x2D, 0x00, 0xCD, 0x18, 0xEB, 0xFE,
79 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
80 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
81 0x0A, 0x00, 0xBB, 0x01, 0x00, 0xB4, 0x0E, 0xCD, 0x10, 0xAC, 0x3C, 0x00, 0x75, 0xF4, 0xC3, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
85 initrd_info
*g_initrd_img_list
= NULL
;
86 initrd_info
*g_initrd_img_tail
= NULL
;
87 int g_initrd_img_count
= 0;
88 int g_valid_initrd_count
= 0;
89 int g_default_menu_mode
= 0;
90 int g_filt_dot_underscore_file
= 0;
91 int g_sort_case_sensitive
= 0;
92 int g_tree_view_menu_style
= 0;
93 static grub_file_t g_old_file
;
94 static int g_ventoy_last_entry_back
;
97 char g_img_swap_tmp_buf
[1024];
98 img_info g_img_swap_tmp
;
99 img_info
*g_ventoy_img_list
= NULL
;
101 int g_ventoy_img_count
= 0;
103 grub_device_t g_enum_dev
= NULL
;
104 grub_fs_t g_enum_fs
= NULL
;
105 int g_img_max_search_level
= -1;
106 img_iterator_node g_img_iterator_head
;
107 img_iterator_node
*g_img_iterator_tail
= NULL
;
109 grub_uint8_t g_ventoy_break_level
= 0;
110 grub_uint8_t g_ventoy_debug_level
= 0;
111 grub_uint8_t g_ventoy_chain_type
= 0;
113 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
114 grub_uint32_t g_ventoy_cpio_size
= 0;
115 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
116 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
118 int g_plugin_image_list
= 0;
120 ventoy_grub_param
*g_grub_param
= NULL
;
122 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
124 ventoy_img_chunk_list g_img_chunk_list
;
126 int g_wimboot_enable
= 0;
127 ventoy_img_chunk_list g_wimiso_chunk_list
;
128 char *g_wimiso_path
= NULL
;
130 int g_vhdboot_enable
= 0;
132 grub_uint64_t g_conf_replace_offset
= 0;
133 grub_uint64_t g_svd_replace_offset
= 0;
134 conf_replace
*g_conf_replace_node
= NULL
;
135 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
136 int g_conf_replace_new_len
= 0;
137 int g_conf_replace_new_len_align
= 0;
139 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
140 grub_uint64_t g_ventoy_disk_size
= 0;
141 grub_uint64_t g_ventoy_disk_part_size
[2];
143 static char *g_tree_script_buf
= NULL
;
144 static int g_tree_script_pos
= 0;
146 static char *g_list_script_buf
= NULL
;
147 static int g_list_script_pos
= 0;
149 static char *g_part_list_buf
= NULL
;
150 static int g_part_list_pos
= 0;
152 static int g_video_mode_max
= 0;
153 static int g_video_mode_num
= 0;
154 static ventoy_video_mode
*g_video_mode_list
= NULL
;
156 static int g_enumerate_time_checked
= 0;
157 static grub_uint64_t g_enumerate_start_time_ms
;
158 static grub_uint64_t g_enumerate_finish_time_ms
;
159 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
161 static int g_pager_flag
= 0;
162 static char g_old_pager
[32];
164 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
166 static const char *g_menu_class
[] =
168 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
171 const char *g_menu_prefix
[img_type_max
] =
173 "iso", "wim", "efi", "img", "vhd", "vtoy"
176 static int g_vtoy_load_prompt
= 0;
177 static char g_vtoy_prompt_msg
[64];
179 static char g_json_case_mis_path
[32];
181 static int ventoy_get_fs_type(const char *fs
)
185 return ventoy_fs_max
;
187 else if (grub_strncmp(fs
, "exfat", 5) == 0)
189 return ventoy_fs_exfat
;
191 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
193 return ventoy_fs_ntfs
;
195 else if (grub_strncmp(fs
, "ext", 3) == 0)
197 return ventoy_fs_ext
;
199 else if (grub_strncmp(fs
, "xfs", 3) == 0)
201 return ventoy_fs_xfs
;
203 else if (grub_strncmp(fs
, "udf", 3) == 0)
205 return ventoy_fs_udf
;
207 else if (grub_strncmp(fs
, "fat", 3) == 0)
209 return ventoy_fs_fat
;
212 return ventoy_fs_max
;
215 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
234 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
236 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
240 static int ventoy_control_get_flag(const char *key
)
242 const char *val
= ventoy_get_env(key
);
244 if (val
&& val
[0] == '1' && val
[1] == 0)
251 static grub_err_t
ventoy_fs_close(grub_file_t file
)
253 grub_file_close(g_old_file
);
254 grub_free(file
->data
);
262 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
268 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
273 for (i
= 0; i
< g_video_mode_num
; i
++)
275 if (g_video_mode_list
[i
].width
== info
->width
&&
276 g_video_mode_list
[i
].height
== info
->height
&&
277 g_video_mode_list
[i
].bpp
== info
->bpp
)
283 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
284 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
285 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
288 if (g_video_mode_num
== g_video_mode_max
)
290 g_video_mode_max
*= 2;
291 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
297 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
299 if (v1
->bpp
== v2
->bpp
)
301 if (v1
->width
== v2
->width
)
303 if (v1
->height
== v2
->height
)
309 return (v1
->height
< v2
->height
) ? -1 : 1;
314 return (v1
->width
< v2
->width
) ? -1 : 1;
319 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
323 static int ventoy_enum_video_mode(void)
326 grub_video_adapter_t adapter
;
327 grub_video_driver_id_t id
;
328 ventoy_video_mode mode
;
330 g_video_mode_num
= 0;
331 g_video_mode_max
= 1024;
332 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
333 if (!g_video_mode_list
)
338 #ifdef GRUB_MACHINE_PCBIOS
339 grub_dl_load ("vbe");
342 id
= grub_video_get_driver_id ();
344 FOR_VIDEO_ADAPTERS (adapter
)
346 if (!adapter
->iterate
||
347 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
348 adapter
->init() != GRUB_ERR_NONE
)))
353 adapter
->iterate(ventoy_video_hook
, NULL
);
355 if (adapter
->id
!= id
)
361 /* sort video mode */
362 for (i
= 0; i
< g_video_mode_num
; i
++)
363 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
365 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
367 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
368 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
369 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
373 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
376 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
380 static struct grub_fs vtoy_fs
=
385 .fs_read
= ventoy_fs_read
,
386 .fs_close
= ventoy_fs_close
,
396 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
402 file
->data
= grub_malloc(rawFile
->size
+ 4096);
408 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
409 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
411 g_old_file
= rawFile
;
413 file
->size
= rawFile
->size
+ len
;
414 file
->device
= rawFile
->device
;
416 file
->not_easily_seekable
= 1;
421 static int ventoy_check_decimal_var(const char *name
, long *value
)
423 const char *value_str
= NULL
;
425 value_str
= grub_env_get(name
);
426 if (NULL
== value_str
)
428 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
431 if (!ventoy_is_decimal(value_str
))
433 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
436 *value
= grub_strtol(value_str
, NULL
, 10);
438 return GRUB_ERR_NONE
;
441 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
443 grub_uint64_t sectors
;
445 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
447 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
451 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
454 return sectors
* 512;
457 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
463 grub_uint32_t offset
;
465 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
468 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
472 len
= (int)file
->size
;
474 data
= (char *)grub_malloc(file
->size
);
480 grub_file_read(file
, data
, file
->size
);
481 grub_file_close(file
);
483 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
484 grub_script_execute_sourcecode(exec
);
486 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
487 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
488 grub_file_close(file
);
490 grub_script_execute_sourcecode("loopback -d efiboot");
494 *direntoff
= offset
+ 2;
499 static int ventoy_set_check_result(int ret
)
503 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
504 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
505 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
509 grub_printf(VTOY_WARNING
"\n");
510 grub_printf(VTOY_WARNING
"\n");
511 grub_printf(VTOY_WARNING
"\n\n\n");
513 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
514 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
516 grub_printf("\n\nWill exit after 10 seconds ...... ");
524 static int ventoy_check_official_device(grub_device_t dev
)
528 grub_uint64_t offset
;
531 grub_uint8_t mbr
[512];
535 struct grub_partition
*partition
;
537 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
539 return ventoy_set_check_result(1 | 0x1000);
542 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
543 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
544 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
546 #ifndef GRUB_MACHINE_EFI
547 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
548 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
549 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
551 return ventoy_set_check_result(2 | 0x1000);
560 /* We must have partition 2 */
563 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
567 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
571 return ventoy_set_check_result(3 | 0x1000);
574 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
576 grub_file_close(file
);
577 return ventoy_set_check_result(4 | 0x1000);
580 partition
= dev
->disk
->partition
;
581 if (partition
->number
!= 0 || partition
->start
!= 2048)
583 return ventoy_set_check_result(5);
588 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
590 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
591 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
592 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
594 grub_file_close(file
);
595 return ventoy_set_check_result(6);
600 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
601 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
602 PartTbl
[1].SectorCount
!= 65536)
604 grub_file_close(file
);
605 return ventoy_set_check_result(6);
611 offset
= partition
->start
+ partition
->len
;
612 partition
= file
->device
->disk
->partition
;
613 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
615 grub_file_close(file
);
616 return ventoy_set_check_result(7);
620 grub_file_close(file
);
624 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
625 dev2
= grub_device_open(devname
);
628 return ventoy_set_check_result(8);
631 fs
= grub_fs_probe(dev2
);
634 grub_device_close(dev2
);
635 return ventoy_set_check_result(9);
638 fs
->fs_label(dev2
, &label
);
639 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
641 grub_device_close(dev2
);
642 return ventoy_set_check_result(10);
645 grub_device_close(dev2
);
649 disk
= grub_disk_open(dev
->disk
->name
);
652 return ventoy_set_check_result(11);
655 grub_memset(mbr
, 0, 512);
656 grub_disk_read(disk
, 0, 0, 512, mbr
);
657 grub_disk_close(disk
);
659 g_check_mbr_data
[92] = mbr
[92];
660 g_check_mbr_data
[102] = mbr
[102];
661 g_check_mbr_data
[103] = mbr
[103];
662 grub_memcpy(g_check_mbr_data
+ 0x180, mbr
+ 0x180, 16);
663 if (grub_memcmp(g_check_mbr_data
, mbr
, 440))
665 return ventoy_set_check_result(12);
668 return ventoy_set_check_result(0);
671 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
675 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
685 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
687 grub_uint64_t size
= 0;
690 char fullpath
[256] = {0};
693 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
696 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
699 debug("grub_file_open failed <%s>\n", fullpath
);
705 grub_file_close(file
);
709 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
713 char fullpath
[256] = {0};
716 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
719 file
= grub_file_open(fullpath
, type
);
722 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
729 int ventoy_is_file_exist(const char *fmt
, ...)
736 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
740 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
743 grub_strncpy(pos
+ len
, "\" ]", 3);
745 debug("script exec %s\n", buf
);
747 if (0 == grub_script_execute_sourcecode(buf
))
755 int ventoy_is_dir_exist(const char *fmt
, ...)
762 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
766 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
769 grub_strncpy(pos
+ len
, "\" ]", 3);
771 debug("script exec %s\n", buf
);
773 if (0 == grub_script_execute_sourcecode(buf
))
781 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
784 grub_uint8_t
*outbuf
;
785 grub_uint8_t gzHdr
[10] =
787 0x1F, 0x8B, /* magic */
795 grub_memset(&s
, 0, sizeof(mz_stream
));
797 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
799 outbuf
= (grub_uint8_t
*)mem_out
;
801 mem_out_len
-= sizeof(gzHdr
) + 8;
802 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
803 outbuf
+= sizeof(gzHdr
);
805 s
.avail_in
= mem_in_len
;
808 s
.avail_out
= mem_out_len
;
811 mz_deflate(&s
, MZ_FINISH
);
815 outbuf
+= s
.total_out
;
816 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
817 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
819 return s
.total_out
+ sizeof(gzHdr
) + 8;
827 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
831 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
834 if (0 == grub_strcmp(args
[0], "on"))
837 grub_env_set("vtdebug_flag", "debug");
842 grub_env_set("vtdebug_flag", "");
845 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
848 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
852 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
854 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
855 grub_printf(" level:\r\n");
856 grub_printf(" 01/11: busybox / (+cat log)\r\n");
857 grub_printf(" 02/12: initrd / (+cat log)\r\n");
858 grub_printf(" 03/13: hook / (+cat log)\r\n");
860 grub_printf(" debug:\r\n");
861 grub_printf(" 0: debug is off\r\n");
862 grub_printf(" 1: debug is on\r\n");
864 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
867 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
869 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
871 g_ventoy_debug_level
= 1;
874 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
877 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
886 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
889 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
921 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
937 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
953 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
958 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
960 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
963 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
968 value_long
+= grub_strtol(args
[1], NULL
, 10);
970 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
971 grub_env_set(args
[0], buf
);
973 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
976 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
978 ulonglong value1
= 0;
979 ulonglong value2
= 0;
984 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
987 value1
= grub_strtoull(args
[0], NULL
, 10);
988 value2
= grub_strtoull(args
[1], NULL
, 10);
990 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
991 grub_env_set(args
[2], buf
);
993 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
996 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1011 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1014 debug("failed to open file <%s> for udf check\n", args
[0]);
1018 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
1020 grub_env_set(args
[1], buf
);
1022 grub_file_close(file
);
1028 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1036 g_wimboot_enable
= 0;
1037 grub_check_free(g_wimiso_path
);
1038 grub_check_free(g_wimiso_chunk_list
.chunk
);
1040 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1046 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1047 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1048 if (NULL
== g_wimiso_chunk_list
.chunk
)
1050 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1053 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1054 g_wimiso_chunk_list
.cur_chunk
= 0;
1056 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1058 g_wimboot_enable
= 1;
1059 g_wimiso_path
= grub_strdup(args
[0]);
1061 grub_file_close(file
);
1066 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1076 ventoy_iso9660_override
*dirent
;
1085 totlen
= sizeof(ventoy_chain_head
);
1087 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1089 debug("failed to load efiboot template %d\n", len
);
1095 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1097 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1100 debug("failed to open file <%s>\n", args
[0]);
1104 totlen
+= ventoy_align_2k(file
->size
);
1106 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1107 dirent
->first_sector
= len
/ 2048;
1108 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1109 dirent
->size
= (grub_uint32_t
)file
->size
;
1110 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1112 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1114 #ifdef GRUB_MACHINE_EFI
1115 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1117 data
= (char *)grub_malloc(totlen
);
1120 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1122 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1123 grub_check_free(buf
);
1125 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1126 grub_file_close(file
);
1128 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1129 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1130 grub_env_set(name
, value
);
1132 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1133 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1134 grub_env_set(name
, value
);
1139 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1145 g_vtoy_load_prompt
= 0;
1146 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1148 if (argc
== 2 && args
[0][0] == '1')
1150 g_vtoy_load_prompt
= 1;
1151 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1154 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1157 int ventoy_need_prompt_load_file(void)
1159 return g_vtoy_load_prompt
;
1162 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1164 grub_uint64_t ro
= 0;
1165 grub_uint64_t div
= 0;
1166 grub_ssize_t left
= size
;
1167 char *cur
= (char *)buf
;
1169 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1172 while (left
>= VTOY_SIZE_2MB
)
1174 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1175 cur
+= VTOY_SIZE_2MB
;
1176 left
-= VTOY_SIZE_2MB
;
1178 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1179 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1185 grub_file_read(file
, cur
, left
);
1188 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1194 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1201 enum grub_file_type type
;
1212 if (grub_strcmp(args
[0], "nodecompress") == 0)
1214 type
= VENTOY_FILE_TYPE
;
1218 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1221 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1224 debug("failed to open file <%s>\n", args
[1]);
1228 #ifdef GRUB_MACHINE_EFI
1229 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1231 buf
= (char *)grub_malloc(file
->size
);
1236 grub_file_close(file
);
1240 if (g_vtoy_load_prompt
)
1242 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1246 grub_file_read(file
, buf
, file
->size
);
1249 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1250 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1251 grub_env_set(name
, value
);
1253 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1254 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1255 grub_env_set(name
, value
);
1257 grub_file_close(file
);
1263 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1281 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1284 debug("failed to open file <%s> for udf check\n", args
[0]);
1288 headlen
= sizeof(ventoy_chain_head
);
1290 #ifdef GRUB_MACHINE_EFI
1291 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1293 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1296 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1298 grub_file_read(file
, buf
+ headlen
, file
->size
);
1300 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1301 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1302 grub_env_set(name
, value
);
1304 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1305 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1306 grub_env_set(name
, value
);
1308 grub_file_close(file
);
1314 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1320 if (grub_iso9660_is_joliet())
1322 debug("This time has joliet process\n");
1331 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1340 if (args
[0][0] == '1')
1342 grub_iso9660_set_nojoliet(1);
1346 grub_iso9660_set_nojoliet(0);
1352 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1357 grub_uint8_t buf
[32];
1368 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1371 debug("failed to open file <%s> for udf check\n", args
[0]);
1375 for (i
= 16; i
< 32; i
++)
1377 grub_file_seek(file
, i
* 2048);
1378 grub_file_read(file
, buf
, sizeof(buf
));
1386 grub_file_seek(file
, i
* 2048);
1387 grub_file_read(file
, buf
, sizeof(buf
));
1389 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1392 grub_file_seek(file
, i
* 2048);
1393 grub_file_read(file
, buf
, sizeof(buf
));
1395 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1396 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1402 grub_file_close(file
);
1404 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1409 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1411 long value_long1
= 0;
1412 long value_long2
= 0;
1414 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1416 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1419 value_long1
= grub_strtol(args
[0], NULL
, 10);
1420 value_long2
= grub_strtol(args
[2], NULL
, 10);
1422 if (0 == grub_strcmp(args
[1], "eq"))
1424 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1426 else if (0 == grub_strcmp(args
[1], "ne"))
1428 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1430 else if (0 == grub_strcmp(args
[1], "gt"))
1432 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1434 else if (0 == grub_strcmp(args
[1], "lt"))
1436 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1438 else if (0 == grub_strcmp(args
[1], "ge"))
1440 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1442 else if (0 == grub_strcmp(args
[1], "le"))
1444 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1448 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1454 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1457 char buf
[128] = {0};
1461 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1464 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1465 pos
= grub_strstr(buf
, ",");
1471 grub_env_set(args
[1], buf
);
1473 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1476 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1482 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1488 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1491 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1493 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1494 if (0 == grub_script_execute_sourcecode(buf
))
1496 debug("file %s exist, ventoy_compatible YES\n", buf
);
1497 grub_env_set("ventoy_compatible", "YES");
1498 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1502 debug("file %s NOT exist\n", buf
);
1506 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1507 pos
= grub_strstr(buf
, ")");
1513 disk
= grub_disk_open(buf
);
1516 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1517 grub_disk_close(disk
);
1519 g_img_swap_tmp_buf
[703] = 0;
1520 for (i
= 318; i
< 703; i
++)
1522 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1523 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1525 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1526 grub_env_set("ventoy_compatible", "YES");
1527 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1533 debug("failed to open disk <%s>\n", buf
);
1536 grub_env_set("ventoy_compatible", "NO");
1537 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1540 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1546 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1548 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1551 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1556 if (0 == g_sort_case_sensitive
)
1558 if (grub_islower(c1
))
1560 c1
= c1
- 'a' + 'A';
1563 if (grub_islower(c2
))
1565 c2
= c2
- 'a' + 'A';
1578 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1584 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1586 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1589 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1594 if (0 == g_sort_case_sensitive
)
1596 if (grub_islower(c1
))
1598 c1
= c1
- 'a' + 'A';
1601 if (grub_islower(c2
))
1603 c2
= c2
- 'a' + 'A';
1616 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1618 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1620 grub_memcpy(img1
, img2
, sizeof(img_info
));
1621 img1
->next
= g_img_swap_tmp
.next
;
1622 img1
->prev
= g_img_swap_tmp
.prev
;
1624 g_img_swap_tmp
.next
= img2
->next
;
1625 g_img_swap_tmp
.prev
= img2
->prev
;
1626 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1629 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1633 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1641 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1650 const menu_tip
*tip
;
1651 img_iterator_node
*tmp
;
1652 img_iterator_node
*new_node
;
1653 img_iterator_node
*node
= (img_iterator_node
*)data
;
1655 if (g_enumerate_time_checked
== 0)
1657 g_enumerate_finish_time_ms
= grub_get_time_ms();
1658 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1661 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1663 g_enumerate_time_checked
= 1;
1667 len
= grub_strlen(filename
);
1671 if (node
->level
+ 1 > g_img_max_search_level
)
1676 if ((len
== 1 && filename
[0] == '.') ||
1677 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1682 if (!ventoy_img_name_valid(filename
, len
))
1687 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1692 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1694 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1695 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1698 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1703 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1706 new_node
->level
= node
->level
+ 1;
1707 new_node
->plugin_list_index
= index
;
1708 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1710 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1713 debug("Directory %s ignored...\n", new_node
->dir
);
1714 grub_free(new_node
);
1718 new_node
->tail
= node
->tail
;
1720 new_node
->parent
= node
;
1721 if (!node
->firstchild
)
1723 node
->firstchild
= new_node
;
1726 if (g_img_iterator_tail
)
1728 g_img_iterator_tail
->next
= new_node
;
1729 g_img_iterator_tail
= new_node
;
1733 g_img_iterator_head
.next
= new_node
;
1734 g_img_iterator_tail
= new_node
;
1740 debug("Find a file %s\n", filename
);
1746 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1748 type
= img_type_iso
;
1750 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1752 type
= img_type_wim
;
1754 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1755 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1757 type
= img_type_vhd
;
1759 #ifdef GRUB_MACHINE_EFI
1760 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1762 type
= img_type_efi
;
1765 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1767 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1769 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1770 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1775 type
= img_type_img
;
1777 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1779 type
= img_type_vtoy
;
1781 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1783 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1785 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1786 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1795 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1800 if (g_plugin_image_list
)
1802 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1803 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1804 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1806 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1809 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1811 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1816 img
= grub_zalloc(sizeof(img_info
));
1820 img
->plugin_list_index
= index
;
1821 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1823 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1825 img
->size
= info
->size
;
1828 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1831 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1833 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1838 if (g_ventoy_img_list
)
1840 tail
= *(node
->tail
);
1846 g_ventoy_img_list
= img
;
1849 img
->id
= g_ventoy_img_count
;
1851 if (node
&& NULL
== node
->firstiso
)
1853 node
->firstiso
= img
;
1864 *((img_info
**)(node
->tail
)) = img
;
1865 g_ventoy_img_count
++;
1867 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1869 tip
= ventoy_plugin_get_menu_tip(img
->path
);
1872 img
->tip1
= tip
->tip1
;
1873 img
->tip2
= tip
->tip2
;
1876 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1879 img
->class = g_menu_class
[type
];
1881 img
->menu_prefix
= g_menu_prefix
[type
];
1883 if (img_type_iso
== type
)
1885 if (ventoy_plugin_check_memdisk(img
->path
))
1887 img
->menu_prefix
= "miso";
1891 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1898 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1900 int len
= GRUB_UINT_MAX
;
1901 const char *value
= NULL
;
1902 char name
[32] = {0};
1903 char plat
[32] = {0};
1904 char guidstr
[32] = {0};
1905 ventoy_guid guid
= VENTOY_GUID
;
1906 const char *fmt1
= NULL
;
1907 const char *fmt2
= NULL
;
1908 const char *fmt3
= NULL
;
1909 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1910 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1911 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1912 const char fmtcode
[]={
1913 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1914 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1915 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1916 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1917 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1918 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1921 grub_memset(name
, 0, sizeof(name
));
1922 puint
[0] = grub_swap_bytes32(0x56454e54);
1923 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1924 puint
[2] = grub_swap_bytes32(0x45525349);
1925 puint
[1] = grub_swap_bytes32(0x4f595f56);
1926 value
= ventoy_get_env(name
);
1928 grub_memset(name
, 0, sizeof(name
));
1929 puint
[1] = grub_swap_bytes32(0x5f544f50);
1930 puint
[0] = grub_swap_bytes32(0x56544c45);
1931 fmt1
= ventoy_get_env(name
);
1937 grub_memset(name
, 0, sizeof(name
));
1938 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1939 puint
[0] = grub_swap_bytes32(0x56544c45);
1940 fmt2
= ventoy_get_env(name
);
1942 grub_memset(name
, 0, sizeof(name
));
1943 puint
[1] = grub_swap_bytes32(0x5f434c52);
1944 puint
[0] = grub_swap_bytes32(0x56544c45);
1945 fmt3
= ventoy_get_env(name
);
1947 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1949 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1951 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1952 #pragma GCC diagnostic push
1953 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1954 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1955 fmt1
? fmt1
: fmtdata
,
1956 fmt2
? fmt2
: fmtdata
+ 4,
1957 value
? value
: "", plat
, guidstr
,
1958 fmt3
? fmt3
: fmtdata
+ 6);
1959 #pragma GCC diagnostic pop
1961 grub_memset(name
, 0, sizeof(name
));
1962 puint
[0] = grub_swap_bytes32(0x76746f79);
1963 puint
[2] = grub_swap_bytes32(0x656e7365);
1964 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1965 ventoy_set_env(name
, guidstr
);
1970 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1974 grub_uint8_t md5
[16];
1978 grub_memset(input
, 0, sizeof(input
));
1980 grub_printf("Enter password: ");
1983 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1985 grub_password_get(input
, 128);
1986 if (grub_strcmp(pwd
->text
, input
) == 0)
1991 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1993 grub_password_get(input
, 128);
1994 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1995 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2000 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2002 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2003 grub_password_get(input
+ offset
, 128);
2005 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2006 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2012 grub_printf("Invalid password!\n\n");
2019 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2021 img_info
*minimg
= NULL
;
2022 img_info
*img
= (img_info
*)(node
->firstiso
);
2024 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2026 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2041 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2043 img_iterator_node
*Minchild
= NULL
;
2044 img_iterator_node
*child
= node
->firstchild
;
2046 while (child
&& child
->parent
== node
)
2048 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2052 child
= child
->next
;
2057 Minchild
->select
= 1;
2063 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2066 img_info
*img
= NULL
;
2067 const char *dir_class
= NULL
;
2068 const char *dir_alias
= NULL
;
2069 img_iterator_node
*child
= NULL
;
2071 if (node
->isocnt
== 0 || node
->done
== 1)
2076 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2078 offset
= node
->parent
->dirlen
;
2081 if (node
== &g_img_iterator_head
)
2083 if (g_default_menu_mode
== 0)
2085 if (g_tree_view_menu_style
== 0)
2087 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2088 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2089 " echo 'return ...' \n"
2094 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2095 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2103 node
->dir
[node
->dirlen
- 1] = 0;
2104 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2107 dir_class
= "vtoydir";
2110 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2113 if (g_tree_view_menu_style
== 0)
2115 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2116 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2117 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2121 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2122 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2123 dir_alias
, dir_class
, node
->dir
+ offset
);
2128 dir_alias
= node
->dir
+ offset
;
2130 if (g_tree_view_menu_style
== 0)
2132 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2133 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2134 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2138 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2139 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2140 dir_alias
, dir_class
, node
->dir
+ offset
);
2144 if (g_tree_view_menu_style
== 0)
2146 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2147 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2148 " echo 'return ...' \n"
2153 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2154 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2160 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2162 ventoy_dynamic_tree_menu(child
);
2165 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2167 if (g_tree_view_menu_style
== 0)
2169 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2170 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2173 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2174 img
->unsupport
? "[***********] " : "",
2175 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2177 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2181 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2182 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2185 img
->unsupport
? "[***********] " : "",
2186 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2188 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2192 if (node
!= &g_img_iterator_head
)
2194 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2201 static int ventoy_set_default_menu(void)
2207 const char *strdata
= NULL
;
2208 img_info
*cur
= NULL
;
2209 img_info
*default_node
= NULL
;
2210 const char *default_image
= NULL
;
2212 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2213 if (default_image
&& default_image
[0] == '/')
2215 img_len
= grub_strlen(default_image
);
2217 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2219 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2231 if (0 == g_default_menu_mode
)
2233 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2237 def
= grub_strdup(default_image
);
2243 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2245 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2246 if (strdata
&& strdata
[0] == '/')
2248 pos
= def
+ grub_strlen(strdata
);
2259 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2262 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2266 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2274 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2276 img_info
*next
= NULL
;
2277 img_info
*cur
= g_ventoy_img_list
;
2290 g_ventoy_img_list
= NULL
;
2291 g_ventoy_img_count
= 0;
2293 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2296 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2299 img_info
*cur
= g_ventoy_img_list
;
2303 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2305 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2308 img_id
= grub_strtol(args
[0], NULL
, 10);
2309 if (img_id
>= g_ventoy_img_count
)
2311 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2314 debug("Find image %ld name \n", img_id
);
2316 while (cur
&& img_id
> 0)
2324 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2327 debug("image name is %s\n", cur
->name
);
2329 grub_env_set(args
[1], cur
->name
);
2331 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2334 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2338 img_info
*cur
= g_ventoy_img_list
;
2344 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2347 len
= (int)grub_strlen(args
[0]);
2351 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2360 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2363 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2364 grub_env_set("chosen", id
);
2365 grub_env_export("chosen");
2367 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2370 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2374 const char *id
= NULL
;
2375 img_info
*cur
= NULL
;
2379 if (argc
< 1 || argc
> 2)
2381 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2384 id
= grub_env_get("chosen");
2386 pos
= grub_strstr(id
, "VID_");
2389 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2393 cur
= g_ventoy_img_list
;
2398 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2401 grub_env_set(args
[0], cur
->path
);
2405 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2406 grub_env_set(args
[1], value
);
2409 g_svd_replace_offset
= 0;
2411 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2415 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2419 grub_device_t dev
= NULL
;
2420 img_info
*cur
= NULL
;
2421 img_info
*tail
= NULL
;
2422 img_info
*min
= NULL
;
2423 img_info
*head
= NULL
;
2424 const char *strdata
= NULL
;
2425 char *device_name
= NULL
;
2427 img_iterator_node
*node
= NULL
;
2428 img_iterator_node
*tmp
= NULL
;
2434 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2437 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2439 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2444 g_enumerate_time_checked
= 0;
2445 g_enumerate_start_time_ms
= grub_get_time_ms();
2447 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2448 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2450 g_filt_dot_underscore_file
= 1;
2453 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2454 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2456 g_sort_case_sensitive
= 1;
2459 device_name
= grub_file_get_device_name(args
[0]);
2465 g_enum_dev
= dev
= grub_device_open(device_name
);
2471 g_enum_fs
= fs
= grub_fs_probe(dev
);
2477 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2479 debug("unsupported fs:<%s>\n", fs
->name
);
2480 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2484 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2486 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2487 if (strdata
&& strdata
[0] == '1')
2489 g_default_menu_mode
= 1;
2492 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2494 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2496 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2497 if (strdata
&& strdata
[0] == '/')
2499 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2500 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2502 g_img_iterator_head
.dir
[len
++] = '/';
2504 g_img_iterator_head
.dirlen
= len
;
2508 g_img_iterator_head
.dirlen
= 1;
2509 grub_strcpy(g_img_iterator_head
.dir
, "/");
2512 g_img_iterator_head
.tail
= &tail
;
2514 if (g_img_max_search_level
< 0)
2516 g_img_max_search_level
= GRUB_INT_MAX
;
2517 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2518 if (strdata
&& ventoy_is_decimal(strdata
))
2520 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2524 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2525 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2526 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2527 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2528 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2529 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2531 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2533 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2536 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2537 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2539 g_tree_view_menu_style
= 1;
2542 ventoy_set_default_menu();
2544 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2546 ventoy_dynamic_tree_menu(node
);
2550 node
= g_img_iterator_head
.next
;
2558 /* sort image list by image name */
2559 while (g_ventoy_img_list
)
2561 min
= g_ventoy_img_list
;
2562 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2564 if (ventoy_cmp_img(min
, cur
) > 0)
2572 min
->prev
->next
= min
->next
;
2577 min
->next
->prev
= min
->prev
;
2580 if (min
== g_ventoy_img_list
)
2582 g_ventoy_img_list
= min
->next
;
2600 g_ventoy_img_list
= head
;
2602 if (g_default_menu_mode
== 1)
2604 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2605 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2606 " echo 'return ...' \n"
2610 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2612 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2613 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2616 cur
->unsupport
? "[***********] " : "",
2617 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2619 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2622 g_tree_script_buf
[g_tree_script_pos
] = 0;
2623 g_list_script_buf
[g_list_script_pos
] = 0;
2625 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2626 grub_env_set(args
[1], buf
);
2630 check_free(device_name
, grub_free
);
2631 check_free(dev
, grub_device_close
);
2633 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2636 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2643 device_name
= grub_file_get_device_name(filename
);
2655 pos2
= grub_strstr(pos
, ",");
2658 pos2
= grub_strstr(pos
, ")");
2666 disk
= grub_disk_open(pos
);
2669 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2670 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2671 grub_disk_close(disk
);
2678 grub_free(device_name
);
2682 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2684 eltorito_descriptor desc
;
2686 grub_memset(&desc
, 0, sizeof(desc
));
2687 grub_file_seek(file
, 17 * 2048);
2688 grub_file_read(file
, &desc
, sizeof(desc
));
2690 if (desc
.type
!= 0 || desc
.version
!= 1)
2695 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2696 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2704 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2706 grub_uint8_t buf
[512];
2708 grub_file_seek(file
, sector
* 2048);
2709 grub_file_read(file
, buf
, sizeof(buf
));
2711 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2712 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2714 return *((grub_uint32_t
*)(buf
+ 40));
2720 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2724 grub_uint8_t buf
[512];
2725 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2727 grub_file_seek(file
, sector
* 2048);
2728 grub_file_read(file
, buf
, sizeof(buf
));
2730 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2732 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2736 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2741 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2743 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2745 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2749 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2751 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2756 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2758 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2760 if (buf
[36] == parttype
[i
])
2762 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2768 debug("%s does not contain efi eltorito\n", file
->name
);
2772 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2775 const char *fs
= NULL
;
2776 const char *cdprompt
= NULL
;
2778 grub_uint8_t chksum
= 0;
2781 disk
= file
->device
->disk
;
2782 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2784 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2785 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2786 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2788 pos
= grub_strstr(file
->name
, "/");
2794 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2796 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2798 param
->vtoy_img_size
= file
->size
;
2800 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2801 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2803 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2805 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2806 param
->vtoy_reserved
[4] = 0;
2807 if (g_ventoy_chain_type
== 1) /* Windows */
2809 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2810 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2812 param
->vtoy_reserved
[4] = 1;
2816 fs
= ventoy_get_env("ventoy_fs_probe");
2817 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2819 param
->vtoy_reserved
[3] = 1;
2822 /* calculate checksum */
2823 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2825 chksum
+= *((grub_uint8_t
*)param
+ i
);
2827 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2832 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2834 grub_uint32_t i
= 0;
2835 grub_uint64_t total
= 0;
2836 grub_uint64_t fileblk
= 0;
2837 ventoy_img_chunk
*chunk
= NULL
;
2839 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2841 chunk
= chunklist
->chunk
+ i
;
2843 if (chunk
->disk_start_sector
<= start
)
2845 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2849 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2852 fileblk
= (file
->size
+ 511) / 512;
2854 if (total
!= fileblk
)
2856 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2857 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2859 debug("maybe img file to be processed.\n");
2869 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2873 grub_uint32_t i
= 0;
2874 grub_uint32_t sector
= 0;
2875 grub_uint32_t count
= 0;
2876 grub_off_t size
= 0;
2877 grub_off_t read
= 0;
2879 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2880 if (fs_type
== ventoy_fs_exfat
)
2882 grub_fat_get_file_chunk(start
, file
, chunklist
);
2884 else if (fs_type
== ventoy_fs_ext
)
2886 grub_ext_get_file_chunk(start
, file
, chunklist
);
2890 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2891 file
->read_hook_data
= chunklist
;
2893 for (size
= file
->size
; size
> 0; size
-= read
)
2895 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2896 grub_file_read(file
, NULL
, read
);
2899 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2901 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2902 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2905 if (ventoy_fs_udf
== fs_type
)
2907 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2909 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2910 chunklist
->chunk
[i
].img_start_sector
= sector
;
2911 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2917 len
= (int)grub_strlen(file
->name
);
2918 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2919 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2920 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2921 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2923 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2925 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2935 chunklist
->chunk
[i
].img_start_sector
= sector
;
2936 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2944 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2948 grub_disk_addr_t start
;
2953 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2956 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2959 g_conf_replace_node
= NULL
;
2960 g_conf_replace_offset
= 0;
2962 if (g_img_chunk_list
.chunk
)
2964 grub_free(g_img_chunk_list
.chunk
);
2967 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2969 grub_file_close(file
);
2970 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2973 /* get image chunk data */
2974 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2975 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2976 if (NULL
== g_img_chunk_list
.chunk
)
2978 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2981 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2982 g_img_chunk_list
.cur_chunk
= 0;
2984 start
= file
->device
->disk
->partition
->start
;
2986 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2988 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2989 grub_file_close(file
);
2993 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2996 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2997 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
2998 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3001 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3003 grub_uint64_t offset
= 0;
3004 grub_uint32_t align
= 0;
3005 grub_file_t file
= NULL
;
3006 conf_replace
*node
= NULL
;
3012 debug("select conf replace argc:%d\n", argc
);
3019 node
= ventoy_plugin_find_conf_replace(args
[1]);
3022 debug("Conf replace not found for %s\n", args
[1]);
3026 debug("Find conf replace for %s\n", args
[1]);
3028 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3031 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3032 grub_file_close(file
);
3034 else if (node
->img
> 0)
3040 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3044 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3047 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3051 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3053 if (align
> vtoy_max_replace_file_size
)
3055 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3059 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3060 g_conf_replace_new_len
= (int)file
->size
;
3061 g_conf_replace_new_len_align
= align
;
3063 g_conf_replace_node
= node
;
3064 g_conf_replace_offset
= offset
+ 2;
3068 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3069 g_grub_param
->img_replace
.old_name_cnt
= 1;
3070 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3073 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3078 grub_file_close(file
);
3080 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3083 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3089 char configfile
[128];
3090 install_template
*node
= NULL
;
3096 debug("select auto installation argc:%d\n", argc
);
3103 node
= ventoy_plugin_find_install_template(args
[0]);
3106 debug("Auto install template not found for %s\n", args
[0]);
3110 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3112 defidx
= node
->autosel
;
3113 if (node
->timeout
< 0)
3115 node
->cursel
= node
->autosel
- 1;
3116 debug("Auto install template auto select %d\n", node
->autosel
);
3121 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3127 if (node
->timeout
> 0)
3129 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3132 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3133 " echo %s\n}\n", "");
3135 for (i
= 0; i
< node
->templatenum
; i
++)
3137 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3139 node
->templatepath
[i
].path
);
3142 g_ventoy_menu_esc
= 1;
3143 g_ventoy_suppress_esc
= 1;
3144 g_ventoy_suppress_esc_default
= defidx
;
3146 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3147 grub_script_execute_sourcecode(configfile
);
3149 g_ventoy_menu_esc
= 0;
3150 g_ventoy_suppress_esc
= 0;
3151 g_ventoy_suppress_esc_default
= 1;
3155 node
->cursel
= g_ventoy_last_entry
- 1;
3157 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3160 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3166 char configfile
[128];
3167 persistence_config
*node
;
3173 debug("select persistence argc:%d\n", argc
);
3180 node
= ventoy_plugin_find_persistent(args
[0]);
3183 debug("Persistence image not found for %s\n", args
[0]);
3187 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3189 defidx
= node
->autosel
;
3190 if (node
->timeout
< 0)
3192 node
->cursel
= node
->autosel
- 1;
3193 debug("Persistence image auto select %d\n", node
->autosel
);
3198 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3204 if (node
->timeout
> 0)
3206 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3209 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3210 " echo %s\n}\n", "");
3212 for (i
= 0; i
< node
->backendnum
; i
++)
3214 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3216 node
->backendpath
[i
].path
);
3220 g_ventoy_menu_esc
= 1;
3221 g_ventoy_suppress_esc
= 1;
3222 g_ventoy_suppress_esc_default
= defidx
;
3224 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3225 grub_script_execute_sourcecode(configfile
);
3227 g_ventoy_menu_esc
= 0;
3228 g_ventoy_suppress_esc
= 0;
3229 g_ventoy_suppress_esc_default
= 1;
3233 node
->cursel
= g_ventoy_last_entry
- 1;
3235 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3238 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3241 ventoy_img_chunk
*cur
;
3247 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3249 cur
= g_img_chunk_list
.chunk
+ i
;
3250 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3251 cur
->img_start_sector
, cur
->img_end_sector
,
3252 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3256 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3259 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3263 ventoy_img_chunk_list chunklist
;
3268 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3271 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3274 /* get image chunk data */
3275 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3276 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3277 if (NULL
== chunklist
.chunk
)
3279 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3282 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3283 chunklist
.cur_chunk
= 0;
3285 ventoy_get_block_list(file
, &chunklist
, 0);
3287 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3289 grub_printf("########## UNSUPPORTED ###############\n");
3292 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3294 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3296 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3297 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3300 grub_printf("\n==================================\n");
3302 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3304 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3305 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3306 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3307 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3308 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3312 grub_free(chunklist
.chunk
);
3313 grub_file_close(file
);
3315 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3318 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3321 ventoy_grub_param_file_replace
*replace
= NULL
;
3329 replace
= &(g_grub_param
->file_replace
);
3330 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3332 replace
->old_name_cnt
= 0;
3333 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3335 replace
->old_name_cnt
++;
3336 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3339 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3342 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3345 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3348 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3354 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3355 grub_env_set(args
[0], buf
);
3358 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3361 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3369 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3370 grub_printf("%s", g_list_script_buf
);
3374 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3375 grub_printf("%s", g_tree_script_buf
);
3381 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3383 img_info
*cur
= g_ventoy_img_list
;
3391 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3392 grub_printf("name:<%s>\n\n", cur
->name
);
3399 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3405 ventoy_plugin_dump_injection();
3410 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3416 ventoy_plugin_dump_auto_install();
3421 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3427 ventoy_plugin_dump_persistence();
3432 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3443 if (args
[0][0] == '0')
3445 return g_ventoy_memdisk_mode
? 0 : 1;
3447 else if (args
[0][0] == '1')
3449 return g_ventoy_iso_raw
? 0 : 1;
3451 else if (args
[0][0] == '2')
3453 return g_ventoy_iso_uefi_drv
? 0 : 1;
3455 else if (args
[0][0] == '3')
3457 return g_ventoy_grub2_mode
? 0 : 1;
3459 else if (args
[0][0] == '4')
3461 return g_ventoy_wimboot_mode
? 0 : 1;
3467 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3469 static int configfile_mode
= 0;
3470 char memfile
[128] = {0};
3477 * args[0]: 0:normal 1:configfile
3478 * args[1]: 0:list_buf 1:tree_buf
3483 debug("Invalid argc %d\n", argc
);
3489 if (args
[0][0] == '0')
3491 if (args
[1][0] == '0')
3493 grub_script_execute_sourcecode(g_list_script_buf
);
3497 grub_script_execute_sourcecode(g_tree_script_buf
);
3502 if (configfile_mode
)
3504 debug("Now already in F3 mode %d\n", configfile_mode
);
3508 if (args
[1][0] == '0')
3510 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3511 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3515 g_ventoy_last_entry
= -1;
3516 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3517 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3520 configfile_mode
= 1;
3521 grub_script_execute_sourcecode(memfile
);
3522 configfile_mode
= 0;
3528 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3539 g_ventoy_case_insensitive
= 1;
3540 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3541 g_ventoy_case_insensitive
= 0;
3547 grub_file_close(file
);
3553 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3558 const char *isopath
= NULL
;
3560 ventoy_mbr_head mbr
;
3567 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3570 isopath
= grub_env_get("vtoy_iso_part");
3573 debug("isopath is null %p\n", isopath
);
3577 debug("isopath is %s\n", isopath
);
3579 for (id
= 0; id
< 30 && (find
== 0); id
++)
3581 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3582 if (grub_strstr(isopath
, hdname
))
3584 debug("skip %s ...\n", hdname
);
3588 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3590 disk
= grub_disk_open(hdname
);
3593 debug("%s not exist\n", hdname
);
3597 grub_memset(&mbr
, 0, sizeof(mbr
));
3598 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3600 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3602 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3603 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3606 grub_env_set(args
[0], hdname
);
3610 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3614 debug("read %s failed\n", hdname
);
3617 grub_disk_close(disk
);
3623 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3634 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3637 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3640 debug("failed to open file %s\n", args
[0]);
3644 buf
= grub_malloc(len
);
3651 grub_file_read(file
, buf
, len
- 1);
3653 ventoy_get_line(buf
);
3654 ventoy_set_env(args
[1], buf
);
3658 grub_check_free(buf
);
3659 grub_file_close(file
);
3664 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3666 int *pCnt
= (int *)data
;
3671 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3672 "0 %llu linear /dev/ventoy %llu\n",
3673 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3678 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3681 char *device_name
= NULL
;
3682 grub_device_t dev
= NULL
;
3687 g_part_list_pos
= 0;
3688 grub_env_unset("vtoy_img_part_file");
3695 device_name
= grub_file_get_device_name(args
[0]);
3698 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3702 dev
= grub_device_open(device_name
);
3705 debug("grub_device_open failed, %s\n", device_name
);
3709 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3711 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3712 grub_env_set("vtoy_img_part_file", buf
);
3714 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3715 grub_env_set("vtoy_img_part_cnt", buf
);
3719 check_free(device_name
, grub_free
);
3720 check_free(dev
, grub_device_close
);
3726 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3737 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3740 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3743 debug("failed to open file %s\n", args
[0]);
3747 buf
= grub_malloc(file
->size
+ 1);
3753 buf
[file
->size
] = 0;
3754 grub_file_read(file
, buf
, file
->size
);
3756 if (grub_strstr(buf
, args
[1]))
3763 grub_check_free(buf
);
3764 grub_file_close(file
);
3769 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3775 ventoy_iso9660_vd pvd
;
3782 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3785 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3788 debug("failed to open file %s\n", args
[0]);
3792 grub_file_seek(file
, 16 * 2048);
3793 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3794 if (len
!= sizeof(pvd
))
3796 debug("failed to read pvd %d\n", len
);
3800 grub_memset(buf
, 0, sizeof(buf
));
3801 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3802 ventoy_set_env(args
[1], buf
);
3804 grub_memset(buf
, 0, sizeof(buf
));
3805 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3806 ventoy_set_env(args
[2], buf
);
3810 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3811 ventoy_set_env(args
[3], buf
);
3814 grub_file_close(file
);
3819 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3830 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3833 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3836 debug("failed to open file %s\n", args
[0]);
3840 grub_memset(buf
, 0, sizeof(buf
));
3841 grub_file_seek(file
, 16 * 2048 + 813);
3842 len
= (int)grub_file_read(file
, buf
, 17);
3845 debug("failed to read create date %d\n", len
);
3849 ventoy_set_env(args
[1], buf
);
3852 grub_file_close(file
);
3857 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3863 ventoy_env_hook_root(1);
3868 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3874 ventoy_env_hook_root(0);
3879 #ifdef GRUB_MACHINE_EFI
3880 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3885 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3891 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3892 if (var
&& *var
== 1)
3900 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3909 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3914 grub_uint64_t FileSectors
= 0;
3915 ventoy_gpt_info
*gpt
= NULL
;
3916 ventoy_part_table
*pt
= NULL
;
3917 grub_uint8_t zeroguid
[16] = {0};
3922 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3925 debug("failed to open file %s\n", args
[0]);
3929 if (file
->size
% 512)
3931 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3935 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3941 FileSectors
= file
->size
/ 512;
3943 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3944 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3946 debug("This is EFI partition table\n");
3948 for (i
= 0; i
< 128; i
++)
3950 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3952 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3954 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3955 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3963 debug("This is MBR partition table\n");
3965 for (i
= 0; i
< 4; i
++)
3967 pt
= gpt
->MBR
.PartTbl
+ i
;
3968 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3970 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3971 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3972 (ulonglong
)FileSectors
);
3981 grub_file_close(file
);
3982 grub_check_free(gpt
);
3983 grub_errno
= GRUB_ERR_NONE
;
3987 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3996 for (i
= 0; i
< 500; i
++)
3998 ret
= grub_getkey_noblock();
3999 if (ret
== GRUB_TERM_NO_KEY
)
4008 grub_printf("\n\n Still have key input after clear.\n");
4016 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4023 int image_sector_size
;
4025 ventoy_chain_head
*chain
;
4026 ventoy_img_chunk
*chunk
;
4027 ventoy_os_param
*osparam
;
4028 ventoy_image_location
*location
;
4029 ventoy_image_disk_region
*region
;
4030 struct grub_acpi_table_header
*acpi
;
4039 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4041 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4047 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4049 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4051 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4055 img_chunk_num
= chain
->img_chunk_num
;
4057 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4058 datalen
= sizeof(ventoy_os_param
) + loclen
;
4060 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4061 acpi
= grub_zalloc(buflen
);
4067 /* Step1: Fill acpi table header */
4068 grub_memcpy(acpi
->signature
, "VTOY", 4);
4069 acpi
->length
= buflen
;
4071 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4072 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4074 acpi
->creator_id
[0] = 1;
4075 acpi
->creator_rev
= 1;
4077 /* Step2: Fill data */
4078 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4079 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4080 osparam
->vtoy_img_location_addr
= 0;
4081 osparam
->vtoy_img_location_len
= loclen
;
4082 osparam
->chksum
= 0;
4083 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4085 location
= (ventoy_image_location
*)(osparam
+ 1);
4086 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4087 location
->image_sector_size
= image_sector_size
;
4088 location
->disk_sector_size
= chain
->disk_sector_size
;
4089 location
->region_count
= img_chunk_num
;
4091 region
= location
->regions
;
4092 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4093 if (512 == image_sector_size
)
4095 for (i
= 0; i
< img_chunk_num
; i
++)
4097 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4098 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4099 region
->disk_start_sector
= chunk
->disk_start_sector
;
4106 for (i
= 0; i
< img_chunk_num
; i
++)
4108 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4109 region
->image_start_sector
= chunk
->img_start_sector
;
4110 region
->disk_start_sector
= chunk
->disk_start_sector
;
4116 /* Step3: Fill acpi checksum */
4118 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4120 /* load acpi table */
4121 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4122 grub_script_execute_sourcecode(cmd
);
4126 VENTOY_CMD_RETURN(0);
4129 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4135 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4136 g_ventoy_last_entry
= -1;
4141 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4147 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4152 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4154 const char *pos
= filename
+ 1;
4162 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4164 grub_strncpy((char *)data
, filename
, 128);
4175 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4178 char *device_name
= NULL
;
4179 grub_device_t dev
= NULL
;
4180 grub_fs_t fs
= NULL
;
4181 char buf
[128] = {0};
4187 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4191 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4193 device_name
= grub_file_get_device_name(args
[0]);
4196 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4200 dev
= grub_device_open(device_name
);
4203 debug("grub_device_open failed, %s\n", device_name
);
4207 fs
= grub_fs_probe(dev
);
4210 debug("grub_fs_probe failed, %s\n", device_name
);
4214 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4218 ventoy_set_env(args
[2], buf
);
4225 check_free(device_name
, grub_free
);
4226 check_free(dev
, grub_device_close
);
4231 int ventoy_load_part_table(const char *diskname
)
4238 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4239 if (!g_ventoy_part_info
)
4244 disk
= grub_disk_open(diskname
);
4247 debug("Failed to open disk %s\n", diskname
);
4251 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4253 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4254 grub_disk_close(disk
);
4256 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4257 dev
= grub_device_open(name
);
4260 /* Check for official Ventoy device */
4261 ret
= ventoy_check_official_device(dev
);
4262 grub_device_close(dev
);
4270 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4271 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4276 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4283 ret
= ventoy_load_part_table(args
[0]);
4289 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4290 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4295 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4298 const char *vcfg
= NULL
;
4303 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4306 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4307 grub_env_set(args
[1], vcfg
);
4312 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4320 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4323 grub_uint8_t zeroguid
[16] = {0};
4328 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4331 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4333 if (id
>= 1 && id
<= 128)
4335 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4343 if (id
>= 1 && id
<= 4)
4345 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4355 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4358 char *device_name
= NULL
;
4359 grub_device_t dev
= NULL
;
4360 grub_fs_t fs
= NULL
;
4365 debug("get fs label for %s\n", args
[0]);
4369 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4373 device_name
= grub_file_get_device_name(args
[0]);
4376 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4380 dev
= grub_device_open(device_name
);
4383 debug("grub_device_open failed, %s\n", device_name
);
4387 fs
= grub_fs_probe(dev
);
4388 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4390 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4394 fs
->fs_label(dev
, &label
);
4397 debug("label=<%s>\n", label
);
4398 ventoy_set_env(args
[1], label
);
4406 check_free(device_name
, grub_free
);
4407 check_free(dev
, grub_device_close
);
4412 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4416 grub_snprintf((char *)data
, 256, "%s", filename
);
4423 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4425 if (info
->dir
&& filename
&& filename
[0] != '.')
4427 grub_snprintf((char *)data
, 256, "%s", filename
);
4434 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4437 char *device_name
= NULL
;
4438 grub_device_t dev
= NULL
;
4439 grub_fs_t fs
= NULL
;
4440 char name
[256] ={0};
4444 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4448 device_name
= grub_file_get_device_name(args
[0]);
4451 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4455 dev
= grub_device_open(device_name
);
4458 debug("grub_device_open failed, %s\n", device_name
);
4462 fs
= grub_fs_probe(dev
);
4465 debug("grub_fs_probe failed, %s\n", device_name
);
4469 fs
->fs_dir(dev
, args
[1], hook
, name
);
4472 ventoy_set_env(args
[2], name
);
4479 check_free(device_name
, grub_free
);
4480 check_free(dev
, grub_device_close
);
4485 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4488 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4491 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4494 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4497 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4507 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4511 for (pos
= args
[0]; *pos
; pos
++)
4525 grub_env_set(args
[1], args
[0]);
4535 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4545 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4550 len
= (int)grub_strlen(buf
);
4551 for (i
= len
; i
> 0; i
--)
4553 if (buf
[i
- 1] == '/')
4555 grub_env_set(args
[1], buf
+ i
);
4560 grub_env_set(args
[1], buf
);
4565 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4567 struct grub_video_mode_info info
;
4574 if (!g_video_mode_list
)
4576 ventoy_enum_video_mode();
4579 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4581 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4585 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4588 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4590 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4591 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4593 VENTOY_CMD_RETURN(0);
4596 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4598 struct grub_video_mode_info info
;
4605 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4607 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4611 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4614 grub_env_set(args
[0], buf
);
4616 VENTOY_CMD_RETURN(0);
4619 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4627 if (!g_video_mode_list
)
4632 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4633 if (id
< g_video_mode_num
)
4635 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4636 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4639 grub_env_set(args
[1], buf
);
4641 VENTOY_CMD_RETURN(0);
4644 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4647 grub_uint32_t loadsector
= 0;
4650 grub_uint32_t boot_catlog
= 0;
4651 grub_uint8_t buf
[512];
4657 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4661 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4664 debug("failed to open %s\n", args
[0]);
4668 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4669 if (boot_catlog
== 0)
4671 debug("No bootcatlog found\n");
4672 grub_file_close(file
);
4676 grub_memset(buf
, 0, sizeof(buf
));
4677 grub_file_seek(file
, boot_catlog
* 2048);
4678 grub_file_read(file
, buf
, sizeof(buf
));
4679 grub_file_close(file
);
4681 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4683 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4685 if (buf
[i
+ 32] == 0x88)
4687 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4688 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4694 if (loadsector
== 0)
4696 debug("No EFI eltorito info found\n");
4700 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4701 grub_env_set(args
[1], value
);
4702 VENTOY_CMD_RETURN(0);
4705 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4710 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4712 if (pfsdir
->initrd
[0])
4717 curpos
= pfsdir
->curpos
;
4718 len
= grub_strlen(filename
);
4722 if ((len
== 1 && filename
[0] == '.') ||
4723 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4728 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4731 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4732 pfsdir
->curpos
= curpos
+ printlen
;
4733 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4734 pfsdir
->curpos
= curpos
;
4735 pfsdir
->fullpath
[curpos
] = 0;
4739 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4742 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4743 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4745 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4747 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4756 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4760 char *device_name
= NULL
;
4761 grub_device_t dev
= NULL
;
4762 grub_fs_t fs
= NULL
;
4763 replace_fs_dir
*pfsdir
= NULL
;
4769 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4773 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4779 device_name
= grub_file_get_device_name(args
[0]);
4785 dev
= grub_device_open(device_name
);
4791 fs
= grub_fs_probe(dev
);
4800 pfsdir
->fullpath
[0] = '/';
4801 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4803 if (pfsdir
->initrd
[0])
4805 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4807 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4809 if (pfsdir
->initrd
[i
] == '/')
4811 pfsdir
->initrd
[i
] = '\\';
4815 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4816 grub_env_set(args
[1], pos
);
4820 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4825 grub_check_free(pfsdir
);
4826 grub_check_free(device_name
);
4827 check_free(dev
, grub_device_close
);
4829 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4832 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4834 const char *pager
= NULL
;
4840 pager
= grub_env_get("pager");
4844 grub_env_set("pager", "1");
4846 else if (pager
[0] == '1')
4852 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4854 grub_env_set("pager", "1");
4857 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4860 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4866 if (g_pager_flag
== 1)
4868 grub_env_unset("pager");
4870 else if (g_pager_flag
== 2)
4872 grub_env_set("pager", g_old_pager
);
4875 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4878 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4880 if (g_json_case_mis_path
[0])
4885 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
4887 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4893 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4896 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4898 if (g_json_case_mis_path
[0])
4903 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4905 if (grub_strcasecmp(filename
, "ventoy") == 0)
4907 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4908 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4909 if (g_json_case_mis_path
[0])
4919 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4922 char *device_name
= NULL
;
4923 grub_device_t dev
= NULL
;
4924 grub_fs_t fs
= NULL
;
4925 chk_case_fs_dir fs_dir
;
4931 device_name
= grub_file_get_device_name(args
[0]);
4937 dev
= grub_device_open(device_name
);
4943 fs
= grub_fs_probe(dev
);
4949 fstype
= ventoy_get_fs_type(fs
->name
);
4950 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4955 g_json_case_mis_path
[0] = 0;
4958 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4960 if (g_json_case_mis_path
[0])
4962 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4967 grub_check_free(device_name
);
4968 check_free(dev
, grub_device_close
);
4970 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4973 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4976 grub_partition_t part
;
4977 char priority_str
[3]; /* Maximum value 15 */
4981 if (argc
< 2 || argc
> 3)
4982 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4983 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4985 /* Open the disk if it exists */
4986 disk
= grub_disk_open (args
[0]);
4989 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4993 part
= grub_partition_probe (disk
, args
[1]);
4996 grub_disk_close (disk
);
4997 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4998 "No such partition");
5001 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5003 grub_disk_close (disk
);
5004 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5005 "Not a GPT partition");
5008 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5009 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5013 grub_env_set (args
[2], priority_str
);
5014 grub_env_export (args
[2]);
5018 grub_printf ("Priority is %s\n", priority_str
);
5021 grub_disk_close (disk
);
5022 return GRUB_ERR_NONE
;
5026 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5030 grub_file_t file
= NULL
;
5031 grub_uint32_t loadrba
= 0;
5032 grub_uint32_t boot_catlog
= 0;
5033 grub_uint8_t sector
[512];
5034 boot_info_table
*info
= NULL
;
5039 /* This also trigger a iso9660 fs parse */
5040 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5045 joliet
= grub_iso9660_is_joliet();
5051 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5054 debug("failed to open %s\n", args
[0]);
5058 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5059 if (boot_catlog
== 0)
5061 debug("no bootcatlog found %u\n", boot_catlog
);
5065 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5068 debug("no bios eltorito rba found %u\n", loadrba
);
5072 grub_file_seek(file
, loadrba
* 2048);
5073 grub_file_read(file
, sector
, 512);
5075 info
= (boot_info_table
*)sector
;
5076 if (info
->bi_data0
== 0x7c6ceafa &&
5077 info
->bi_data1
== 0x90900000 &&
5078 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5079 info
->bi_BootFileLocation
== loadrba
)
5081 debug("bootloader is syslinux, %u.\n", loadrba
);
5087 grub_file_close(file
);
5088 grub_errno
= GRUB_ERR_NONE
;
5092 int ventoy_env_init(void)
5096 grub_env_set("vtdebug_flag", "");
5098 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5099 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5100 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5101 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5103 ventoy_filt_register(0, ventoy_wrapper_open
);
5105 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5108 g_grub_param
->grub_env_get
= grub_env_get
;
5109 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5110 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5111 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5112 grub_env_set("env_param", buf
);
5113 grub_env_set("ventoy_env_param", buf
);
5115 grub_env_export("env_param");
5116 grub_env_export("ventoy_env_param");
5119 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5120 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5122 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5123 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5125 grub_env_export("vtoy_winpeshl_ini_addr");
5126 grub_env_export("vtoy_winpeshl_ini_size");
5128 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5129 grub_env_set("vtoy_chain_file_size", buf
);
5130 grub_env_export("vtoy_chain_file_size");
5132 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5133 grub_env_set("vtoy_chain_file_read", buf
);
5134 grub_env_export("vtoy_chain_file_read");
5141 static cmd_para ventoy_cmds
[] =
5143 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5144 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5145 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5146 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5147 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5148 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5149 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5150 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5151 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5152 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5153 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5154 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5155 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5156 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5157 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5158 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5159 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5160 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5161 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5162 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5163 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5164 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5165 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5166 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5167 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5169 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5170 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5171 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5172 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5173 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5174 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5175 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5177 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5178 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5179 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5180 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5181 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5182 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5183 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5184 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5185 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5186 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5189 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5190 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5191 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5192 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5193 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5194 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5195 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5196 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5197 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5198 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5199 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5201 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5202 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5203 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5204 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5205 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5206 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5207 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5209 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5210 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5211 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5212 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5213 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5214 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5215 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5216 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5217 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5218 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5220 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5221 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5222 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5223 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5224 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5225 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5226 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5227 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5228 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5230 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5231 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5232 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5233 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5236 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5237 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5238 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5240 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5241 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5242 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5245 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5246 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5247 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5248 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5249 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5250 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5251 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5252 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5253 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5254 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5255 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5257 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5258 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5259 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5260 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5261 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5262 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5263 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5264 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5265 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5266 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5268 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5269 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5270 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5271 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5272 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5273 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5274 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5275 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5278 int ventoy_register_all_cmd(void)
5281 cmd_para
*cur
= NULL
;
5283 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5285 cur
= ventoy_cmds
+ i
;
5286 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5287 cur
->summary
, cur
->description
, cur
->parser
);
5293 int ventoy_unregister_all_cmd(void)
5297 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5299 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);