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(vtoy_tip_image_file
, 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
;
2070 const menu_tip
*tip
= NULL
;
2072 if (node
->isocnt
== 0 || node
->done
== 1)
2077 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2079 offset
= node
->parent
->dirlen
;
2082 if (node
== &g_img_iterator_head
)
2084 if (g_default_menu_mode
== 0)
2086 if (g_tree_view_menu_style
== 0)
2088 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2089 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2090 " echo 'return ...' \n"
2095 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2096 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2104 node
->dir
[node
->dirlen
- 1] = 0;
2105 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2108 dir_class
= "vtoydir";
2111 tip
= ventoy_plugin_get_menu_tip(vtoy_tip_directory
, node
->dir
);
2113 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2116 if (g_tree_view_menu_style
== 0)
2118 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2119 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2120 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2124 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2125 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2126 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2131 dir_alias
= node
->dir
+ offset
;
2133 if (g_tree_view_menu_style
== 0)
2135 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2136 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2137 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2141 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2142 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2143 dir_alias
, dir_class
, node
->dir
+ offset
, tip
);
2147 if (g_tree_view_menu_style
== 0)
2149 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2150 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2151 " echo 'return ...' \n"
2156 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2157 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2163 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2165 ventoy_dynamic_tree_menu(child
);
2168 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2170 if (g_tree_view_menu_style
== 0)
2172 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2173 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2176 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2177 img
->unsupport
? "[***********] " : "",
2178 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2180 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2184 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2185 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2188 img
->unsupport
? "[***********] " : "",
2189 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2191 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2195 if (node
!= &g_img_iterator_head
)
2197 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2204 static int ventoy_set_default_menu(void)
2210 const char *strdata
= NULL
;
2211 img_info
*cur
= NULL
;
2212 img_info
*default_node
= NULL
;
2213 const char *default_image
= NULL
;
2215 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2216 if (default_image
&& default_image
[0] == '/')
2218 img_len
= grub_strlen(default_image
);
2220 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2222 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2234 if (0 == g_default_menu_mode
)
2236 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2240 def
= grub_strdup(default_image
);
2246 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2248 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2249 if (strdata
&& strdata
[0] == '/')
2251 pos
= def
+ grub_strlen(strdata
);
2262 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2265 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2269 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2277 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2279 img_info
*next
= NULL
;
2280 img_info
*cur
= g_ventoy_img_list
;
2293 g_ventoy_img_list
= NULL
;
2294 g_ventoy_img_count
= 0;
2296 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2299 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2302 img_info
*cur
= g_ventoy_img_list
;
2306 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2308 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2311 img_id
= grub_strtol(args
[0], NULL
, 10);
2312 if (img_id
>= g_ventoy_img_count
)
2314 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2317 debug("Find image %ld name \n", img_id
);
2319 while (cur
&& img_id
> 0)
2327 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2330 debug("image name is %s\n", cur
->name
);
2332 grub_env_set(args
[1], cur
->name
);
2334 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2337 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2341 img_info
*cur
= g_ventoy_img_list
;
2347 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2350 len
= (int)grub_strlen(args
[0]);
2354 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2363 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2366 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2367 grub_env_set("chosen", id
);
2368 grub_env_export("chosen");
2370 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2373 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2377 const char *id
= NULL
;
2378 img_info
*cur
= NULL
;
2382 if (argc
< 1 || argc
> 2)
2384 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2387 id
= grub_env_get("chosen");
2389 pos
= grub_strstr(id
, "VID_");
2392 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2396 cur
= g_ventoy_img_list
;
2401 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2404 grub_env_set(args
[0], cur
->path
);
2408 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2409 grub_env_set(args
[1], value
);
2412 g_svd_replace_offset
= 0;
2414 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2418 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2422 grub_device_t dev
= NULL
;
2423 img_info
*cur
= NULL
;
2424 img_info
*tail
= NULL
;
2425 img_info
*min
= NULL
;
2426 img_info
*head
= NULL
;
2427 const char *strdata
= NULL
;
2428 char *device_name
= NULL
;
2430 img_iterator_node
*node
= NULL
;
2431 img_iterator_node
*tmp
= NULL
;
2437 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2440 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2442 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2447 g_enumerate_time_checked
= 0;
2448 g_enumerate_start_time_ms
= grub_get_time_ms();
2450 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2451 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2453 g_filt_dot_underscore_file
= 1;
2456 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2457 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2459 g_sort_case_sensitive
= 1;
2462 device_name
= grub_file_get_device_name(args
[0]);
2468 g_enum_dev
= dev
= grub_device_open(device_name
);
2474 g_enum_fs
= fs
= grub_fs_probe(dev
);
2480 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2482 debug("unsupported fs:<%s>\n", fs
->name
);
2483 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2487 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2489 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2490 if (strdata
&& strdata
[0] == '1')
2492 g_default_menu_mode
= 1;
2495 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2497 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2499 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2500 if (strdata
&& strdata
[0] == '/')
2502 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2503 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2505 g_img_iterator_head
.dir
[len
++] = '/';
2507 g_img_iterator_head
.dirlen
= len
;
2511 g_img_iterator_head
.dirlen
= 1;
2512 grub_strcpy(g_img_iterator_head
.dir
, "/");
2515 g_img_iterator_head
.tail
= &tail
;
2517 if (g_img_max_search_level
< 0)
2519 g_img_max_search_level
= GRUB_INT_MAX
;
2520 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2521 if (strdata
&& ventoy_is_decimal(strdata
))
2523 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2527 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2528 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2529 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2530 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2531 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2532 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2534 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2536 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2539 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2540 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2542 g_tree_view_menu_style
= 1;
2545 ventoy_set_default_menu();
2547 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2549 ventoy_dynamic_tree_menu(node
);
2553 node
= g_img_iterator_head
.next
;
2561 /* sort image list by image name */
2562 while (g_ventoy_img_list
)
2564 min
= g_ventoy_img_list
;
2565 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2567 if (ventoy_cmp_img(min
, cur
) > 0)
2575 min
->prev
->next
= min
->next
;
2580 min
->next
->prev
= min
->prev
;
2583 if (min
== g_ventoy_img_list
)
2585 g_ventoy_img_list
= min
->next
;
2603 g_ventoy_img_list
= head
;
2605 if (g_default_menu_mode
== 1)
2607 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2608 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2609 " echo 'return ...' \n"
2613 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2615 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2616 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2619 cur
->unsupport
? "[***********] " : "",
2620 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2622 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2625 g_tree_script_buf
[g_tree_script_pos
] = 0;
2626 g_list_script_buf
[g_list_script_pos
] = 0;
2628 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2629 grub_env_set(args
[1], buf
);
2633 check_free(device_name
, grub_free
);
2634 check_free(dev
, grub_device_close
);
2636 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2639 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2646 device_name
= grub_file_get_device_name(filename
);
2658 pos2
= grub_strstr(pos
, ",");
2661 pos2
= grub_strstr(pos
, ")");
2669 disk
= grub_disk_open(pos
);
2672 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2673 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2674 grub_disk_close(disk
);
2681 grub_free(device_name
);
2685 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2687 eltorito_descriptor desc
;
2689 grub_memset(&desc
, 0, sizeof(desc
));
2690 grub_file_seek(file
, 17 * 2048);
2691 grub_file_read(file
, &desc
, sizeof(desc
));
2693 if (desc
.type
!= 0 || desc
.version
!= 1)
2698 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2699 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2707 static grub_uint32_t
ventoy_get_bios_eltorito_rba(grub_file_t file
, grub_uint32_t sector
)
2709 grub_uint8_t buf
[512];
2711 grub_file_seek(file
, sector
* 2048);
2712 grub_file_read(file
, buf
, sizeof(buf
));
2714 if (buf
[0] == 0x01 && buf
[1] == 0x00 &&
2715 buf
[30] == 0x55 && buf
[31] == 0xaa && buf
[32] == 0x88)
2717 return *((grub_uint32_t
*)(buf
+ 40));
2723 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2727 grub_uint8_t buf
[512];
2728 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2730 grub_file_seek(file
, sector
* 2048);
2731 grub_file_read(file
, buf
, sizeof(buf
));
2733 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2735 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2739 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2744 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2746 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2748 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2752 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2754 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2759 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2761 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2763 if (buf
[36] == parttype
[i
])
2765 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2771 debug("%s does not contain efi eltorito\n", file
->name
);
2775 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2778 const char *fs
= NULL
;
2779 const char *cdprompt
= NULL
;
2781 grub_uint8_t chksum
= 0;
2784 disk
= file
->device
->disk
;
2785 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2787 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2788 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2789 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2791 pos
= grub_strstr(file
->name
, "/");
2797 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2799 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2801 param
->vtoy_img_size
= file
->size
;
2803 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2804 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2806 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2808 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2809 param
->vtoy_reserved
[4] = 0;
2810 if (g_ventoy_chain_type
== 1) /* Windows */
2812 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2813 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2815 param
->vtoy_reserved
[4] = 1;
2819 fs
= ventoy_get_env("ventoy_fs_probe");
2820 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2822 param
->vtoy_reserved
[3] = 1;
2825 /* calculate checksum */
2826 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2828 chksum
+= *((grub_uint8_t
*)param
+ i
);
2830 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2835 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2837 grub_uint32_t i
= 0;
2838 grub_uint64_t total
= 0;
2839 grub_uint64_t fileblk
= 0;
2840 ventoy_img_chunk
*chunk
= NULL
;
2842 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2844 chunk
= chunklist
->chunk
+ i
;
2846 if (chunk
->disk_start_sector
<= start
)
2848 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2852 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2855 fileblk
= (file
->size
+ 511) / 512;
2857 if (total
!= fileblk
)
2859 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2860 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2862 debug("maybe img file to be processed.\n");
2872 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2876 grub_uint32_t i
= 0;
2877 grub_uint32_t sector
= 0;
2878 grub_uint32_t count
= 0;
2879 grub_off_t size
= 0;
2880 grub_off_t read
= 0;
2882 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2883 if (fs_type
== ventoy_fs_exfat
)
2885 grub_fat_get_file_chunk(start
, file
, chunklist
);
2887 else if (fs_type
== ventoy_fs_ext
)
2889 grub_ext_get_file_chunk(start
, file
, chunklist
);
2893 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2894 file
->read_hook_data
= chunklist
;
2896 for (size
= file
->size
; size
> 0; size
-= read
)
2898 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2899 grub_file_read(file
, NULL
, read
);
2902 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2904 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2905 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2908 if (ventoy_fs_udf
== fs_type
)
2910 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2912 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2913 chunklist
->chunk
[i
].img_start_sector
= sector
;
2914 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2920 len
= (int)grub_strlen(file
->name
);
2921 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2922 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2923 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2924 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2926 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2928 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2938 chunklist
->chunk
[i
].img_start_sector
= sector
;
2939 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2947 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2951 grub_disk_addr_t start
;
2956 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2959 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2962 g_conf_replace_node
= NULL
;
2963 g_conf_replace_offset
= 0;
2965 if (g_img_chunk_list
.chunk
)
2967 grub_free(g_img_chunk_list
.chunk
);
2970 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2972 grub_file_close(file
);
2973 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2976 /* get image chunk data */
2977 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2978 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2979 if (NULL
== g_img_chunk_list
.chunk
)
2981 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2984 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2985 g_img_chunk_list
.cur_chunk
= 0;
2987 start
= file
->device
->disk
->partition
->start
;
2989 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2991 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2992 grub_file_close(file
);
2996 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2999 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
3000 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
3001 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3004 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3006 grub_uint64_t offset
= 0;
3007 grub_uint32_t align
= 0;
3008 grub_file_t file
= NULL
;
3009 conf_replace
*node
= NULL
;
3015 debug("select conf replace argc:%d\n", argc
);
3022 node
= ventoy_plugin_find_conf_replace(args
[1]);
3025 debug("Conf replace not found for %s\n", args
[1]);
3029 debug("Find conf replace for %s\n", args
[1]);
3031 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3034 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3035 grub_file_close(file
);
3037 else if (node
->img
> 0)
3043 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3047 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3050 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3054 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3056 if (align
> vtoy_max_replace_file_size
)
3058 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3062 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3063 g_conf_replace_new_len
= (int)file
->size
;
3064 g_conf_replace_new_len_align
= align
;
3066 g_conf_replace_node
= node
;
3067 g_conf_replace_offset
= offset
+ 2;
3071 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3072 g_grub_param
->img_replace
.old_name_cnt
= 1;
3073 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3076 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3081 grub_file_close(file
);
3083 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3086 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3092 char configfile
[128];
3093 install_template
*node
= NULL
;
3099 debug("select auto installation argc:%d\n", argc
);
3106 node
= ventoy_plugin_find_install_template(args
[0]);
3109 debug("Auto install template not found for %s\n", args
[0]);
3113 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3115 defidx
= node
->autosel
;
3116 if (node
->timeout
< 0)
3118 node
->cursel
= node
->autosel
- 1;
3119 debug("Auto install template auto select %d\n", node
->autosel
);
3124 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3130 if (node
->timeout
> 0)
3132 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3135 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3136 " echo %s\n}\n", "");
3138 for (i
= 0; i
< node
->templatenum
; i
++)
3140 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3142 node
->templatepath
[i
].path
);
3145 g_ventoy_menu_esc
= 1;
3146 g_ventoy_suppress_esc
= 1;
3147 g_ventoy_suppress_esc_default
= defidx
;
3149 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3150 grub_script_execute_sourcecode(configfile
);
3152 g_ventoy_menu_esc
= 0;
3153 g_ventoy_suppress_esc
= 0;
3154 g_ventoy_suppress_esc_default
= 1;
3158 node
->cursel
= g_ventoy_last_entry
- 1;
3160 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3163 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3169 char configfile
[128];
3170 persistence_config
*node
;
3176 debug("select persistence argc:%d\n", argc
);
3183 node
= ventoy_plugin_find_persistent(args
[0]);
3186 debug("Persistence image not found for %s\n", args
[0]);
3190 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3192 defidx
= node
->autosel
;
3193 if (node
->timeout
< 0)
3195 node
->cursel
= node
->autosel
- 1;
3196 debug("Persistence image auto select %d\n", node
->autosel
);
3201 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3207 if (node
->timeout
> 0)
3209 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3212 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3213 " echo %s\n}\n", "");
3215 for (i
= 0; i
< node
->backendnum
; i
++)
3217 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3219 node
->backendpath
[i
].path
);
3223 g_ventoy_menu_esc
= 1;
3224 g_ventoy_suppress_esc
= 1;
3225 g_ventoy_suppress_esc_default
= defidx
;
3227 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3228 grub_script_execute_sourcecode(configfile
);
3230 g_ventoy_menu_esc
= 0;
3231 g_ventoy_suppress_esc
= 0;
3232 g_ventoy_suppress_esc_default
= 1;
3236 node
->cursel
= g_ventoy_last_entry
- 1;
3238 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3241 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3244 ventoy_img_chunk
*cur
;
3250 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3252 cur
= g_img_chunk_list
.chunk
+ i
;
3253 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3254 cur
->img_start_sector
, cur
->img_end_sector
,
3255 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3259 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3262 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3266 ventoy_img_chunk_list chunklist
;
3271 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3274 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3277 /* get image chunk data */
3278 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3279 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3280 if (NULL
== chunklist
.chunk
)
3282 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3285 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3286 chunklist
.cur_chunk
= 0;
3288 ventoy_get_block_list(file
, &chunklist
, 0);
3290 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3292 grub_printf("########## UNSUPPORTED ###############\n");
3295 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3297 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3299 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3300 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3303 grub_printf("\n==================================\n");
3305 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3307 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3308 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3309 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3310 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3311 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3315 grub_free(chunklist
.chunk
);
3316 grub_file_close(file
);
3318 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3321 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3324 ventoy_grub_param_file_replace
*replace
= NULL
;
3332 replace
= &(g_grub_param
->file_replace
);
3333 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3335 replace
->old_name_cnt
= 0;
3336 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3338 replace
->old_name_cnt
++;
3339 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3342 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3345 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3348 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3351 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3357 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3358 grub_env_set(args
[0], buf
);
3361 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3364 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3372 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3373 grub_printf("%s", g_list_script_buf
);
3377 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3378 grub_printf("%s", g_tree_script_buf
);
3384 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3386 img_info
*cur
= g_ventoy_img_list
;
3394 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3395 grub_printf("name:<%s>\n\n", cur
->name
);
3402 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3408 ventoy_plugin_dump_injection();
3413 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3419 ventoy_plugin_dump_auto_install();
3424 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3430 ventoy_plugin_dump_persistence();
3435 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3446 if (args
[0][0] == '0')
3448 return g_ventoy_memdisk_mode
? 0 : 1;
3450 else if (args
[0][0] == '1')
3452 return g_ventoy_iso_raw
? 0 : 1;
3454 else if (args
[0][0] == '2')
3456 return g_ventoy_iso_uefi_drv
? 0 : 1;
3458 else if (args
[0][0] == '3')
3460 return g_ventoy_grub2_mode
? 0 : 1;
3462 else if (args
[0][0] == '4')
3464 return g_ventoy_wimboot_mode
? 0 : 1;
3470 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3472 static int configfile_mode
= 0;
3473 char memfile
[128] = {0};
3480 * args[0]: 0:normal 1:configfile
3481 * args[1]: 0:list_buf 1:tree_buf
3486 debug("Invalid argc %d\n", argc
);
3492 if (args
[0][0] == '0')
3494 if (args
[1][0] == '0')
3496 grub_script_execute_sourcecode(g_list_script_buf
);
3500 grub_script_execute_sourcecode(g_tree_script_buf
);
3505 if (configfile_mode
)
3507 debug("Now already in F3 mode %d\n", configfile_mode
);
3511 if (args
[1][0] == '0')
3513 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3514 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3518 g_ventoy_last_entry
= -1;
3519 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3520 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3523 configfile_mode
= 1;
3524 grub_script_execute_sourcecode(memfile
);
3525 configfile_mode
= 0;
3531 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3542 g_ventoy_case_insensitive
= 1;
3543 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3544 g_ventoy_case_insensitive
= 0;
3550 grub_file_close(file
);
3556 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3561 const char *isopath
= NULL
;
3563 ventoy_mbr_head mbr
;
3570 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3573 isopath
= grub_env_get("vtoy_iso_part");
3576 debug("isopath is null %p\n", isopath
);
3580 debug("isopath is %s\n", isopath
);
3582 for (id
= 0; id
< 30 && (find
== 0); id
++)
3584 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3585 if (grub_strstr(isopath
, hdname
))
3587 debug("skip %s ...\n", hdname
);
3591 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3593 disk
= grub_disk_open(hdname
);
3596 debug("%s not exist\n", hdname
);
3600 grub_memset(&mbr
, 0, sizeof(mbr
));
3601 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3603 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3605 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3606 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3609 grub_env_set(args
[0], hdname
);
3613 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3617 debug("read %s failed\n", hdname
);
3620 grub_disk_close(disk
);
3626 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3637 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3640 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3643 debug("failed to open file %s\n", args
[0]);
3647 buf
= grub_malloc(len
);
3654 grub_file_read(file
, buf
, len
- 1);
3656 ventoy_get_line(buf
);
3657 ventoy_set_env(args
[1], buf
);
3661 grub_check_free(buf
);
3662 grub_file_close(file
);
3667 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3669 int *pCnt
= (int *)data
;
3674 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3675 "0 %llu linear /dev/ventoy %llu\n",
3676 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3681 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3684 char *device_name
= NULL
;
3685 grub_device_t dev
= NULL
;
3690 g_part_list_pos
= 0;
3691 grub_env_unset("vtoy_img_part_file");
3698 device_name
= grub_file_get_device_name(args
[0]);
3701 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3705 dev
= grub_device_open(device_name
);
3708 debug("grub_device_open failed, %s\n", device_name
);
3712 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3714 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3715 grub_env_set("vtoy_img_part_file", buf
);
3717 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3718 grub_env_set("vtoy_img_part_cnt", buf
);
3722 check_free(device_name
, grub_free
);
3723 check_free(dev
, grub_device_close
);
3729 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3740 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3743 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3746 debug("failed to open file %s\n", args
[0]);
3750 buf
= grub_malloc(file
->size
+ 1);
3756 buf
[file
->size
] = 0;
3757 grub_file_read(file
, buf
, file
->size
);
3759 if (grub_strstr(buf
, args
[1]))
3766 grub_check_free(buf
);
3767 grub_file_close(file
);
3772 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3778 ventoy_iso9660_vd pvd
;
3785 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3788 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3791 debug("failed to open file %s\n", args
[0]);
3795 grub_file_seek(file
, 16 * 2048);
3796 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3797 if (len
!= sizeof(pvd
))
3799 debug("failed to read pvd %d\n", len
);
3803 grub_memset(buf
, 0, sizeof(buf
));
3804 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3805 ventoy_set_env(args
[1], buf
);
3807 grub_memset(buf
, 0, sizeof(buf
));
3808 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3809 ventoy_set_env(args
[2], buf
);
3813 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3814 ventoy_set_env(args
[3], buf
);
3817 grub_file_close(file
);
3822 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3833 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3836 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3839 debug("failed to open file %s\n", args
[0]);
3843 grub_memset(buf
, 0, sizeof(buf
));
3844 grub_file_seek(file
, 16 * 2048 + 813);
3845 len
= (int)grub_file_read(file
, buf
, 17);
3848 debug("failed to read create date %d\n", len
);
3852 ventoy_set_env(args
[1], buf
);
3855 grub_file_close(file
);
3860 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3866 ventoy_env_hook_root(1);
3871 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3877 ventoy_env_hook_root(0);
3882 #ifdef GRUB_MACHINE_EFI
3883 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3888 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3894 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3895 if (var
&& *var
== 1)
3903 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3912 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3917 grub_uint64_t FileSectors
= 0;
3918 ventoy_gpt_info
*gpt
= NULL
;
3919 ventoy_part_table
*pt
= NULL
;
3920 grub_uint8_t zeroguid
[16] = {0};
3925 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3928 debug("failed to open file %s\n", args
[0]);
3932 if (file
->size
% 512)
3934 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3938 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3944 FileSectors
= file
->size
/ 512;
3946 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3947 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3949 debug("This is EFI partition table\n");
3951 for (i
= 0; i
< 128; i
++)
3953 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3955 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3957 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3958 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3966 debug("This is MBR partition table\n");
3968 for (i
= 0; i
< 4; i
++)
3970 pt
= gpt
->MBR
.PartTbl
+ i
;
3971 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3973 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3974 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3975 (ulonglong
)FileSectors
);
3984 grub_file_close(file
);
3985 grub_check_free(gpt
);
3986 grub_errno
= GRUB_ERR_NONE
;
3990 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3999 for (i
= 0; i
< 500; i
++)
4001 ret
= grub_getkey_noblock();
4002 if (ret
== GRUB_TERM_NO_KEY
)
4011 grub_printf("\n\n Still have key input after clear.\n");
4019 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4026 int image_sector_size
;
4028 ventoy_chain_head
*chain
;
4029 ventoy_img_chunk
*chunk
;
4030 ventoy_os_param
*osparam
;
4031 ventoy_image_location
*location
;
4032 ventoy_image_disk_region
*region
;
4033 struct grub_acpi_table_header
*acpi
;
4042 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4044 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4050 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4052 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4054 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4058 img_chunk_num
= chain
->img_chunk_num
;
4060 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4061 datalen
= sizeof(ventoy_os_param
) + loclen
;
4063 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4064 acpi
= grub_zalloc(buflen
);
4070 /* Step1: Fill acpi table header */
4071 grub_memcpy(acpi
->signature
, "VTOY", 4);
4072 acpi
->length
= buflen
;
4074 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4075 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4077 acpi
->creator_id
[0] = 1;
4078 acpi
->creator_rev
= 1;
4080 /* Step2: Fill data */
4081 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4082 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4083 osparam
->vtoy_img_location_addr
= 0;
4084 osparam
->vtoy_img_location_len
= loclen
;
4085 osparam
->chksum
= 0;
4086 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4088 location
= (ventoy_image_location
*)(osparam
+ 1);
4089 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4090 location
->image_sector_size
= image_sector_size
;
4091 location
->disk_sector_size
= chain
->disk_sector_size
;
4092 location
->region_count
= img_chunk_num
;
4094 region
= location
->regions
;
4095 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4096 if (512 == image_sector_size
)
4098 for (i
= 0; i
< img_chunk_num
; i
++)
4100 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4101 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4102 region
->disk_start_sector
= chunk
->disk_start_sector
;
4109 for (i
= 0; i
< img_chunk_num
; i
++)
4111 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4112 region
->image_start_sector
= chunk
->img_start_sector
;
4113 region
->disk_start_sector
= chunk
->disk_start_sector
;
4119 /* Step3: Fill acpi checksum */
4121 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4123 /* load acpi table */
4124 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4125 grub_script_execute_sourcecode(cmd
);
4129 VENTOY_CMD_RETURN(0);
4132 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4138 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4139 g_ventoy_last_entry
= -1;
4144 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4150 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4155 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4157 const char *pos
= filename
+ 1;
4165 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4167 grub_strncpy((char *)data
, filename
, 128);
4178 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4181 char *device_name
= NULL
;
4182 grub_device_t dev
= NULL
;
4183 grub_fs_t fs
= NULL
;
4184 char buf
[128] = {0};
4190 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4194 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4196 device_name
= grub_file_get_device_name(args
[0]);
4199 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4203 dev
= grub_device_open(device_name
);
4206 debug("grub_device_open failed, %s\n", device_name
);
4210 fs
= grub_fs_probe(dev
);
4213 debug("grub_fs_probe failed, %s\n", device_name
);
4217 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4221 ventoy_set_env(args
[2], buf
);
4228 check_free(device_name
, grub_free
);
4229 check_free(dev
, grub_device_close
);
4234 int ventoy_load_part_table(const char *diskname
)
4241 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4242 if (!g_ventoy_part_info
)
4247 disk
= grub_disk_open(diskname
);
4250 debug("Failed to open disk %s\n", diskname
);
4254 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4256 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4257 grub_disk_close(disk
);
4259 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4260 dev
= grub_device_open(name
);
4263 /* Check for official Ventoy device */
4264 ret
= ventoy_check_official_device(dev
);
4265 grub_device_close(dev
);
4273 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4274 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4279 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4286 ret
= ventoy_load_part_table(args
[0]);
4292 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4293 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4298 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4301 const char *vcfg
= NULL
;
4306 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4309 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4310 grub_env_set(args
[1], vcfg
);
4315 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4323 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4326 grub_uint8_t zeroguid
[16] = {0};
4331 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4334 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4336 if (id
>= 1 && id
<= 128)
4338 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4346 if (id
>= 1 && id
<= 4)
4348 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4358 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4361 char *device_name
= NULL
;
4362 grub_device_t dev
= NULL
;
4363 grub_fs_t fs
= NULL
;
4368 debug("get fs label for %s\n", args
[0]);
4372 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4376 device_name
= grub_file_get_device_name(args
[0]);
4379 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4383 dev
= grub_device_open(device_name
);
4386 debug("grub_device_open failed, %s\n", device_name
);
4390 fs
= grub_fs_probe(dev
);
4391 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4393 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4397 fs
->fs_label(dev
, &label
);
4400 debug("label=<%s>\n", label
);
4401 ventoy_set_env(args
[1], label
);
4409 check_free(device_name
, grub_free
);
4410 check_free(dev
, grub_device_close
);
4415 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4419 grub_snprintf((char *)data
, 256, "%s", filename
);
4426 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4428 if (info
->dir
&& filename
&& filename
[0] != '.')
4430 grub_snprintf((char *)data
, 256, "%s", filename
);
4437 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4440 char *device_name
= NULL
;
4441 grub_device_t dev
= NULL
;
4442 grub_fs_t fs
= NULL
;
4443 char name
[256] ={0};
4447 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4451 device_name
= grub_file_get_device_name(args
[0]);
4454 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4458 dev
= grub_device_open(device_name
);
4461 debug("grub_device_open failed, %s\n", device_name
);
4465 fs
= grub_fs_probe(dev
);
4468 debug("grub_fs_probe failed, %s\n", device_name
);
4472 fs
->fs_dir(dev
, args
[1], hook
, name
);
4475 ventoy_set_env(args
[2], name
);
4482 check_free(device_name
, grub_free
);
4483 check_free(dev
, grub_device_close
);
4488 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4491 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4494 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4497 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4500 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4510 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4514 for (pos
= args
[0]; *pos
; pos
++)
4528 grub_env_set(args
[1], args
[0]);
4538 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4548 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4553 len
= (int)grub_strlen(buf
);
4554 for (i
= len
; i
> 0; i
--)
4556 if (buf
[i
- 1] == '/')
4558 grub_env_set(args
[1], buf
+ i
);
4563 grub_env_set(args
[1], buf
);
4568 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4570 struct grub_video_mode_info info
;
4577 if (!g_video_mode_list
)
4579 ventoy_enum_video_mode();
4582 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4584 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4588 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4591 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4593 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4594 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4596 VENTOY_CMD_RETURN(0);
4599 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4601 struct grub_video_mode_info info
;
4608 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4610 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4614 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4617 grub_env_set(args
[0], buf
);
4619 VENTOY_CMD_RETURN(0);
4622 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4630 if (!g_video_mode_list
)
4635 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4636 if (id
< g_video_mode_num
)
4638 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4639 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4642 grub_env_set(args
[1], buf
);
4644 VENTOY_CMD_RETURN(0);
4647 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4650 grub_uint32_t loadsector
= 0;
4653 grub_uint32_t boot_catlog
= 0;
4654 grub_uint8_t buf
[512];
4660 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4664 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4667 debug("failed to open %s\n", args
[0]);
4671 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4672 if (boot_catlog
== 0)
4674 debug("No bootcatlog found\n");
4675 grub_file_close(file
);
4679 grub_memset(buf
, 0, sizeof(buf
));
4680 grub_file_seek(file
, boot_catlog
* 2048);
4681 grub_file_read(file
, buf
, sizeof(buf
));
4682 grub_file_close(file
);
4684 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4686 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4688 if (buf
[i
+ 32] == 0x88)
4690 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4691 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4697 if (loadsector
== 0)
4699 debug("No EFI eltorito info found\n");
4703 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4704 grub_env_set(args
[1], value
);
4705 VENTOY_CMD_RETURN(0);
4708 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4713 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4715 if (pfsdir
->initrd
[0])
4720 curpos
= pfsdir
->curpos
;
4721 len
= grub_strlen(filename
);
4725 if ((len
== 1 && filename
[0] == '.') ||
4726 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4731 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4734 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4735 pfsdir
->curpos
= curpos
+ printlen
;
4736 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4737 pfsdir
->curpos
= curpos
;
4738 pfsdir
->fullpath
[curpos
] = 0;
4742 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4745 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4746 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4748 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4750 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4759 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4763 char *device_name
= NULL
;
4764 grub_device_t dev
= NULL
;
4765 grub_fs_t fs
= NULL
;
4766 replace_fs_dir
*pfsdir
= NULL
;
4772 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4776 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4782 device_name
= grub_file_get_device_name(args
[0]);
4788 dev
= grub_device_open(device_name
);
4794 fs
= grub_fs_probe(dev
);
4803 pfsdir
->fullpath
[0] = '/';
4804 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4806 if (pfsdir
->initrd
[0])
4808 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4810 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4812 if (pfsdir
->initrd
[i
] == '/')
4814 pfsdir
->initrd
[i
] = '\\';
4818 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4819 grub_env_set(args
[1], pos
);
4823 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4828 grub_check_free(pfsdir
);
4829 grub_check_free(device_name
);
4830 check_free(dev
, grub_device_close
);
4832 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4835 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4837 const char *pager
= NULL
;
4843 pager
= grub_env_get("pager");
4847 grub_env_set("pager", "1");
4849 else if (pager
[0] == '1')
4855 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4857 grub_env_set("pager", "1");
4860 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4863 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4869 if (g_pager_flag
== 1)
4871 grub_env_unset("pager");
4873 else if (g_pager_flag
== 2)
4875 grub_env_set("pager", g_old_pager
);
4878 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4881 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4883 if (g_json_case_mis_path
[0])
4888 if (0 == info
->dir
&& grub_strcasecmp(filename
, "ventoy.json") == 0)
4890 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4896 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4899 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4901 if (g_json_case_mis_path
[0])
4906 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4908 if (grub_strcasecmp(filename
, "ventoy") == 0)
4910 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4911 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4912 if (g_json_case_mis_path
[0])
4922 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4925 char *device_name
= NULL
;
4926 grub_device_t dev
= NULL
;
4927 grub_fs_t fs
= NULL
;
4928 chk_case_fs_dir fs_dir
;
4934 device_name
= grub_file_get_device_name(args
[0]);
4940 dev
= grub_device_open(device_name
);
4946 fs
= grub_fs_probe(dev
);
4952 fstype
= ventoy_get_fs_type(fs
->name
);
4953 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4958 g_json_case_mis_path
[0] = 0;
4961 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4963 if (g_json_case_mis_path
[0])
4965 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4970 grub_check_free(device_name
);
4971 check_free(dev
, grub_device_close
);
4973 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4976 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4979 grub_partition_t part
;
4980 char priority_str
[3]; /* Maximum value 15 */
4984 if (argc
< 2 || argc
> 3)
4985 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4986 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4988 /* Open the disk if it exists */
4989 disk
= grub_disk_open (args
[0]);
4992 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4996 part
= grub_partition_probe (disk
, args
[1]);
4999 grub_disk_close (disk
);
5000 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
5001 "No such partition");
5004 if (grub_strcmp (part
->partmap
->name
, "gpt"))
5006 grub_disk_close (disk
);
5007 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
5008 "Not a GPT partition");
5011 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
5012 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
5016 grub_env_set (args
[2], priority_str
);
5017 grub_env_export (args
[2]);
5021 grub_printf ("Priority is %s\n", priority_str
);
5024 grub_disk_close (disk
);
5025 return GRUB_ERR_NONE
;
5029 static grub_err_t
grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
5033 grub_file_t file
= NULL
;
5034 grub_uint32_t loadrba
= 0;
5035 grub_uint32_t boot_catlog
= 0;
5036 grub_uint8_t sector
[512];
5037 boot_info_table
*info
= NULL
;
5042 /* This also trigger a iso9660 fs parse */
5043 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5048 joliet
= grub_iso9660_is_joliet();
5054 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
5057 debug("failed to open %s\n", args
[0]);
5061 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
5062 if (boot_catlog
== 0)
5064 debug("no bootcatlog found %u\n", boot_catlog
);
5068 loadrba
= ventoy_get_bios_eltorito_rba(file
, boot_catlog
);
5071 debug("no bios eltorito rba found %u\n", loadrba
);
5075 grub_file_seek(file
, loadrba
* 2048);
5076 grub_file_read(file
, sector
, 512);
5078 info
= (boot_info_table
*)sector
;
5079 if (info
->bi_data0
== 0x7c6ceafa &&
5080 info
->bi_data1
== 0x90900000 &&
5081 info
->bi_PrimaryVolumeDescriptor
== 16 &&
5082 info
->bi_BootFileLocation
== loadrba
)
5084 debug("bootloader is syslinux, %u.\n", loadrba
);
5090 grub_file_close(file
);
5091 grub_errno
= GRUB_ERR_NONE
;
5095 int ventoy_env_init(void)
5099 grub_env_set("vtdebug_flag", "");
5101 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5102 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5103 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5104 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5106 ventoy_filt_register(0, ventoy_wrapper_open
);
5108 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5111 g_grub_param
->grub_env_get
= grub_env_get
;
5112 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5113 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5114 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5115 grub_env_set("env_param", buf
);
5116 grub_env_set("ventoy_env_param", buf
);
5118 grub_env_export("env_param");
5119 grub_env_export("ventoy_env_param");
5122 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5123 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5125 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5126 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5128 grub_env_export("vtoy_winpeshl_ini_addr");
5129 grub_env_export("vtoy_winpeshl_ini_size");
5131 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5132 grub_env_set("vtoy_chain_file_size", buf
);
5133 grub_env_export("vtoy_chain_file_size");
5135 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5136 grub_env_set("vtoy_chain_file_read", buf
);
5137 grub_env_export("vtoy_chain_file_read");
5144 static cmd_para ventoy_cmds
[] =
5146 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5147 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5148 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5149 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5150 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5151 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5152 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5153 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5154 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5155 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5156 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5157 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5158 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5159 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5160 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5161 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5162 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5163 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5164 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5165 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5166 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5167 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5168 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5169 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5170 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5172 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5173 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5174 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5175 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5176 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5177 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5178 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5180 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5181 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5182 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5183 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5184 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5185 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5186 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5187 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5188 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5189 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5192 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5193 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5194 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5195 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5196 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5197 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5198 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5199 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5200 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5201 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5202 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5204 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5205 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5206 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5207 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5208 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5209 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5210 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5212 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5213 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5214 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5215 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5216 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5217 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5218 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5219 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5220 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5221 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5223 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5224 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5225 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5226 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5227 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5228 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5229 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5230 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5231 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5233 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5234 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5235 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5236 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5239 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5240 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5241 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5243 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5244 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5245 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5248 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5249 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5250 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5251 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5252 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5253 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5254 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5255 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5256 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5257 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5258 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5260 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5261 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5262 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5263 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5264 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5265 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5266 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5267 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5268 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5269 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5271 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5272 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5273 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5274 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5275 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5276 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5277 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5278 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet
, 0, NULL
, "", "", NULL
},
5281 int ventoy_register_all_cmd(void)
5284 cmd_para
*cur
= NULL
;
5286 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5288 cur
= ventoy_cmds
+ i
;
5289 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5290 cur
->summary
, cur
->description
, cur
->parser
);
5296 int ventoy_unregister_all_cmd(void)
5300 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5302 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);