1 /******************************************************************************
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/misc.h>
26 #include <grub/disk.h>
27 #include <grub/device.h>
28 #include <grub/term.h>
29 #include <grub/partition.h>
30 #include <grub/file.h>
31 #include <grub/normal.h>
32 #include <grub/extcmd.h>
33 #include <grub/datetime.h>
34 #include <grub/i18n.h>
36 #include <grub/misc.h>
37 #include <grub/kernel.h>
38 #ifdef GRUB_MACHINE_EFI
39 #include <grub/efi/api.h>
40 #include <grub/efi/efi.h>
42 #include <grub/time.h>
43 #include <grub/video.h>
44 #include <grub/acpi.h>
45 #include <grub/charset.h>
46 #include <grub/crypto.h>
47 #include <grub/lib/crc.h>
48 #include <grub/ventoy.h>
49 #include "ventoy_def.h"
52 GRUB_MOD_LICENSE ("GPLv3+");
54 static grub_uint8_t g_check_mbr_data
[440] = {
55 0xEB, 0x63, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFA, 0x90, 0x90, 0xF6, 0xC2, 0x80, 0x74, 0x05, 0xF6, 0xC2, 0x70,
62 0x74, 0x02, 0xB2, 0x80, 0xEA, 0x79, 0x7C, 0x00, 0x00, 0x31, 0xC0, 0x8E, 0xD8, 0x8E, 0xD0, 0xBC,
63 0x00, 0x20, 0xFB, 0xA0, 0x64, 0x7C, 0x3C, 0xFF, 0x74, 0x02, 0x88, 0xC2, 0x52, 0xBE, 0x90, 0x7D,
64 0xE8, 0x16, 0x01, 0xBE, 0x05, 0x7C, 0xB4, 0x41, 0xBB, 0xAA, 0x55, 0xCD, 0x13, 0x5A, 0x52, 0x72,
65 0x3D, 0x81, 0xFB, 0x55, 0xAA, 0x75, 0x37, 0x83, 0xE1, 0x01, 0x74, 0x32, 0x31, 0xC0, 0x89, 0x44,
66 0x04, 0x40, 0x88, 0x44, 0xFF, 0x89, 0x44, 0x02, 0xC7, 0x04, 0x10, 0x00, 0x66, 0x8B, 0x1E, 0x5C,
67 0x7C, 0x66, 0x89, 0x5C, 0x08, 0x66, 0x8B, 0x1E, 0x60, 0x7C, 0x66, 0x89, 0x5C, 0x0C, 0xC7, 0x44,
68 0x06, 0x00, 0x70, 0xB4, 0x42, 0xCD, 0x13, 0x72, 0x05, 0xBB, 0x00, 0x70, 0xEB, 0x76, 0xB4, 0x08,
69 0xCD, 0x13, 0x73, 0x0D, 0x5A, 0x84, 0xD2, 0x0F, 0x83, 0xD8, 0x00, 0xBE, 0x96, 0x7D, 0xE9, 0x82,
70 0x00, 0x66, 0x0F, 0xB6, 0xC6, 0x88, 0x64, 0xFF, 0x40, 0x66, 0x89, 0x44, 0x04, 0x0F, 0xB6, 0xD1,
71 0xC1, 0xE2, 0x02, 0x88, 0xE8, 0x88, 0xF4, 0x40, 0x89, 0x44, 0x08, 0x0F, 0xB6, 0xC2, 0xC0, 0xE8,
72 0x02, 0x66, 0x89, 0x04, 0x66, 0xA1, 0x60, 0x7C, 0x66, 0x09, 0xC0, 0x75, 0x4E, 0x66, 0xA1, 0x5C,
73 0x7C, 0x66, 0x31, 0xD2, 0x66, 0xF7, 0x34, 0x88, 0xD1, 0x31, 0xD2, 0x66, 0xF7, 0x74, 0x04, 0x3B,
74 0x44, 0x08, 0x7D, 0x37, 0xFE, 0xC1, 0x88, 0xC5, 0x30, 0xC0, 0xC1, 0xE8, 0x02, 0x08, 0xC1, 0x88,
75 0xD0, 0x5A, 0x88, 0xC6, 0xBB, 0x00, 0x70, 0x8E, 0xC3, 0x31, 0xDB, 0xB8, 0x01, 0x02, 0xCD, 0x13,
76 0x72, 0x1E, 0x8C, 0xC3, 0x60, 0x1E, 0xB9, 0x00, 0x01, 0x8E, 0xDB, 0x31, 0xF6, 0xBF, 0x00, 0x80,
77 0x8E, 0xC6, 0xFC, 0xF3, 0xA5, 0x1F, 0x61, 0xFF, 0x26, 0x5A, 0x7C, 0xBE, 0x93, 0x7D, 0xEB, 0x03,
78 0xBE, 0x99, 0x7D, 0xE8, 0x33, 0x00, 0xBE, 0x9C, 0x7D, 0xE8, 0x2D, 0x00, 0xCD, 0x18, 0xEB, 0xFE,
79 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
80 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
81 0x0A, 0x00, 0xBB, 0x01, 0x00, 0xB4, 0x0E, 0xCD, 0x10, 0xAC, 0x3C, 0x00, 0x75, 0xF4, 0xC3, 0x00,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
85 initrd_info
*g_initrd_img_list
= NULL
;
86 initrd_info
*g_initrd_img_tail
= NULL
;
87 int g_initrd_img_count
= 0;
88 int g_valid_initrd_count
= 0;
89 int g_default_menu_mode
= 0;
90 int g_filt_dot_underscore_file
= 0;
91 int g_sort_case_sensitive
= 0;
92 int g_tree_view_menu_style
= 0;
93 static grub_file_t g_old_file
;
94 static int g_ventoy_last_entry_back
;
97 char g_img_swap_tmp_buf
[1024];
98 img_info g_img_swap_tmp
;
99 img_info
*g_ventoy_img_list
= NULL
;
101 int g_ventoy_img_count
= 0;
103 grub_device_t g_enum_dev
= NULL
;
104 grub_fs_t g_enum_fs
= NULL
;
105 int g_img_max_search_level
= -1;
106 img_iterator_node g_img_iterator_head
;
107 img_iterator_node
*g_img_iterator_tail
= NULL
;
109 grub_uint8_t g_ventoy_break_level
= 0;
110 grub_uint8_t g_ventoy_debug_level
= 0;
111 grub_uint8_t g_ventoy_chain_type
= 0;
113 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
114 grub_uint32_t g_ventoy_cpio_size
= 0;
115 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
116 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
118 int g_plugin_image_list
= 0;
120 ventoy_grub_param
*g_grub_param
= NULL
;
122 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
124 ventoy_img_chunk_list g_img_chunk_list
;
126 int g_wimboot_enable
= 0;
127 ventoy_img_chunk_list g_wimiso_chunk_list
;
128 char *g_wimiso_path
= NULL
;
130 int g_vhdboot_enable
= 0;
132 grub_uint64_t g_conf_replace_offset
= 0;
133 grub_uint64_t g_svd_replace_offset
= 0;
134 conf_replace
*g_conf_replace_node
= NULL
;
135 grub_uint8_t
*g_conf_replace_new_buf
= NULL
;
136 int g_conf_replace_new_len
= 0;
137 int g_conf_replace_new_len_align
= 0;
139 ventoy_gpt_info
*g_ventoy_part_info
= NULL
;
140 grub_uint64_t g_ventoy_disk_size
= 0;
141 grub_uint64_t g_ventoy_disk_part_size
[2];
143 static char *g_tree_script_buf
= NULL
;
144 static int g_tree_script_pos
= 0;
146 static char *g_list_script_buf
= NULL
;
147 static int g_list_script_pos
= 0;
149 static char *g_part_list_buf
= NULL
;
150 static int g_part_list_pos
= 0;
152 static int g_video_mode_max
= 0;
153 static int g_video_mode_num
= 0;
154 static ventoy_video_mode
*g_video_mode_list
= NULL
;
156 static int g_enumerate_time_checked
= 0;
157 static grub_uint64_t g_enumerate_start_time_ms
;
158 static grub_uint64_t g_enumerate_finish_time_ms
;
159 static int g_vtoy_file_flt
[VTOY_FILE_FLT_BUTT
] = {0};
161 static int g_pager_flag
= 0;
162 static char g_old_pager
[32];
164 static const char *g_vtoy_winpeshl_ini
= "[LaunchApps]\r\nvtoyjump.exe";
166 static const char *g_menu_class
[] =
168 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
171 const char *g_menu_prefix
[img_type_max
] =
173 "iso", "wim", "efi", "img", "vhd", "vtoy"
176 static int g_vtoy_load_prompt
= 0;
177 static char g_vtoy_prompt_msg
[64];
179 static char g_json_case_mis_path
[32];
181 static int ventoy_get_fs_type(const char *fs
)
185 return ventoy_fs_max
;
187 else if (grub_strncmp(fs
, "exfat", 5) == 0)
189 return ventoy_fs_exfat
;
191 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
193 return ventoy_fs_ntfs
;
195 else if (grub_strncmp(fs
, "ext", 3) == 0)
197 return ventoy_fs_ext
;
199 else if (grub_strncmp(fs
, "xfs", 3) == 0)
201 return ventoy_fs_xfs
;
203 else if (grub_strncmp(fs
, "udf", 3) == 0)
205 return ventoy_fs_udf
;
207 else if (grub_strncmp(fs
, "fat", 3) == 0)
209 return ventoy_fs_fat
;
212 return ventoy_fs_max
;
215 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
234 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
236 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
240 static int ventoy_control_get_flag(const char *key
)
242 const char *val
= ventoy_get_env(key
);
244 if (val
&& val
[0] == '1' && val
[1] == 0)
251 static grub_err_t
ventoy_fs_close(grub_file_t file
)
253 grub_file_close(g_old_file
);
254 grub_free(file
->data
);
262 static int ventoy_video_hook(const struct grub_video_mode_info
*info
, void *hook_arg
)
268 if (info
->mode_type
& GRUB_VIDEO_MODE_TYPE_PURE_TEXT
)
273 for (i
= 0; i
< g_video_mode_num
; i
++)
275 if (g_video_mode_list
[i
].width
== info
->width
&&
276 g_video_mode_list
[i
].height
== info
->height
&&
277 g_video_mode_list
[i
].bpp
== info
->bpp
)
283 g_video_mode_list
[g_video_mode_num
].width
= info
->width
;
284 g_video_mode_list
[g_video_mode_num
].height
= info
->height
;
285 g_video_mode_list
[g_video_mode_num
].bpp
= info
->bpp
;
288 if (g_video_mode_num
== g_video_mode_max
)
290 g_video_mode_max
*= 2;
291 g_video_mode_list
= grub_realloc(g_video_mode_list
, g_video_mode_max
* sizeof(ventoy_video_mode
));
297 static int ventoy_video_mode_cmp(ventoy_video_mode
*v1
, ventoy_video_mode
*v2
)
299 if (v1
->bpp
== v2
->bpp
)
301 if (v1
->width
== v2
->width
)
303 if (v1
->height
== v2
->height
)
309 return (v1
->height
< v2
->height
) ? -1 : 1;
314 return (v1
->width
< v2
->width
) ? -1 : 1;
319 return (v1
->bpp
< v2
->bpp
) ? -1 : 1;
323 static int ventoy_enum_video_mode(void)
326 grub_video_adapter_t adapter
;
327 grub_video_driver_id_t id
;
328 ventoy_video_mode mode
;
330 g_video_mode_num
= 0;
331 g_video_mode_max
= 1024;
332 g_video_mode_list
= grub_malloc(sizeof(ventoy_video_mode
) * g_video_mode_max
);
333 if (!g_video_mode_list
)
338 #ifdef GRUB_MACHINE_PCBIOS
339 grub_dl_load ("vbe");
342 id
= grub_video_get_driver_id ();
344 FOR_VIDEO_ADAPTERS (adapter
)
346 if (!adapter
->iterate
||
347 (adapter
->id
!= id
&& (id
!= GRUB_VIDEO_DRIVER_NONE
||
348 adapter
->init() != GRUB_ERR_NONE
)))
353 adapter
->iterate(ventoy_video_hook
, NULL
);
355 if (adapter
->id
!= id
)
361 /* sort video mode */
362 for (i
= 0; i
< g_video_mode_num
; i
++)
363 for (j
= i
+ 1; j
< g_video_mode_num
; j
++)
365 if (ventoy_video_mode_cmp(g_video_mode_list
+ i
, g_video_mode_list
+ j
) < 0)
367 grub_memcpy(&mode
, g_video_mode_list
+ i
, sizeof(ventoy_video_mode
));
368 grub_memcpy(g_video_mode_list
+ i
, g_video_mode_list
+ j
, sizeof(ventoy_video_mode
));
369 grub_memcpy(g_video_mode_list
+ j
, &mode
, sizeof(ventoy_video_mode
));
373 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
376 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
380 static struct grub_fs vtoy_fs
=
385 .fs_read
= ventoy_fs_read
,
386 .fs_close
= ventoy_fs_close
,
396 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
402 file
->data
= grub_malloc(rawFile
->size
+ 4096);
408 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
409 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
411 g_old_file
= rawFile
;
413 file
->size
= rawFile
->size
+ len
;
414 file
->device
= rawFile
->device
;
416 file
->not_easily_seekable
= 1;
421 static int ventoy_check_decimal_var(const char *name
, long *value
)
423 const char *value_str
= NULL
;
425 value_str
= grub_env_get(name
);
426 if (NULL
== value_str
)
428 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
431 if (!ventoy_is_decimal(value_str
))
433 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
436 *value
= grub_strtol(value_str
, NULL
, 10);
438 return GRUB_ERR_NONE
;
441 grub_uint64_t
ventoy_get_vtoy_partsize(int part
)
443 grub_uint64_t sectors
;
445 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
447 sectors
= g_ventoy_part_info
->PartTbl
[part
].LastLBA
+ 1 - g_ventoy_part_info
->PartTbl
[part
].StartLBA
;
451 sectors
= g_ventoy_part_info
->MBR
.PartTbl
[part
].SectorCount
;
454 return sectors
* 512;
457 static int ventoy_load_efiboot_template(char **buf
, int *datalen
, int *direntoff
)
463 grub_uint32_t offset
;
465 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
468 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
472 len
= (int)file
->size
;
474 data
= (char *)grub_malloc(file
->size
);
480 grub_file_read(file
, data
, file
->size
);
481 grub_file_close(file
);
483 grub_snprintf(exec
, sizeof(exec
), "loopback efiboot mem:0x%llx:size:%d", (ulonglong
)(ulong
)data
, len
);
484 grub_script_execute_sourcecode(exec
);
486 file
= grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD
);
487 offset
= (grub_uint32_t
)grub_iso9660_get_last_file_dirent_pos(file
);
488 grub_file_close(file
);
490 grub_script_execute_sourcecode("loopback -d efiboot");
494 *direntoff
= offset
+ 2;
499 static int ventoy_set_check_result(int ret
)
503 grub_snprintf(buf
, sizeof(buf
), "%d", (ret
& 0x7FFF));
504 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf
);
505 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
509 grub_printf(VTOY_WARNING
"\n");
510 grub_printf(VTOY_WARNING
"\n");
511 grub_printf(VTOY_WARNING
"\n\n\n");
513 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n\n", ret
);
514 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
516 grub_printf("\n\nWill exit after 10 seconds ...... ");
524 static int ventoy_check_official_device(grub_device_t dev
)
528 grub_uint64_t offset
;
531 grub_uint8_t mbr
[512];
535 struct grub_partition
*partition
;
537 if (dev
->disk
== NULL
|| dev
->disk
->partition
== NULL
)
539 return ventoy_set_check_result(1 | 0x1000);
542 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
543 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev
->disk
->name
) ||
544 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
546 #ifndef GRUB_MACHINE_EFI
547 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev
->disk
->name
) ||
548 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev
->disk
->name
) ||
549 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev
->disk
->name
))
551 return ventoy_set_check_result(2 | 0x1000);
560 /* We must have partition 2 */
563 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
567 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(%s,2)/ventoy/ventoy.cpio", dev
->disk
->name
);
571 return ventoy_set_check_result(3 | 0x1000);
574 if (NULL
== grub_strstr(file
->fs
->name
, "fat"))
576 grub_file_close(file
);
577 return ventoy_set_check_result(4 | 0x1000);
580 partition
= dev
->disk
->partition
;
581 if (partition
->number
!= 0 || partition
->start
!= 2048)
583 return ventoy_set_check_result(5);
588 if (grub_strncmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
590 ventoy_gpt_part_tbl
*PartTbl
= g_ventoy_part_info
->PartTbl
;
591 if (PartTbl
[1].StartLBA
!= PartTbl
[0].LastLBA
+ 1 ||
592 (PartTbl
[1].LastLBA
+ 1 - PartTbl
[1].StartLBA
) != 65536)
594 grub_file_close(file
);
595 return ventoy_set_check_result(6);
600 ventoy_part_table
*PartTbl
= g_ventoy_part_info
->MBR
.PartTbl
;
601 if (PartTbl
[1].StartSectorId
!= PartTbl
[0].StartSectorId
+ PartTbl
[0].SectorCount
||
602 PartTbl
[1].SectorCount
!= 65536)
604 grub_file_close(file
);
605 return ventoy_set_check_result(6);
611 offset
= partition
->start
+ partition
->len
;
612 partition
= file
->device
->disk
->partition
;
613 if ((partition
->number
!= 1) || (partition
->len
!= 65536) || (offset
!= partition
->start
))
615 grub_file_close(file
);
616 return ventoy_set_check_result(7);
620 grub_file_close(file
);
624 grub_snprintf(devname
, sizeof(devname
), "%s,2", dev
->disk
->name
);
625 dev2
= grub_device_open(devname
);
628 return ventoy_set_check_result(8);
631 fs
= grub_fs_probe(dev2
);
634 grub_device_close(dev2
);
635 return ventoy_set_check_result(9);
638 fs
->fs_label(dev2
, &label
);
639 if ((!label
) || grub_strncmp("VTOYEFI", label
, 7))
641 grub_device_close(dev2
);
642 return ventoy_set_check_result(10);
645 grub_device_close(dev2
);
649 disk
= grub_disk_open(dev
->disk
->name
);
652 return ventoy_set_check_result(11);
655 grub_memset(mbr
, 0, 512);
656 grub_disk_read(disk
, 0, 0, 512, mbr
);
657 grub_disk_close(disk
);
659 g_check_mbr_data
[92] = mbr
[92];
660 g_check_mbr_data
[102] = mbr
[102];
661 g_check_mbr_data
[103] = mbr
[103];
662 grub_memcpy(g_check_mbr_data
+ 0x180, mbr
+ 0x180, 16);
663 if (grub_memcmp(g_check_mbr_data
, mbr
, 440))
665 return ventoy_set_check_result(12);
668 return ventoy_set_check_result(0);
671 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
675 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
685 grub_uint64_t
ventoy_grub_get_file_size(const char *fmt
, ...)
687 grub_uint64_t size
= 0;
690 char fullpath
[256] = {0};
693 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
696 file
= grub_file_open(fullpath
, VENTOY_FILE_TYPE
);
699 debug("grub_file_open failed <%s>\n", fullpath
);
705 grub_file_close(file
);
709 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
713 char fullpath
[256] = {0};
716 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
719 file
= grub_file_open(fullpath
, type
);
722 debug("grub_file_open failed <%s> %d\n", fullpath
, grub_errno
);
729 int ventoy_is_file_exist(const char *fmt
, ...)
736 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f \"");
740 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
743 grub_strncpy(pos
+ len
, "\" ]", 3);
745 debug("script exec %s\n", buf
);
747 if (0 == grub_script_execute_sourcecode(buf
))
755 int ventoy_is_dir_exist(const char *fmt
, ...)
762 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -d \"");
766 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
769 grub_strncpy(pos
+ len
, "\" ]", 3);
771 debug("script exec %s\n", buf
);
773 if (0 == grub_script_execute_sourcecode(buf
))
781 int ventoy_gzip_compress(void *mem_in
, int mem_in_len
, void *mem_out
, int mem_out_len
)
784 grub_uint8_t
*outbuf
;
785 grub_uint8_t gzHdr
[10] =
787 0x1F, 0x8B, /* magic */
795 grub_memset(&s
, 0, sizeof(mz_stream
));
797 mz_deflateInit2(&s
, 1, MZ_DEFLATED
, -MZ_DEFAULT_WINDOW_BITS
, 6, MZ_DEFAULT_STRATEGY
);
799 outbuf
= (grub_uint8_t
*)mem_out
;
801 mem_out_len
-= sizeof(gzHdr
) + 8;
802 grub_memcpy(outbuf
, gzHdr
, sizeof(gzHdr
));
803 outbuf
+= sizeof(gzHdr
);
805 s
.avail_in
= mem_in_len
;
808 s
.avail_out
= mem_out_len
;
811 mz_deflate(&s
, MZ_FINISH
);
815 outbuf
+= s
.total_out
;
816 *(grub_uint32_t
*)outbuf
= grub_getcrc32c(0, outbuf
, s
.total_out
);
817 *(grub_uint32_t
*)(outbuf
+ 4) = (grub_uint32_t
)(s
.total_out
);
819 return s
.total_out
+ sizeof(gzHdr
) + 8;
827 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
831 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
834 if (0 == grub_strcmp(args
[0], "on"))
837 grub_env_set("vtdebug_flag", "debug");
842 grub_env_set("vtdebug_flag", "");
845 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
848 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
852 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
854 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
855 grub_printf(" level:\r\n");
856 grub_printf(" 01/11: busybox / (+cat log)\r\n");
857 grub_printf(" 02/12: initrd / (+cat log)\r\n");
858 grub_printf(" 03/13: hook / (+cat log)\r\n");
860 grub_printf(" debug:\r\n");
861 grub_printf(" 0: debug is off\r\n");
862 grub_printf(" 1: debug is on\r\n");
864 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
867 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
869 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
871 g_ventoy_debug_level
= 1;
874 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
877 static grub_err_t
ventoy_cmd_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
886 return (grub_strstr(args
[0], args
[1])) ? 0 : 1;
889 static grub_err_t
ventoy_cmd_strbegin(grub_extcmd_context_t ctxt
, int argc
, char **args
)
921 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
926 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
928 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
931 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
936 value_long
+= grub_strtol(args
[1], NULL
, 10);
938 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
939 grub_env_set(args
[0], buf
);
941 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
944 static grub_err_t
ventoy_cmd_mod(grub_extcmd_context_t ctxt
, int argc
, char **args
)
946 ulonglong value1
= 0;
947 ulonglong value2
= 0;
952 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name
);
955 value1
= grub_strtoull(args
[0], NULL
, 10);
956 value2
= grub_strtoull(args
[1], NULL
, 10);
958 grub_snprintf(buf
, sizeof(buf
), "%llu", (value1
& (value2
- 1)));
959 grub_env_set(args
[2], buf
);
961 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
964 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
979 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
982 debug("failed to open file <%s> for udf check\n", args
[0]);
986 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
988 grub_env_set(args
[1], buf
);
990 grub_file_close(file
);
996 static grub_err_t
ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1004 g_wimboot_enable
= 0;
1005 grub_check_free(g_wimiso_path
);
1006 grub_check_free(g_wimiso_chunk_list
.chunk
);
1008 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
1014 grub_memset(&g_wimiso_chunk_list
, 0, sizeof(g_wimiso_chunk_list
));
1015 g_wimiso_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1016 if (NULL
== g_wimiso_chunk_list
.chunk
)
1018 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1021 g_wimiso_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1022 g_wimiso_chunk_list
.cur_chunk
= 0;
1024 ventoy_get_block_list(file
, &g_wimiso_chunk_list
, file
->device
->disk
->partition
->start
);
1026 g_wimboot_enable
= 1;
1027 g_wimiso_path
= grub_strdup(args
[0]);
1029 grub_file_close(file
);
1034 static grub_err_t
ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1044 ventoy_iso9660_override
*dirent
;
1053 totlen
= sizeof(ventoy_chain_head
);
1055 if (ventoy_load_efiboot_template(&buf
, &len
, &offset
))
1057 debug("failed to load efiboot template %d\n", len
);
1063 debug("efiboot template len:%d offset:%d\n", len
, offset
);
1065 file
= ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD
, "%s", args
[0]);
1068 debug("failed to open file <%s>\n", args
[0]);
1072 totlen
+= ventoy_align_2k(file
->size
);
1074 dirent
= (ventoy_iso9660_override
*)(buf
+ offset
);
1075 dirent
->first_sector
= len
/ 2048;
1076 dirent
->first_sector_be
= grub_swap_bytes32(dirent
->first_sector
);
1077 dirent
->size
= (grub_uint32_t
)file
->size
;
1078 dirent
->size_be
= grub_swap_bytes32(dirent
->size
);
1080 debug("rawiso len:%d efilen:%d total:%d\n", len
, (int)file
->size
, totlen
);
1082 #ifdef GRUB_MACHINE_EFI
1083 data
= (char *)grub_efi_allocate_iso_buf(totlen
);
1085 data
= (char *)grub_malloc(totlen
);
1088 ventoy_fill_os_param(file
, (ventoy_os_param
*)data
);
1090 grub_memcpy(data
+ sizeof(ventoy_chain_head
), buf
, len
);
1091 grub_check_free(buf
);
1093 grub_file_read(file
, data
+ sizeof(ventoy_chain_head
) + len
, file
->size
);
1094 grub_file_close(file
);
1096 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1097 grub_snprintf(value
, sizeof(value
), "0x%llx", (ulonglong
)(ulong
)data
);
1098 grub_env_set(name
, value
);
1100 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1101 grub_snprintf(value
, sizeof(value
), "%d", (int)(totlen
));
1102 grub_env_set(name
, value
);
1107 grub_err_t
ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1113 g_vtoy_load_prompt
= 0;
1114 grub_memset(g_vtoy_prompt_msg
, 0, sizeof(g_vtoy_prompt_msg
));
1116 if (argc
== 2 && args
[0][0] == '1')
1118 g_vtoy_load_prompt
= 1;
1119 grub_snprintf(g_vtoy_prompt_msg
, sizeof(g_vtoy_prompt_msg
), "%s", args
[1]);
1122 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1125 int ventoy_need_prompt_load_file(void)
1127 return g_vtoy_load_prompt
;
1130 grub_ssize_t
ventoy_load_file_with_prompt(grub_file_t file
, void *buf
, grub_ssize_t size
)
1132 grub_uint64_t ro
= 0;
1133 grub_uint64_t div
= 0;
1134 grub_ssize_t left
= size
;
1135 char *cur
= (char *)buf
;
1137 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg
);
1140 while (left
>= VTOY_SIZE_2MB
)
1142 grub_file_read(file
, cur
, VTOY_SIZE_2MB
);
1143 cur
+= VTOY_SIZE_2MB
;
1144 left
-= VTOY_SIZE_2MB
;
1146 div
= grub_divmod64((grub_uint64_t
)((size
- left
) * 100), (grub_uint64_t
)size
, &ro
);
1147 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg
, (int)div
);
1153 grub_file_read(file
, cur
, left
);
1156 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg
);
1162 static grub_err_t
ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1169 enum grub_file_type type
;
1180 if (grub_strcmp(args
[0], "nodecompress") == 0)
1182 type
= VENTOY_FILE_TYPE
;
1186 type
= GRUB_FILE_TYPE_LINUX_INITRD
;
1189 file
= ventoy_grub_file_open(type
, "%s", args
[1]);
1192 debug("failed to open file <%s>\n", args
[1]);
1196 #ifdef GRUB_MACHINE_EFI
1197 buf
= (char *)grub_efi_allocate_chain_buf(file
->size
);
1199 buf
= (char *)grub_malloc(file
->size
);
1204 grub_file_close(file
);
1208 if (g_vtoy_load_prompt
)
1210 ventoy_load_file_with_prompt(file
, buf
, file
->size
);
1214 grub_file_read(file
, buf
, file
->size
);
1217 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[2]);
1218 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1219 grub_env_set(name
, value
);
1221 grub_snprintf(name
, sizeof(name
), "%s_size", args
[2]);
1222 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1223 grub_env_set(name
, value
);
1225 grub_file_close(file
);
1231 static grub_err_t
ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1249 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1252 debug("failed to open file <%s> for udf check\n", args
[0]);
1256 headlen
= sizeof(ventoy_chain_head
);
1258 #ifdef GRUB_MACHINE_EFI
1259 buf
= (char *)grub_efi_allocate_iso_buf(headlen
+ file
->size
);
1261 buf
= (char *)grub_malloc(headlen
+ file
->size
);
1264 ventoy_fill_os_param(file
, (ventoy_os_param
*)buf
);
1266 grub_file_read(file
, buf
+ headlen
, file
->size
);
1268 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
1269 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
1270 grub_env_set(name
, value
);
1272 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
1273 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
1274 grub_env_set(name
, value
);
1276 grub_file_close(file
);
1282 static grub_err_t
ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1288 if (grub_iso9660_is_joliet())
1290 debug("This time has joliet process\n");
1299 static grub_err_t
ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1308 if (args
[0][0] == '1')
1310 grub_iso9660_set_nojoliet(1);
1314 grub_iso9660_set_nojoliet(0);
1320 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1325 grub_uint8_t buf
[32];
1336 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1339 debug("failed to open file <%s> for udf check\n", args
[0]);
1343 for (i
= 16; i
< 32; i
++)
1345 grub_file_seek(file
, i
* 2048);
1346 grub_file_read(file
, buf
, sizeof(buf
));
1354 grub_file_seek(file
, i
* 2048);
1355 grub_file_read(file
, buf
, sizeof(buf
));
1357 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
1360 grub_file_seek(file
, i
* 2048);
1361 grub_file_read(file
, buf
, sizeof(buf
));
1363 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
1364 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
1370 grub_file_close(file
);
1372 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
1377 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1379 long value_long1
= 0;
1380 long value_long2
= 0;
1382 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
1384 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
1387 value_long1
= grub_strtol(args
[0], NULL
, 10);
1388 value_long2
= grub_strtol(args
[2], NULL
, 10);
1390 if (0 == grub_strcmp(args
[1], "eq"))
1392 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1394 else if (0 == grub_strcmp(args
[1], "ne"))
1396 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1398 else if (0 == grub_strcmp(args
[1], "gt"))
1400 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1402 else if (0 == grub_strcmp(args
[1], "lt"))
1404 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1406 else if (0 == grub_strcmp(args
[1], "ge"))
1408 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1410 else if (0 == grub_strcmp(args
[1], "le"))
1412 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
1416 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
1422 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1425 char buf
[128] = {0};
1429 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
1432 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
1433 pos
= grub_strstr(buf
, ",");
1439 grub_env_set(args
[1], buf
);
1441 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1444 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1450 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
1456 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
1459 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
1461 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e \"%s/%s\" ]", args
[0], files
[i
]);
1462 if (0 == grub_script_execute_sourcecode(buf
))
1464 debug("file %s exist, ventoy_compatible YES\n", buf
);
1465 grub_env_set("ventoy_compatible", "YES");
1466 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1470 debug("file %s NOT exist\n", buf
);
1474 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
1475 pos
= grub_strstr(buf
, ")");
1481 disk
= grub_disk_open(buf
);
1484 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
1485 grub_disk_close(disk
);
1487 g_img_swap_tmp_buf
[703] = 0;
1488 for (i
= 318; i
< 703; i
++)
1490 if (g_img_swap_tmp_buf
[i
] == 'V' &&
1491 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
1493 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
1494 grub_env_set("ventoy_compatible", "YES");
1495 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1501 debug("failed to open disk <%s>\n", buf
);
1504 grub_env_set("ventoy_compatible", "NO");
1505 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1508 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
1514 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1516 return (img1
->plugin_list_index
- img2
->plugin_list_index
);
1519 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
1524 if (0 == g_sort_case_sensitive
)
1526 if (grub_islower(c1
))
1528 c1
= c1
- 'a' + 'A';
1531 if (grub_islower(c2
))
1533 c2
= c2
- 'a' + 'A';
1546 static int ventoy_cmp_subdir(img_iterator_node
*node1
, img_iterator_node
*node2
)
1552 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1554 return (node1
->plugin_list_index
- node2
->plugin_list_index
);
1557 for (s1
= node1
->dir
, s2
= node2
->dir
; *s1
&& *s2
; s1
++, s2
++)
1562 if (0 == g_sort_case_sensitive
)
1564 if (grub_islower(c1
))
1566 c1
= c1
- 'a' + 'A';
1569 if (grub_islower(c2
))
1571 c2
= c2
- 'a' + 'A';
1584 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
1586 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
1588 grub_memcpy(img1
, img2
, sizeof(img_info
));
1589 img1
->next
= g_img_swap_tmp
.next
;
1590 img1
->prev
= g_img_swap_tmp
.prev
;
1592 g_img_swap_tmp
.next
= img2
->next
;
1593 g_img_swap_tmp
.prev
= img2
->prev
;
1594 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
1597 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
1601 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1609 static int ventoy_collect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
1618 const menu_tip
*tip
;
1619 img_iterator_node
*tmp
;
1620 img_iterator_node
*new_node
;
1621 img_iterator_node
*node
= (img_iterator_node
*)data
;
1623 if (g_enumerate_time_checked
== 0)
1625 g_enumerate_finish_time_ms
= grub_get_time_ms();
1626 if ((g_enumerate_finish_time_ms
- g_enumerate_start_time_ms
) >= 3000)
1629 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1631 g_enumerate_time_checked
= 1;
1635 len
= grub_strlen(filename
);
1639 if (node
->level
+ 1 > g_img_max_search_level
)
1644 if ((len
== 1 && filename
[0] == '.') ||
1645 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
1650 if (!ventoy_img_name_valid(filename
, len
))
1655 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
1660 if (g_plugin_image_list
== VENTOY_IMG_WHITE_LIST
)
1662 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s/", node
->dir
, filename
);
1663 index
= ventoy_plugin_get_image_list_index(vtoy_class_directory
, g_img_swap_tmp_buf
);
1666 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1671 new_node
= grub_zalloc(sizeof(img_iterator_node
));
1674 new_node
->level
= node
->level
+ 1;
1675 new_node
->plugin_list_index
= index
;
1676 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
1678 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
1681 debug("Directory %s ignored...\n", new_node
->dir
);
1682 grub_free(new_node
);
1686 new_node
->tail
= node
->tail
;
1688 new_node
->parent
= node
;
1689 if (!node
->firstchild
)
1691 node
->firstchild
= new_node
;
1694 if (g_img_iterator_tail
)
1696 g_img_iterator_tail
->next
= new_node
;
1697 g_img_iterator_tail
= new_node
;
1701 g_img_iterator_head
.next
= new_node
;
1702 g_img_iterator_tail
= new_node
;
1708 debug("Find a file %s\n", filename
);
1714 if (FILE_FLT(ISO
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".iso"))
1716 type
= img_type_iso
;
1718 else if (FILE_FLT(WIM
) && g_wimboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".wim")))
1720 type
= img_type_wim
;
1722 else if (FILE_FLT(VHD
) && g_vhdboot_enable
&& (0 == grub_strcasecmp(filename
+ len
- 4, ".vhd") ||
1723 (len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vhdx"))))
1725 type
= img_type_vhd
;
1727 #ifdef GRUB_MACHINE_EFI
1728 else if (FILE_FLT(EFI
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".efi"))
1730 type
= img_type_efi
;
1733 else if (FILE_FLT(IMG
) && 0 == grub_strcasecmp(filename
+ len
- 4, ".img"))
1735 if (len
== 18 && grub_strncmp(filename
, "ventoy_", 7) == 0)
1737 if (grub_strncmp(filename
+ 7, "wimboot", 7) == 0 ||
1738 grub_strncmp(filename
+ 7, "vhdboot", 7) == 0)
1743 type
= img_type_img
;
1745 else if (FILE_FLT(VTOY
) && len
>= 5 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vtoy"))
1747 type
= img_type_vtoy
;
1749 else if (len
>= 9 && 0 == grub_strcasecmp(filename
+ len
- 5, ".vcfg"))
1751 if (filename
[len
- 9] == '.' || (len
>= 10 && filename
[len
- 10] == '.'))
1753 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1754 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf
);
1763 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
1768 if (g_plugin_image_list
)
1770 grub_snprintf(g_img_swap_tmp_buf
, sizeof(g_img_swap_tmp_buf
), "%s%s", node
->dir
, filename
);
1771 index
= ventoy_plugin_get_image_list_index(vtoy_class_image_file
, g_img_swap_tmp_buf
);
1772 if (VENTOY_IMG_WHITE_LIST
== g_plugin_image_list
&& index
== 0)
1774 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf
);
1777 else if (VENTOY_IMG_BLACK_LIST
== g_plugin_image_list
&& index
> 0)
1779 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf
, index
);
1784 img
= grub_zalloc(sizeof(img_info
));
1788 img
->plugin_list_index
= index
;
1789 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
1791 img
->pathlen
= grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, img
->name
);
1793 img
->size
= info
->size
;
1796 img
->size
= ventoy_grub_get_file_size("%s/%s%s", g_iso_path
, node
->dir
, filename
);
1799 if (img
->size
< VTOY_FILT_MIN_FILE_SIZE
)
1801 debug("img <%s> size too small %llu\n", img
->name
, (ulonglong
)img
->size
);
1806 if (g_ventoy_img_list
)
1808 tail
= *(node
->tail
);
1814 g_ventoy_img_list
= img
;
1817 img
->id
= g_ventoy_img_count
;
1819 if (node
&& NULL
== node
->firstiso
)
1821 node
->firstiso
= img
;
1832 *((img_info
**)(node
->tail
)) = img
;
1833 g_ventoy_img_count
++;
1835 img
->alias
= ventoy_plugin_get_menu_alias(vtoy_alias_image_file
, img
->path
);
1837 tip
= ventoy_plugin_get_menu_tip(img
->path
);
1840 img
->tip1
= tip
->tip1
;
1841 img
->tip2
= tip
->tip2
;
1844 img
->class = ventoy_plugin_get_menu_class(vtoy_class_image_file
, img
->name
, img
->path
);
1847 img
->class = g_menu_class
[type
];
1849 img
->menu_prefix
= g_menu_prefix
[type
];
1851 if (img_type_iso
== type
)
1853 if (ventoy_plugin_check_memdisk(img
->path
))
1855 img
->menu_prefix
= "miso";
1859 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
1866 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
1868 int len
= GRUB_UINT_MAX
;
1869 const char *value
= NULL
;
1870 char name
[32] = {0};
1871 char plat
[32] = {0};
1872 char guidstr
[32] = {0};
1873 ventoy_guid guid
= VENTOY_GUID
;
1874 const char *fmt1
= NULL
;
1875 const char *fmt2
= NULL
;
1876 const char *fmt3
= NULL
;
1877 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
1878 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
1879 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1880 const char fmtcode
[]={
1881 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1882 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1883 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1884 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1885 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1886 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1889 grub_memset(name
, 0, sizeof(name
));
1890 puint
[0] = grub_swap_bytes32(0x56454e54);
1891 puint
[3] = grub_swap_bytes32(0x4f4e0000);
1892 puint
[2] = grub_swap_bytes32(0x45525349);
1893 puint
[1] = grub_swap_bytes32(0x4f595f56);
1894 value
= ventoy_get_env(name
);
1896 grub_memset(name
, 0, sizeof(name
));
1897 puint
[1] = grub_swap_bytes32(0x5f544f50);
1898 puint
[0] = grub_swap_bytes32(0x56544c45);
1899 fmt1
= ventoy_get_env(name
);
1905 grub_memset(name
, 0, sizeof(name
));
1906 puint
[1] = grub_swap_bytes32(0x5f4c4654);
1907 puint
[0] = grub_swap_bytes32(0x56544c45);
1908 fmt2
= ventoy_get_env(name
);
1910 grub_memset(name
, 0, sizeof(name
));
1911 puint
[1] = grub_swap_bytes32(0x5f434c52);
1912 puint
[0] = grub_swap_bytes32(0x56544c45);
1913 fmt3
= ventoy_get_env(name
);
1915 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
1917 puint2
[0] = grub_swap_bytes32(g_ventoy_plat_data
);
1919 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1920 #pragma GCC diagnostic push
1921 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1922 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
1923 fmt1
? fmt1
: fmtdata
,
1924 fmt2
? fmt2
: fmtdata
+ 4,
1925 value
? value
: "", plat
, guidstr
,
1926 fmt3
? fmt3
: fmtdata
+ 6);
1927 #pragma GCC diagnostic pop
1929 grub_memset(name
, 0, sizeof(name
));
1930 puint
[0] = grub_swap_bytes32(0x76746f79);
1931 puint
[2] = grub_swap_bytes32(0x656e7365);
1932 puint
[1] = grub_swap_bytes32(0x5f6c6963);
1933 ventoy_set_env(name
, guidstr
);
1938 int ventoy_check_password(const vtoy_password
*pwd
, int retry
)
1942 grub_uint8_t md5
[16];
1946 grub_memset(input
, 0, sizeof(input
));
1948 grub_printf("Enter password: ");
1951 if (pwd
->type
== VTOY_PASSWORD_TXT
)
1953 grub_password_get(input
, 128);
1954 if (grub_strcmp(pwd
->text
, input
) == 0)
1959 else if (pwd
->type
== VTOY_PASSWORD_MD5
)
1961 grub_password_get(input
, 128);
1962 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1963 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1968 else if (pwd
->type
== VTOY_PASSWORD_SALT_MD5
)
1970 offset
= (int)grub_snprintf(input
, 128, "%s", pwd
->salt
);
1971 grub_password_get(input
+ offset
, 128);
1973 grub_crypto_hash(GRUB_MD_MD5
, md5
, input
, grub_strlen(input
));
1974 if (grub_memcmp(pwd
->md5
, md5
, 16) == 0)
1980 grub_printf("Invalid password!\n\n");
1987 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
1989 img_info
*minimg
= NULL
;
1990 img_info
*img
= (img_info
*)(node
->firstiso
);
1992 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
1994 if (img
->select
== 0 && (NULL
== minimg
|| ventoy_cmp_img(img
, minimg
) < 0))
2009 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
2011 img_iterator_node
*Minchild
= NULL
;
2012 img_iterator_node
*child
= node
->firstchild
;
2014 while (child
&& child
->parent
== node
)
2016 if (child
->select
== 0 && (NULL
== Minchild
|| ventoy_cmp_subdir(child
, Minchild
) < 0))
2020 child
= child
->next
;
2025 Minchild
->select
= 1;
2031 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
2034 img_info
*img
= NULL
;
2035 const char *dir_class
= NULL
;
2036 const char *dir_alias
= NULL
;
2037 img_iterator_node
*child
= NULL
;
2039 if (node
->isocnt
== 0 || node
->done
== 1)
2044 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
2046 offset
= node
->parent
->dirlen
;
2049 if (node
== &g_img_iterator_head
)
2051 if (g_default_menu_mode
== 0)
2053 if (g_tree_view_menu_style
== 0)
2055 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2056 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2057 " echo 'return ...' \n"
2062 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2063 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
2071 node
->dir
[node
->dirlen
- 1] = 0;
2072 dir_class
= ventoy_plugin_get_menu_class(vtoy_class_directory
, node
->dir
, node
->dir
);
2075 dir_class
= "vtoydir";
2078 dir_alias
= ventoy_plugin_get_menu_alias(vtoy_alias_directory
, node
->dir
);
2081 if (g_tree_view_menu_style
== 0)
2083 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2084 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2085 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2089 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2090 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2091 dir_alias
, dir_class
, node
->dir
+ offset
);
2096 dir_alias
= node
->dir
+ offset
;
2098 if (g_tree_view_menu_style
== 0)
2100 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2101 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2102 "DIR", dir_alias
, dir_class
, node
->dir
+ offset
);
2106 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2107 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
2108 dir_alias
, dir_class
, node
->dir
+ offset
);
2112 if (g_tree_view_menu_style
== 0)
2114 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2115 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
2116 " echo 'return ...' \n"
2121 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2122 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
2128 while ((child
= ventoy_get_min_child(node
)) != NULL
)
2130 ventoy_dynamic_tree_menu(child
);
2133 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
2135 if (g_tree_view_menu_style
== 0)
2137 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2138 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2141 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
),
2142 img
->unsupport
? "[***********] " : "",
2143 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2145 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2149 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
,
2150 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2153 img
->unsupport
? "[***********] " : "",
2154 img
->alias
? img
->alias
: img
->name
, img
->class, img
,
2156 img
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2160 if (node
!= &g_img_iterator_head
)
2162 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "%s", "}\n");
2169 static int ventoy_set_default_menu(void)
2175 const char *strdata
= NULL
;
2176 img_info
*cur
= NULL
;
2177 img_info
*default_node
= NULL
;
2178 const char *default_image
= NULL
;
2180 default_image
= ventoy_get_env("VTOY_DEFAULT_IMAGE");
2181 if (default_image
&& default_image
[0] == '/')
2183 img_len
= grub_strlen(default_image
);
2185 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2187 if (img_len
== cur
->pathlen
&& grub_strcmp(default_image
, cur
->path
) == 0)
2199 if (0 == g_default_menu_mode
)
2201 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
, "set default='VID_%p'\n", default_node
);
2205 def
= grub_strdup(default_image
);
2211 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "set default=%c", '\'');
2213 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2214 if (strdata
&& strdata
[0] == '/')
2216 pos
= def
+ grub_strlen(strdata
);
2227 while ((end
= grub_strchr(pos
, '/')) != NULL
)
2230 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "DIR_%s>", pos
);
2234 vtoy_ssprintf(g_tree_script_buf
, g_tree_script_pos
, "VID_%p'\n", default_node
);
2242 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2244 img_info
*next
= NULL
;
2245 img_info
*cur
= g_ventoy_img_list
;
2258 g_ventoy_img_list
= NULL
;
2259 g_ventoy_img_count
= 0;
2261 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2264 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2267 img_info
*cur
= g_ventoy_img_list
;
2271 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
2273 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
2276 img_id
= grub_strtol(args
[0], NULL
, 10);
2277 if (img_id
>= g_ventoy_img_count
)
2279 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
2282 debug("Find image %ld name \n", img_id
);
2284 while (cur
&& img_id
> 0)
2292 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
2295 debug("image name is %s\n", cur
->name
);
2297 grub_env_set(args
[1], cur
->name
);
2299 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2302 static grub_err_t
ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2306 img_info
*cur
= g_ventoy_img_list
;
2312 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2315 len
= (int)grub_strlen(args
[0]);
2319 if (len
== cur
->pathlen
&& 0 == grub_strcmp(args
[0], cur
->path
))
2328 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2331 grub_snprintf(id
, sizeof(id
), "VID_%p", cur
);
2332 grub_env_set("chosen", id
);
2333 grub_env_export("chosen");
2335 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2338 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2342 const char *id
= NULL
;
2343 img_info
*cur
= NULL
;
2347 if (argc
< 1 || argc
> 2)
2349 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
2352 id
= grub_env_get("chosen");
2354 pos
= grub_strstr(id
, "VID_");
2357 cur
= (img_info
*)(void *)grub_strtoul(pos
+ 4, NULL
, 16);
2361 cur
= g_ventoy_img_list
;
2366 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
2369 grub_env_set(args
[0], cur
->path
);
2373 grub_snprintf(value
, sizeof(value
), "%llu", (ulonglong
)(cur
->size
));
2374 grub_env_set(args
[1], value
);
2377 g_svd_replace_offset
= 0;
2379 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2383 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2387 grub_device_t dev
= NULL
;
2388 img_info
*cur
= NULL
;
2389 img_info
*tail
= NULL
;
2390 img_info
*min
= NULL
;
2391 img_info
*head
= NULL
;
2392 const char *strdata
= NULL
;
2393 char *device_name
= NULL
;
2395 img_iterator_node
*node
= NULL
;
2396 img_iterator_node
*tmp
= NULL
;
2402 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
2405 if (g_ventoy_img_list
|| g_ventoy_img_count
)
2407 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
2412 g_enumerate_time_checked
= 0;
2413 g_enumerate_start_time_ms
= grub_get_time_ms();
2415 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2416 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2418 g_filt_dot_underscore_file
= 1;
2421 strdata
= ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2422 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2424 g_sort_case_sensitive
= 1;
2427 device_name
= grub_file_get_device_name(args
[0]);
2433 g_enum_dev
= dev
= grub_device_open(device_name
);
2439 g_enum_fs
= fs
= grub_fs_probe(dev
);
2445 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
2447 debug("unsupported fs:<%s>\n", fs
->name
);
2448 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2452 ventoy_set_env("vtoy_iso_fs", fs
->name
);
2454 strdata
= ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2455 if (strdata
&& strdata
[0] == '1')
2457 g_default_menu_mode
= 1;
2460 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
2462 grub_snprintf(g_iso_path
, sizeof(g_iso_path
), "%s", args
[0]);
2464 strdata
= ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2465 if (strdata
&& strdata
[0] == '/')
2467 len
= grub_snprintf(g_img_iterator_head
.dir
, sizeof(g_img_iterator_head
.dir
) - 1, "%s", strdata
);
2468 if (g_img_iterator_head
.dir
[len
- 1] != '/')
2470 g_img_iterator_head
.dir
[len
++] = '/';
2472 g_img_iterator_head
.dirlen
= len
;
2476 g_img_iterator_head
.dirlen
= 1;
2477 grub_strcpy(g_img_iterator_head
.dir
, "/");
2480 g_img_iterator_head
.tail
= &tail
;
2482 if (g_img_max_search_level
< 0)
2484 g_img_max_search_level
= GRUB_INT_MAX
;
2485 strdata
= ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2486 if (strdata
&& ventoy_is_decimal(strdata
))
2488 g_img_max_search_level
= (int)grub_strtoul(strdata
, NULL
, 10);
2492 g_vtoy_file_flt
[VTOY_FILE_FLT_ISO
] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2493 g_vtoy_file_flt
[VTOY_FILE_FLT_WIM
] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2494 g_vtoy_file_flt
[VTOY_FILE_FLT_EFI
] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2495 g_vtoy_file_flt
[VTOY_FILE_FLT_IMG
] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2496 g_vtoy_file_flt
[VTOY_FILE_FLT_VHD
] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2497 g_vtoy_file_flt
[VTOY_FILE_FLT_VTOY
] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2499 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2501 fs
->fs_dir(dev
, node
->dir
, ventoy_collect_img_files
, node
);
2504 strdata
= ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2505 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
2507 g_tree_view_menu_style
= 1;
2510 ventoy_set_default_menu();
2512 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
2514 ventoy_dynamic_tree_menu(node
);
2518 node
= g_img_iterator_head
.next
;
2526 /* sort image list by image name */
2527 while (g_ventoy_img_list
)
2529 min
= g_ventoy_img_list
;
2530 for (cur
= g_ventoy_img_list
->next
; cur
; cur
= cur
->next
)
2532 if (ventoy_cmp_img(min
, cur
) > 0)
2540 min
->prev
->next
= min
->next
;
2545 min
->next
->prev
= min
->prev
;
2548 if (min
== g_ventoy_img_list
)
2550 g_ventoy_img_list
= min
->next
;
2568 g_ventoy_img_list
= head
;
2570 if (g_default_menu_mode
== 1)
2572 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2573 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2574 " echo 'return ...' \n"
2578 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
2580 vtoy_ssprintf(g_list_script_buf
, g_list_script_pos
,
2581 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2584 cur
->unsupport
? "[***********] " : "",
2585 cur
->alias
? cur
->alias
: cur
->name
, cur
->class, cur
,
2587 cur
->unsupport
? "unsupport_menuentry" : "common_menuentry");
2590 g_tree_script_buf
[g_tree_script_pos
] = 0;
2591 g_list_script_buf
[g_list_script_pos
] = 0;
2593 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
2594 grub_env_set(args
[1], buf
);
2598 check_free(device_name
, grub_free
);
2599 check_free(dev
, grub_device_close
);
2601 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2604 int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
, grub_uint8_t
*signature
)
2611 device_name
= grub_file_get_device_name(filename
);
2623 pos2
= grub_strstr(pos
, ",");
2626 pos2
= grub_strstr(pos
, ")");
2634 disk
= grub_disk_open(pos
);
2637 grub_disk_read(disk
, 0, 0x180, 16, guid
);
2638 grub_disk_read(disk
, 0, 0x1b8, 4, signature
);
2639 grub_disk_close(disk
);
2646 grub_free(device_name
);
2650 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
2652 eltorito_descriptor desc
;
2654 grub_memset(&desc
, 0, sizeof(desc
));
2655 grub_file_seek(file
, 17 * 2048);
2656 grub_file_read(file
, &desc
, sizeof(desc
));
2658 if (desc
.type
!= 0 || desc
.version
!= 1)
2663 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
2664 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
2672 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
2676 grub_uint8_t buf
[512];
2677 grub_uint8_t parttype
[] = { 0x04, 0x06, 0x0B, 0x0C };
2679 grub_file_seek(file
, sector
* 2048);
2680 grub_file_read(file
, buf
, sizeof(buf
));
2682 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
2684 debug("%s efi eltorito in Validation Entry\n", file
->name
);
2688 if (buf
[0] == 0x01 && buf
[1] == 0x00)
2693 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
2695 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
2697 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2701 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0x00 && x86count
== 1)
2703 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
2708 if (x86count
&& buf
[32] == 0x88 && buf
[33] == 0x04)
2710 for (i
= 0; i
< (int)(ARRAY_SIZE(parttype
)); i
++)
2712 if (buf
[36] == parttype
[i
])
2714 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file
->name
, buf
[36]);
2720 debug("%s does not contain efi eltorito\n", file
->name
);
2724 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
2727 const char *fs
= NULL
;
2728 const char *cdprompt
= NULL
;
2730 grub_uint8_t chksum
= 0;
2733 disk
= file
->device
->disk
;
2734 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
2736 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
2737 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
2738 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
2740 pos
= grub_strstr(file
->name
, "/");
2746 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
2748 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
, param
->vtoy_disk_signature
);
2750 param
->vtoy_img_size
= file
->size
;
2752 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
2753 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
2755 param
->vtoy_reserved
[2] = g_ventoy_chain_type
;
2757 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2758 param
->vtoy_reserved
[4] = 0;
2759 if (g_ventoy_chain_type
== 1) /* Windows */
2761 cdprompt
= ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2762 if (cdprompt
&& cdprompt
[0] == '1' && cdprompt
[1] == 0)
2764 param
->vtoy_reserved
[4] = 1;
2768 fs
= ventoy_get_env("ventoy_fs_probe");
2769 if (fs
&& grub_strcmp(fs
, "udf") == 0)
2771 param
->vtoy_reserved
[3] = 1;
2774 /* calculate checksum */
2775 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
2777 chksum
+= *((grub_uint8_t
*)param
+ i
);
2779 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
2784 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2786 grub_uint32_t i
= 0;
2787 grub_uint64_t total
= 0;
2788 grub_uint64_t fileblk
= 0;
2789 ventoy_img_chunk
*chunk
= NULL
;
2791 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2793 chunk
= chunklist
->chunk
+ i
;
2795 if (chunk
->disk_start_sector
<= start
)
2797 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
2801 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
2804 fileblk
= (file
->size
+ 511) / 512;
2806 if (total
!= fileblk
)
2808 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)fileblk
);
2809 if ((file
->size
% 512) && (total
+ 1 == fileblk
))
2811 debug("maybe img file to be processed.\n");
2821 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
2825 grub_uint32_t i
= 0;
2826 grub_uint32_t sector
= 0;
2827 grub_uint32_t count
= 0;
2828 grub_off_t size
= 0;
2829 grub_off_t read
= 0;
2831 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
2832 if (fs_type
== ventoy_fs_exfat
)
2834 grub_fat_get_file_chunk(start
, file
, chunklist
);
2836 else if (fs_type
== ventoy_fs_ext
)
2838 grub_ext_get_file_chunk(start
, file
, chunklist
);
2842 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
2843 file
->read_hook_data
= chunklist
;
2845 for (size
= file
->size
; size
> 0; size
-= read
)
2847 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
2848 grub_file_read(file
, NULL
, read
);
2851 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
2853 chunklist
->chunk
[i
].disk_start_sector
+= start
;
2854 chunklist
->chunk
[i
].disk_end_sector
+= start
;
2857 if (ventoy_fs_udf
== fs_type
)
2859 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2861 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
2862 chunklist
->chunk
[i
].img_start_sector
= sector
;
2863 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2869 len
= (int)grub_strlen(file
->name
);
2870 if ((len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".img", 4) == 0) ||
2871 (len
> 4 && grub_strncasecmp(file
->name
+ len
- 4, ".vhd", 4) == 0) ||
2872 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vhdx", 5) == 0) ||
2873 (len
> 5 && grub_strncasecmp(file
->name
+ len
- 5, ".vtoy", 5) == 0))
2875 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
2877 count
= chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
;
2887 chunklist
->chunk
[i
].img_start_sector
= sector
;
2888 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
2896 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2900 grub_disk_addr_t start
;
2905 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
2908 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
2911 g_conf_replace_node
= NULL
;
2912 g_conf_replace_offset
= 0;
2914 if (g_img_chunk_list
.chunk
)
2916 grub_free(g_img_chunk_list
.chunk
);
2919 if (ventoy_get_fs_type(file
->fs
->name
) >= ventoy_fs_max
)
2921 grub_file_close(file
);
2922 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Unsupported filesystem %s\n", file
->fs
->name
);
2925 /* get image chunk data */
2926 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
2927 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
2928 if (NULL
== g_img_chunk_list
.chunk
)
2930 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
2933 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
2934 g_img_chunk_list
.cur_chunk
= 0;
2936 start
= file
->device
->disk
->partition
->start
;
2938 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
2940 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
2941 grub_file_close(file
);
2945 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
2948 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
2949 grub_memset(&g_grub_param
->img_replace
, 0, sizeof(g_grub_param
->img_replace
));
2950 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
2953 static grub_err_t
ventoy_select_conf_replace(grub_extcmd_context_t ctxt
, int argc
, char **args
)
2955 grub_uint64_t offset
= 0;
2956 grub_uint32_t align
= 0;
2957 grub_file_t file
= NULL
;
2958 conf_replace
*node
= NULL
;
2964 debug("select conf replace argc:%d\n", argc
);
2971 node
= ventoy_plugin_find_conf_replace(args
[1]);
2974 debug("Conf replace not found for %s\n", args
[1]);
2978 debug("Find conf replace for %s\n", args
[1]);
2980 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "(loop)%s", node
->orgconf
);
2983 offset
= grub_iso9660_get_last_file_dirent_pos(file
);
2984 grub_file_close(file
);
2986 else if (node
->img
> 0)
2992 debug("<(loop)%s> NOT exist\n", node
->orgconf
);
2996 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s%s", args
[0], node
->newconf
);
2999 debug("New config file <%s%s> NOT exist\n", args
[0], node
->newconf
);
3003 align
= ((int)file
->size
+ 2047) / 2048 * 2048;
3005 if (align
> vtoy_max_replace_file_size
)
3007 debug("New config file <%s%s> too big\n", args
[0], node
->newconf
);
3011 grub_file_read(file
, g_conf_replace_new_buf
, file
->size
);
3012 g_conf_replace_new_len
= (int)file
->size
;
3013 g_conf_replace_new_len_align
= align
;
3015 g_conf_replace_node
= node
;
3016 g_conf_replace_offset
= offset
+ 2;
3020 g_grub_param
->img_replace
.magic
= GRUB_IMG_REPLACE_MAGIC
;
3021 g_grub_param
->img_replace
.old_name_cnt
= 1;
3022 grub_snprintf(g_grub_param
->img_replace
.old_file_name
[0], 256, "%s", node
->orgconf
);
3025 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len
);
3030 grub_file_close(file
);
3032 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3035 static grub_err_t
ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3041 char configfile
[128];
3042 install_template
*node
= NULL
;
3048 debug("select auto installation argc:%d\n", argc
);
3055 node
= ventoy_plugin_find_install_template(args
[0]);
3058 debug("Auto install template not found for %s\n", args
[0]);
3062 if (node
->autosel
>= 0 && node
->autosel
<= node
->templatenum
)
3064 defidx
= node
->autosel
;
3065 if (node
->timeout
< 0)
3067 node
->cursel
= node
->autosel
- 1;
3068 debug("Auto install template auto select %d\n", node
->autosel
);
3073 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3079 if (node
->timeout
> 0)
3081 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3084 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without auto installation template\" {\n"
3085 " echo %s\n}\n", "");
3087 for (i
= 0; i
< node
->templatenum
; i
++)
3089 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\"{\n"
3091 node
->templatepath
[i
].path
);
3094 g_ventoy_menu_esc
= 1;
3095 g_ventoy_suppress_esc
= 1;
3096 g_ventoy_suppress_esc_default
= defidx
;
3098 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3099 grub_script_execute_sourcecode(configfile
);
3101 g_ventoy_menu_esc
= 0;
3102 g_ventoy_suppress_esc
= 0;
3103 g_ventoy_suppress_esc_default
= 1;
3107 node
->cursel
= g_ventoy_last_entry
- 1;
3109 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3112 static grub_err_t
ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3118 char configfile
[128];
3119 persistence_config
*node
;
3125 debug("select persistence argc:%d\n", argc
);
3132 node
= ventoy_plugin_find_persistent(args
[0]);
3135 debug("Persistence image not found for %s\n", args
[0]);
3139 if (node
->autosel
>= 0 && node
->autosel
<= node
->backendnum
)
3141 defidx
= node
->autosel
;
3142 if (node
->timeout
< 0)
3144 node
->cursel
= node
->autosel
- 1;
3145 debug("Persistence image auto select %d\n", node
->autosel
);
3150 buf
= (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF
);
3156 if (node
->timeout
> 0)
3158 vtoy_ssprintf(buf
, pos
, "set timeout=%d\n", node
->timeout
);
3161 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot without persistence\" {\n"
3162 " echo %s\n}\n", "");
3164 for (i
= 0; i
< node
->backendnum
; i
++)
3166 vtoy_ssprintf(buf
, pos
, "menuentry \"Boot with %s\" {\n"
3168 node
->backendpath
[i
].path
);
3172 g_ventoy_menu_esc
= 1;
3173 g_ventoy_suppress_esc
= 1;
3174 g_ventoy_suppress_esc_default
= defidx
;
3176 grub_snprintf(configfile
, sizeof(configfile
), "configfile mem:0x%llx:size:%d", (ulonglong
)(ulong
)buf
, pos
);
3177 grub_script_execute_sourcecode(configfile
);
3179 g_ventoy_menu_esc
= 0;
3180 g_ventoy_suppress_esc
= 0;
3181 g_ventoy_suppress_esc_default
= 1;
3185 node
->cursel
= g_ventoy_last_entry
- 1;
3187 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3190 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3193 ventoy_img_chunk
*cur
;
3199 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
3201 cur
= g_img_chunk_list
.chunk
+ i
;
3202 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3203 cur
->img_start_sector
, cur
->img_end_sector
,
3204 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
3208 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3211 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3215 ventoy_img_chunk_list chunklist
;
3220 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3223 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
3226 /* get image chunk data */
3227 grub_memset(&chunklist
, 0, sizeof(chunklist
));
3228 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
3229 if (NULL
== chunklist
.chunk
)
3231 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
3234 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
3235 chunklist
.cur_chunk
= 0;
3237 ventoy_get_block_list(file
, &chunklist
, 0);
3239 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
3241 grub_printf("########## UNSUPPORTED ###############\n");
3244 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
3246 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3248 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3249 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
3252 grub_printf("\n==================================\n");
3254 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
3256 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
3257 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
3258 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
3259 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
3260 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
3264 grub_free(chunklist
.chunk
);
3265 grub_file_close(file
);
3267 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3270 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3273 ventoy_grub_param_file_replace
*replace
= NULL
;
3281 replace
= &(g_grub_param
->file_replace
);
3282 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
3284 replace
->old_name_cnt
= 0;
3285 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
3287 replace
->old_name_cnt
++;
3288 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
3291 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
3294 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3297 static grub_err_t
ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3300 ventoy_grub_param_file_replace
*replace
= &(g_grub_param
->file_replace
);
3306 grub_snprintf(buf
, sizeof(buf
), "%u", replace
->old_name_cnt
);
3307 grub_env_set(args
[0], buf
);
3310 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
3313 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3321 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3322 grub_printf("%s", g_list_script_buf
);
3326 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
3327 grub_printf("%s", g_tree_script_buf
);
3333 static grub_err_t
ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3335 img_info
*cur
= g_ventoy_img_list
;
3343 grub_printf("path:<%s> id=%d list_index=%d\n", cur
->path
, cur
->id
, cur
->plugin_list_index
);
3344 grub_printf("name:<%s>\n\n", cur
->name
);
3351 static grub_err_t
ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3357 ventoy_plugin_dump_injection();
3362 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3368 ventoy_plugin_dump_auto_install();
3373 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3379 ventoy_plugin_dump_persistence();
3384 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3395 if (args
[0][0] == '0')
3397 return g_ventoy_memdisk_mode
? 0 : 1;
3399 else if (args
[0][0] == '1')
3401 return g_ventoy_iso_raw
? 0 : 1;
3403 else if (args
[0][0] == '2')
3405 return g_ventoy_iso_uefi_drv
? 0 : 1;
3407 else if (args
[0][0] == '3')
3409 return g_ventoy_grub2_mode
? 0 : 1;
3411 else if (args
[0][0] == '4')
3413 return g_ventoy_wimboot_mode
? 0 : 1;
3419 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3421 static int configfile_mode
= 0;
3422 char memfile
[128] = {0};
3429 * args[0]: 0:normal 1:configfile
3430 * args[1]: 0:list_buf 1:tree_buf
3435 debug("Invalid argc %d\n", argc
);
3441 if (args
[0][0] == '0')
3443 if (args
[1][0] == '0')
3445 grub_script_execute_sourcecode(g_list_script_buf
);
3449 grub_script_execute_sourcecode(g_tree_script_buf
);
3454 if (configfile_mode
)
3456 debug("Now already in F3 mode %d\n", configfile_mode
);
3460 if (args
[1][0] == '0')
3462 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3463 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
3467 g_ventoy_last_entry
= -1;
3468 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
3469 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
3472 configfile_mode
= 1;
3473 grub_script_execute_sourcecode(memfile
);
3474 configfile_mode
= 0;
3480 static grub_err_t
ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3491 g_ventoy_case_insensitive
= 1;
3492 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
3493 g_ventoy_case_insensitive
= 0;
3499 grub_file_close(file
);
3505 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3510 const char *isopath
= NULL
;
3512 ventoy_mbr_head mbr
;
3519 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
3522 isopath
= grub_env_get("vtoy_iso_part");
3525 debug("isopath is null %p\n", isopath
);
3529 debug("isopath is %s\n", isopath
);
3531 for (id
= 0; id
< 30 && (find
== 0); id
++)
3533 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
3534 if (grub_strstr(isopath
, hdname
))
3536 debug("skip %s ...\n", hdname
);
3540 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
3542 disk
= grub_disk_open(hdname
);
3545 debug("%s not exist\n", hdname
);
3549 grub_memset(&mbr
, 0, sizeof(mbr
));
3550 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
3552 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
3554 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
3555 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
3558 grub_env_set(args
[0], hdname
);
3562 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
3566 debug("read %s failed\n", hdname
);
3569 grub_disk_close(disk
);
3575 static grub_err_t
ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3586 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file var \n", cmd_raw_name
);
3589 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3592 debug("failed to open file %s\n", args
[0]);
3596 buf
= grub_malloc(len
);
3603 grub_file_read(file
, buf
, len
- 1);
3605 ventoy_get_line(buf
);
3606 ventoy_set_env(args
[1], buf
);
3610 grub_check_free(buf
);
3611 grub_file_close(file
);
3616 static int ventoy_img_partition_callback (struct grub_disk
*disk
, const grub_partition_t partition
, void *data
)
3618 int *pCnt
= (int *)data
;
3623 g_part_list_pos
+= grub_snprintf(g_part_list_buf
+ g_part_list_pos
, VTOY_MAX_SCRIPT_BUF
- g_part_list_pos
,
3624 "0 %llu linear /dev/ventoy %llu\n",
3625 (ulonglong
)partition
->len
, (ulonglong
)partition
->start
);
3630 static grub_err_t
ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3633 char *device_name
= NULL
;
3634 grub_device_t dev
= NULL
;
3639 g_part_list_pos
= 0;
3640 grub_env_unset("vtoy_img_part_file");
3647 device_name
= grub_file_get_device_name(args
[0]);
3650 debug("ventoy_cmd_img_part_info failed, %s\n", args
[0]);
3654 dev
= grub_device_open(device_name
);
3657 debug("grub_device_open failed, %s\n", device_name
);
3661 grub_partition_iterate(dev
->disk
, ventoy_img_partition_callback
, &cnt
);
3663 grub_snprintf(buf
, sizeof(buf
), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong
)(ulong
)g_part_list_buf
, g_part_list_pos
);
3664 grub_env_set("vtoy_img_part_file", buf
);
3666 grub_snprintf(buf
, sizeof(buf
), "%d", cnt
);
3667 grub_env_set("vtoy_img_part_cnt", buf
);
3671 check_free(device_name
, grub_free
);
3672 check_free(dev
, grub_device_close
);
3678 static grub_err_t
ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3689 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s file str \n", cmd_raw_name
);
3692 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3695 debug("failed to open file %s\n", args
[0]);
3699 buf
= grub_malloc(file
->size
+ 1);
3705 buf
[file
->size
] = 0;
3706 grub_file_read(file
, buf
, file
->size
);
3708 if (grub_strstr(buf
, args
[1]))
3715 grub_check_free(buf
);
3716 grub_file_close(file
);
3721 static grub_err_t
ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3727 ventoy_iso9660_vd pvd
;
3734 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s sysid volid space \n", cmd_raw_name
);
3737 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3740 debug("failed to open file %s\n", args
[0]);
3744 grub_file_seek(file
, 16 * 2048);
3745 len
= (int)grub_file_read(file
, &pvd
, sizeof(pvd
));
3746 if (len
!= sizeof(pvd
))
3748 debug("failed to read pvd %d\n", len
);
3752 grub_memset(buf
, 0, sizeof(buf
));
3753 grub_memcpy(buf
, pvd
.sys
, sizeof(pvd
.sys
));
3754 ventoy_set_env(args
[1], buf
);
3756 grub_memset(buf
, 0, sizeof(buf
));
3757 grub_memcpy(buf
, pvd
.vol
, sizeof(pvd
.vol
));
3758 ventoy_set_env(args
[2], buf
);
3762 grub_snprintf(buf
, sizeof(buf
), "%llu", (ulonglong
)size
);
3763 ventoy_set_env(args
[3], buf
);
3766 grub_file_close(file
);
3771 static grub_err_t
ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3782 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s var \n", cmd_raw_name
);
3785 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3788 debug("failed to open file %s\n", args
[0]);
3792 grub_memset(buf
, 0, sizeof(buf
));
3793 grub_file_seek(file
, 16 * 2048 + 813);
3794 len
= (int)grub_file_read(file
, buf
, 17);
3797 debug("failed to read create date %d\n", len
);
3801 ventoy_set_env(args
[1], buf
);
3804 grub_file_close(file
);
3809 static grub_err_t
ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3815 ventoy_env_hook_root(1);
3820 static grub_err_t
ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3826 ventoy_env_hook_root(0);
3831 #ifdef GRUB_MACHINE_EFI
3832 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3837 grub_efi_guid_t global
= GRUB_EFI_GLOBAL_VARIABLE_GUID
;
3843 var
= grub_efi_get_variable("SecureBoot", &global
, &size
);
3844 if (var
&& *var
== 1)
3852 static grub_err_t
ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3861 static grub_err_t
ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3866 grub_uint64_t FileSectors
= 0;
3867 ventoy_gpt_info
*gpt
= NULL
;
3868 ventoy_part_table
*pt
= NULL
;
3869 grub_uint8_t zeroguid
[16] = {0};
3874 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
3877 debug("failed to open file %s\n", args
[0]);
3881 if (file
->size
% 512)
3883 debug("unaligned file size: %llu\n", (ulonglong
)file
->size
);
3887 gpt
= grub_zalloc(sizeof(ventoy_gpt_info
));
3893 FileSectors
= file
->size
/ 512;
3895 grub_file_read(file
, gpt
, sizeof(ventoy_gpt_info
));
3896 if (grub_strncmp(gpt
->Head
.Signature
, "EFI PART", 8) == 0)
3898 debug("This is EFI partition table\n");
3900 for (i
= 0; i
< 128; i
++)
3902 if (grub_memcmp(gpt
->PartTbl
[i
].PartGuid
, zeroguid
, 16))
3904 if (FileSectors
< gpt
->PartTbl
[i
].LastLBA
)
3906 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3907 (ulonglong
)gpt
->PartTbl
[i
].LastLBA
, (ulonglong
)FileSectors
);
3915 debug("This is MBR partition table\n");
3917 for (i
= 0; i
< 4; i
++)
3919 pt
= gpt
->MBR
.PartTbl
+ i
;
3920 if (FileSectors
< pt
->StartSectorId
+ pt
->SectorCount
)
3922 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i
,
3923 (ulonglong
)(pt
->StartSectorId
+ pt
->SectorCount
),
3924 (ulonglong
)FileSectors
);
3933 grub_file_close(file
);
3934 grub_check_free(gpt
);
3935 grub_errno
= GRUB_ERR_NONE
;
3939 static grub_err_t
ventoy_cmd_clear_key(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3948 for (i
= 0; i
< 500; i
++)
3950 ret
= grub_getkey_noblock();
3951 if (ret
== GRUB_TERM_NO_KEY
)
3960 grub_printf("\n\n Still have key input after clear.\n");
3968 static grub_err_t
ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt
, int argc
, char **args
)
3975 int image_sector_size
;
3977 ventoy_chain_head
*chain
;
3978 ventoy_img_chunk
*chunk
;
3979 ventoy_os_param
*osparam
;
3980 ventoy_image_location
*location
;
3981 ventoy_image_disk_region
*region
;
3982 struct grub_acpi_table_header
*acpi
;
3991 debug("ventoy_cmd_acpi_param %s %s\n", args
[0], args
[1]);
3993 chain
= (ventoy_chain_head
*)(ulong
)grub_strtoul(args
[0], NULL
, 16);
3999 image_sector_size
= (int)grub_strtol(args
[1], NULL
, 10);
4001 if (grub_memcmp(&g_ventoy_guid
, &(chain
->os_param
.guid
), 16))
4003 debug("Invalid ventoy guid 0x%x\n", chain
->os_param
.guid
.data1
);
4007 img_chunk_num
= chain
->img_chunk_num
;
4009 loclen
= sizeof(ventoy_image_location
) + (img_chunk_num
- 1) * sizeof(ventoy_image_disk_region
);
4010 datalen
= sizeof(ventoy_os_param
) + loclen
;
4012 buflen
= sizeof(struct grub_acpi_table_header
) + datalen
;
4013 acpi
= grub_zalloc(buflen
);
4019 /* Step1: Fill acpi table header */
4020 grub_memcpy(acpi
->signature
, "VTOY", 4);
4021 acpi
->length
= buflen
;
4023 grub_memcpy(acpi
->oemid
, "VENTOY", 6);
4024 grub_memcpy(acpi
->oemtable
, "OSPARAMS", 8);
4026 acpi
->creator_id
[0] = 1;
4027 acpi
->creator_rev
= 1;
4029 /* Step2: Fill data */
4030 osparam
= (ventoy_os_param
*)(acpi
+ 1);
4031 grub_memcpy(osparam
, &chain
->os_param
, sizeof(ventoy_os_param
));
4032 osparam
->vtoy_img_location_addr
= 0;
4033 osparam
->vtoy_img_location_len
= loclen
;
4034 osparam
->chksum
= 0;
4035 osparam
->chksum
= 0x100 - grub_byte_checksum(osparam
, sizeof(ventoy_os_param
));
4037 location
= (ventoy_image_location
*)(osparam
+ 1);
4038 grub_memcpy(&location
->guid
, &osparam
->guid
, sizeof(ventoy_guid
));
4039 location
->image_sector_size
= image_sector_size
;
4040 location
->disk_sector_size
= chain
->disk_sector_size
;
4041 location
->region_count
= img_chunk_num
;
4043 region
= location
->regions
;
4044 chunk
= (ventoy_img_chunk
*)((char *)chain
+ chain
->img_chunk_offset
);
4045 if (512 == image_sector_size
)
4047 for (i
= 0; i
< img_chunk_num
; i
++)
4049 region
->image_sector_count
= chunk
->disk_end_sector
- chunk
->disk_start_sector
+ 1;
4050 region
->image_start_sector
= chunk
->img_start_sector
* 4;
4051 region
->disk_start_sector
= chunk
->disk_start_sector
;
4058 for (i
= 0; i
< img_chunk_num
; i
++)
4060 region
->image_sector_count
= chunk
->img_end_sector
- chunk
->img_start_sector
+ 1;
4061 region
->image_start_sector
= chunk
->img_start_sector
;
4062 region
->disk_start_sector
= chunk
->disk_start_sector
;
4068 /* Step3: Fill acpi checksum */
4070 acpi
->checksum
= 0x100 - grub_byte_checksum(acpi
, acpi
->length
);
4072 /* load acpi table */
4073 grub_snprintf(cmd
, sizeof(cmd
), "acpi mem:0x%lx:size:%d", (ulong
)acpi
, acpi
->length
);
4074 grub_script_execute_sourcecode(cmd
);
4078 VENTOY_CMD_RETURN(0);
4081 static grub_err_t
ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4087 g_ventoy_last_entry_back
= g_ventoy_last_entry
;
4088 g_ventoy_last_entry
= -1;
4093 static grub_err_t
ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4099 g_ventoy_last_entry
= g_ventoy_last_entry_back
;
4104 static int ventoy_lib_module_callback(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4106 const char *pos
= filename
+ 1;
4114 if ((*(pos
- 1) >= '0' && *(pos
- 1) <= '9') && (*(pos
+ 1) >= '0' && *(pos
+ 1) <= '9'))
4116 grub_strncpy((char *)data
, filename
, 128);
4127 static grub_err_t
ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4130 char *device_name
= NULL
;
4131 grub_device_t dev
= NULL
;
4132 grub_fs_t fs
= NULL
;
4133 char buf
[128] = {0};
4139 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc
);
4143 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args
[0], args
[1], args
[2]);
4145 device_name
= grub_file_get_device_name(args
[0]);
4148 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4152 dev
= grub_device_open(device_name
);
4155 debug("grub_device_open failed, %s\n", device_name
);
4159 fs
= grub_fs_probe(dev
);
4162 debug("grub_fs_probe failed, %s\n", device_name
);
4166 fs
->fs_dir(dev
, args
[1], ventoy_lib_module_callback
, buf
);
4170 ventoy_set_env(args
[2], buf
);
4177 check_free(device_name
, grub_free
);
4178 check_free(dev
, grub_device_close
);
4183 int ventoy_load_part_table(const char *diskname
)
4190 g_ventoy_part_info
= grub_zalloc(sizeof(ventoy_gpt_info
));
4191 if (!g_ventoy_part_info
)
4196 disk
= grub_disk_open(diskname
);
4199 debug("Failed to open disk %s\n", diskname
);
4203 g_ventoy_disk_size
= disk
->total_sectors
* (1U << disk
->log_sector_size
);
4205 grub_disk_read(disk
, 0, 0, sizeof(ventoy_gpt_info
), g_ventoy_part_info
);
4206 grub_disk_close(disk
);
4208 grub_snprintf(name
, sizeof(name
), "%s,1", diskname
);
4209 dev
= grub_device_open(name
);
4212 /* Check for official Ventoy device */
4213 ret
= ventoy_check_official_device(dev
);
4214 grub_device_close(dev
);
4222 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4223 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4228 static grub_err_t
ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4235 ret
= ventoy_load_part_table(args
[0]);
4241 g_ventoy_disk_part_size
[0] = ventoy_get_vtoy_partsize(0);
4242 g_ventoy_disk_part_size
[1] = ventoy_get_vtoy_partsize(1);
4247 static grub_err_t
ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4250 const char *vcfg
= NULL
;
4255 vcfg
= ventoy_plugin_get_custom_boot(args
[0]);
4258 debug("custom boot <%s>:<%s>\n", args
[0], vcfg
);
4259 grub_env_set(args
[1], vcfg
);
4264 debug("custom boot <%s>:<NOT FOUND>\n", args
[0]);
4272 static grub_err_t
ventoy_cmd_part_exist(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4275 grub_uint8_t zeroguid
[16] = {0};
4280 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4283 if (grub_memcmp(g_ventoy_part_info
->Head
.Signature
, "EFI PART", 8) == 0)
4285 if (id
>= 1 && id
<= 128)
4287 if (grub_memcmp(g_ventoy_part_info
->PartTbl
[id
- 1].PartGuid
, zeroguid
, 16))
4295 if (id
>= 1 && id
<= 4)
4297 if (g_ventoy_part_info
->MBR
.PartTbl
[id
- 1].FsFlag
)
4307 static grub_err_t
ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4310 char *device_name
= NULL
;
4311 grub_device_t dev
= NULL
;
4312 grub_fs_t fs
= NULL
;
4317 debug("get fs label for %s\n", args
[0]);
4321 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc
);
4325 device_name
= grub_file_get_device_name(args
[0]);
4328 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4332 dev
= grub_device_open(device_name
);
4335 debug("grub_device_open failed, %s\n", device_name
);
4339 fs
= grub_fs_probe(dev
);
4340 if (NULL
== fs
|| NULL
== fs
->fs_label
)
4342 debug("grub_fs_probe failed, %s %p %p\n", device_name
, fs
, fs
->fs_label
);
4346 fs
->fs_label(dev
, &label
);
4349 debug("label=<%s>\n", label
);
4350 ventoy_set_env(args
[1], label
);
4358 check_free(device_name
, grub_free
);
4359 check_free(dev
, grub_device_close
);
4364 static int ventoy_fs_enum_1st_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4368 grub_snprintf((char *)data
, 256, "%s", filename
);
4375 static int ventoy_fs_enum_1st_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4377 if (info
->dir
&& filename
&& filename
[0] != '.')
4379 grub_snprintf((char *)data
, 256, "%s", filename
);
4386 static grub_err_t
ventoy_fs_enum_1st_child(int argc
, char **args
, grub_fs_dir_hook_t hook
)
4389 char *device_name
= NULL
;
4390 grub_device_t dev
= NULL
;
4391 grub_fs_t fs
= NULL
;
4392 char name
[256] ={0};
4396 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc
);
4400 device_name
= grub_file_get_device_name(args
[0]);
4403 debug("grub_file_get_device_name failed, %s\n", args
[0]);
4407 dev
= grub_device_open(device_name
);
4410 debug("grub_device_open failed, %s\n", device_name
);
4414 fs
= grub_fs_probe(dev
);
4417 debug("grub_fs_probe failed, %s\n", device_name
);
4421 fs
->fs_dir(dev
, args
[1], hook
, name
);
4424 ventoy_set_env(args
[2], name
);
4431 check_free(device_name
, grub_free
);
4432 check_free(dev
, grub_device_close
);
4437 static grub_err_t
ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4440 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_file
);
4443 static grub_err_t
ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4446 return ventoy_fs_enum_1st_child(argc
, args
, ventoy_fs_enum_1st_dir
);
4449 static grub_err_t
ventoy_cmd_basename(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4459 debug("ventoy_cmd_basename, invalid param num %d\n", argc
);
4463 for (pos
= args
[0]; *pos
; pos
++)
4477 grub_env_set(args
[1], args
[0]);
4487 static grub_err_t
ventoy_cmd_basefile(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4497 debug("ventoy_cmd_basefile, invalid param num %d\n", argc
);
4502 len
= (int)grub_strlen(buf
);
4503 for (i
= len
; i
> 0; i
--)
4505 if (buf
[i
- 1] == '/')
4507 grub_env_set(args
[1], buf
+ i
);
4512 grub_env_set(args
[1], buf
);
4517 static grub_err_t
ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4519 struct grub_video_mode_info info
;
4526 if (!g_video_mode_list
)
4528 ventoy_enum_video_mode();
4531 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4533 grub_snprintf(buf
, sizeof(buf
), "Resolution (%ux%u)", info
.width
, info
.height
);
4537 grub_snprintf(buf
, sizeof(buf
), "Resolution (0x0)");
4540 grub_env_set("VTOY_CUR_VIDEO_MODE", buf
);
4542 grub_snprintf(buf
, sizeof(buf
), "%d", g_video_mode_num
);
4543 grub_env_set("VTOY_VIDEO_MODE_NUM", buf
);
4545 VENTOY_CMD_RETURN(0);
4548 static grub_err_t
vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4550 struct grub_video_mode_info info
;
4557 if (grub_video_get_info(&info
) == GRUB_ERR_NONE
)
4559 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u", info
.width
, info
.height
, info
.bpp
);
4563 grub_snprintf(buf
, sizeof(buf
), "0x0x0");
4566 grub_env_set(args
[0], buf
);
4568 VENTOY_CMD_RETURN(0);
4571 static grub_err_t
ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4579 if (!g_video_mode_list
)
4584 id
= (int)grub_strtoul(args
[0], NULL
, 10);
4585 if (id
< g_video_mode_num
)
4587 grub_snprintf(buf
, sizeof(buf
), "%ux%ux%u",
4588 g_video_mode_list
[id
].width
, g_video_mode_list
[id
].height
, g_video_mode_list
[id
].bpp
);
4591 grub_env_set(args
[1], buf
);
4593 VENTOY_CMD_RETURN(0);
4596 static grub_err_t
ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4599 grub_uint32_t loadsector
= 0;
4602 grub_uint32_t boot_catlog
= 0;
4603 grub_uint8_t buf
[512];
4609 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc
);
4613 file
= grub_file_open(args
[0], VENTOY_FILE_TYPE
);
4616 debug("failed to open %s\n", args
[0]);
4620 boot_catlog
= ventoy_get_iso_boot_catlog(file
);
4621 if (boot_catlog
== 0)
4623 debug("No bootcatlog found\n");
4624 grub_file_close(file
);
4628 grub_memset(buf
, 0, sizeof(buf
));
4629 grub_file_seek(file
, boot_catlog
* 2048);
4630 grub_file_read(file
, buf
, sizeof(buf
));
4631 grub_file_close(file
);
4633 for (i
= 0; i
< sizeof(buf
); i
+= 32)
4635 if ((buf
[i
] == 0 || buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
4637 if (buf
[i
+ 32] == 0x88)
4639 loadsector
= *(grub_uint32_t
*)(buf
+ i
+ 32 + 8);
4640 grub_snprintf(value
, sizeof(value
), "%u", loadsector
* 4); //change to sector size 512
4646 if (loadsector
== 0)
4648 debug("No EFI eltorito info found\n");
4652 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value
);
4653 grub_env_set(args
[1], value
);
4654 VENTOY_CMD_RETURN(0);
4657 static int ventoy_collect_replace_initrd(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4662 replace_fs_dir
*pfsdir
= (replace_fs_dir
*)data
;
4664 if (pfsdir
->initrd
[0])
4669 curpos
= pfsdir
->curpos
;
4670 len
= grub_strlen(filename
);
4674 if ((len
== 1 && filename
[0] == '.') ||
4675 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
4680 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
4683 printlen
= grub_snprintf(pfsdir
->fullpath
+ curpos
, 512 - curpos
, "%s/", filename
);
4684 pfsdir
->curpos
= curpos
+ printlen
;
4685 pfsdir
->fs
->fs_dir(pfsdir
->dev
, pfsdir
->fullpath
, ventoy_collect_replace_initrd
, pfsdir
);
4686 pfsdir
->curpos
= curpos
;
4687 pfsdir
->fullpath
[curpos
] = 0;
4691 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
4694 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
4695 if (len
> 4 && grub_strncmp(filename
+ len
- 4, ".img", 4) == 0)
4697 if (info
->size
> 32 * VTOY_SIZE_1MB
)
4699 grub_snprintf(pfsdir
->initrd
, sizeof(pfsdir
->initrd
), "%s%s", pfsdir
->fullpath
, filename
);
4708 static grub_err_t
ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4712 char *device_name
= NULL
;
4713 grub_device_t dev
= NULL
;
4714 grub_fs_t fs
= NULL
;
4715 replace_fs_dir
*pfsdir
= NULL
;
4721 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc
);
4725 pfsdir
= grub_zalloc(sizeof(replace_fs_dir
));
4731 device_name
= grub_file_get_device_name(args
[0]);
4737 dev
= grub_device_open(device_name
);
4743 fs
= grub_fs_probe(dev
);
4752 pfsdir
->fullpath
[0] = '/';
4753 fs
->fs_dir(dev
, "/", ventoy_collect_replace_initrd
, pfsdir
);
4755 if (pfsdir
->initrd
[0])
4757 debug("Replace initrd <%s> <%d %d>\n", pfsdir
->initrd
, pfsdir
->dircnt
, pfsdir
->filecnt
);
4759 for (i
= 0; i
< (int)sizeof(pfsdir
->initrd
) && pfsdir
->initrd
[i
]; i
++)
4761 if (pfsdir
->initrd
[i
] == '/')
4763 pfsdir
->initrd
[i
] = '\\';
4767 pos
= (pfsdir
->initrd
[0] == '\\') ? pfsdir
->initrd
+ 1 : pfsdir
->initrd
;
4768 grub_env_set(args
[1], pos
);
4772 debug("Replace initrd NOT found <%s> <%d %d>\n", args
[0], pfsdir
->dircnt
, pfsdir
->filecnt
);
4777 grub_check_free(pfsdir
);
4778 grub_check_free(device_name
);
4779 check_free(dev
, grub_device_close
);
4781 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4784 static grub_err_t
ventoy_cmd_push_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4786 const char *pager
= NULL
;
4792 pager
= grub_env_get("pager");
4796 grub_env_set("pager", "1");
4798 else if (pager
[0] == '1')
4804 grub_snprintf(g_old_pager
, sizeof(g_old_pager
), "%s", pager
);
4806 grub_env_set("pager", "1");
4809 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4812 static grub_err_t
ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4818 if (g_pager_flag
== 1)
4820 grub_env_unset("pager");
4822 else if (g_pager_flag
== 2)
4824 grub_env_set("pager", g_old_pager
);
4827 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4830 static int ventoy_chk_case_file(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4832 if (g_json_case_mis_path
[0])
4837 if (0 == info
->dir
&& grub_strncasecmp(filename
, "ventoy.json", 11) == 0)
4839 grub_snprintf(g_json_case_mis_path
, 32, "%s/%s", (char *)data
, filename
);
4845 static int ventoy_chk_case_dir(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
4848 chk_case_fs_dir
*fs_dir
= (chk_case_fs_dir
*)data
;
4850 if (g_json_case_mis_path
[0])
4855 if (info
->dir
&& (filename
[0] == 'v' || filename
[0] == 'V'))
4857 if (grub_strncasecmp(filename
, "ventoy", 6) == 0)
4859 grub_snprintf(path
, sizeof(path
), "/%s", filename
);
4860 fs_dir
->fs
->fs_dir(fs_dir
->dev
, path
, ventoy_chk_case_file
, path
);
4861 if (g_json_case_mis_path
[0])
4871 static grub_err_t
ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4874 char *device_name
= NULL
;
4875 grub_device_t dev
= NULL
;
4876 grub_fs_t fs
= NULL
;
4877 chk_case_fs_dir fs_dir
;
4883 device_name
= grub_file_get_device_name(args
[0]);
4889 dev
= grub_device_open(device_name
);
4895 fs
= grub_fs_probe(dev
);
4901 fstype
= ventoy_get_fs_type(fs
->name
);
4902 if (fstype
== ventoy_fs_fat
|| fstype
== ventoy_fs_exfat
|| fstype
>= ventoy_fs_max
)
4907 g_json_case_mis_path
[0] = 0;
4910 fs
->fs_dir(dev
, "/", ventoy_chk_case_dir
, &fs_dir
);
4912 if (g_json_case_mis_path
[0])
4914 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path
);
4919 grub_check_free(device_name
);
4920 check_free(dev
, grub_device_close
);
4922 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
4925 static grub_err_t
grub_cmd_gptpriority(grub_extcmd_context_t ctxt
, int argc
, char **args
)
4928 grub_partition_t part
;
4929 char priority_str
[3]; /* Maximum value 15 */
4933 if (argc
< 2 || argc
> 3)
4934 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4935 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
4937 /* Open the disk if it exists */
4938 disk
= grub_disk_open (args
[0]);
4941 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4945 part
= grub_partition_probe (disk
, args
[1]);
4948 grub_disk_close (disk
);
4949 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
4950 "No such partition");
4953 if (grub_strcmp (part
->partmap
->name
, "gpt"))
4955 grub_disk_close (disk
);
4956 return grub_error (GRUB_ERR_BAD_PART_TABLE
,
4957 "Not a GPT partition");
4960 grub_snprintf (priority_str
, sizeof(priority_str
), "%u",
4961 (grub_uint32_t
)((part
->gpt_attrib
>> 48) & 0xfULL
));
4965 grub_env_set (args
[2], priority_str
);
4966 grub_env_export (args
[2]);
4970 grub_printf ("Priority is %s\n", priority_str
);
4973 grub_disk_close (disk
);
4974 return GRUB_ERR_NONE
;
4979 /* <BEGIN>: Deleted by longpanda, 20210916 PN:XX LABEL:XX */
4981 void ventoy_tip_set_menu_label(const char *vid
)
4985 g_ventoy_tip_msg1
= g_ventoy_tip_msg2
= NULL
;
4988 node
= (img_info
*)(void *)grub_strtoul(vid
+ 4, NULL
, 16);
4991 g_ventoy_tip_msg1
= node
->tip1
;
4992 g_ventoy_tip_msg2
= node
->tip2
;
4997 /* <END> : Deleted by longpanda, 20210916 PN:XX LABEL:XX */
4999 int ventoy_env_init(void)
5003 grub_env_set("vtdebug_flag", "");
5005 g_part_list_buf
= grub_malloc(VTOY_PART_BUF_LEN
);
5006 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5007 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
5008 g_conf_replace_new_buf
= grub_malloc(vtoy_max_replace_file_size
);
5010 ventoy_filt_register(0, ventoy_wrapper_open
);
5012 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
5015 g_grub_param
->grub_env_get
= grub_env_get
;
5016 g_grub_param
->grub_env_set
= (grub_env_set_pf
)grub_env_set
;
5017 g_grub_param
->grub_env_printf
= (grub_env_printf_pf
)grub_printf
;
5018 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
5019 grub_env_set("env_param", buf
);
5020 grub_env_set("ventoy_env_param", buf
);
5022 grub_env_export("env_param");
5023 grub_env_export("ventoy_env_param");
5026 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)g_vtoy_winpeshl_ini
);
5027 grub_env_set("vtoy_winpeshl_ini_addr", buf
);
5029 grub_snprintf(buf
, sizeof(buf
), "%d", (int)grub_strlen(g_vtoy_winpeshl_ini
));
5030 grub_env_set("vtoy_winpeshl_ini_size", buf
);
5032 grub_env_export("vtoy_winpeshl_ini_addr");
5033 grub_env_export("vtoy_winpeshl_ini_size");
5035 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_size
);
5036 grub_env_set("vtoy_chain_file_size", buf
);
5037 grub_env_export("vtoy_chain_file_size");
5039 grub_snprintf(buf
, sizeof(buf
), "0x%lx", (ulong
)ventoy_chain_file_read
);
5040 grub_env_set("vtoy_chain_file_read", buf
);
5041 grub_env_export("vtoy_chain_file_read");
5048 static cmd_para ventoy_cmds
[] =
5050 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
5051 { "vt_mod", ventoy_cmd_mod
, 0, NULL
, "{Int} {Int} {Var}", "mod integer variable", NULL
},
5052 { "vt_strstr", ventoy_cmd_strstr
, 0, NULL
, "", "", NULL
},
5053 { "vt_str_begin", ventoy_cmd_strbegin
, 0, NULL
, "", "", NULL
},
5054 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5055 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
5056 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
5057 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
5058 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
5059 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
5060 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
5061 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
5062 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
5063 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
5064 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path
, 0, NULL
, "{var}", "select chosen img path", NULL
},
5065 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
5066 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
5067 { "vt_load_wimboot", ventoy_cmd_load_wimboot
, 0, NULL
, "", "", NULL
},
5068 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot
, 0, NULL
, "", "", NULL
},
5069 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot
, 0, NULL
, "", "", NULL
},
5070 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data
, 0, NULL
, "", "", NULL
},
5071 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type
, 0, NULL
, "", "", NULL
},
5072 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot
, 0, NULL
, "", "", NULL
},
5073 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot
, 0, NULL
, "", "", NULL
},
5075 { "vt_skip_svd", ventoy_cmd_skip_svd
, 0, NULL
, "", "", NULL
},
5076 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64
, 0, NULL
, "", "", NULL
},
5077 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
5078 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio
, 0, NULL
, "", "", NULL
},
5079 { "vt_push_last_entry", ventoy_cmd_push_last_entry
, 0, NULL
, "", "", NULL
},
5080 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry
, 0, NULL
, "", "", NULL
},
5081 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver
, 0, NULL
, "", "", NULL
},
5083 { "vt_load_part_table", ventoy_cmd_load_part_table
, 0, NULL
, "", "", NULL
},
5084 { "vt_check_part_exist", ventoy_cmd_part_exist
, 0, NULL
, "", "", NULL
},
5085 { "vt_get_fs_label", ventoy_cmd_get_fs_label
, 0, NULL
, "", "", NULL
},
5086 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file
, 0, NULL
, "", "", NULL
},
5087 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir
, 0, NULL
, "", "", NULL
},
5088 { "vt_file_basename", ventoy_cmd_basename
, 0, NULL
, "", "", NULL
},
5089 { "vt_file_basefile", ventoy_cmd_basefile
, 0, NULL
, "", "", NULL
},
5090 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode
, 0, NULL
, "", "", NULL
},
5091 { "vt_get_video_mode", ventoy_cmd_get_video_mode
, 0, NULL
, "", "", NULL
},
5092 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode
, 0, NULL
, "", "", NULL
},
5095 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
5096 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
5097 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
5098 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
5099 { "vt_dump_img_list", ventoy_cmd_dump_img_list
, 0, NULL
, "", "", NULL
},
5100 { "vt_dump_injection", ventoy_cmd_dump_injection
, 0, NULL
, "", "", NULL
},
5101 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
5102 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
5103 { "vt_select_auto_install", ventoy_cmd_sel_auto_install
, 0, NULL
, "", "", NULL
},
5104 { "vt_select_persistence", ventoy_cmd_sel_persistence
, 0, NULL
, "", "", NULL
},
5105 { "vt_select_conf_replace", ventoy_select_conf_replace
, 0, NULL
, "", "", NULL
},
5107 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet
, 0, NULL
, "", "", NULL
},
5108 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet
, 0, NULL
, "", "", NULL
},
5109 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
5110 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
5111 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem
, 0, NULL
, "", "", NULL
},
5112 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk
, 0, NULL
, "", "", NULL
},
5113 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso
, 0, NULL
, "", "", NULL
},
5115 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5116 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
5117 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
5118 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
5119 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
5120 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
5121 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
5122 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
5123 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
5124 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index
, 0, NULL
, "", "", NULL
},
5126 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
5127 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
5128 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data
, 0, NULL
, "", "", NULL
},
5129 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch
, 0, NULL
, "", "", NULL
},
5130 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch
, 0, NULL
, "", "", NULL
},
5131 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count
, 0, NULL
, "", "", NULL
},
5132 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch
, 0, NULL
, "", "", NULL
},
5133 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable
, 0, NULL
, "", "", NULL
},
5134 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data
, 0, NULL
, "", "", NULL
},
5136 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
5137 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt
, 0, NULL
, "", "", NULL
},
5138 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
5139 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase
, 0, NULL
, "", "", NULL
},
5142 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
5143 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json
, 0, NULL
, "", "", NULL
},
5144 { "vt_check_password", ventoy_cmd_check_password
, 0, NULL
, "", "", NULL
},
5146 { "vt_1st_line", ventoy_cmd_read_1st_line
, 0, NULL
, "", "", NULL
},
5147 { "vt_file_strstr", ventoy_cmd_file_strstr
, 0, NULL
, "", "", NULL
},
5148 { "vt_img_part_info", ventoy_cmd_img_part_info
, 0, NULL
, "", "", NULL
},
5151 { "vt_parse_iso_volume", ventoy_cmd_parse_volume
, 0, NULL
, "", "", NULL
},
5152 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date
, 0, NULL
, "", "", NULL
},
5153 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver
, 0, NULL
, "", "", NULL
},
5154 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver
, 0, NULL
, "", "", NULL
},
5155 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf
, 0, NULL
, "", "", NULL
},
5156 { "vt_unix_reset", ventoy_cmd_unix_reset
, 0, NULL
, "", "", NULL
},
5157 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf
, 0, NULL
, "", "", NULL
},
5158 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko
, 0, NULL
, "", "", NULL
},
5159 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc
, 0, NULL
, "", "", NULL
},
5160 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko
, 0, NULL
, "", "", NULL
},
5161 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data
, 0, NULL
, "", "", NULL
},
5163 { "vt_img_hook_root", ventoy_cmd_img_hook_root
, 0, NULL
, "", "", NULL
},
5164 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root
, 0, NULL
, "", "", NULL
},
5165 { "vt_acpi_param", ventoy_cmd_acpi_param
, 0, NULL
, "", "", NULL
},
5166 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var
, 0, NULL
, "", "", NULL
},
5167 { "vt_clear_key", ventoy_cmd_clear_key
, 0, NULL
, "", "", NULL
},
5168 { "vt_img_check_range", ventoy_cmd_img_check_range
, 0, NULL
, "", "", NULL
},
5169 { "vt_is_pe64", ventoy_cmd_is_pe64
, 0, NULL
, "", "", NULL
},
5170 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot
, 0, NULL
, "", "", NULL
},
5171 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt
, 0, NULL
, "", "", NULL
},
5172 { "vt_set_theme", ventoy_cmd_set_theme
, 0, NULL
, "", "", NULL
},
5174 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset
, 0, NULL
, "", "", NULL
},
5175 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd
, 0, NULL
, "", "", NULL
},
5176 { "vt_push_pager", ventoy_cmd_push_pager
, 0, NULL
, "", "", NULL
},
5177 { "vt_pop_pager", ventoy_cmd_pop_pager
, 0, NULL
, "", "", NULL
},
5178 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase
, 0, NULL
, "", "", NULL
},
5179 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector
, 0, NULL
, "", "", NULL
},
5180 { "gptpriority", grub_cmd_gptpriority
, 0, NULL
, "", "", NULL
},
5183 int ventoy_register_all_cmd(void)
5186 cmd_para
*cur
= NULL
;
5188 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5190 cur
= ventoy_cmds
+ i
;
5191 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
5192 cur
->summary
, cur
->description
, cur
->parser
);
5198 int ventoy_unregister_all_cmd(void)
5202 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
5204 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);