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_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
926 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
928 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
931 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
936 value_long
+= grub_strtol(args
[1], NULL
, 10);
938 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
939 grub_env_set(args
[0], buf
);
941 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
944 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
946 ulonglong value1
= 0;
947 ulonglong value2
= 0;
952 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
955 value1
= grub_strtoull(args
[0], NULL
, 10);
956 value2
= grub_strtoull(args
[1], NULL
, 10);
958 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
959 grub_env_set(args
[2], buf
);
961 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
964 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
979 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
982 debug("failed to open file <%s> for udf check\n", args
[0]);
986 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
988 grub_env_set(args
[1], buf
);
990 grub_file_close(file
);
996 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1004 g_wimboot_enable
= 0;
1005 grub_check_free(g_wimiso_path
);
1006 grub_check_free(g_wimiso_chunk_list
.chunk
);
1008 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1014 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1015 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1016 if (NULL
== g_wimiso_chunk_list
.chunk
)
1018 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1021 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1022 g_wimiso_chunk_list
.cur_chunk
= 0;
1024 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1026 g_wimboot_enable
= 1;
1027 g_wimiso_path
= grub_strdup(args
[0]);
1029 grub_file_close(file
);
1034 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1044 ventoy_iso9660_override
*dirent
;
1053 totlen
= sizeof(ventoy_chain_head
);
1055 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1057 debug("failed to load efiboot template %d\n", len
);
1063 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1065 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1068 debug("failed to open file <%s>\n", args
[0]);
1072 totlen
+= ventoy_align_2k(file
->size
);
1074 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1075 dirent
->first_sector
= len
/ 2048;
1076 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1077 dirent
->size
= (grub_uint32_t
)file
->size
;
1078 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1080 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1082 #ifdef GRUB_MACHINE_EFI
1083 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1085 data
= (char *)grub_malloc(totlen
);
1088 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1090 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1091 grub_check_free(buf
);
1093 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1094 grub_file_close(file
);
1096 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1097 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1098 grub_env_set(name
, value
);
1100 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1101 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1102 grub_env_set(name
, value
);
1107 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1113 g_vtoy_load_prompt
= 0;
1114 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1116 if (argc
== 2 && args
[0][0] == '1')
1118 g_vtoy_load_prompt
= 1;
1119 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1122 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1125 int ventoy_need_prompt_load_file(void)
1127 return g_vtoy_load_prompt
;
1130 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1132 grub_uint64_t ro
= 0;
1133 grub_uint64_t div
= 0;
1134 grub_ssize_t left
= size
;
1135 char *cur
= (char *)buf
;
1137 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1140 while (left
>= VTOY_SIZE_2MB
)
1142 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1143 cur
+= VTOY_SIZE_2MB
;
1144 left
-= VTOY_SIZE_2MB
;
1146 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1147 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1153 grub_file_read(file
, cur
, left
);
1156 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1162 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1169 enum grub_file_type type
;
1180 if (grub_strcmp(args
[0], "nodecompress") == 0)
1182 type
= VENTOY_FILE_TYPE
;
1186 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1189 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1192 debug("failed to open file <%s>\n", args
[1]);
1196 #ifdef GRUB_MACHINE_EFI
1197 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1199 buf
= (char *)grub_malloc(file
->size
);
1204 grub_file_close(file
);
1208 if (g_vtoy_load_prompt
)
1210 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1214 grub_file_read(file
, buf
, file
->size
);
1217 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1218 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1219 grub_env_set(name
, value
);
1221 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1222 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1223 grub_env_set(name
, value
);
1225 grub_file_close(file
);
1231 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1249 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1252 debug("failed to open file <%s> for udf check\n", args
[0]);
1256 headlen
= sizeof(ventoy_chain_head
);
1258 #ifdef GRUB_MACHINE_EFI
1259 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1261 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1264 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1266 grub_file_read(file
, buf
+ headlen
, file
->size
);
1268 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1269 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1270 grub_env_set(name
, value
);
1272 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1273 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1274 grub_env_set(name
, value
);
1276 grub_file_close(file
);
1282 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1288 if (grub_iso9660_is_joliet())
1290 debug("This time has joliet process\n");
1299 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1308 if (args
[0][0] == '1')
1310 grub_iso9660_set_nojoliet(1);
1314 grub_iso9660_set_nojoliet(0);
1320 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1325 grub_uint8_t buf
[32];
1336 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1339 debug("failed to open file <%s> for udf check\n", args
[0]);
1343 for (i
= 16; i
< 32; i
++)
1345 grub_file_seek(file
, i
* 2048);
1346 grub_file_read(file
, buf
, sizeof(buf
));
1354 grub_file_seek(file
, i
* 2048);
1355 grub_file_read(file
, buf
, sizeof(buf
));
1357 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1360 grub_file_seek(file
, i
* 2048);
1361 grub_file_read(file
, buf
, sizeof(buf
));
1363 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1364 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1370 grub_file_close(file
);
1372 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1377 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1379 long value_long1
= 0;
1380 long value_long2
= 0;
1382 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1384 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1387 value_long1
= grub_strtol(args
[0], NULL
, 10);
1388 value_long2
= grub_strtol(args
[2], NULL
, 10);
1390 if (0 == grub_strcmp(args
[1], "eq"))
1392 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1394 else if (0 == grub_strcmp(args
[1], "ne"))
1396 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1398 else if (0 == grub_strcmp(args
[1], "gt"))
1400 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1402 else if (0 == grub_strcmp(args
[1], "lt"))
1404 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1406 else if (0 == grub_strcmp(args
[1], "ge"))
1408 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1410 else if (0 == grub_strcmp(args
[1], "le"))
1412 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1416 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1422 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1425 char buf
[128] = {0};
1429 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1432 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1433 pos
= grub_strstr(buf
, ",");
1439 grub_env_set(args
[1], buf
);
1441 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1444 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1450 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1456 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1459 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1461 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1462 if (0 == grub_script_execute_sourcecode(buf
))
1464 debug("file %s exist, ventoy_compatible YES\n", buf
);
1465 grub_env_set("ventoy_compatible", "YES");
1466 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1470 debug("file %s NOT exist\n", buf
);
1474 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1475 pos
= grub_strstr(buf
, ")");
1481 disk
= grub_disk_open(buf
);
1484 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1485 grub_disk_close(disk
);
1487 g_img_swap_tmp_buf
[703] = 0;
1488 for (i
= 318; i
< 703; i
++)
1490 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1491 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1493 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1494 grub_env_set("ventoy_compatible", "YES");
1495 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1501 debug("failed to open disk <%s>\n", buf
);
1504 grub_env_set("ventoy_compatible", "NO");
1505 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1508 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1514 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1516 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1519 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1524 if (0 == g_sort_case_sensitive
)
1526 if (grub_islower(c1
))
1528 c1
= c1
- 'a' + 'A';
1531 if (grub_islower(c2
))
1533 c2
= c2
- 'a' + 'A';
1546 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1552 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1554 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1557 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1562 if (0 == g_sort_case_sensitive
)
1564 if (grub_islower(c1
))
1566 c1
= c1
- 'a' + 'A';
1569 if (grub_islower(c2
))
1571 c2
= c2
- 'a' + 'A';
1584 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1586 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1588 grub_memcpy(img1
, img2
, sizeof(img_info
));
1589 img1
->next
= g_img_swap_tmp
.next
;
1590 img1
->prev
= g_img_swap_tmp
.prev
;
1592 g_img_swap_tmp
.next
= img2
->next
;
1593 g_img_swap_tmp
.prev
= img2
->prev
;
1594 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1597 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1601 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1609 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1618 const menu_tip
*tip
;
1619 img_iterator_node
*tmp
;
1620 img_iterator_node
*new_node
;
1621 img_iterator_node
*node
= (img_iterator_node
*)data
;
1623 if (g_enumerate_time_checked
== 0)
1625 g_enumerate_finish_time_ms
= grub_get_time_ms();
1626 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1629 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1631 g_enumerate_time_checked
= 1;
1635 len
= grub_strlen(filename
);
1639 if (node
->level
+ 1 > g_img_max_search_level
)
1644 if ((len
== 1 && filename
[0] == '.') ||
1645 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1650 if (!ventoy_img_name_valid(filename
, len
))
1655 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1660 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1662 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1663 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1666 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1671 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1674 new_node
->level
= node
->level
+ 1;
1675 new_node
->plugin_list_index
= index
;
1676 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1678 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1681 debug("Directory %s ignored...\n", new_node
->dir
);
1682 grub_free(new_node
);
1686 new_node
->tail
= node
->tail
;
1688 new_node
->parent
= node
;
1689 if (!node
->firstchild
)
1691 node
->firstchild
= new_node
;
1694 if (g_img_iterator_tail
)
1696 g_img_iterator_tail
->next
= new_node
;
1697 g_img_iterator_tail
= new_node
;
1701 g_img_iterator_head
.next
= new_node
;
1702 g_img_iterator_tail
= new_node
;
1708 debug("Find a file %s\n", filename
);
1714 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1716 type
= img_type_iso
;
1718 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1720 type
= img_type_wim
;
1722 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1723 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1725 type
= img_type_vhd
;
1727 #ifdef GRUB_MACHINE_EFI
1728 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1730 type
= img_type_efi
;
1733 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1735 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1737 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1738 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1743 type
= img_type_img
;
1745 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1747 type
= img_type_vtoy
;
1749 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1751 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1753 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1754 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1763 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1768 if (g_plugin_image_list
)
1770 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1771 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1772 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1774 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1777 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1779 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1784 img
= grub_zalloc(sizeof(img_info
));
1788 img
->plugin_list_index
= index
;
1789 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1791 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1793 img
->size
= info
->size
;
1796 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1799 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1801 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1806 if (g_ventoy_img_list
)
1808 tail
= *(node
->tail
);
1814 g_ventoy_img_list
= img
;
1817 img
->id
= g_ventoy_img_count
;
1819 if (node
&& NULL
== node
->firstiso
)
1821 node
->firstiso
= img
;
1832 *((img_info
**)(node
->tail
)) = img
;
1833 g_ventoy_img_count
++;
1835 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1837 tip
= ventoy_plugin_get_menu_tip(img
->path
);
1840 img
->tip1
= tip
->tip1
;
1841 img
->tip2
= tip
->tip2
;
1844 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1847 img
->class = g_menu_class
[type
];
1849 img
->menu_prefix
= g_menu_prefix
[type
];
1851 if (img_type_iso
== type
)
1853 if (ventoy_plugin_check_memdisk(img
->path
))
1855 img
->menu_prefix
= "miso";
1859 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1866 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1868 int len
= GRUB_UINT_MAX
;
1869 const char *value
= NULL
;
1870 char name
[32] = {0};
1871 char plat
[32] = {0};
1872 char guidstr
[32] = {0};
1873 ventoy_guid guid
= VENTOY_GUID
;
1874 const char *fmt1
= NULL
;
1875 const char *fmt2
= NULL
;
1876 const char *fmt3
= NULL
;
1877 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1878 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1879 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1880 const char fmtcode
[]={
1881 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1882 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1883 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1884 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1885 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1886 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1889 grub_memset(name
, 0, sizeof(name
));
1890 puint
[0] = grub_swap_bytes32(0x56454e54);
1891 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1892 puint
[2] = grub_swap_bytes32(0x45525349);
1893 puint
[1] = grub_swap_bytes32(0x4f595f56);
1894 value
= ventoy_get_env(name
);
1896 grub_memset(name
, 0, sizeof(name
));
1897 puint
[1] = grub_swap_bytes32(0x5f544f50);
1898 puint
[0] = grub_swap_bytes32(0x56544c45);
1899 fmt1
= ventoy_get_env(name
);
1905 grub_memset(name
, 0, sizeof(name
));
1906 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1907 puint
[0] = grub_swap_bytes32(0x56544c45);
1908 fmt2
= ventoy_get_env(name
);
1910 grub_memset(name
, 0, sizeof(name
));
1911 puint
[1] = grub_swap_bytes32(0x5f434c52);
1912 puint
[0] = grub_swap_bytes32(0x56544c45);
1913 fmt3
= ventoy_get_env(name
);
1915 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1917 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1919 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1920 #pragma GCC diagnostic push
1921 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1922 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1923 fmt1
? fmt1
: fmtdata
,
1924 fmt2
? fmt2
: fmtdata
+ 4,
1925 value
? value
: "", plat
, guidstr
,
1926 fmt3
? fmt3
: fmtdata
+ 6);
1927 #pragma GCC diagnostic pop
1929 grub_memset(name
, 0, sizeof(name
));
1930 puint
[0] = grub_swap_bytes32(0x76746f79);
1931 puint
[2] = grub_swap_bytes32(0x656e7365);
1932 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1933 ventoy_set_env(name
, guidstr
);
1938 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1942 grub_uint8_t md5
[16];
1946 grub_memset(input
, 0, sizeof(input
));
1948 grub_printf("Enter password: ");
1951 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1953 grub_password_get(input
, 128);
1954 if (grub_strcmp(pwd
->text
, input
) == 0)
1959 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1961 grub_password_get(input
, 128);
1962 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1963 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1968 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1970 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1971 grub_password_get(input
+ offset
, 128);
1973 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1974 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1980 grub_printf("Invalid password!\n\n");
1987 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1989 img_info
*minimg
= NULL
;
1990 img_info
*img
= (img_info
*)(node
->firstiso
);
1992 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1994 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2009 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2011 img_iterator_node
*Minchild
= NULL
;
2012 img_iterator_node
*child
= node
->firstchild
;
2014 while (child
&& child
->parent
== node
)
2016 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2020 child
= child
->next
;
2025 Minchild
->select
= 1;
2031 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2034 img_info
*img
= NULL
;
2035 const char *dir_class
= NULL
;
2036 const char *dir_alias
= NULL
;
2037 img_iterator_node
*child
= NULL
;
2039 if (node
->isocnt
== 0 || node
->done
== 1)
2044 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2046 offset
= node
->parent
->dirlen
;
2049 if (node
== &g_img_iterator_head
)
2051 if (g_default_menu_mode
== 0)
2053 if (g_tree_view_menu_style
== 0)
2055 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2056 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2057 " echo 'return ...' \n"
2062 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2063 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2071 node
->dir
[node
->dirlen
- 1] = 0;
2072 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2075 dir_class
= "vtoydir";
2078 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2081 if (g_tree_view_menu_style
== 0)
2083 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2084 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2085 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2089 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2090 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2091 dir_alias
, dir_class
, node
->dir
+ offset
);
2096 dir_alias
= node
->dir
+ offset
;
2098 if (g_tree_view_menu_style
== 0)
2100 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2101 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2102 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2106 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2107 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2108 dir_alias
, dir_class
, node
->dir
+ offset
);
2112 if (g_tree_view_menu_style
== 0)
2114 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2115 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2116 " echo 'return ...' \n"
2121 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2122 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2128 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2130 ventoy_dynamic_tree_menu(child
);
2133 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2135 if (g_tree_view_menu_style
== 0)
2137 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2138 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2141 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2142 img
->unsupport
? "[***********] " : "",
2143 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2145 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2149 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2150 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2153 img
->unsupport
? "[***********] " : "",
2154 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2156 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2160 if (node
!= &g_img_iterator_head
)
2162 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2169 static int ventoy_set_default_menu(void)
2175 const char *strdata
= NULL
;
2176 img_info
*cur
= NULL
;
2177 img_info
*default_node
= NULL
;
2178 const char *default_image
= NULL
;
2180 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2181 if (default_image
&& default_image
[0] == '/')
2183 img_len
= grub_strlen(default_image
);
2185 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2187 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2199 if (0 == g_default_menu_mode
)
2201 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2205 def
= grub_strdup(default_image
);
2211 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2213 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2214 if (strdata
&& strdata
[0] == '/')
2216 pos
= def
+ grub_strlen(strdata
);
2227 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2230 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2234 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2242 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2244 img_info
*next
= NULL
;
2245 img_info
*cur
= g_ventoy_img_list
;
2258 g_ventoy_img_list
= NULL
;
2259 g_ventoy_img_count
= 0;
2261 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2264 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2267 img_info
*cur
= g_ventoy_img_list
;
2271 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2273 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2276 img_id
= grub_strtol(args
[0], NULL
, 10);
2277 if (img_id
>= g_ventoy_img_count
)
2279 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2282 debug("Find image %ld name \n", img_id
);
2284 while (cur
&& img_id
> 0)
2292 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2295 debug("image name is %s\n", cur
->name
);
2297 grub_env_set(args
[1], cur
->name
);
2299 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2302 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2306 img_info
*cur
= g_ventoy_img_list
;
2312 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2315 len
= (int)grub_strlen(args
[0]);
2319 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2328 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2331 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2332 grub_env_set("chosen", id
);
2333 grub_env_export("chosen");
2335 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2338 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2342 const char *id
= NULL
;
2343 img_info
*cur
= NULL
;
2347 if (argc
< 1 || argc
> 2)
2349 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2352 id
= grub_env_get("chosen");
2354 pos
= grub_strstr(id
, "VID_");
2357 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2361 cur
= g_ventoy_img_list
;
2366 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2369 grub_env_set(args
[0], cur
->path
);
2373 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2374 grub_env_set(args
[1], value
);
2377 g_svd_replace_offset
= 0;
2379 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2383 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2387 grub_device_t dev
= NULL
;
2388 img_info
*cur
= NULL
;
2389 img_info
*tail
= NULL
;
2390 img_info
*min
= NULL
;
2391 img_info
*head
= NULL
;
2392 const char *strdata
= NULL
;
2393 char *device_name
= NULL
;
2395 img_iterator_node
*node
= NULL
;
2396 img_iterator_node
*tmp
= NULL
;
2402 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2405 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2407 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2412 g_enumerate_time_checked
= 0;
2413 g_enumerate_start_time_ms
= grub_get_time_ms();
2415 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2416 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2418 g_filt_dot_underscore_file
= 1;
2421 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2422 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2424 g_sort_case_sensitive
= 1;
2427 device_name
= grub_file_get_device_name(args
[0]);
2433 g_enum_dev
= dev
= grub_device_open(device_name
);
2439 g_enum_fs
= fs
= grub_fs_probe(dev
);
2445 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2447 debug("unsupported fs:<%s>\n", fs
->name
);
2448 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2452 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2454 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2455 if (strdata
&& strdata
[0] == '1')
2457 g_default_menu_mode
= 1;
2460 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2462 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2464 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2465 if (strdata
&& strdata
[0] == '/')
2467 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2468 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2470 g_img_iterator_head
.dir
[len
++] = '/';
2472 g_img_iterator_head
.dirlen
= len
;
2476 g_img_iterator_head
.dirlen
= 1;
2477 grub_strcpy(g_img_iterator_head
.dir
, "/");
2480 g_img_iterator_head
.tail
= &tail
;
2482 if (g_img_max_search_level
< 0)
2484 g_img_max_search_level
= GRUB_INT_MAX
;
2485 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2486 if (strdata
&& ventoy_is_decimal(strdata
))
2488 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2492 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2493 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2494 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2495 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2496 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2497 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2499 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2501 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2504 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2505 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2507 g_tree_view_menu_style
= 1;
2510 ventoy_set_default_menu();
2512 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2514 ventoy_dynamic_tree_menu(node
);
2518 node
= g_img_iterator_head
.next
;
2526 /* sort image list by image name */
2527 while (g_ventoy_img_list
)
2529 min
= g_ventoy_img_list
;
2530 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2532 if (ventoy_cmp_img(min
, cur
) > 0)
2540 min
->prev
->next
= min
->next
;
2545 min
->next
->prev
= min
->prev
;
2548 if (min
== g_ventoy_img_list
)
2550 g_ventoy_img_list
= min
->next
;
2568 g_ventoy_img_list
= head
;
2570 if (g_default_menu_mode
== 1)
2572 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2573 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2574 " echo 'return ...' \n"
2578 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2580 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2581 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2584 cur
->unsupport
? "[***********] " : "",
2585 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2587 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2590 g_tree_script_buf
[g_tree_script_pos
] = 0;
2591 g_list_script_buf
[g_list_script_pos
] = 0;
2593 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2594 grub_env_set(args
[1], buf
);
2598 check_free(device_name
, grub_free
);
2599 check_free(dev
, grub_device_close
);
2601 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2604 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2611 device_name
= grub_file_get_device_name(filename
);
2623 pos2
= grub_strstr(pos
, ",");
2626 pos2
= grub_strstr(pos
, ")");
2634 disk
= grub_disk_open(pos
);
2637 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2638 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2639 grub_disk_close(disk
);
2646 grub_free(device_name
);
2650 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2652 eltorito_descriptor desc
;
2654 grub_memset(&desc
, 0, sizeof(desc
));
2655 grub_file_seek(file
, 17 * 2048);
2656 grub_file_read(file
, &desc
, sizeof(desc
));
2658 if (desc
.type
!= 0 || desc
.version
!= 1)
2663 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2664 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2672 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2676 grub_uint8_t buf
[512];
2677 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2679 grub_file_seek(file
, sector
* 2048);
2680 grub_file_read(file
, buf
, sizeof(buf
));
2682 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2684 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2688 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2693 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2695 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2697 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2701 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2703 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2708 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2710 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2712 if (buf
[36] == parttype
[i
])
2714 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2720 debug("%s does not contain efi eltorito\n", file
->name
);
2724 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2727 const char *fs
= NULL
;
2728 const char *cdprompt
= NULL
;
2730 grub_uint8_t chksum
= 0;
2733 disk
= file
->device
->disk
;
2734 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2736 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2737 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2738 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2740 pos
= grub_strstr(file
->name
, "/");
2746 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2748 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2750 param
->vtoy_img_size
= file
->size
;
2752 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2753 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2755 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2757 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2758 param
->vtoy_reserved
[4] = 0;
2759 if (g_ventoy_chain_type
== 1) /* Windows */
2761 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2762 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2764 param
->vtoy_reserved
[4] = 1;
2768 fs
= ventoy_get_env("ventoy_fs_probe");
2769 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2771 param
->vtoy_reserved
[3] = 1;
2774 /* calculate checksum */
2775 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2777 chksum
+= *((grub_uint8_t
*)param
+ i
);
2779 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2784 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2786 grub_uint32_t i
= 0;
2787 grub_uint64_t total
= 0;
2788 grub_uint64_t fileblk
= 0;
2789 ventoy_img_chunk
*chunk
= NULL
;
2791 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2793 chunk
= chunklist
->chunk
+ i
;
2795 if (chunk
->disk_start_sector
<= start
)
2797 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2801 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2804 fileblk
= (file
->size
+ 511) / 512;
2806 if (total
!= fileblk
)
2808 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2809 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2811 debug("maybe img file to be processed.\n");
2821 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2825 grub_uint32_t i
= 0;
2826 grub_uint32_t sector
= 0;
2827 grub_uint32_t count
= 0;
2828 grub_off_t size
= 0;
2829 grub_off_t read
= 0;
2831 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2832 if (fs_type
== ventoy_fs_exfat
)
2834 grub_fat_get_file_chunk(start
, file
, chunklist
);
2836 else if (fs_type
== ventoy_fs_ext
)
2838 grub_ext_get_file_chunk(start
, file
, chunklist
);
2842 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2843 file
->read_hook_data
= chunklist
;
2845 for (size
= file
->size
; size
> 0; size
-= read
)
2847 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2848 grub_file_read(file
, NULL
, read
);
2851 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2853 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2854 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2857 if (ventoy_fs_udf
== fs_type
)
2859 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2861 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2862 chunklist
->chunk
[i
].img_start_sector
= sector
;
2863 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2869 len
= (int)grub_strlen(file
->name
);
2870 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2871 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2872 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2873 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2875 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2877 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2887 chunklist
->chunk
[i
].img_start_sector
= sector
;
2888 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2896 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2900 grub_disk_addr_t start
;
2905 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2908 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2911 g_conf_replace_node
= NULL
;
2912 g_conf_replace_offset
= 0;
2914 if (g_img_chunk_list
.chunk
)
2916 grub_free(g_img_chunk_list
.chunk
);
2919 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2921 grub_file_close(file
);
2922 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2925 /* get image chunk data */
2926 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2927 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2928 if (NULL
== g_img_chunk_list
.chunk
)
2930 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2933 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2934 g_img_chunk_list
.cur_chunk
= 0;
2936 start
= file
->device
->disk
->partition
->start
;
2938 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2940 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2941 grub_file_close(file
);
2945 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2948 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2949 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2952 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2954 grub_uint64_t offset
= 0;
2955 grub_uint32_t align
= 0;
2956 grub_file_t file
= NULL
;
2957 conf_replace
*node
= NULL
;
2963 debug("select conf replace argc:%d\n", argc
);
2970 node
= ventoy_plugin_find_conf_replace(args
[1]);
2973 debug("Conf replace not found for %s\n", args
[1]);
2977 debug("Find conf replace for %s\n", args
[1]);
2979 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2982 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2986 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2987 grub_file_close(file
);
2989 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2992 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
2996 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
2998 if (align
> vtoy_max_replace_file_size
)
3000 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3004 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3005 g_conf_replace_new_len
= (int)file
->size
;
3006 g_conf_replace_new_len_align
= align
;
3008 g_conf_replace_node
= node
;
3009 g_conf_replace_offset
= offset
+ 2;
3011 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3016 grub_file_close(file
);
3018 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3021 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3027 char configfile
[128];
3028 install_template
*node
= NULL
;
3034 debug("select auto installation argc:%d\n", argc
);
3041 node
= ventoy_plugin_find_install_template(args
[0]);
3044 debug("Auto install template not found for %s\n", args
[0]);
3048 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3050 defidx
= node
->autosel
;
3051 if (node
->timeout
< 0)
3053 node
->cursel
= node
->autosel
- 1;
3054 debug("Auto install template auto select %d\n", node
->autosel
);
3059 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3065 if (node
->timeout
> 0)
3067 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3070 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3071 " echo %s\n}\n", "");
3073 for (i
= 0; i
< node
->templatenum
; i
++)
3075 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3077 node
->templatepath
[i
].path
);
3080 g_ventoy_menu_esc
= 1;
3081 g_ventoy_suppress_esc
= 1;
3082 g_ventoy_suppress_esc_default
= defidx
;
3084 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3085 grub_script_execute_sourcecode(configfile
);
3087 g_ventoy_menu_esc
= 0;
3088 g_ventoy_suppress_esc
= 0;
3089 g_ventoy_suppress_esc_default
= 1;
3093 node
->cursel
= g_ventoy_last_entry
- 1;
3095 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3098 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3104 char configfile
[128];
3105 persistence_config
*node
;
3111 debug("select persistence argc:%d\n", argc
);
3118 node
= ventoy_plugin_find_persistent(args
[0]);
3121 debug("Persistence image not found for %s\n", args
[0]);
3125 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3127 defidx
= node
->autosel
;
3128 if (node
->timeout
< 0)
3130 node
->cursel
= node
->autosel
- 1;
3131 debug("Persistence image auto select %d\n", node
->autosel
);
3136 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3142 if (node
->timeout
> 0)
3144 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3147 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3148 " echo %s\n}\n", "");
3150 for (i
= 0; i
< node
->backendnum
; i
++)
3152 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3154 node
->backendpath
[i
].path
);
3158 g_ventoy_menu_esc
= 1;
3159 g_ventoy_suppress_esc
= 1;
3160 g_ventoy_suppress_esc_default
= defidx
;
3162 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3163 grub_script_execute_sourcecode(configfile
);
3165 g_ventoy_menu_esc
= 0;
3166 g_ventoy_suppress_esc
= 0;
3167 g_ventoy_suppress_esc_default
= 1;
3171 node
->cursel
= g_ventoy_last_entry
- 1;
3173 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3176 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3179 ventoy_img_chunk
*cur
;
3185 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3187 cur
= g_img_chunk_list
.chunk
+ i
;
3188 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3189 cur
->img_start_sector
, cur
->img_end_sector
,
3190 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3194 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3197 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3201 ventoy_img_chunk_list chunklist
;
3206 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3209 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3212 /* get image chunk data */
3213 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3214 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3215 if (NULL
== chunklist
.chunk
)
3217 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3220 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3221 chunklist
.cur_chunk
= 0;
3223 ventoy_get_block_list(file
, &chunklist
, 0);
3225 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3227 grub_printf("########## UNSUPPORTED ###############\n");
3230 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3232 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3234 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3235 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3238 grub_printf("\n==================================\n");
3240 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3242 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3243 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3244 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3245 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3246 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3250 grub_free(chunklist
.chunk
);
3251 grub_file_close(file
);
3253 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3256 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3259 ventoy_grub_param_file_replace
*replace
= NULL
;
3267 replace
= &(g_grub_param
->file_replace
);
3268 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3270 replace
->old_name_cnt
= 0;
3271 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3273 replace
->old_name_cnt
++;
3274 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3277 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3280 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3283 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3286 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3292 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3293 grub_env_set(args
[0], buf
);
3296 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3299 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3307 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3308 grub_printf("%s", g_list_script_buf
);
3312 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3313 grub_printf("%s", g_tree_script_buf
);
3319 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3321 img_info
*cur
= g_ventoy_img_list
;
3329 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3330 grub_printf("name:<%s>\n\n", cur
->name
);
3337 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3343 ventoy_plugin_dump_injection();
3348 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3354 ventoy_plugin_dump_auto_install();
3359 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3365 ventoy_plugin_dump_persistence();
3370 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3381 if (args
[0][0] == '0')
3383 return g_ventoy_memdisk_mode
? 0 : 1;
3385 else if (args
[0][0] == '1')
3387 return g_ventoy_iso_raw
? 0 : 1;
3389 else if (args
[0][0] == '2')
3391 return g_ventoy_iso_uefi_drv
? 0 : 1;
3393 else if (args
[0][0] == '3')
3395 return g_ventoy_grub2_mode
? 0 : 1;
3397 else if (args
[0][0] == '4')
3399 return g_ventoy_wimboot_mode
? 0 : 1;
3405 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3407 static int configfile_mode
= 0;
3408 char memfile
[128] = {0};
3415 * args[0]: 0:normal 1:configfile
3416 * args[1]: 0:list_buf 1:tree_buf
3421 debug("Invalid argc %d\n", argc
);
3427 if (args
[0][0] == '0')
3429 if (args
[1][0] == '0')
3431 grub_script_execute_sourcecode(g_list_script_buf
);
3435 grub_script_execute_sourcecode(g_tree_script_buf
);
3440 if (configfile_mode
)
3442 debug("Now already in F3 mode %d\n", configfile_mode
);
3446 if (args
[1][0] == '0')
3448 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3449 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3453 g_ventoy_last_entry
= -1;
3454 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3455 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3458 configfile_mode
= 1;
3459 grub_script_execute_sourcecode(memfile
);
3460 configfile_mode
= 0;
3466 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3477 g_ventoy_case_insensitive
= 1;
3478 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3479 g_ventoy_case_insensitive
= 0;
3485 grub_file_close(file
);
3491 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3496 const char *isopath
= NULL
;
3498 ventoy_mbr_head mbr
;
3505 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3508 isopath
= grub_env_get("vtoy_iso_part");
3511 debug("isopath is null %p\n", isopath
);
3515 debug("isopath is %s\n", isopath
);
3517 for (id
= 0; id
< 30 && (find
== 0); id
++)
3519 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3520 if (grub_strstr(isopath
, hdname
))
3522 debug("skip %s ...\n", hdname
);
3526 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3528 disk
= grub_disk_open(hdname
);
3531 debug("%s not exist\n", hdname
);
3535 grub_memset(&mbr
, 0, sizeof(mbr
));
3536 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3538 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3540 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3541 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3544 grub_env_set(args
[0], hdname
);
3548 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3552 debug("read %s failed\n", hdname
);
3555 grub_disk_close(disk
);
3561 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3572 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3575 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3578 debug("failed to open file %s\n", args
[0]);
3582 buf
= grub_malloc(len
);
3589 grub_file_read(file
, buf
, len
- 1);
3591 ventoy_get_line(buf
);
3592 ventoy_set_env(args
[1], buf
);
3596 grub_check_free(buf
);
3597 grub_file_close(file
);
3602 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3604 int *pCnt
= (int *)data
;
3609 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3610 "0 %llu linear /dev/ventoy %llu\n",
3611 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3616 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3619 char *device_name
= NULL
;
3620 grub_device_t dev
= NULL
;
3625 g_part_list_pos
= 0;
3626 grub_env_unset("vtoy_img_part_file");
3633 device_name
= grub_file_get_device_name(args
[0]);
3636 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3640 dev
= grub_device_open(device_name
);
3643 debug("grub_device_open failed, %s\n", device_name
);
3647 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3649 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3650 grub_env_set("vtoy_img_part_file", buf
);
3652 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3653 grub_env_set("vtoy_img_part_cnt", buf
);
3657 check_free(device_name
, grub_free
);
3658 check_free(dev
, grub_device_close
);
3664 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3675 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3678 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3681 debug("failed to open file %s\n", args
[0]);
3685 buf
= grub_malloc(file
->size
+ 1);
3691 buf
[file
->size
] = 0;
3692 grub_file_read(file
, buf
, file
->size
);
3694 if (grub_strstr(buf
, args
[1]))
3701 grub_check_free(buf
);
3702 grub_file_close(file
);
3707 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3713 ventoy_iso9660_vd pvd
;
3720 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3723 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3726 debug("failed to open file %s\n", args
[0]);
3730 grub_file_seek(file
, 16 * 2048);
3731 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3732 if (len
!= sizeof(pvd
))
3734 debug("failed to read pvd %d\n", len
);
3738 grub_memset(buf
, 0, sizeof(buf
));
3739 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3740 ventoy_set_env(args
[1], buf
);
3742 grub_memset(buf
, 0, sizeof(buf
));
3743 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3744 ventoy_set_env(args
[2], buf
);
3748 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3749 ventoy_set_env(args
[3], buf
);
3752 grub_file_close(file
);
3757 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3768 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3771 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3774 debug("failed to open file %s\n", args
[0]);
3778 grub_memset(buf
, 0, sizeof(buf
));
3779 grub_file_seek(file
, 16 * 2048 + 813);
3780 len
= (int)grub_file_read(file
, buf
, 17);
3783 debug("failed to read create date %d\n", len
);
3787 ventoy_set_env(args
[1], buf
);
3790 grub_file_close(file
);
3795 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3801 ventoy_env_hook_root(1);
3806 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3812 ventoy_env_hook_root(0);
3817 #ifdef GRUB_MACHINE_EFI
3818 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3823 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3829 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3830 if (var
&& *var
== 1)
3838 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3847 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3852 grub_uint64_t FileSectors
= 0;
3853 ventoy_gpt_info
*gpt
= NULL
;
3854 ventoy_part_table
*pt
= NULL
;
3855 grub_uint8_t zeroguid
[16] = {0};
3860 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3863 debug("failed to open file %s\n", args
[0]);
3867 if (file
->size
% 512)
3869 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3873 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3879 FileSectors
= file
->size
/ 512;
3881 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3882 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3884 debug("This is EFI partition table\n");
3886 for (i
= 0; i
< 128; i
++)
3888 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3890 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3892 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3893 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3901 debug("This is MBR partition table\n");
3903 for (i
= 0; i
< 4; i
++)
3905 pt
= gpt
->MBR
.PartTbl
+ i
;
3906 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3908 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3909 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3910 (ulonglong
)FileSectors
);
3919 grub_file_close(file
);
3920 grub_check_free(gpt
);
3921 grub_errno
= GRUB_ERR_NONE
;
3925 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3934 for (i
= 0; i
< 500; i
++)
3936 ret
= grub_getkey_noblock();
3937 if (ret
== GRUB_TERM_NO_KEY
)
3946 grub_printf("\n\n Still have key input after clear.\n");
3954 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3961 int image_sector_size
;
3963 ventoy_chain_head
*chain
;
3964 ventoy_img_chunk
*chunk
;
3965 ventoy_os_param
*osparam
;
3966 ventoy_image_location
*location
;
3967 ventoy_image_disk_region
*region
;
3968 struct grub_acpi_table_header
*acpi
;
3977 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3979 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3985 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
3987 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
3989 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
3993 img_chunk_num
= chain
->img_chunk_num
;
3995 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
3996 datalen
= sizeof(ventoy_os_param
) + loclen
;
3998 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
3999 acpi
= grub_zalloc(buflen
);
4005 /* Step1: Fill acpi table header */
4006 grub_memcpy(acpi
->signature
, "VTOY", 4);
4007 acpi
->length
= buflen
;
4009 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4010 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4012 acpi
->creator_id
[0] = 1;
4013 acpi
->creator_rev
= 1;
4015 /* Step2: Fill data */
4016 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4017 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4018 osparam
->vtoy_img_location_addr
= 0;
4019 osparam
->vtoy_img_location_len
= loclen
;
4020 osparam
->chksum
= 0;
4021 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4023 location
= (ventoy_image_location
*)(osparam
+ 1);
4024 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4025 location
->image_sector_size
= image_sector_size
;
4026 location
->disk_sector_size
= chain
->disk_sector_size
;
4027 location
->region_count
= img_chunk_num
;
4029 region
= location
->regions
;
4030 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4031 if (512 == image_sector_size
)
4033 for (i
= 0; i
< img_chunk_num
; i
++)
4035 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4036 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4037 region
->disk_start_sector
= chunk
->disk_start_sector
;
4044 for (i
= 0; i
< img_chunk_num
; i
++)
4046 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4047 region
->image_start_sector
= chunk
->img_start_sector
;
4048 region
->disk_start_sector
= chunk
->disk_start_sector
;
4054 /* Step3: Fill acpi checksum */
4056 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4058 /* load acpi table */
4059 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4060 grub_script_execute_sourcecode(cmd
);
4064 VENTOY_CMD_RETURN(0);
4067 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4073 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4074 g_ventoy_last_entry
= -1;
4079 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4085 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4090 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4092 const char *pos
= filename
+ 1;
4100 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4102 grub_strncpy((char *)data
, filename
, 128);
4113 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4116 char *device_name
= NULL
;
4117 grub_device_t dev
= NULL
;
4118 grub_fs_t fs
= NULL
;
4119 char buf
[128] = {0};
4125 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4129 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4131 device_name
= grub_file_get_device_name(args
[0]);
4134 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4138 dev
= grub_device_open(device_name
);
4141 debug("grub_device_open failed, %s\n", device_name
);
4145 fs
= grub_fs_probe(dev
);
4148 debug("grub_fs_probe failed, %s\n", device_name
);
4152 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4156 ventoy_set_env(args
[2], buf
);
4163 check_free(device_name
, grub_free
);
4164 check_free(dev
, grub_device_close
);
4169 int ventoy_load_part_table(const char *diskname
)
4176 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4177 if (!g_ventoy_part_info
)
4182 disk
= grub_disk_open(diskname
);
4185 debug("Failed to open disk %s\n", diskname
);
4189 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4191 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4192 grub_disk_close(disk
);
4194 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4195 dev
= grub_device_open(name
);
4198 /* Check for official Ventoy device */
4199 ret
= ventoy_check_official_device(dev
);
4200 grub_device_close(dev
);
4208 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4209 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4214 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4221 ret
= ventoy_load_part_table(args
[0]);
4227 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4228 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4233 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4236 const char *vcfg
= NULL
;
4241 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4244 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4245 grub_env_set(args
[1], vcfg
);
4250 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4258 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4261 grub_uint8_t zeroguid
[16] = {0};
4266 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4269 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4271 if (id
>= 1 && id
<= 128)
4273 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4281 if (id
>= 1 && id
<= 4)
4283 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4293 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4296 char *device_name
= NULL
;
4297 grub_device_t dev
= NULL
;
4298 grub_fs_t fs
= NULL
;
4303 debug("get fs label for %s\n", args
[0]);
4307 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4311 device_name
= grub_file_get_device_name(args
[0]);
4314 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4318 dev
= grub_device_open(device_name
);
4321 debug("grub_device_open failed, %s\n", device_name
);
4325 fs
= grub_fs_probe(dev
);
4326 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4328 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4332 fs
->fs_label(dev
, &label
);
4335 debug("label=<%s>\n", label
);
4336 ventoy_set_env(args
[1], label
);
4344 check_free(device_name
, grub_free
);
4345 check_free(dev
, grub_device_close
);
4350 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4354 grub_snprintf((char *)data
, 256, "%s", filename
);
4361 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4363 if (info
->dir
&& filename
&& filename
[0] != '.')
4365 grub_snprintf((char *)data
, 256, "%s", filename
);
4372 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4375 char *device_name
= NULL
;
4376 grub_device_t dev
= NULL
;
4377 grub_fs_t fs
= NULL
;
4378 char name
[256] ={0};
4382 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4386 device_name
= grub_file_get_device_name(args
[0]);
4389 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4393 dev
= grub_device_open(device_name
);
4396 debug("grub_device_open failed, %s\n", device_name
);
4400 fs
= grub_fs_probe(dev
);
4403 debug("grub_fs_probe failed, %s\n", device_name
);
4407 fs
->fs_dir(dev
, args
[1], hook
, name
);
4410 ventoy_set_env(args
[2], name
);
4417 check_free(device_name
, grub_free
);
4418 check_free(dev
, grub_device_close
);
4423 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4426 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4429 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4432 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4435 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4445 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4449 for (pos
= args
[0]; *pos
; pos
++)
4463 grub_env_set(args
[1], args
[0]);
4473 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4483 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4488 len
= (int)grub_strlen(buf
);
4489 for (i
= len
; i
> 0; i
--)
4491 if (buf
[i
- 1] == '/')
4493 grub_env_set(args
[1], buf
+ i
);
4498 grub_env_set(args
[1], buf
);
4503 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4505 struct grub_video_mode_info info
;
4512 if (!g_video_mode_list
)
4514 ventoy_enum_video_mode();
4517 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4519 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4523 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4526 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4528 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4529 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4531 VENTOY_CMD_RETURN(0);
4534 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4536 struct grub_video_mode_info info
;
4543 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4545 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4549 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4552 grub_env_set(args
[0], buf
);
4554 VENTOY_CMD_RETURN(0);
4557 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4565 if (!g_video_mode_list
)
4570 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4571 if (id
< g_video_mode_num
)
4573 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4574 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4577 grub_env_set(args
[1], buf
);
4579 VENTOY_CMD_RETURN(0);
4582 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4585 grub_uint32_t loadsector
= 0;
4588 grub_uint32_t boot_catlog
= 0;
4589 grub_uint8_t buf
[512];
4595 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4599 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4602 debug("failed to open %s\n", args
[0]);
4606 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4607 if (boot_catlog
== 0)
4609 debug("No bootcatlog found\n");
4610 grub_file_close(file
);
4614 grub_memset(buf
, 0, sizeof(buf
));
4615 grub_file_seek(file
, boot_catlog
* 2048);
4616 grub_file_read(file
, buf
, sizeof(buf
));
4617 grub_file_close(file
);
4619 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4621 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4623 if (buf
[i
+ 32] == 0x88)
4625 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4626 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4632 if (loadsector
== 0)
4634 debug("No EFI eltorito info found\n");
4638 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4639 grub_env_set(args
[1], value
);
4640 VENTOY_CMD_RETURN(0);
4643 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4648 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4650 if (pfsdir
->initrd
[0])
4655 curpos
= pfsdir
->curpos
;
4656 len
= grub_strlen(filename
);
4660 if ((len
== 1 && filename
[0] == '.') ||
4661 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4666 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4669 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4670 pfsdir
->curpos
= curpos
+ printlen
;
4671 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4672 pfsdir
->curpos
= curpos
;
4673 pfsdir
->fullpath
[curpos
] = 0;
4677 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4680 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4681 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4683 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4685 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4694 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4698 char *device_name
= NULL
;
4699 grub_device_t dev
= NULL
;
4700 grub_fs_t fs
= NULL
;
4701 replace_fs_dir
*pfsdir
= NULL
;
4707 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4711 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4717 device_name
= grub_file_get_device_name(args
[0]);
4723 dev
= grub_device_open(device_name
);
4729 fs
= grub_fs_probe(dev
);
4738 pfsdir
->fullpath
[0] = '/';
4739 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4741 if (pfsdir
->initrd
[0])
4743 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4745 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4747 if (pfsdir
->initrd
[i
] == '/')
4749 pfsdir
->initrd
[i
] = '\\';
4753 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4754 grub_env_set(args
[1], pos
);
4758 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4763 grub_check_free(pfsdir
);
4764 grub_check_free(device_name
);
4765 check_free(dev
, grub_device_close
);
4767 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4770 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4772 const char *pager
= NULL
;
4778 pager
= grub_env_get("pager");
4782 grub_env_set("pager", "1");
4784 else if (pager
[0] == '1')
4790 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4792 grub_env_set("pager", "1");
4795 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4798 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4804 if (g_pager_flag
== 1)
4806 grub_env_unset("pager");
4808 else if (g_pager_flag
== 2)
4810 grub_env_set("pager", g_old_pager
);
4813 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4816 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4818 if (g_json_case_mis_path
[0])
4823 if (0 == info
->dir
&& grub_strncasecmp(filename
, "ventoy.json", 11) == 0)
4825 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4831 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4834 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4836 if (g_json_case_mis_path
[0])
4841 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4843 if (grub_strncasecmp(filename
, "ventoy", 6) == 0)
4845 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4846 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4847 if (g_json_case_mis_path
[0])
4857 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4860 char *device_name
= NULL
;
4861 grub_device_t dev
= NULL
;
4862 grub_fs_t fs
= NULL
;
4863 chk_case_fs_dir fs_dir
;
4869 device_name
= grub_file_get_device_name(args
[0]);
4875 dev
= grub_device_open(device_name
);
4881 fs
= grub_fs_probe(dev
);
4887 fstype
= ventoy_get_fs_type(fs
->name
);
4888 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4893 g_json_case_mis_path
[0] = 0;
4896 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4898 if (g_json_case_mis_path
[0])
4900 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4905 grub_check_free(device_name
);
4906 check_free(dev
, grub_device_close
);
4908 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4911 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4914 grub_partition_t part
;
4915 char priority_str
[3]; /* Maximum value 15 */
4919 if (argc
< 2 || argc
> 3)
4920 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4921 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4923 /* Open the disk if it exists */
4924 disk
= grub_disk_open (args
[0]);
4927 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4931 part
= grub_partition_probe (disk
, args
[1]);
4934 grub_disk_close (disk
);
4935 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4936 "No such partition");
4939 if (grub_strcmp (part
->partmap
->name
, "gpt"))
4941 grub_disk_close (disk
);
4942 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
4943 "Not a GPT partition");
4946 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
4947 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
4951 grub_env_set (args
[2], priority_str
);
4952 grub_env_export (args
[2]);
4956 grub_printf ("Priority is %s\n", priority_str
);
4959 grub_disk_close (disk
);
4960 return GRUB_ERR_NONE
;
4965 /* <BEGIN>: Deleted by longpanda, 20210916 PN:XX LABEL:XX */
4967 void ventoy_tip_set_menu_label(const char *vid
)
4971 g_ventoy_tip_msg1
= g_ventoy_tip_msg2
= NULL
;
4974 node
= (img_info
*)(void *)grub_strtoul(vid
+ 4, NULL
, 16);
4977 g_ventoy_tip_msg1
= node
->tip1
;
4978 g_ventoy_tip_msg2
= node
->tip2
;
4983 /* <END> : Deleted by longpanda, 20210916 PN:XX LABEL:XX */
4985 int ventoy_env_init(void)
4989 grub_env_set("vtdebug_flag", "");
4991 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
4992 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4993 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
4994 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
4996 ventoy_filt_register(0, ventoy_wrapper_open
);
4998 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5001 g_grub_param
->grub_env_get
= grub_env_get
;
5002 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5003 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5004 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5005 grub_env_set("env_param", buf
);
5006 grub_env_set("ventoy_env_param", buf
);
5008 grub_env_export("env_param");
5009 grub_env_export("ventoy_env_param");
5012 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5013 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5015 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5016 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5018 grub_env_export("vtoy_winpeshl_ini_addr");
5019 grub_env_export("vtoy_winpeshl_ini_size");
5021 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5022 grub_env_set("vtoy_chain_file_size", buf
);
5023 grub_env_export("vtoy_chain_file_size");
5025 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5026 grub_env_set("vtoy_chain_file_read", buf
);
5027 grub_env_export("vtoy_chain_file_read");
5034 static cmd_para ventoy_cmds
[] =
5036 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5037 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5038 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5039 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5040 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5041 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5042 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5043 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5044 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5045 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5046 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5047 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5048 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5049 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5050 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5051 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5052 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5053 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5054 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5055 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5056 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5057 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5058 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5059 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5061 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5062 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5063 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5064 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5065 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5066 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5067 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5069 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5070 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5071 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5072 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5073 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5074 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5075 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5076 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5077 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5078 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5081 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5082 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5083 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5084 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5085 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5086 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5087 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5088 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5089 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5090 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5091 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5093 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5094 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5095 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5096 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5097 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5098 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5099 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5101 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5102 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5103 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5104 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5105 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5106 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5107 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5108 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5109 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5110 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5112 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5113 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5114 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5115 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5116 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5117 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5118 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5119 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5120 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5122 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5123 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5124 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5125 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5128 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5129 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5130 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5132 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5133 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5134 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5137 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5138 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5139 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5140 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5141 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5142 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5143 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5144 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5145 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5146 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5147 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5149 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5150 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5151 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5152 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5153 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5154 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5155 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5156 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5157 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5158 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5160 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5161 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5162 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5163 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5164 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5165 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5166 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5169 int ventoy_register_all_cmd(void)
5172 cmd_para
*cur
= NULL
;
5174 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5176 cur
= ventoy_cmds
+ i
;
5177 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5178 cur
->summary
, cur
->description
, cur
->parser
);
5184 int ventoy_unregister_all_cmd(void)
5188 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5190 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);