1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 static grub_uint8_t g_check_mbr_data
[440] = {
55 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFA, 0x90, 0x90, 0xF6, 0xC2, 0x80, 0x74, 0x05, 0xF6, 0xC2, 0x70,
62 0x74, 0x02, 0xB2, 0x80, 0xEA, 0x79, 0x7C, 0x00, 0x00, 0x31, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC,
63 0x00, 0x20, 0xFB, 0xA0, 0x64, 0x7C, 0x3C, 0xFF, 0x74, 0x02, 0x88, 0xC2, 0x52, 0xBE, 0x90, 0x7D,
64 0xE8, 0x16, 0x01, 0xBE, 0x05, 0x7C, 0xB4, 0x41, 0xBB, 0xAA, 0x55, 0xCD, 0x13, 0x5A, 0x52, 0x72,
65 0x3D, 0x81, 0xFB, 0x55, 0xAA, 0x75, 0x37, 0x83, 0xE1, 0x01, 0x74, 0x32, 0x31, 0xC0, 0x89, 0x44,
66 0x04, 0x40, 0x88, 0x44, 0xFF, 0x89, 0x44, 0x02, 0xC7, 0x04, 0x10, 0x00, 0x66, 0x8B, 0x1E, 0x5C,
67 0x7C, 0x66, 0x89, 0x5C, 0x08, 0x66, 0x8B, 0x1E, 0x60, 0x7C, 0x66, 0x89, 0x5C, 0x0C, 0xC7, 0x44,
68 0x06, 0x00, 0x70, 0xB4, 0x42, 0xCD, 0x13, 0x72, 0x05, 0xBB, 0x00, 0x70, 0xEB, 0x76, 0xB4, 0x08,
69 0xCD, 0x13, 0x73, 0x0D, 0x5A, 0x84, 0xD2, 0x0F, 0x83, 0xD8, 0x00, 0xBE, 0x96, 0x7D, 0xE9, 0x82,
70 0x00, 0x66, 0x0F, 0xB6, 0xC6, 0x88, 0x64, 0xFF, 0x40, 0x66, 0x89, 0x44, 0x04, 0x0F, 0xB6, 0xD1,
71 0xC1, 0xE2, 0x02, 0x88, 0xE8, 0x88, 0xF4, 0x40, 0x89, 0x44, 0x08, 0x0F, 0xB6, 0xC2, 0xC0, 0xE8,
72 0x02, 0x66, 0x89, 0x04, 0x66, 0xA1, 0x60, 0x7C, 0x66, 0x09, 0xC0, 0x75, 0x4E, 0x66, 0xA1, 0x5C,
73 0x7C, 0x66, 0x31, 0xD2, 0x66, 0xF7, 0x34, 0x88, 0xD1, 0x31, 0xD2, 0x66, 0xF7, 0x74, 0x04, 0x3B,
74 0x44, 0x08, 0x7D, 0x37, 0xFE, 0xC1, 0x88, 0xC5, 0x30, 0xC0, 0xC1, 0xE8, 0x02, 0x08, 0xC1, 0x88,
75 0xD0, 0x5A, 0x88, 0xC6, 0xBB, 0x00, 0x70, 0x8E, 0xC3, 0x31, 0xDB, 0xB8, 0x01, 0x02, 0xCD, 0x13,
76 0x72, 0x1E, 0x8C, 0xC3, 0x60, 0x1E, 0xB9, 0x00, 0x01, 0x8E, 0xDB, 0x31, 0xF6, 0xBF, 0x00, 0x80,
77 0x8E, 0xC6, 0xFC, 0xF3, 0xA5, 0x1F, 0x61, 0xFF, 0x26, 0x5A, 0x7C, 0xBE, 0x93, 0x7D, 0xEB, 0x03,
78 0xBE, 0x99, 0x7D, 0xE8, 0x33, 0x00, 0xBE, 0x9C, 0x7D, 0xE8, 0x2D, 0x00, 0xCD, 0x18, 0xEB, 0xFE,
79 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
80 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
81 0x0A, 0x00, 0xBB, 0x01, 0x00, 0xB4, 0x0E, 0xCD, 0x10, 0xAC, 0x3C, 0x00, 0x75, 0xF4, 0xC3, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
85 initrd_info
*g_initrd_img_list
= NULL
;
86 initrd_info
*g_initrd_img_tail
= NULL
;
87 int g_initrd_img_count
= 0;
88 int g_valid_initrd_count
= 0;
89 int g_default_menu_mode
= 0;
90 int g_filt_dot_underscore_file
= 0;
91 int g_sort_case_sensitive
= 0;
92 int g_tree_view_menu_style
= 0;
93 static grub_file_t g_old_file
;
94 static int g_ventoy_last_entry_back
;
97 char g_img_swap_tmp_buf
[1024];
98 img_info g_img_swap_tmp
;
99 img_info
*g_ventoy_img_list
= NULL
;
101 int g_ventoy_img_count
= 0;
103 grub_device_t g_enum_dev
= NULL
;
104 grub_fs_t g_enum_fs
= NULL
;
105 int g_img_max_search_level
= -1;
106 img_iterator_node g_img_iterator_head
;
107 img_iterator_node
*g_img_iterator_tail
= NULL
;
109 grub_uint8_t g_ventoy_break_level
= 0;
110 grub_uint8_t g_ventoy_debug_level
= 0;
111 grub_uint8_t g_ventoy_chain_type
= 0;
113 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
114 grub_uint32_t g_ventoy_cpio_size
= 0;
115 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
116 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
118 int g_plugin_image_list
= 0;
120 ventoy_grub_param
*g_grub_param
= NULL
;
122 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
124 ventoy_img_chunk_list g_img_chunk_list
;
126 int g_wimboot_enable
= 0;
127 ventoy_img_chunk_list g_wimiso_chunk_list
;
128 char *g_wimiso_path
= NULL
;
130 int g_vhdboot_enable
= 0;
132 grub_uint64_t g_conf_replace_offset
= 0;
133 grub_uint64_t g_svd_replace_offset
= 0;
134 conf_replace
*g_conf_replace_node
= NULL
;
135 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
136 int g_conf_replace_new_len
= 0;
137 int g_conf_replace_new_len_align
= 0;
139 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
140 grub_uint64_t g_ventoy_disk_size
= 0;
141 grub_uint64_t g_ventoy_disk_part_size
[2];
143 static char *g_tree_script_buf
= NULL
;
144 static int g_tree_script_pos
= 0;
146 static char *g_list_script_buf
= NULL
;
147 static int g_list_script_pos
= 0;
149 static char *g_part_list_buf
= NULL
;
150 static int g_part_list_pos
= 0;
152 static int g_video_mode_max
= 0;
153 static int g_video_mode_num
= 0;
154 static ventoy_video_mode
*g_video_mode_list
= NULL
;
156 static int g_enumerate_time_checked
= 0;
157 static grub_uint64_t g_enumerate_start_time_ms
;
158 static grub_uint64_t g_enumerate_finish_time_ms
;
159 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
161 static int g_pager_flag
= 0;
162 static char g_old_pager
[32];
164 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
166 static const char *g_menu_class
[] =
168 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
171 const char *g_menu_prefix
[img_type_max
] =
173 "iso", "wim", "efi", "img", "vhd", "vtoy"
176 static int g_vtoy_load_prompt
= 0;
177 static char g_vtoy_prompt_msg
[64];
179 static char g_json_case_mis_path
[32];
181 static int ventoy_get_fs_type(const char *fs
)
185 return ventoy_fs_max
;
187 else if (grub_strncmp(fs
, "exfat", 5) == 0)
189 return ventoy_fs_exfat
;
191 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
193 return ventoy_fs_ntfs
;
195 else if (grub_strncmp(fs
, "ext", 3) == 0)
197 return ventoy_fs_ext
;
199 else if (grub_strncmp(fs
, "xfs", 3) == 0)
201 return ventoy_fs_xfs
;
203 else if (grub_strncmp(fs
, "udf", 3) == 0)
205 return ventoy_fs_udf
;
207 else if (grub_strncmp(fs
, "fat", 3) == 0)
209 return ventoy_fs_fat
;
212 return ventoy_fs_max
;
215 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
234 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
236 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
240 static int ventoy_control_get_flag(const char *key
)
242 const char *val
= ventoy_get_env(key
);
244 if (val
&& val
[0] == '1' && val
[1] == 0)
251 static grub_err_t
ventoy_fs_close(grub_file_t file
)
253 grub_file_close(g_old_file
);
254 grub_free(file
->data
);
262 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
268 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
273 for (i
= 0; i
< g_video_mode_num
; i
++)
275 if (g_video_mode_list
[i
].width
== info
->width
&&
276 g_video_mode_list
[i
].height
== info
->height
&&
277 g_video_mode_list
[i
].bpp
== info
->bpp
)
283 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
284 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
285 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
288 if (g_video_mode_num
== g_video_mode_max
)
290 g_video_mode_max
*= 2;
291 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
297 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
299 if (v1
->bpp
== v2
->bpp
)
301 if (v1
->width
== v2
->width
)
303 if (v1
->height
== v2
->height
)
309 return (v1
->height
< v2
->height
) ? -1 : 1;
314 return (v1
->width
< v2
->width
) ? -1 : 1;
319 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
323 static int ventoy_enum_video_mode(void)
326 grub_video_adapter_t adapter
;
327 grub_video_driver_id_t id
;
328 ventoy_video_mode mode
;
330 g_video_mode_num
= 0;
331 g_video_mode_max
= 1024;
332 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
333 if (!g_video_mode_list
)
338 #ifdef GRUB_MACHINE_PCBIOS
339 grub_dl_load ("vbe");
342 id
= grub_video_get_driver_id ();
344 FOR_VIDEO_ADAPTERS (adapter
)
346 if (!adapter
->iterate
||
347 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
348 adapter
->init() != GRUB_ERR_NONE
)))
353 adapter
->iterate(ventoy_video_hook
, NULL
);
355 if (adapter
->id
!= id
)
361 /* sort video mode */
362 for (i
= 0; i
< g_video_mode_num
; i
++)
363 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
365 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
367 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
368 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
369 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
373 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
376 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
380 static struct grub_fs vtoy_fs
=
385 .fs_read
= ventoy_fs_read
,
386 .fs_close
= ventoy_fs_close
,
396 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
402 file
->data
= grub_malloc(rawFile
->size
+ 4096);
408 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
409 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
411 g_old_file
= rawFile
;
413 file
->size
= rawFile
->size
+ len
;
414 file
->device
= rawFile
->device
;
416 file
->not_easily_seekable
= 1;
421 static int ventoy_check_decimal_var(const char *name
, long *value
)
423 const char *value_str
= NULL
;
425 value_str
= grub_env_get(name
);
426 if (NULL
== value_str
)
428 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
431 if (!ventoy_is_decimal(value_str
))
433 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
436 *value
= grub_strtol(value_str
, NULL
, 10);
438 return GRUB_ERR_NONE
;
441 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
443 grub_uint64_t sectors
;
445 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
447 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
451 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
454 return sectors
* 512;
457 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
463 grub_uint32_t offset
;
465 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
468 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
472 len
= (int)file
->size
;
474 data
= (char *)grub_malloc(file
->size
);
480 grub_file_read(file
, data
, file
->size
);
481 grub_file_close(file
);
483 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
484 grub_script_execute_sourcecode(exec
);
486 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
487 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
488 grub_file_close(file
);
490 grub_script_execute_sourcecode("loopback -d efiboot");
494 *direntoff
= offset
+ 2;
499 static int ventoy_set_check_result(int ret
)
503 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
504 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
505 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
509 grub_printf(VTOY_WARNING
"\n");
510 grub_printf(VTOY_WARNING
"\n");
511 grub_printf(VTOY_WARNING
"\n\n\n");
513 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
514 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
516 grub_printf("\n\nWill exit after 10 seconds ...... ");
524 static int ventoy_check_official_device(grub_device_t dev
)
528 grub_uint64_t offset
;
531 grub_uint8_t mbr
[512];
535 struct grub_partition
*partition
;
537 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
539 return ventoy_set_check_result(1 | 0x1000);
542 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
543 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
544 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
546 #ifndef GRUB_MACHINE_EFI
547 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
548 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
549 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
551 return ventoy_set_check_result(2 | 0x1000);
560 /* We must have partition 2 */
563 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
567 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
571 return ventoy_set_check_result(3 | 0x1000);
574 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
576 grub_file_close(file
);
577 return ventoy_set_check_result(4 | 0x1000);
580 partition
= dev
->disk
->partition
;
581 if (partition
->number
!= 0 || partition
->start
!= 2048)
583 return ventoy_set_check_result(5);
588 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
590 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
591 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
592 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
594 grub_file_close(file
);
595 return ventoy_set_check_result(6);
600 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
601 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
602 PartTbl
[1].SectorCount
!= 65536)
604 grub_file_close(file
);
605 return ventoy_set_check_result(6);
611 offset
= partition
->start
+ partition
->len
;
612 partition
= file
->device
->disk
->partition
;
613 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
615 grub_file_close(file
);
616 return ventoy_set_check_result(7);
620 grub_file_close(file
);
624 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
625 dev2
= grub_device_open(devname
);
628 return ventoy_set_check_result(8);
631 fs
= grub_fs_probe(dev2
);
634 grub_device_close(dev2
);
635 return ventoy_set_check_result(9);
638 fs
->fs_label(dev2
, &label
);
639 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
641 grub_device_close(dev2
);
642 return ventoy_set_check_result(10);
645 grub_device_close(dev2
);
649 disk
= grub_disk_open(dev
->disk
->name
);
652 return ventoy_set_check_result(11);
655 grub_memset(mbr
, 0, 512);
656 grub_disk_read(disk
, 0, 0, 512, mbr
);
657 grub_disk_close(disk
);
659 g_check_mbr_data
[92] = mbr
[92];
660 g_check_mbr_data
[102] = mbr
[102];
661 g_check_mbr_data
[103] = mbr
[103];
662 grub_memcpy(g_check_mbr_data
+ 0x180, mbr
+ 0x180, 16);
663 if (grub_memcmp(g_check_mbr_data
, mbr
, 440))
665 return ventoy_set_check_result(12);
668 return ventoy_set_check_result(0);
671 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
675 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
685 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
687 grub_uint64_t size
= 0;
690 char fullpath
[256] = {0};
693 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
696 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
699 debug("grub_file_open failed <%s>\n", fullpath
);
705 grub_file_close(file
);
709 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
713 char fullpath
[256] = {0};
716 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
719 file
= grub_file_open(fullpath
, type
);
722 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
729 int ventoy_is_file_exist(const char *fmt
, ...)
736 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
740 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
743 grub_strncpy(pos
+ len
, "\" ]", 3);
745 debug("script exec %s\n", buf
);
747 if (0 == grub_script_execute_sourcecode(buf
))
755 int ventoy_is_dir_exist(const char *fmt
, ...)
762 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
766 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
769 grub_strncpy(pos
+ len
, "\" ]", 3);
771 debug("script exec %s\n", buf
);
773 if (0 == grub_script_execute_sourcecode(buf
))
781 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
784 grub_uint8_t
*outbuf
;
785 grub_uint8_t gzHdr
[10] =
787 0x1F, 0x8B, /* magic */
795 grub_memset(&s
, 0, sizeof(mz_stream
));
797 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
799 outbuf
= (grub_uint8_t
*)mem_out
;
801 mem_out_len
-= sizeof(gzHdr
) + 8;
802 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
803 outbuf
+= sizeof(gzHdr
);
805 s
.avail_in
= mem_in_len
;
808 s
.avail_out
= mem_out_len
;
811 mz_deflate(&s
, MZ_FINISH
);
815 outbuf
+= s
.total_out
;
816 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
817 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
819 return s
.total_out
+ sizeof(gzHdr
) + 8;
827 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
831 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
834 if (0 == grub_strcmp(args
[0], "on"))
837 grub_env_set("vtdebug_flag", "debug");
842 grub_env_set("vtdebug_flag", "");
845 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
848 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
852 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
854 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
855 grub_printf(" level:\r\n");
856 grub_printf(" 01/11: busybox / (+cat log)\r\n");
857 grub_printf(" 02/12: initrd / (+cat log)\r\n");
858 grub_printf(" 03/13: hook / (+cat log)\r\n");
860 grub_printf(" debug:\r\n");
861 grub_printf(" 0: debug is off\r\n");
862 grub_printf(" 1: debug is on\r\n");
864 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
867 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
869 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
871 g_ventoy_debug_level
= 1;
874 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
877 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
886 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
889 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
921 static grub_err_t
ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
937 if ((*c0
!= *c1
) && (*c0
!= grub_toupper(*c1
)))
953 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
958 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
960 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
963 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
968 value_long
+= grub_strtol(args
[1], NULL
, 10);
970 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
971 grub_env_set(args
[0], buf
);
973 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
976 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
978 ulonglong value1
= 0;
979 ulonglong value2
= 0;
984 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
987 value1
= grub_strtoull(args
[0], NULL
, 10);
988 value2
= grub_strtoull(args
[1], NULL
, 10);
990 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
991 grub_env_set(args
[2], buf
);
993 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
996 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1011 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1014 debug("failed to open file <%s> for udf check\n", args
[0]);
1018 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
1020 grub_env_set(args
[1], buf
);
1022 grub_file_close(file
);
1028 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1036 g_wimboot_enable
= 0;
1037 grub_check_free(g_wimiso_path
);
1038 grub_check_free(g_wimiso_chunk_list
.chunk
);
1040 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1046 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1047 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1048 if (NULL
== g_wimiso_chunk_list
.chunk
)
1050 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1053 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1054 g_wimiso_chunk_list
.cur_chunk
= 0;
1056 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1058 g_wimboot_enable
= 1;
1059 g_wimiso_path
= grub_strdup(args
[0]);
1061 grub_file_close(file
);
1066 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1076 ventoy_iso9660_override
*dirent
;
1085 totlen
= sizeof(ventoy_chain_head
);
1087 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1089 debug("failed to load efiboot template %d\n", len
);
1095 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1097 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1100 debug("failed to open file <%s>\n", args
[0]);
1104 totlen
+= ventoy_align_2k(file
->size
);
1106 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1107 dirent
->first_sector
= len
/ 2048;
1108 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1109 dirent
->size
= (grub_uint32_t
)file
->size
;
1110 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1112 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1114 #ifdef GRUB_MACHINE_EFI
1115 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1117 data
= (char *)grub_malloc(totlen
);
1120 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1122 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1123 grub_check_free(buf
);
1125 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1126 grub_file_close(file
);
1128 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1129 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1130 grub_env_set(name
, value
);
1132 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1133 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1134 grub_env_set(name
, value
);
1139 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1145 g_vtoy_load_prompt
= 0;
1146 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1148 if (argc
== 2 && args
[0][0] == '1')
1150 g_vtoy_load_prompt
= 1;
1151 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1154 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1157 int ventoy_need_prompt_load_file(void)
1159 return g_vtoy_load_prompt
;
1162 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1164 grub_uint64_t ro
= 0;
1165 grub_uint64_t div
= 0;
1166 grub_ssize_t left
= size
;
1167 char *cur
= (char *)buf
;
1169 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1172 while (left
>= VTOY_SIZE_2MB
)
1174 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1175 cur
+= VTOY_SIZE_2MB
;
1176 left
-= VTOY_SIZE_2MB
;
1178 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1179 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1185 grub_file_read(file
, cur
, left
);
1188 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1194 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1201 enum grub_file_type type
;
1212 if (grub_strcmp(args
[0], "nodecompress") == 0)
1214 type
= VENTOY_FILE_TYPE
;
1218 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1221 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1224 debug("failed to open file <%s>\n", args
[1]);
1228 #ifdef GRUB_MACHINE_EFI
1229 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1231 buf
= (char *)grub_malloc(file
->size
);
1236 grub_file_close(file
);
1240 if (g_vtoy_load_prompt
)
1242 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1246 grub_file_read(file
, buf
, file
->size
);
1249 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1250 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1251 grub_env_set(name
, value
);
1253 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1254 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1255 grub_env_set(name
, value
);
1257 grub_file_close(file
);
1263 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1281 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1284 debug("failed to open file <%s> for udf check\n", args
[0]);
1288 headlen
= sizeof(ventoy_chain_head
);
1290 #ifdef GRUB_MACHINE_EFI
1291 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1293 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1296 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1298 grub_file_read(file
, buf
+ headlen
, file
->size
);
1300 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1301 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1302 grub_env_set(name
, value
);
1304 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1305 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1306 grub_env_set(name
, value
);
1308 grub_file_close(file
);
1314 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1320 if (grub_iso9660_is_joliet())
1322 debug("This time has joliet process\n");
1331 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1340 if (args
[0][0] == '1')
1342 grub_iso9660_set_nojoliet(1);
1346 grub_iso9660_set_nojoliet(0);
1352 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1357 grub_uint8_t buf
[32];
1368 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1371 debug("failed to open file <%s> for udf check\n", args
[0]);
1375 for (i
= 16; i
< 32; i
++)
1377 grub_file_seek(file
, i
* 2048);
1378 grub_file_read(file
, buf
, sizeof(buf
));
1386 grub_file_seek(file
, i
* 2048);
1387 grub_file_read(file
, buf
, sizeof(buf
));
1389 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1392 grub_file_seek(file
, i
* 2048);
1393 grub_file_read(file
, buf
, sizeof(buf
));
1395 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1396 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1402 grub_file_close(file
);
1404 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1409 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1411 long value_long1
= 0;
1412 long value_long2
= 0;
1414 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1416 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1419 value_long1
= grub_strtol(args
[0], NULL
, 10);
1420 value_long2
= grub_strtol(args
[2], NULL
, 10);
1422 if (0 == grub_strcmp(args
[1], "eq"))
1424 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1426 else if (0 == grub_strcmp(args
[1], "ne"))
1428 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1430 else if (0 == grub_strcmp(args
[1], "gt"))
1432 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1434 else if (0 == grub_strcmp(args
[1], "lt"))
1436 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1438 else if (0 == grub_strcmp(args
[1], "ge"))
1440 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1442 else if (0 == grub_strcmp(args
[1], "le"))
1444 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1448 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1454 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1457 char buf
[128] = {0};
1461 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1464 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1465 pos
= grub_strstr(buf
, ",");
1471 grub_env_set(args
[1], buf
);
1473 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1476 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1482 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1488 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1491 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1493 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1494 if (0 == grub_script_execute_sourcecode(buf
))
1496 debug("file %s exist, ventoy_compatible YES\n", buf
);
1497 grub_env_set("ventoy_compatible", "YES");
1498 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1502 debug("file %s NOT exist\n", buf
);
1506 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1507 pos
= grub_strstr(buf
, ")");
1513 disk
= grub_disk_open(buf
);
1516 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1517 grub_disk_close(disk
);
1519 g_img_swap_tmp_buf
[703] = 0;
1520 for (i
= 318; i
< 703; i
++)
1522 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1523 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1525 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1526 grub_env_set("ventoy_compatible", "YES");
1527 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1533 debug("failed to open disk <%s>\n", buf
);
1536 grub_env_set("ventoy_compatible", "NO");
1537 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1540 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1546 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1548 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1551 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1556 if (0 == g_sort_case_sensitive
)
1558 if (grub_islower(c1
))
1560 c1
= c1
- 'a' + 'A';
1563 if (grub_islower(c2
))
1565 c2
= c2
- 'a' + 'A';
1578 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1584 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1586 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1589 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1594 if (0 == g_sort_case_sensitive
)
1596 if (grub_islower(c1
))
1598 c1
= c1
- 'a' + 'A';
1601 if (grub_islower(c2
))
1603 c2
= c2
- 'a' + 'A';
1616 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1618 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1620 grub_memcpy(img1
, img2
, sizeof(img_info
));
1621 img1
->next
= g_img_swap_tmp
.next
;
1622 img1
->prev
= g_img_swap_tmp
.prev
;
1624 g_img_swap_tmp
.next
= img2
->next
;
1625 g_img_swap_tmp
.prev
= img2
->prev
;
1626 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1629 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1633 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1641 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1650 const menu_tip
*tip
;
1651 img_iterator_node
*tmp
;
1652 img_iterator_node
*new_node
;
1653 img_iterator_node
*node
= (img_iterator_node
*)data
;
1655 if (g_enumerate_time_checked
== 0)
1657 g_enumerate_finish_time_ms
= grub_get_time_ms();
1658 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1661 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1663 g_enumerate_time_checked
= 1;
1667 len
= grub_strlen(filename
);
1671 if (node
->level
+ 1 > g_img_max_search_level
)
1676 if ((len
== 1 && filename
[0] == '.') ||
1677 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1682 if (!ventoy_img_name_valid(filename
, len
))
1687 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1692 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1694 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1695 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1698 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1703 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1706 new_node
->level
= node
->level
+ 1;
1707 new_node
->plugin_list_index
= index
;
1708 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1710 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1713 debug("Directory %s ignored...\n", new_node
->dir
);
1714 grub_free(new_node
);
1718 new_node
->tail
= node
->tail
;
1720 new_node
->parent
= node
;
1721 if (!node
->firstchild
)
1723 node
->firstchild
= new_node
;
1726 if (g_img_iterator_tail
)
1728 g_img_iterator_tail
->next
= new_node
;
1729 g_img_iterator_tail
= new_node
;
1733 g_img_iterator_head
.next
= new_node
;
1734 g_img_iterator_tail
= new_node
;
1740 debug("Find a file %s\n", filename
);
1746 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1748 type
= img_type_iso
;
1750 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1752 type
= img_type_wim
;
1754 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1755 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1757 type
= img_type_vhd
;
1759 #ifdef GRUB_MACHINE_EFI
1760 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1762 type
= img_type_efi
;
1765 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1767 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1769 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1770 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1775 type
= img_type_img
;
1777 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1779 type
= img_type_vtoy
;
1781 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1783 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1785 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1786 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1795 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1800 if (g_plugin_image_list
)
1802 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1803 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1804 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1806 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1809 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1811 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1816 img
= grub_zalloc(sizeof(img_info
));
1820 img
->plugin_list_index
= index
;
1821 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1823 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1825 img
->size
= info
->size
;
1828 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1831 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1833 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1838 if (g_ventoy_img_list
)
1840 tail
= *(node
->tail
);
1846 g_ventoy_img_list
= img
;
1849 img
->id
= g_ventoy_img_count
;
1851 if (node
&& NULL
== node
->firstiso
)
1853 node
->firstiso
= img
;
1864 *((img_info
**)(node
->tail
)) = img
;
1865 g_ventoy_img_count
++;
1867 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1869 tip
= ventoy_plugin_get_menu_tip(img
->path
);
1872 img
->tip1
= tip
->tip1
;
1873 img
->tip2
= tip
->tip2
;
1876 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1879 img
->class = g_menu_class
[type
];
1881 img
->menu_prefix
= g_menu_prefix
[type
];
1883 if (img_type_iso
== type
)
1885 if (ventoy_plugin_check_memdisk(img
->path
))
1887 img
->menu_prefix
= "miso";
1891 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1898 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1900 int len
= GRUB_UINT_MAX
;
1901 const char *value
= NULL
;
1902 char name
[32] = {0};
1903 char plat
[32] = {0};
1904 char guidstr
[32] = {0};
1905 ventoy_guid guid
= VENTOY_GUID
;
1906 const char *fmt1
= NULL
;
1907 const char *fmt2
= NULL
;
1908 const char *fmt3
= NULL
;
1909 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1910 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1911 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1912 const char fmtcode
[]={
1913 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1914 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1915 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1916 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1917 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1918 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1921 grub_memset(name
, 0, sizeof(name
));
1922 puint
[0] = grub_swap_bytes32(0x56454e54);
1923 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1924 puint
[2] = grub_swap_bytes32(0x45525349);
1925 puint
[1] = grub_swap_bytes32(0x4f595f56);
1926 value
= ventoy_get_env(name
);
1928 grub_memset(name
, 0, sizeof(name
));
1929 puint
[1] = grub_swap_bytes32(0x5f544f50);
1930 puint
[0] = grub_swap_bytes32(0x56544c45);
1931 fmt1
= ventoy_get_env(name
);
1937 grub_memset(name
, 0, sizeof(name
));
1938 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1939 puint
[0] = grub_swap_bytes32(0x56544c45);
1940 fmt2
= ventoy_get_env(name
);
1942 grub_memset(name
, 0, sizeof(name
));
1943 puint
[1] = grub_swap_bytes32(0x5f434c52);
1944 puint
[0] = grub_swap_bytes32(0x56544c45);
1945 fmt3
= ventoy_get_env(name
);
1947 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1949 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1951 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1952 #pragma GCC diagnostic push
1953 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1954 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1955 fmt1
? fmt1
: fmtdata
,
1956 fmt2
? fmt2
: fmtdata
+ 4,
1957 value
? value
: "", plat
, guidstr
,
1958 fmt3
? fmt3
: fmtdata
+ 6);
1959 #pragma GCC diagnostic pop
1961 grub_memset(name
, 0, sizeof(name
));
1962 puint
[0] = grub_swap_bytes32(0x76746f79);
1963 puint
[2] = grub_swap_bytes32(0x656e7365);
1964 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1965 ventoy_set_env(name
, guidstr
);
1970 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1974 grub_uint8_t md5
[16];
1978 grub_memset(input
, 0, sizeof(input
));
1980 grub_printf("Enter password: ");
1983 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1985 grub_password_get(input
, 128);
1986 if (grub_strcmp(pwd
->text
, input
) == 0)
1991 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1993 grub_password_get(input
, 128);
1994 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1995 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2000 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
2002 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
2003 grub_password_get(input
+ offset
, 128);
2005 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
2006 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
2012 grub_printf("Invalid password!\n\n");
2019 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
2021 img_info
*minimg
= NULL
;
2022 img_info
*img
= (img_info
*)(node
->firstiso
);
2024 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
2026 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2041 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2043 img_iterator_node
*Minchild
= NULL
;
2044 img_iterator_node
*child
= node
->firstchild
;
2046 while (child
&& child
->parent
== node
)
2048 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2052 child
= child
->next
;
2057 Minchild
->select
= 1;
2063 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2066 img_info
*img
= NULL
;
2067 const char *dir_class
= NULL
;
2068 const char *dir_alias
= NULL
;
2069 img_iterator_node
*child
= NULL
;
2071 if (node
->isocnt
== 0 || node
->done
== 1)
2076 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2078 offset
= node
->parent
->dirlen
;
2081 if (node
== &g_img_iterator_head
)
2083 if (g_default_menu_mode
== 0)
2085 if (g_tree_view_menu_style
== 0)
2087 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2088 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2089 " echo 'return ...' \n"
2094 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2095 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2103 node
->dir
[node
->dirlen
- 1] = 0;
2104 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2107 dir_class
= "vtoydir";
2110 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2113 if (g_tree_view_menu_style
== 0)
2115 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2116 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2117 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2121 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2122 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2123 dir_alias
, dir_class
, node
->dir
+ offset
);
2128 dir_alias
= node
->dir
+ offset
;
2130 if (g_tree_view_menu_style
== 0)
2132 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2133 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2134 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2138 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2139 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2140 dir_alias
, dir_class
, node
->dir
+ offset
);
2144 if (g_tree_view_menu_style
== 0)
2146 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2147 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2148 " echo 'return ...' \n"
2153 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2154 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2160 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2162 ventoy_dynamic_tree_menu(child
);
2165 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2167 if (g_tree_view_menu_style
== 0)
2169 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2170 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2173 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2174 img
->unsupport
? "[***********] " : "",
2175 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2177 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2181 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2182 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2185 img
->unsupport
? "[***********] " : "",
2186 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2188 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2192 if (node
!= &g_img_iterator_head
)
2194 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2201 static int ventoy_set_default_menu(void)
2207 const char *strdata
= NULL
;
2208 img_info
*cur
= NULL
;
2209 img_info
*default_node
= NULL
;
2210 const char *default_image
= NULL
;
2212 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2213 if (default_image
&& default_image
[0] == '/')
2215 img_len
= grub_strlen(default_image
);
2217 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2219 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2231 if (0 == g_default_menu_mode
)
2233 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2237 def
= grub_strdup(default_image
);
2243 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2245 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2246 if (strdata
&& strdata
[0] == '/')
2248 pos
= def
+ grub_strlen(strdata
);
2259 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2262 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2266 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2274 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2276 img_info
*next
= NULL
;
2277 img_info
*cur
= g_ventoy_img_list
;
2290 g_ventoy_img_list
= NULL
;
2291 g_ventoy_img_count
= 0;
2293 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2296 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2299 img_info
*cur
= g_ventoy_img_list
;
2303 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2305 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2308 img_id
= grub_strtol(args
[0], NULL
, 10);
2309 if (img_id
>= g_ventoy_img_count
)
2311 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2314 debug("Find image %ld name \n", img_id
);
2316 while (cur
&& img_id
> 0)
2324 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2327 debug("image name is %s\n", cur
->name
);
2329 grub_env_set(args
[1], cur
->name
);
2331 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2334 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2338 img_info
*cur
= g_ventoy_img_list
;
2344 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2347 len
= (int)grub_strlen(args
[0]);
2351 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2360 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2363 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2364 grub_env_set("chosen", id
);
2365 grub_env_export("chosen");
2367 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2370 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2374 const char *id
= NULL
;
2375 img_info
*cur
= NULL
;
2379 if (argc
< 1 || argc
> 2)
2381 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2384 id
= grub_env_get("chosen");
2386 pos
= grub_strstr(id
, "VID_");
2389 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2393 cur
= g_ventoy_img_list
;
2398 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2401 grub_env_set(args
[0], cur
->path
);
2405 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2406 grub_env_set(args
[1], value
);
2409 g_svd_replace_offset
= 0;
2411 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2415 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2419 grub_device_t dev
= NULL
;
2420 img_info
*cur
= NULL
;
2421 img_info
*tail
= NULL
;
2422 img_info
*min
= NULL
;
2423 img_info
*head
= NULL
;
2424 const char *strdata
= NULL
;
2425 char *device_name
= NULL
;
2427 img_iterator_node
*node
= NULL
;
2428 img_iterator_node
*tmp
= NULL
;
2434 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2437 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2439 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2444 g_enumerate_time_checked
= 0;
2445 g_enumerate_start_time_ms
= grub_get_time_ms();
2447 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2448 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2450 g_filt_dot_underscore_file
= 1;
2453 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2454 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2456 g_sort_case_sensitive
= 1;
2459 device_name
= grub_file_get_device_name(args
[0]);
2465 g_enum_dev
= dev
= grub_device_open(device_name
);
2471 g_enum_fs
= fs
= grub_fs_probe(dev
);
2477 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2479 debug("unsupported fs:<%s>\n", fs
->name
);
2480 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2484 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2486 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2487 if (strdata
&& strdata
[0] == '1')
2489 g_default_menu_mode
= 1;
2492 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2494 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2496 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2497 if (strdata
&& strdata
[0] == '/')
2499 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2500 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2502 g_img_iterator_head
.dir
[len
++] = '/';
2504 g_img_iterator_head
.dirlen
= len
;
2508 g_img_iterator_head
.dirlen
= 1;
2509 grub_strcpy(g_img_iterator_head
.dir
, "/");
2512 g_img_iterator_head
.tail
= &tail
;
2514 if (g_img_max_search_level
< 0)
2516 g_img_max_search_level
= GRUB_INT_MAX
;
2517 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2518 if (strdata
&& ventoy_is_decimal(strdata
))
2520 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2524 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2525 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2526 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2527 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2528 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2529 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2531 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2533 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2536 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2537 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2539 g_tree_view_menu_style
= 1;
2542 ventoy_set_default_menu();
2544 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2546 ventoy_dynamic_tree_menu(node
);
2550 node
= g_img_iterator_head
.next
;
2558 /* sort image list by image name */
2559 while (g_ventoy_img_list
)
2561 min
= g_ventoy_img_list
;
2562 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2564 if (ventoy_cmp_img(min
, cur
) > 0)
2572 min
->prev
->next
= min
->next
;
2577 min
->next
->prev
= min
->prev
;
2580 if (min
== g_ventoy_img_list
)
2582 g_ventoy_img_list
= min
->next
;
2600 g_ventoy_img_list
= head
;
2602 if (g_default_menu_mode
== 1)
2604 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2605 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2606 " echo 'return ...' \n"
2610 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2612 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2613 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2616 cur
->unsupport
? "[***********] " : "",
2617 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2619 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2622 g_tree_script_buf
[g_tree_script_pos
] = 0;
2623 g_list_script_buf
[g_list_script_pos
] = 0;
2625 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2626 grub_env_set(args
[1], buf
);
2630 check_free(device_name
, grub_free
);
2631 check_free(dev
, grub_device_close
);
2633 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2636 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2643 device_name
= grub_file_get_device_name(filename
);
2655 pos2
= grub_strstr(pos
, ",");
2658 pos2
= grub_strstr(pos
, ")");
2666 disk
= grub_disk_open(pos
);
2669 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2670 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2671 grub_disk_close(disk
);
2678 grub_free(device_name
);
2682 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2684 eltorito_descriptor desc
;
2686 grub_memset(&desc
, 0, sizeof(desc
));
2687 grub_file_seek(file
, 17 * 2048);
2688 grub_file_read(file
, &desc
, sizeof(desc
));
2690 if (desc
.type
!= 0 || desc
.version
!= 1)
2695 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2696 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2704 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2708 grub_uint8_t buf
[512];
2709 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2711 grub_file_seek(file
, sector
* 2048);
2712 grub_file_read(file
, buf
, sizeof(buf
));
2714 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2716 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2720 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2725 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2727 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2729 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2733 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2735 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2740 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2742 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2744 if (buf
[36] == parttype
[i
])
2746 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2752 debug("%s does not contain efi eltorito\n", file
->name
);
2756 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2759 const char *fs
= NULL
;
2760 const char *cdprompt
= NULL
;
2762 grub_uint8_t chksum
= 0;
2765 disk
= file
->device
->disk
;
2766 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2768 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2769 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2770 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2772 pos
= grub_strstr(file
->name
, "/");
2778 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2780 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2782 param
->vtoy_img_size
= file
->size
;
2784 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2785 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2787 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2789 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2790 param
->vtoy_reserved
[4] = 0;
2791 if (g_ventoy_chain_type
== 1) /* Windows */
2793 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2794 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2796 param
->vtoy_reserved
[4] = 1;
2800 fs
= ventoy_get_env("ventoy_fs_probe");
2801 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2803 param
->vtoy_reserved
[3] = 1;
2806 /* calculate checksum */
2807 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2809 chksum
+= *((grub_uint8_t
*)param
+ i
);
2811 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2816 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2818 grub_uint32_t i
= 0;
2819 grub_uint64_t total
= 0;
2820 grub_uint64_t fileblk
= 0;
2821 ventoy_img_chunk
*chunk
= NULL
;
2823 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2825 chunk
= chunklist
->chunk
+ i
;
2827 if (chunk
->disk_start_sector
<= start
)
2829 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2833 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2836 fileblk
= (file
->size
+ 511) / 512;
2838 if (total
!= fileblk
)
2840 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2841 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2843 debug("maybe img file to be processed.\n");
2853 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2857 grub_uint32_t i
= 0;
2858 grub_uint32_t sector
= 0;
2859 grub_uint32_t count
= 0;
2860 grub_off_t size
= 0;
2861 grub_off_t read
= 0;
2863 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2864 if (fs_type
== ventoy_fs_exfat
)
2866 grub_fat_get_file_chunk(start
, file
, chunklist
);
2868 else if (fs_type
== ventoy_fs_ext
)
2870 grub_ext_get_file_chunk(start
, file
, chunklist
);
2874 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2875 file
->read_hook_data
= chunklist
;
2877 for (size
= file
->size
; size
> 0; size
-= read
)
2879 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2880 grub_file_read(file
, NULL
, read
);
2883 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2885 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2886 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2889 if (ventoy_fs_udf
== fs_type
)
2891 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2893 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2894 chunklist
->chunk
[i
].img_start_sector
= sector
;
2895 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2901 len
= (int)grub_strlen(file
->name
);
2902 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2903 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2904 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2905 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2907 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2909 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2919 chunklist
->chunk
[i
].img_start_sector
= sector
;
2920 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2928 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2932 grub_disk_addr_t start
;
2937 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2940 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2943 g_conf_replace_node
= NULL
;
2944 g_conf_replace_offset
= 0;
2946 if (g_img_chunk_list
.chunk
)
2948 grub_free(g_img_chunk_list
.chunk
);
2951 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2953 grub_file_close(file
);
2954 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2957 /* get image chunk data */
2958 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2959 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2960 if (NULL
== g_img_chunk_list
.chunk
)
2962 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2965 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2966 g_img_chunk_list
.cur_chunk
= 0;
2968 start
= file
->device
->disk
->partition
->start
;
2970 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2972 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2973 grub_file_close(file
);
2977 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2980 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2981 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
2982 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2985 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2987 grub_uint64_t offset
= 0;
2988 grub_uint32_t align
= 0;
2989 grub_file_t file
= NULL
;
2990 conf_replace
*node
= NULL
;
2996 debug("select conf replace argc:%d\n", argc
);
3003 node
= ventoy_plugin_find_conf_replace(args
[1]);
3006 debug("Conf replace not found for %s\n", args
[1]);
3010 debug("Find conf replace for %s\n", args
[1]);
3012 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
3015 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
3016 grub_file_close(file
);
3018 else if (node
->img
> 0)
3024 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
3028 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
3031 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3035 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3037 if (align
> vtoy_max_replace_file_size
)
3039 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3043 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3044 g_conf_replace_new_len
= (int)file
->size
;
3045 g_conf_replace_new_len_align
= align
;
3047 g_conf_replace_node
= node
;
3048 g_conf_replace_offset
= offset
+ 2;
3052 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3053 g_grub_param
->img_replace
.old_name_cnt
= 1;
3054 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3057 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3062 grub_file_close(file
);
3064 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3067 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3073 char configfile
[128];
3074 install_template
*node
= NULL
;
3080 debug("select auto installation argc:%d\n", argc
);
3087 node
= ventoy_plugin_find_install_template(args
[0]);
3090 debug("Auto install template not found for %s\n", args
[0]);
3094 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3096 defidx
= node
->autosel
;
3097 if (node
->timeout
< 0)
3099 node
->cursel
= node
->autosel
- 1;
3100 debug("Auto install template auto select %d\n", node
->autosel
);
3105 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3111 if (node
->timeout
> 0)
3113 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3116 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3117 " echo %s\n}\n", "");
3119 for (i
= 0; i
< node
->templatenum
; i
++)
3121 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3123 node
->templatepath
[i
].path
);
3126 g_ventoy_menu_esc
= 1;
3127 g_ventoy_suppress_esc
= 1;
3128 g_ventoy_suppress_esc_default
= defidx
;
3130 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3131 grub_script_execute_sourcecode(configfile
);
3133 g_ventoy_menu_esc
= 0;
3134 g_ventoy_suppress_esc
= 0;
3135 g_ventoy_suppress_esc_default
= 1;
3139 node
->cursel
= g_ventoy_last_entry
- 1;
3141 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3144 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3150 char configfile
[128];
3151 persistence_config
*node
;
3157 debug("select persistence argc:%d\n", argc
);
3164 node
= ventoy_plugin_find_persistent(args
[0]);
3167 debug("Persistence image not found for %s\n", args
[0]);
3171 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3173 defidx
= node
->autosel
;
3174 if (node
->timeout
< 0)
3176 node
->cursel
= node
->autosel
- 1;
3177 debug("Persistence image auto select %d\n", node
->autosel
);
3182 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3188 if (node
->timeout
> 0)
3190 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3193 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3194 " echo %s\n}\n", "");
3196 for (i
= 0; i
< node
->backendnum
; i
++)
3198 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3200 node
->backendpath
[i
].path
);
3204 g_ventoy_menu_esc
= 1;
3205 g_ventoy_suppress_esc
= 1;
3206 g_ventoy_suppress_esc_default
= defidx
;
3208 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3209 grub_script_execute_sourcecode(configfile
);
3211 g_ventoy_menu_esc
= 0;
3212 g_ventoy_suppress_esc
= 0;
3213 g_ventoy_suppress_esc_default
= 1;
3217 node
->cursel
= g_ventoy_last_entry
- 1;
3219 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3222 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3225 ventoy_img_chunk
*cur
;
3231 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3233 cur
= g_img_chunk_list
.chunk
+ i
;
3234 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3235 cur
->img_start_sector
, cur
->img_end_sector
,
3236 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3240 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3243 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3247 ventoy_img_chunk_list chunklist
;
3252 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3255 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3258 /* get image chunk data */
3259 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3260 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3261 if (NULL
== chunklist
.chunk
)
3263 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3266 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3267 chunklist
.cur_chunk
= 0;
3269 ventoy_get_block_list(file
, &chunklist
, 0);
3271 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3273 grub_printf("########## UNSUPPORTED ###############\n");
3276 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3278 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3280 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3281 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3284 grub_printf("\n==================================\n");
3286 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3288 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3289 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3290 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3291 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3292 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3296 grub_free(chunklist
.chunk
);
3297 grub_file_close(file
);
3299 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3302 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3305 ventoy_grub_param_file_replace
*replace
= NULL
;
3313 replace
= &(g_grub_param
->file_replace
);
3314 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3316 replace
->old_name_cnt
= 0;
3317 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3319 replace
->old_name_cnt
++;
3320 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3323 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3326 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3329 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3332 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3338 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3339 grub_env_set(args
[0], buf
);
3342 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3345 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3353 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3354 grub_printf("%s", g_list_script_buf
);
3358 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3359 grub_printf("%s", g_tree_script_buf
);
3365 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3367 img_info
*cur
= g_ventoy_img_list
;
3375 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3376 grub_printf("name:<%s>\n\n", cur
->name
);
3383 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3389 ventoy_plugin_dump_injection();
3394 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3400 ventoy_plugin_dump_auto_install();
3405 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3411 ventoy_plugin_dump_persistence();
3416 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3427 if (args
[0][0] == '0')
3429 return g_ventoy_memdisk_mode
? 0 : 1;
3431 else if (args
[0][0] == '1')
3433 return g_ventoy_iso_raw
? 0 : 1;
3435 else if (args
[0][0] == '2')
3437 return g_ventoy_iso_uefi_drv
? 0 : 1;
3439 else if (args
[0][0] == '3')
3441 return g_ventoy_grub2_mode
? 0 : 1;
3443 else if (args
[0][0] == '4')
3445 return g_ventoy_wimboot_mode
? 0 : 1;
3451 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3453 static int configfile_mode
= 0;
3454 char memfile
[128] = {0};
3461 * args[0]: 0:normal 1:configfile
3462 * args[1]: 0:list_buf 1:tree_buf
3467 debug("Invalid argc %d\n", argc
);
3473 if (args
[0][0] == '0')
3475 if (args
[1][0] == '0')
3477 grub_script_execute_sourcecode(g_list_script_buf
);
3481 grub_script_execute_sourcecode(g_tree_script_buf
);
3486 if (configfile_mode
)
3488 debug("Now already in F3 mode %d\n", configfile_mode
);
3492 if (args
[1][0] == '0')
3494 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3495 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3499 g_ventoy_last_entry
= -1;
3500 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3501 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3504 configfile_mode
= 1;
3505 grub_script_execute_sourcecode(memfile
);
3506 configfile_mode
= 0;
3512 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3523 g_ventoy_case_insensitive
= 1;
3524 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3525 g_ventoy_case_insensitive
= 0;
3531 grub_file_close(file
);
3537 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3542 const char *isopath
= NULL
;
3544 ventoy_mbr_head mbr
;
3551 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3554 isopath
= grub_env_get("vtoy_iso_part");
3557 debug("isopath is null %p\n", isopath
);
3561 debug("isopath is %s\n", isopath
);
3563 for (id
= 0; id
< 30 && (find
== 0); id
++)
3565 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3566 if (grub_strstr(isopath
, hdname
))
3568 debug("skip %s ...\n", hdname
);
3572 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3574 disk
= grub_disk_open(hdname
);
3577 debug("%s not exist\n", hdname
);
3581 grub_memset(&mbr
, 0, sizeof(mbr
));
3582 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3584 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3586 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3587 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3590 grub_env_set(args
[0], hdname
);
3594 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3598 debug("read %s failed\n", hdname
);
3601 grub_disk_close(disk
);
3607 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3618 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3621 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3624 debug("failed to open file %s\n", args
[0]);
3628 buf
= grub_malloc(len
);
3635 grub_file_read(file
, buf
, len
- 1);
3637 ventoy_get_line(buf
);
3638 ventoy_set_env(args
[1], buf
);
3642 grub_check_free(buf
);
3643 grub_file_close(file
);
3648 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3650 int *pCnt
= (int *)data
;
3655 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3656 "0 %llu linear /dev/ventoy %llu\n",
3657 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3662 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3665 char *device_name
= NULL
;
3666 grub_device_t dev
= NULL
;
3671 g_part_list_pos
= 0;
3672 grub_env_unset("vtoy_img_part_file");
3679 device_name
= grub_file_get_device_name(args
[0]);
3682 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3686 dev
= grub_device_open(device_name
);
3689 debug("grub_device_open failed, %s\n", device_name
);
3693 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3695 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3696 grub_env_set("vtoy_img_part_file", buf
);
3698 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3699 grub_env_set("vtoy_img_part_cnt", buf
);
3703 check_free(device_name
, grub_free
);
3704 check_free(dev
, grub_device_close
);
3710 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3721 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3724 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3727 debug("failed to open file %s\n", args
[0]);
3731 buf
= grub_malloc(file
->size
+ 1);
3737 buf
[file
->size
] = 0;
3738 grub_file_read(file
, buf
, file
->size
);
3740 if (grub_strstr(buf
, args
[1]))
3747 grub_check_free(buf
);
3748 grub_file_close(file
);
3753 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3759 ventoy_iso9660_vd pvd
;
3766 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3769 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3772 debug("failed to open file %s\n", args
[0]);
3776 grub_file_seek(file
, 16 * 2048);
3777 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3778 if (len
!= sizeof(pvd
))
3780 debug("failed to read pvd %d\n", len
);
3784 grub_memset(buf
, 0, sizeof(buf
));
3785 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3786 ventoy_set_env(args
[1], buf
);
3788 grub_memset(buf
, 0, sizeof(buf
));
3789 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3790 ventoy_set_env(args
[2], buf
);
3794 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3795 ventoy_set_env(args
[3], buf
);
3798 grub_file_close(file
);
3803 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3814 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3817 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3820 debug("failed to open file %s\n", args
[0]);
3824 grub_memset(buf
, 0, sizeof(buf
));
3825 grub_file_seek(file
, 16 * 2048 + 813);
3826 len
= (int)grub_file_read(file
, buf
, 17);
3829 debug("failed to read create date %d\n", len
);
3833 ventoy_set_env(args
[1], buf
);
3836 grub_file_close(file
);
3841 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3847 ventoy_env_hook_root(1);
3852 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3858 ventoy_env_hook_root(0);
3863 #ifdef GRUB_MACHINE_EFI
3864 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3869 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3875 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3876 if (var
&& *var
== 1)
3884 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3893 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3898 grub_uint64_t FileSectors
= 0;
3899 ventoy_gpt_info
*gpt
= NULL
;
3900 ventoy_part_table
*pt
= NULL
;
3901 grub_uint8_t zeroguid
[16] = {0};
3906 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3909 debug("failed to open file %s\n", args
[0]);
3913 if (file
->size
% 512)
3915 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3919 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3925 FileSectors
= file
->size
/ 512;
3927 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3928 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3930 debug("This is EFI partition table\n");
3932 for (i
= 0; i
< 128; i
++)
3934 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3936 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3938 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3939 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3947 debug("This is MBR partition table\n");
3949 for (i
= 0; i
< 4; i
++)
3951 pt
= gpt
->MBR
.PartTbl
+ i
;
3952 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3954 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3955 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3956 (ulonglong
)FileSectors
);
3965 grub_file_close(file
);
3966 grub_check_free(gpt
);
3967 grub_errno
= GRUB_ERR_NONE
;
3971 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3980 for (i
= 0; i
< 500; i
++)
3982 ret
= grub_getkey_noblock();
3983 if (ret
== GRUB_TERM_NO_KEY
)
3992 grub_printf("\n\n Still have key input after clear.\n");
4000 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4007 int image_sector_size
;
4009 ventoy_chain_head
*chain
;
4010 ventoy_img_chunk
*chunk
;
4011 ventoy_os_param
*osparam
;
4012 ventoy_image_location
*location
;
4013 ventoy_image_disk_region
*region
;
4014 struct grub_acpi_table_header
*acpi
;
4023 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
4025 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
4031 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4033 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4035 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4039 img_chunk_num
= chain
->img_chunk_num
;
4041 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4042 datalen
= sizeof(ventoy_os_param
) + loclen
;
4044 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4045 acpi
= grub_zalloc(buflen
);
4051 /* Step1: Fill acpi table header */
4052 grub_memcpy(acpi
->signature
, "VTOY", 4);
4053 acpi
->length
= buflen
;
4055 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4056 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4058 acpi
->creator_id
[0] = 1;
4059 acpi
->creator_rev
= 1;
4061 /* Step2: Fill data */
4062 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4063 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4064 osparam
->vtoy_img_location_addr
= 0;
4065 osparam
->vtoy_img_location_len
= loclen
;
4066 osparam
->chksum
= 0;
4067 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4069 location
= (ventoy_image_location
*)(osparam
+ 1);
4070 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4071 location
->image_sector_size
= image_sector_size
;
4072 location
->disk_sector_size
= chain
->disk_sector_size
;
4073 location
->region_count
= img_chunk_num
;
4075 region
= location
->regions
;
4076 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4077 if (512 == image_sector_size
)
4079 for (i
= 0; i
< img_chunk_num
; i
++)
4081 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4082 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4083 region
->disk_start_sector
= chunk
->disk_start_sector
;
4090 for (i
= 0; i
< img_chunk_num
; i
++)
4092 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4093 region
->image_start_sector
= chunk
->img_start_sector
;
4094 region
->disk_start_sector
= chunk
->disk_start_sector
;
4100 /* Step3: Fill acpi checksum */
4102 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4104 /* load acpi table */
4105 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4106 grub_script_execute_sourcecode(cmd
);
4110 VENTOY_CMD_RETURN(0);
4113 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4119 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4120 g_ventoy_last_entry
= -1;
4125 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4131 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4136 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4138 const char *pos
= filename
+ 1;
4146 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4148 grub_strncpy((char *)data
, filename
, 128);
4159 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4162 char *device_name
= NULL
;
4163 grub_device_t dev
= NULL
;
4164 grub_fs_t fs
= NULL
;
4165 char buf
[128] = {0};
4171 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4175 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4177 device_name
= grub_file_get_device_name(args
[0]);
4180 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4184 dev
= grub_device_open(device_name
);
4187 debug("grub_device_open failed, %s\n", device_name
);
4191 fs
= grub_fs_probe(dev
);
4194 debug("grub_fs_probe failed, %s\n", device_name
);
4198 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4202 ventoy_set_env(args
[2], buf
);
4209 check_free(device_name
, grub_free
);
4210 check_free(dev
, grub_device_close
);
4215 int ventoy_load_part_table(const char *diskname
)
4222 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4223 if (!g_ventoy_part_info
)
4228 disk
= grub_disk_open(diskname
);
4231 debug("Failed to open disk %s\n", diskname
);
4235 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4237 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4238 grub_disk_close(disk
);
4240 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4241 dev
= grub_device_open(name
);
4244 /* Check for official Ventoy device */
4245 ret
= ventoy_check_official_device(dev
);
4246 grub_device_close(dev
);
4254 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4255 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4260 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4267 ret
= ventoy_load_part_table(args
[0]);
4273 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4274 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4279 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4282 const char *vcfg
= NULL
;
4287 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4290 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4291 grub_env_set(args
[1], vcfg
);
4296 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4304 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4307 grub_uint8_t zeroguid
[16] = {0};
4312 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4315 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4317 if (id
>= 1 && id
<= 128)
4319 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4327 if (id
>= 1 && id
<= 4)
4329 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4339 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4342 char *device_name
= NULL
;
4343 grub_device_t dev
= NULL
;
4344 grub_fs_t fs
= NULL
;
4349 debug("get fs label for %s\n", args
[0]);
4353 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4357 device_name
= grub_file_get_device_name(args
[0]);
4360 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4364 dev
= grub_device_open(device_name
);
4367 debug("grub_device_open failed, %s\n", device_name
);
4371 fs
= grub_fs_probe(dev
);
4372 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4374 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4378 fs
->fs_label(dev
, &label
);
4381 debug("label=<%s>\n", label
);
4382 ventoy_set_env(args
[1], label
);
4390 check_free(device_name
, grub_free
);
4391 check_free(dev
, grub_device_close
);
4396 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4400 grub_snprintf((char *)data
, 256, "%s", filename
);
4407 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4409 if (info
->dir
&& filename
&& filename
[0] != '.')
4411 grub_snprintf((char *)data
, 256, "%s", filename
);
4418 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4421 char *device_name
= NULL
;
4422 grub_device_t dev
= NULL
;
4423 grub_fs_t fs
= NULL
;
4424 char name
[256] ={0};
4428 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4432 device_name
= grub_file_get_device_name(args
[0]);
4435 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4439 dev
= grub_device_open(device_name
);
4442 debug("grub_device_open failed, %s\n", device_name
);
4446 fs
= grub_fs_probe(dev
);
4449 debug("grub_fs_probe failed, %s\n", device_name
);
4453 fs
->fs_dir(dev
, args
[1], hook
, name
);
4456 ventoy_set_env(args
[2], name
);
4463 check_free(device_name
, grub_free
);
4464 check_free(dev
, grub_device_close
);
4469 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4472 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4475 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4478 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4481 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4491 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4495 for (pos
= args
[0]; *pos
; pos
++)
4509 grub_env_set(args
[1], args
[0]);
4519 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4529 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4534 len
= (int)grub_strlen(buf
);
4535 for (i
= len
; i
> 0; i
--)
4537 if (buf
[i
- 1] == '/')
4539 grub_env_set(args
[1], buf
+ i
);
4544 grub_env_set(args
[1], buf
);
4549 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4551 struct grub_video_mode_info info
;
4558 if (!g_video_mode_list
)
4560 ventoy_enum_video_mode();
4563 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4565 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4569 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4572 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4574 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4575 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4577 VENTOY_CMD_RETURN(0);
4580 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4582 struct grub_video_mode_info info
;
4589 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4591 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4595 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4598 grub_env_set(args
[0], buf
);
4600 VENTOY_CMD_RETURN(0);
4603 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4611 if (!g_video_mode_list
)
4616 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4617 if (id
< g_video_mode_num
)
4619 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4620 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4623 grub_env_set(args
[1], buf
);
4625 VENTOY_CMD_RETURN(0);
4628 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4631 grub_uint32_t loadsector
= 0;
4634 grub_uint32_t boot_catlog
= 0;
4635 grub_uint8_t buf
[512];
4641 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4645 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4648 debug("failed to open %s\n", args
[0]);
4652 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4653 if (boot_catlog
== 0)
4655 debug("No bootcatlog found\n");
4656 grub_file_close(file
);
4660 grub_memset(buf
, 0, sizeof(buf
));
4661 grub_file_seek(file
, boot_catlog
* 2048);
4662 grub_file_read(file
, buf
, sizeof(buf
));
4663 grub_file_close(file
);
4665 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4667 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4669 if (buf
[i
+ 32] == 0x88)
4671 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4672 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4678 if (loadsector
== 0)
4680 debug("No EFI eltorito info found\n");
4684 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4685 grub_env_set(args
[1], value
);
4686 VENTOY_CMD_RETURN(0);
4689 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4694 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4696 if (pfsdir
->initrd
[0])
4701 curpos
= pfsdir
->curpos
;
4702 len
= grub_strlen(filename
);
4706 if ((len
== 1 && filename
[0] == '.') ||
4707 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4712 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4715 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4716 pfsdir
->curpos
= curpos
+ printlen
;
4717 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4718 pfsdir
->curpos
= curpos
;
4719 pfsdir
->fullpath
[curpos
] = 0;
4723 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4726 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4727 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4729 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4731 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4740 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4744 char *device_name
= NULL
;
4745 grub_device_t dev
= NULL
;
4746 grub_fs_t fs
= NULL
;
4747 replace_fs_dir
*pfsdir
= NULL
;
4753 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4757 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4763 device_name
= grub_file_get_device_name(args
[0]);
4769 dev
= grub_device_open(device_name
);
4775 fs
= grub_fs_probe(dev
);
4784 pfsdir
->fullpath
[0] = '/';
4785 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4787 if (pfsdir
->initrd
[0])
4789 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4791 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4793 if (pfsdir
->initrd
[i
] == '/')
4795 pfsdir
->initrd
[i
] = '\\';
4799 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4800 grub_env_set(args
[1], pos
);
4804 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4809 grub_check_free(pfsdir
);
4810 grub_check_free(device_name
);
4811 check_free(dev
, grub_device_close
);
4813 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4816 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4818 const char *pager
= NULL
;
4824 pager
= grub_env_get("pager");
4828 grub_env_set("pager", "1");
4830 else if (pager
[0] == '1')
4836 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4838 grub_env_set("pager", "1");
4841 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4844 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4850 if (g_pager_flag
== 1)
4852 grub_env_unset("pager");
4854 else if (g_pager_flag
== 2)
4856 grub_env_set("pager", g_old_pager
);
4859 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4862 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4864 if (g_json_case_mis_path
[0])
4869 if (0 == info
->dir
&& grub_strncasecmp(filename
, "ventoy.json", 11) == 0)
4871 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4877 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4880 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4882 if (g_json_case_mis_path
[0])
4887 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4889 if (grub_strncasecmp(filename
, "ventoy", 6) == 0)
4891 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4892 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4893 if (g_json_case_mis_path
[0])
4903 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4906 char *device_name
= NULL
;
4907 grub_device_t dev
= NULL
;
4908 grub_fs_t fs
= NULL
;
4909 chk_case_fs_dir fs_dir
;
4915 device_name
= grub_file_get_device_name(args
[0]);
4921 dev
= grub_device_open(device_name
);
4927 fs
= grub_fs_probe(dev
);
4933 fstype
= ventoy_get_fs_type(fs
->name
);
4934 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4939 g_json_case_mis_path
[0] = 0;
4942 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4944 if (g_json_case_mis_path
[0])
4946 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4951 grub_check_free(device_name
);
4952 check_free(dev
, grub_device_close
);
4954 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4957 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4960 grub_partition_t part
;
4961 char priority_str
[3]; /* Maximum value 15 */
4965 if (argc
< 2 || argc
> 3)
4966 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4967 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4969 /* Open the disk if it exists */
4970 disk
= grub_disk_open (args
[0]);
4973 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4977 part
= grub_partition_probe (disk
, args
[1]);
4980 grub_disk_close (disk
);
4981 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4982 "No such partition");
4985 if (grub_strcmp (part
->partmap
->name
, "gpt"))
4987 grub_disk_close (disk
);
4988 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
4989 "Not a GPT partition");
4992 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
4993 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
4997 grub_env_set (args
[2], priority_str
);
4998 grub_env_export (args
[2]);
5002 grub_printf ("Priority is %s\n", priority_str
);
5005 grub_disk_close (disk
);
5006 return GRUB_ERR_NONE
;
5011 /* <BEGIN>: Deleted by longpanda, 20210916 PN:XX LABEL:XX */
5013 void ventoy_tip_set_menu_label(const char *vid
)
5017 g_ventoy_tip_msg1
= g_ventoy_tip_msg2
= NULL
;
5020 node
= (img_info
*)(void *)grub_strtoul(vid
+ 4, NULL
, 16);
5023 g_ventoy_tip_msg1
= node
->tip1
;
5024 g_ventoy_tip_msg2
= node
->tip2
;
5029 /* <END> : Deleted by longpanda, 20210916 PN:XX LABEL:XX */
5031 int ventoy_env_init(void)
5035 grub_env_set("vtdebug_flag", "");
5037 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5038 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5039 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5040 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5042 ventoy_filt_register(0, ventoy_wrapper_open
);
5044 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5047 g_grub_param
->grub_env_get
= grub_env_get
;
5048 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5049 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5050 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5051 grub_env_set("env_param", buf
);
5052 grub_env_set("ventoy_env_param", buf
);
5054 grub_env_export("env_param");
5055 grub_env_export("ventoy_env_param");
5058 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5059 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5061 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5062 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5064 grub_env_export("vtoy_winpeshl_ini_addr");
5065 grub_env_export("vtoy_winpeshl_ini_size");
5067 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5068 grub_env_set("vtoy_chain_file_size", buf
);
5069 grub_env_export("vtoy_chain_file_size");
5071 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5072 grub_env_set("vtoy_chain_file_read", buf
);
5073 grub_env_export("vtoy_chain_file_read");
5080 static cmd_para ventoy_cmds
[] =
5082 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5083 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5084 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5085 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5086 { "vt_str_casebegin", ventoy_cmd_strcasebegin
, 0, NULL
, "", "", NULL
},
5087 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5088 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5089 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5090 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5091 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5092 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5093 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5094 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5095 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5096 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5097 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5098 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5099 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5100 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5101 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5102 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5103 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5104 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5105 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5106 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5108 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5109 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5110 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5111 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5112 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5113 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5114 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5116 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5117 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5118 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5119 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5120 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5121 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5122 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5123 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5124 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5125 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5128 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5129 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5130 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5131 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5132 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5133 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5134 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5135 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5136 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5137 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5138 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5140 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5141 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5142 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5143 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5144 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5145 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5146 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5148 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5149 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5150 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5151 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5152 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5153 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5154 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5155 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5156 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5157 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5159 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5160 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5161 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5162 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5163 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5164 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5165 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5166 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5167 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5169 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5170 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5171 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5172 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5175 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5176 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5177 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5179 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5180 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5181 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5184 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5185 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5186 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5187 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5188 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5189 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5190 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5191 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5192 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5193 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5194 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5196 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5197 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5198 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5199 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5200 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5201 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5202 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5203 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5204 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5205 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5207 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5208 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5209 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5210 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5211 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5212 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5213 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5216 int ventoy_register_all_cmd(void)
5219 cmd_para
*cur
= NULL
;
5221 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5223 cur
= ventoy_cmds
+ i
;
5224 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5225 cur
->summary
, cur
->description
, cur
->parser
);
5231 int ventoy_unregister_all_cmd(void)
5235 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5237 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);