]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c
eab86b1aa13344754f8957d465da57700e7a0081
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / ventoy / ventoy_cmd.c
1 /******************************************************************************
2 * ventoy_cmd.c
3 *
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
5 *
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.
10 *
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.
15 *
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/>.
18 *
19 */
20
21 #include <grub/types.h>
22 #include <grub/misc.h>
23 #include <grub/mm.h>
24 #include <grub/err.h>
25 #include <grub/dl.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>
35 #include <grub/net.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>
41 #endif
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/random.h>
49 #include <grub/ventoy.h>
50 #include "ventoy_def.h"
51 #include "miniz.h"
52
53 GRUB_MOD_LICENSE ("GPLv3+");
54
55 static grub_uint8_t g_check_mbr_data[] = {
56 0xEB, 0x63, 0x90, 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 0x56, 0x54, 0x00, 0x47, 0x65, 0x00, 0x48, 0x44, 0x00, 0x52, 0x64, 0x00, 0x20, 0x45, 0x72, 0x0D,
60 };
61
62 initrd_info *g_initrd_img_list = NULL;
63 initrd_info *g_initrd_img_tail = NULL;
64 int g_initrd_img_count = 0;
65 int g_valid_initrd_count = 0;
66 int g_default_menu_mode = 0;
67 int g_filt_dot_underscore_file = 0;
68 int g_sort_case_sensitive = 0;
69 int g_tree_view_menu_style = 0;
70 static grub_file_t g_old_file;
71 static int g_ventoy_last_entry_back;
72
73 char g_iso_path[256];
74 char g_img_swap_tmp_buf[1024];
75 img_info g_img_swap_tmp;
76 img_info *g_ventoy_img_list = NULL;
77
78 int g_ventoy_img_count = 0;
79
80 grub_device_t g_enum_dev = NULL;
81 grub_fs_t g_enum_fs = NULL;
82 int g_img_max_search_level = -1;
83 img_iterator_node g_img_iterator_head;
84 img_iterator_node *g_img_iterator_tail = NULL;
85
86 grub_uint8_t g_ventoy_break_level = 0;
87 grub_uint8_t g_ventoy_debug_level = 0;
88 grub_uint8_t g_ventoy_chain_type = 0;
89
90 grub_uint8_t *g_ventoy_cpio_buf = NULL;
91 grub_uint32_t g_ventoy_cpio_size = 0;
92 cpio_newc_header *g_ventoy_initrd_head = NULL;
93 grub_uint8_t *g_ventoy_runtime_buf = NULL;
94
95 int g_plugin_image_list = 0;
96
97 ventoy_grub_param *g_grub_param = NULL;
98
99 ventoy_guid g_ventoy_guid = VENTOY_GUID;
100
101 ventoy_img_chunk_list g_img_chunk_list;
102
103 int g_wimboot_enable = 0;
104 ventoy_img_chunk_list g_wimiso_chunk_list;
105 char *g_wimiso_path = NULL;
106 grub_uint32_t g_wimiso_size = 0;
107
108 int g_vhdboot_enable = 0;
109
110 grub_uint64_t g_svd_replace_offset = 0;
111
112 int g_conf_replace_count = 0;
113 grub_uint64_t g_conf_replace_offset[VTOY_MAX_CONF_REPLACE] = { 0 };
114 conf_replace *g_conf_replace_node[VTOY_MAX_CONF_REPLACE] = { NULL };
115 grub_uint8_t *g_conf_replace_new_buf[VTOY_MAX_CONF_REPLACE] = { NULL };
116 int g_conf_replace_new_len[VTOY_MAX_CONF_REPLACE] = { 0 };
117 int g_conf_replace_new_len_align[VTOY_MAX_CONF_REPLACE] = { 0 };
118
119 int g_ventoy_disk_bios_id = 0;
120 ventoy_gpt_info *g_ventoy_part_info = NULL;
121 grub_uint64_t g_ventoy_disk_size = 0;
122 grub_uint64_t g_ventoy_disk_part_size[2];
123
124 char *g_tree_script_buf = NULL;
125 int g_tree_script_pos = 0;
126 int g_tree_script_pre = 0;
127
128 static char *g_list_script_buf = NULL;
129 static int g_list_script_pos = 0;
130
131 static char *g_part_list_buf = NULL;
132 static int g_part_list_pos = 0;
133 static grub_uint64_t g_part_end_max = 0;
134
135 static int g_video_mode_max = 0;
136 static int g_video_mode_num = 0;
137 static ventoy_video_mode *g_video_mode_list = NULL;
138
139 static int g_enumerate_time_checked = 0;
140 static grub_uint64_t g_enumerate_start_time_ms;
141 static grub_uint64_t g_enumerate_finish_time_ms;
142 int g_vtoy_file_flt[VTOY_FILE_FLT_BUTT] = {0};
143
144 static char g_iso_vd_id_publisher[130];
145 static char g_iso_vd_id_prepare[130];
146 static char g_iso_vd_id_application[130];
147
148 static int g_pager_flag = 0;
149 static char g_old_pager[32];
150
151 const char *g_menu_class[img_type_max] =
152 {
153 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
154 };
155
156 const char *g_menu_prefix[img_type_max] =
157 {
158 "iso", "wim", "efi", "img", "vhd", "vtoy"
159 };
160
161 static int g_vtoy_secondary_need_recover = 0;
162
163 static int g_vtoy_load_prompt = 0;
164 static char g_vtoy_prompt_msg[64];
165
166 static char g_json_case_mis_path[32];
167
168 static ventoy_vlnk_part *g_vlnk_part_list = NULL;
169
170 int ventoy_get_fs_type(const char *fs)
171 {
172 if (NULL == fs)
173 {
174 return ventoy_fs_max;
175 }
176 else if (grub_strncmp(fs, "exfat", 5) == 0)
177 {
178 return ventoy_fs_exfat;
179 }
180 else if (grub_strncmp(fs, "ntfs", 4) == 0)
181 {
182 return ventoy_fs_ntfs;
183 }
184 else if (grub_strncmp(fs, "ext", 3) == 0)
185 {
186 return ventoy_fs_ext;
187 }
188 else if (grub_strncmp(fs, "xfs", 3) == 0)
189 {
190 return ventoy_fs_xfs;
191 }
192 else if (grub_strncmp(fs, "udf", 3) == 0)
193 {
194 return ventoy_fs_udf;
195 }
196 else if (grub_strncmp(fs, "fat", 3) == 0)
197 {
198 return ventoy_fs_fat;
199 }
200
201 return ventoy_fs_max;
202 }
203
204 static int ventoy_string_check(const char *str, grub_char_check_func check)
205 {
206 if (!str)
207 {
208 return 0;
209 }
210
211 for ( ; *str; str++)
212 {
213 if (!check(*str))
214 {
215 return 0;
216 }
217 }
218
219 return 1;
220 }
221
222
223 static grub_ssize_t ventoy_fs_read(grub_file_t file, char *buf, grub_size_t len)
224 {
225 grub_memcpy(buf, (char *)file->data + file->offset, len);
226 return len;
227 }
228
229 static int ventoy_control_get_flag(const char *key)
230 {
231 const char *val = ventoy_get_env(key);
232
233 if (val && val[0] == '1' && val[1] == 0)
234 {
235 return 1;
236 }
237 return 0;
238 }
239
240 static grub_err_t ventoy_fs_close(grub_file_t file)
241 {
242 grub_file_close(g_old_file);
243 grub_free(file->data);
244
245 file->device = 0;
246 file->name = 0;
247
248 return 0;
249 }
250
251 static int ventoy_video_hook(const struct grub_video_mode_info *info, void *hook_arg)
252 {
253 int i;
254
255 (void)hook_arg;
256
257 if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
258 {
259 return 0;
260 }
261
262 for (i = 0; i < g_video_mode_num; i++)
263 {
264 if (g_video_mode_list[i].width == info->width &&
265 g_video_mode_list[i].height == info->height &&
266 g_video_mode_list[i].bpp == info->bpp)
267 {
268 return 0;
269 }
270 }
271
272 g_video_mode_list[g_video_mode_num].width = info->width;
273 g_video_mode_list[g_video_mode_num].height = info->height;
274 g_video_mode_list[g_video_mode_num].bpp = info->bpp;
275 g_video_mode_num++;
276
277 if (g_video_mode_num == g_video_mode_max)
278 {
279 g_video_mode_max *= 2;
280 g_video_mode_list = grub_realloc(g_video_mode_list, g_video_mode_max * sizeof(ventoy_video_mode));
281 }
282
283 return 0;
284 }
285
286 static int ventoy_video_mode_cmp(ventoy_video_mode *v1, ventoy_video_mode *v2)
287 {
288 if (v1->bpp == v2->bpp)
289 {
290 if (v1->width == v2->width)
291 {
292 if (v1->height == v2->height)
293 {
294 return 0;
295 }
296 else
297 {
298 return (v1->height < v2->height) ? -1 : 1;
299 }
300 }
301 else
302 {
303 return (v1->width < v2->width) ? -1 : 1;
304 }
305 }
306 else
307 {
308 return (v1->bpp < v2->bpp) ? -1 : 1;
309 }
310 }
311
312 static int ventoy_enum_video_mode(void)
313 {
314 int i, j;
315 grub_video_adapter_t adapter;
316 grub_video_driver_id_t id;
317 ventoy_video_mode mode;
318
319 g_video_mode_num = 0;
320 g_video_mode_max = 1024;
321 g_video_mode_list = grub_malloc(sizeof(ventoy_video_mode) * g_video_mode_max);
322 if (!g_video_mode_list)
323 {
324 return 0;
325 }
326
327 #ifdef GRUB_MACHINE_PCBIOS
328 grub_dl_load ("vbe");
329 #endif
330
331 id = grub_video_get_driver_id ();
332
333 FOR_VIDEO_ADAPTERS (adapter)
334 {
335 if (!adapter->iterate ||
336 (adapter->id != id && (id != GRUB_VIDEO_DRIVER_NONE ||
337 adapter->init() != GRUB_ERR_NONE)))
338 {
339 continue;
340 }
341
342 adapter->iterate(ventoy_video_hook, NULL);
343
344 if (adapter->id != id)
345 {
346 adapter->fini();
347 }
348 }
349
350 /* sort video mode */
351 for (i = 0; i < g_video_mode_num; i++)
352 for (j = i + 1; j < g_video_mode_num; j++)
353 {
354 if (ventoy_video_mode_cmp(g_video_mode_list + i, g_video_mode_list + j) < 0)
355 {
356 grub_memcpy(&mode, g_video_mode_list + i, sizeof(ventoy_video_mode));
357 grub_memcpy(g_video_mode_list + i, g_video_mode_list + j, sizeof(ventoy_video_mode));
358 grub_memcpy(g_video_mode_list + j, &mode, sizeof(ventoy_video_mode));
359 }
360 }
361
362 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
363 }
364
365 static grub_file_t ventoy_wrapper_open(grub_file_t rawFile, enum grub_file_type type)
366 {
367 int len;
368 grub_file_t file;
369 static struct grub_fs vtoy_fs =
370 {
371 .name = "vtoy",
372 .fs_dir = 0,
373 .fs_open = 0,
374 .fs_read = ventoy_fs_read,
375 .fs_close = ventoy_fs_close,
376 .fs_label = 0,
377 .next = 0
378 };
379
380 if (type != 52)
381 {
382 return rawFile;
383 }
384
385 file = (grub_file_t)grub_zalloc(sizeof (*file));
386 if (!file)
387 {
388 return 0;
389 }
390
391 file->data = grub_malloc(rawFile->size + 4096);
392 if (!file->data)
393 {
394 return 0;
395 }
396
397 grub_file_read(rawFile, file->data, rawFile->size);
398 len = ventoy_fill_data(4096, (char *)file->data + rawFile->size);
399
400 g_old_file = rawFile;
401
402 file->size = rawFile->size + len;
403 file->device = rawFile->device;
404 file->fs = &vtoy_fs;
405 file->not_easily_seekable = 1;
406
407 return file;
408 }
409
410 static int ventoy_check_decimal_var(const char *name, long *value)
411 {
412 const char *value_str = NULL;
413
414 value_str = grub_env_get(name);
415 if (NULL == value_str)
416 {
417 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s not found", name);
418 }
419
420 if (!ventoy_is_decimal(value_str))
421 {
422 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s value '%s' is not an integer", name, value_str);
423 }
424
425 *value = grub_strtol(value_str, NULL, 10);
426
427 return GRUB_ERR_NONE;
428 }
429
430 grub_uint64_t ventoy_get_vtoy_partsize(int part)
431 {
432 grub_uint64_t sectors;
433
434 if (grub_strncmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
435 {
436 sectors = g_ventoy_part_info->PartTbl[part].LastLBA + 1 - g_ventoy_part_info->PartTbl[part].StartLBA;
437 }
438 else
439 {
440 sectors = g_ventoy_part_info->MBR.PartTbl[part].SectorCount;
441 }
442
443 return sectors * 512;
444 }
445
446 static int ventoy_load_efiboot_template(char **buf, int *datalen, int *direntoff)
447 {
448 int len;
449 grub_file_t file;
450 char exec[128];
451 char *data = NULL;
452 grub_uint32_t offset;
453
454 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
455 if (file == NULL)
456 {
457 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
458 return 1;
459 }
460
461 len = (int)file->size;
462
463 data = (char *)grub_malloc(file->size);
464 if (!data)
465 {
466 return 1;
467 }
468
469 grub_file_read(file, data, file->size);
470 grub_file_close(file);
471
472 grub_snprintf(exec, sizeof(exec), "loopback efiboot mem:0x%llx:size:%d", (ulonglong)(ulong)data, len);
473 grub_script_execute_sourcecode(exec);
474
475 file = grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD);
476 offset = (grub_uint32_t)grub_iso9660_get_last_file_dirent_pos(file);
477 grub_file_close(file);
478
479 grub_script_execute_sourcecode("loopback -d efiboot");
480
481 *buf = data;
482 *datalen = len;
483 *direntoff = offset + 2;
484
485 return 0;
486 }
487
488 static int ventoy_set_check_result(int ret, const char *msg)
489 {
490 char buf[32];
491
492 grub_snprintf(buf, sizeof(buf), "%d", (ret & 0x7FFF));
493 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf);
494 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
495
496 if (ret)
497 {
498 grub_printf(VTOY_WARNING"\n");
499 grub_printf(VTOY_WARNING"\n");
500 grub_printf(VTOY_WARNING"\n\n\n");
501
502 grub_printf("This is NOT a standard Ventoy device and is NOT supported (%d).\n", ret);
503 grub_printf("Error message: <%s>\n\n", msg);
504 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
505
506 grub_printf("\n\nWill exit after 10 seconds ...... ");
507 grub_refresh();
508 grub_sleep(10);
509 }
510
511 return ret;
512 }
513
514 static int ventoy_check_official_device(grub_device_t dev)
515 {
516 int workaround = 0;
517 grub_file_t file;
518 grub_uint64_t offset;
519 char devname[64];
520 grub_fs_t fs;
521 grub_uint8_t mbr[512];
522 grub_disk_t disk;
523 grub_device_t dev2;
524 char *label = NULL;
525 struct grub_partition *partition;
526
527 if (dev->disk == NULL || dev->disk->partition == NULL)
528 {
529 return ventoy_set_check_result(1 | 0x1000, "Internal Error");
530 }
531
532 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev->disk->name) ||
533 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev->disk->name) ||
534 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
535 {
536 #ifndef GRUB_MACHINE_EFI
537 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev->disk->name))
538 {
539 return ventoy_set_check_result(2 | 0x1000, "File ventoy/ventoy.cpio missing in VTOYEFI partition");
540 }
541 else if (0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev->disk->name))
542 {
543 return ventoy_set_check_result(2 | 0x1000, "File grub/localboot.cfg missing in VTOYEFI partition");
544 }
545 else if (0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
546 {
547 return ventoy_set_check_result(2 | 0x1000, "File tool/mount.exfat-fuse_aarch64 missing in VTOYEFI partition");
548 }
549 else
550 {
551 workaround = 1;
552 }
553 #endif
554 }
555
556 /* We must have partition 2 */
557 if (workaround)
558 {
559 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
560 }
561 else
562 {
563 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(%s,2)/ventoy/ventoy.cpio", dev->disk->name);
564 }
565 if (!file)
566 {
567 return ventoy_set_check_result(3 | 0x1000, "File ventoy/ventoy.cpio open failed in VTOYEFI partition");
568 }
569
570 if (NULL == grub_strstr(file->fs->name, "fat"))
571 {
572 grub_file_close(file);
573 return ventoy_set_check_result(4 | 0x1000, "VTOYEFI partition is not FAT filesystem");
574 }
575
576 partition = dev->disk->partition;
577 if (partition->number != 0 || partition->start != 2048)
578 {
579 return ventoy_set_check_result(5, "Ventoy partition is not start at 1MB");
580 }
581
582 if (workaround)
583 {
584 if (grub_strncmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
585 {
586 ventoy_gpt_part_tbl *PartTbl = g_ventoy_part_info->PartTbl;
587 if (PartTbl[1].StartLBA != PartTbl[0].LastLBA + 1 ||
588 (PartTbl[1].LastLBA + 1 - PartTbl[1].StartLBA) != 65536)
589 {
590 grub_file_close(file);
591 return ventoy_set_check_result(6, "Disk partition layout check failed.");
592 }
593 }
594 else
595 {
596 ventoy_part_table *PartTbl = g_ventoy_part_info->MBR.PartTbl;
597 if (PartTbl[1].StartSectorId != PartTbl[0].StartSectorId + PartTbl[0].SectorCount ||
598 PartTbl[1].SectorCount != 65536)
599 {
600 grub_file_close(file);
601 return ventoy_set_check_result(6, "Disk partition layout check failed.");
602 }
603 }
604 }
605 else
606 {
607 offset = partition->start + partition->len;
608 partition = file->device->disk->partition;
609 if ((partition->number != 1) || (partition->len != 65536) || (offset != partition->start))
610 {
611 grub_file_close(file);
612 return ventoy_set_check_result(7, "Disk partition layout check failed.");
613 }
614 }
615
616 grub_file_close(file);
617
618 if (workaround == 0)
619 {
620 grub_snprintf(devname, sizeof(devname), "%s,2", dev->disk->name);
621 dev2 = grub_device_open(devname);
622 if (!dev2)
623 {
624 return ventoy_set_check_result(8, "Disk open failed");
625 }
626
627 fs = grub_fs_probe(dev2);
628 if (!fs)
629 {
630 grub_device_close(dev2);
631 return ventoy_set_check_result(9, "FS probe failed");
632 }
633
634 fs->fs_label(dev2, &label);
635 if ((!label) || grub_strncmp("VTOYEFI", label, 7))
636 {
637 grub_device_close(dev2);
638 return ventoy_set_check_result(10, "Partition name is not VTOYEFI");
639 }
640
641 grub_device_close(dev2);
642 }
643
644 /* MBR check */
645 disk = grub_disk_open(dev->disk->name);
646 if (!disk)
647 {
648 return ventoy_set_check_result(11, "Disk open failed");
649 }
650
651 grub_memset(mbr, 0, 512);
652 grub_disk_read(disk, 0, 0, 512, mbr);
653 grub_disk_close(disk);
654
655 if (grub_memcmp(g_check_mbr_data, mbr, 0x30) || grub_memcmp(g_check_mbr_data + 0x30, mbr + 0x190, 16))
656 {
657 return ventoy_set_check_result(12, "MBR check failed");
658 }
659
660 return ventoy_set_check_result(0, NULL);
661 }
662
663 static int ventoy_check_ignore_flag(const char *filename, const struct grub_dirhook_info *info, void *data)
664 {
665 if (0 == info->dir)
666 {
667 if (filename && filename[0] == '.' && 0 == grub_strncmp(filename, ".ventoyignore", 13))
668 {
669 *((int *)data) = 1;
670 return 0;
671 }
672 }
673
674 return 0;
675 }
676
677 grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...)
678 {
679 grub_uint64_t size = 0;
680 grub_file_t file;
681 va_list ap;
682 char fullpath[256] = {0};
683
684 va_start (ap, fmt);
685 grub_vsnprintf(fullpath, 255, fmt, ap);
686 va_end (ap);
687
688 file = grub_file_open(fullpath, VENTOY_FILE_TYPE);
689 if (!file)
690 {
691 debug("grub_file_open failed <%s>\n", fullpath);
692 grub_errno = 0;
693 return 0;
694 }
695
696 size = file->size;
697 grub_file_close(file);
698 return size;
699 }
700
701 grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...)
702 {
703 va_list ap;
704 grub_file_t file;
705 char fullpath[512] = {0};
706
707 va_start (ap, fmt);
708 grub_vsnprintf(fullpath, 511, fmt, ap);
709 va_end (ap);
710
711 file = grub_file_open(fullpath, type);
712 if (!file)
713 {
714 debug("grub_file_open failed <%s> %d\n", fullpath, grub_errno);
715 grub_errno = 0;
716 }
717
718 return file;
719 }
720
721 int ventoy_is_dir_exist(const char *fmt, ...)
722 {
723 va_list ap;
724 int len;
725 char *pos = NULL;
726 char buf[512] = {0};
727
728 grub_snprintf(buf, sizeof(buf), "%s", "[ -d \"");
729 pos = buf + 6;
730
731 va_start (ap, fmt);
732 len = grub_vsnprintf(pos, 511, fmt, ap);
733 va_end (ap);
734
735 grub_strncpy(pos + len, "\" ]", 3);
736
737 debug("script exec %s\n", buf);
738
739 if (0 == grub_script_execute_sourcecode(buf))
740 {
741 return 1;
742 }
743
744 return 0;
745 }
746
747 int ventoy_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len)
748 {
749 mz_stream s;
750 grub_uint8_t *outbuf;
751 grub_uint8_t gzHdr[10] =
752 {
753 0x1F, 0x8B, /* magic */
754 8, /* z method */
755 0, /* flags */
756 0,0,0,0, /* mtime */
757 4, /* xfl */
758 3, /* OS */
759 };
760
761 grub_memset(&s, 0, sizeof(mz_stream));
762
763 mz_deflateInit2(&s, 1, MZ_DEFLATED, -MZ_DEFAULT_WINDOW_BITS, 6, MZ_DEFAULT_STRATEGY);
764
765 outbuf = (grub_uint8_t *)mem_out;
766
767 mem_out_len -= sizeof(gzHdr) + 8;
768 grub_memcpy(outbuf, gzHdr, sizeof(gzHdr));
769 outbuf += sizeof(gzHdr);
770
771 s.avail_in = mem_in_len;
772 s.next_in = mem_in;
773
774 s.avail_out = mem_out_len;
775 s.next_out = outbuf;
776
777 mz_deflate(&s, MZ_FINISH);
778
779 mz_deflateEnd(&s);
780
781 outbuf += s.total_out;
782 *(grub_uint32_t *)outbuf = grub_getcrc32c(0, outbuf, s.total_out);
783 *(grub_uint32_t *)(outbuf + 4) = (grub_uint32_t)(s.total_out);
784
785 return s.total_out + sizeof(gzHdr) + 8;
786 }
787
788
789 #if 0
790 ventoy grub cmds
791 #endif
792
793 static grub_err_t ventoy_cmd_debug(grub_extcmd_context_t ctxt, int argc, char **args)
794 {
795 if (argc != 1)
796 {
797 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {on|off}", cmd_raw_name);
798 }
799
800 if (0 == grub_strcmp(args[0], "on"))
801 {
802 g_ventoy_debug = 1;
803 grub_env_set("vtdebug_flag", "debug");
804 }
805 else
806 {
807 g_ventoy_debug = 0;
808 grub_env_set("vtdebug_flag", "");
809 }
810
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
812 }
813
814 static grub_err_t ventoy_cmd_break(grub_extcmd_context_t ctxt, int argc, char **args)
815 {
816 (void)ctxt;
817
818 if (argc < 1 || (args[0][0] != '0' && args[0][0] != '1'))
819 {
820 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name);
821 grub_printf(" level:\r\n");
822 grub_printf(" 01/11: busybox / (+cat log)\r\n");
823 grub_printf(" 02/12: initrd / (+cat log)\r\n");
824 grub_printf(" 03/13: hook / (+cat log)\r\n");
825 grub_printf("\r\n");
826 grub_printf(" debug:\r\n");
827 grub_printf(" 0: debug is off\r\n");
828 grub_printf(" 1: debug is on\r\n");
829 grub_printf("\r\n");
830 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
831 }
832
833 g_ventoy_break_level = (grub_uint8_t)grub_strtoul(args[0], NULL, 16);
834
835 if (argc > 1 && grub_strtoul(args[1], NULL, 10) > 0)
836 {
837 g_ventoy_debug_level = 1;
838 }
839
840 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
841 }
842
843 static grub_err_t ventoy_cmd_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
844 {
845 (void)ctxt;
846
847 if (argc != 2)
848 {
849 return 1;
850 }
851
852 return (grub_strstr(args[0], args[1])) ? 0 : 1;
853 }
854
855 static grub_err_t ventoy_cmd_strbegin(grub_extcmd_context_t ctxt, int argc, char **args)
856 {
857 char *c0, *c1;
858
859 (void)ctxt;
860
861 if (argc != 2)
862 {
863 return 1;
864 }
865
866 c0 = args[0];
867 c1 = args[1];
868
869 while (*c0 && *c1)
870 {
871 if (*c0 != *c1)
872 {
873 return 1;
874 }
875 c0++;
876 c1++;
877 }
878
879 if (*c1)
880 {
881 return 1;
882 }
883
884 return 0;
885 }
886
887 static grub_err_t ventoy_cmd_strcasebegin(grub_extcmd_context_t ctxt, int argc, char **args)
888 {
889 char *c0, *c1;
890
891 (void)ctxt;
892
893 if (argc != 2)
894 {
895 return 1;
896 }
897
898 c0 = args[0];
899 c1 = args[1];
900
901 while (*c0 && *c1)
902 {
903 if ((*c0 != *c1) && (*c0 != grub_toupper(*c1)))
904 {
905 return 1;
906 }
907 c0++;
908 c1++;
909 }
910
911 if (*c1)
912 {
913 return 1;
914 }
915
916 return 0;
917 }
918
919 static grub_err_t ventoy_cmd_incr(grub_extcmd_context_t ctxt, int argc, char **args)
920 {
921 long value_long = 0;
922 char buf[32];
923
924 if ((argc != 2) || (!ventoy_is_decimal(args[1])))
925 {
926 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Variable} {Int}", cmd_raw_name);
927 }
928
929 if (GRUB_ERR_NONE != ventoy_check_decimal_var(args[0], &value_long))
930 {
931 return grub_errno;
932 }
933
934 value_long += grub_strtol(args[1], NULL, 10);
935
936 grub_snprintf(buf, sizeof(buf), "%ld", value_long);
937 grub_env_set(args[0], buf);
938
939 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
940 }
941
942 static grub_err_t ventoy_cmd_mod(grub_extcmd_context_t ctxt, int argc, char **args)
943 {
944 ulonglong value1 = 0;
945 ulonglong value2 = 0;
946 char buf[32];
947
948 if (argc != 3)
949 {
950 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name);
951 }
952
953 value1 = grub_strtoull(args[0], NULL, 10);
954 value2 = grub_strtoull(args[1], NULL, 10);
955
956 grub_snprintf(buf, sizeof(buf), "%llu", (value1 & (value2 - 1)));
957 grub_env_set(args[2], buf);
958
959 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
960 }
961
962 static grub_err_t ventoy_cmd_file_size(grub_extcmd_context_t ctxt, int argc, char **args)
963 {
964 int rc = 1;
965 char buf[32];
966 grub_file_t file;
967
968 (void)ctxt;
969 (void)argc;
970 (void)args;
971
972 if (argc != 2)
973 {
974 return rc;
975 }
976
977 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
978 if (file == NULL)
979 {
980 debug("failed to open file <%s> for udf check\n", args[0]);
981 return 1;
982 }
983
984 grub_snprintf(buf, sizeof(buf), "%llu", (unsigned long long)file->size);
985
986 grub_env_set(args[1], buf);
987
988 grub_file_close(file);
989 rc = 0;
990
991 return rc;
992 }
993
994 static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc, char **args)
995 {
996 grub_file_t file;
997
998 (void)ctxt;
999 (void)argc;
1000 (void)args;
1001
1002 g_wimboot_enable = 0;
1003 g_wimiso_size = 0;
1004 grub_check_free(g_wimiso_path);
1005 grub_check_free(g_wimiso_chunk_list.chunk);
1006
1007 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
1008 if (!file)
1009 {
1010 return 0;
1011 }
1012
1013 grub_memset(&g_wimiso_chunk_list, 0, sizeof(g_wimiso_chunk_list));
1014 g_wimiso_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
1015 if (NULL == g_wimiso_chunk_list.chunk)
1016 {
1017 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
1018 }
1019
1020 g_wimiso_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
1021 g_wimiso_chunk_list.cur_chunk = 0;
1022
1023 ventoy_get_block_list(file, &g_wimiso_chunk_list, file->device->disk->partition->start);
1024
1025 g_wimboot_enable = 1;
1026 g_wimiso_path = grub_strdup(args[0]);
1027 g_wimiso_size = (grub_uint32_t)(file->size);
1028 grub_file_close(file);
1029
1030 return 0;
1031 }
1032
1033 static grub_err_t ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc, char **args)
1034 {
1035 int len = 0;
1036 int totlen = 0;
1037 int offset = 0;
1038 grub_file_t file;
1039 char *buf = NULL;
1040 char *data = NULL;
1041 ventoy_iso9660_override *dirent;
1042
1043 (void)ctxt;
1044
1045 if (argc != 2)
1046 {
1047 return 1;
1048 }
1049
1050 totlen = sizeof(ventoy_chain_head);
1051
1052 if (ventoy_load_efiboot_template(&buf, &len, &offset))
1053 {
1054 debug("failed to load efiboot template %d\n", len);
1055 return 1;
1056 }
1057
1058 totlen += len;
1059
1060 debug("efiboot template len:%d offset:%d\n", len, offset);
1061
1062 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
1063 if (file == NULL)
1064 {
1065 debug("failed to open file <%s>\n", args[0]);
1066 return 1;
1067 }
1068
1069 if (grub_strncmp(args[0], g_iso_path, grub_strlen(g_iso_path)))
1070 {
1071 file->vlnk = 1;
1072 }
1073
1074 totlen += ventoy_align_2k(file->size);
1075
1076 dirent = (ventoy_iso9660_override *)(buf + offset);
1077 dirent->first_sector = len / 2048;
1078 dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
1079 dirent->size = (grub_uint32_t)file->size;
1080 dirent->size_be = grub_swap_bytes32(dirent->size);
1081
1082 debug("rawiso len:%d efilen:%d total:%d\n", len, (int)file->size, totlen);
1083
1084 #ifdef GRUB_MACHINE_EFI
1085 data = (char *)grub_efi_allocate_iso_buf(totlen);
1086 #else
1087 data = (char *)grub_malloc(totlen);
1088 #endif
1089
1090 ventoy_fill_os_param(file, (ventoy_os_param *)data);
1091
1092 grub_memcpy(data + sizeof(ventoy_chain_head), buf, len);
1093 grub_check_free(buf);
1094
1095 grub_file_read(file, data + sizeof(ventoy_chain_head) + len, file->size);
1096 grub_file_close(file);
1097
1098 ventoy_memfile_env_set(args[1], data, (ulonglong)totlen);
1099
1100 return 0;
1101 }
1102
1103 grub_err_t ventoy_cmd_set_wim_prompt(grub_extcmd_context_t ctxt, int argc, char **args)
1104 {
1105 (void)ctxt;
1106 (void)argc;
1107 (void)args;
1108
1109 g_vtoy_load_prompt = 0;
1110 grub_memset(g_vtoy_prompt_msg, 0, sizeof(g_vtoy_prompt_msg));
1111
1112 if (argc == 2 && args[0][0] == '1')
1113 {
1114 g_vtoy_load_prompt = 1;
1115 grub_snprintf(g_vtoy_prompt_msg, sizeof(g_vtoy_prompt_msg), "%s", args[1]);
1116 }
1117
1118 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1119 }
1120
1121 int ventoy_need_prompt_load_file(void)
1122 {
1123 return g_vtoy_load_prompt;
1124 }
1125
1126 grub_ssize_t ventoy_load_file_with_prompt(grub_file_t file, void *buf, grub_ssize_t size)
1127 {
1128 grub_uint64_t ro = 0;
1129 grub_uint64_t div = 0;
1130 grub_ssize_t left = size;
1131 char *cur = (char *)buf;
1132
1133 grub_printf("\r%s 1%% ", g_vtoy_prompt_msg);
1134 grub_refresh();
1135
1136 while (left >= VTOY_SIZE_2MB)
1137 {
1138 grub_file_read(file, cur, VTOY_SIZE_2MB);
1139 cur += VTOY_SIZE_2MB;
1140 left -= VTOY_SIZE_2MB;
1141
1142 div = grub_divmod64((grub_uint64_t)((size - left) * 100), (grub_uint64_t)size, &ro);
1143 if (div < 1)
1144 {
1145 div = 1;
1146 }
1147 grub_printf("\r%s %d%% ", g_vtoy_prompt_msg, (int)div);
1148 grub_refresh();
1149 }
1150
1151 if (left > 0)
1152 {
1153 grub_file_read(file, cur, left);
1154 }
1155
1156 grub_printf("\r%s 100%% \n", g_vtoy_prompt_msg);
1157 grub_refresh();
1158
1159 return size;
1160 }
1161
1162 static grub_err_t ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
1163 {
1164 int rc = 1;
1165 char *buf = NULL;
1166 grub_file_t file;
1167 enum grub_file_type type;
1168
1169 (void)ctxt;
1170 (void)argc;
1171 (void)args;
1172
1173 if (argc != 3)
1174 {
1175 return rc;
1176 }
1177
1178 if (grub_strcmp(args[0], "nodecompress") == 0)
1179 {
1180 type = VENTOY_FILE_TYPE;
1181 }
1182 else
1183 {
1184 type = GRUB_FILE_TYPE_LINUX_INITRD;
1185 }
1186
1187 file = ventoy_grub_file_open(type, "%s", args[1]);
1188 if (file == NULL)
1189 {
1190 debug("failed to open file <%s>\n", args[1]);
1191 return 1;
1192 }
1193
1194 #ifdef GRUB_MACHINE_EFI
1195 buf = (char *)grub_efi_allocate_chain_buf(file->size);
1196 #else
1197 buf = (char *)grub_malloc(file->size);
1198 #endif
1199
1200 if (!buf)
1201 {
1202 grub_file_close(file);
1203 return 1;
1204 }
1205
1206 if (g_vtoy_load_prompt)
1207 {
1208 ventoy_load_file_with_prompt(file, buf, file->size);
1209 }
1210 else
1211 {
1212 grub_file_read(file, buf, file->size);
1213 }
1214
1215 ventoy_memfile_env_set(args[2], buf, (ulonglong)(file->size));
1216
1217 grub_file_close(file);
1218 rc = 0;
1219
1220 return rc;
1221 }
1222
1223 static grub_err_t ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt, int argc, char **args)
1224 {
1225 int rc = 1;
1226 int headlen;
1227 char *buf = NULL;
1228 grub_file_t file;
1229
1230 (void)ctxt;
1231 (void)argc;
1232 (void)args;
1233
1234 if (argc != 2)
1235 {
1236 return rc;
1237 }
1238
1239 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1240 if (file == NULL)
1241 {
1242 debug("failed to open file <%s> for udf check\n", args[0]);
1243 return 1;
1244 }
1245
1246 headlen = sizeof(ventoy_chain_head);
1247
1248 #ifdef GRUB_MACHINE_EFI
1249 buf = (char *)grub_efi_allocate_iso_buf(headlen + file->size);
1250 #else
1251 buf = (char *)grub_malloc(headlen + file->size);
1252 #endif
1253
1254 ventoy_fill_os_param(file, (ventoy_os_param *)buf);
1255
1256 grub_file_read(file, buf + headlen, file->size);
1257
1258 ventoy_memfile_env_set(args[1], buf, (ulonglong)(file->size));
1259
1260 grub_file_close(file);
1261 rc = 0;
1262
1263 return rc;
1264 }
1265
1266 static grub_err_t ventoy_cmd_iso9660_is_joliet(grub_extcmd_context_t ctxt, int argc, char **args)
1267 {
1268 (void)ctxt;
1269 (void)argc;
1270 (void)args;
1271
1272 if (grub_iso9660_is_joliet())
1273 {
1274 debug("This time has joliet process\n");
1275 return 0;
1276 }
1277 else
1278 {
1279 return 1;
1280 }
1281 }
1282
1283 static grub_err_t ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
1284 {
1285 (void)ctxt;
1286
1287 if (argc != 1)
1288 {
1289 return 1;
1290 }
1291
1292 if (args[0][0] == '1')
1293 {
1294 grub_iso9660_set_nojoliet(1);
1295 }
1296 else
1297 {
1298 grub_iso9660_set_nojoliet(0);
1299 }
1300
1301 return 0;
1302 }
1303
1304 static grub_err_t ventoy_cmd_is_udf(grub_extcmd_context_t ctxt, int argc, char **args)
1305 {
1306 int i;
1307 int rc = 1;
1308 grub_file_t file;
1309 grub_uint8_t buf[32];
1310
1311 (void)ctxt;
1312 (void)argc;
1313 (void)args;
1314
1315 if (argc != 1)
1316 {
1317 return rc;
1318 }
1319
1320 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1321 if (file == NULL)
1322 {
1323 debug("failed to open file <%s> for udf check\n", args[0]);
1324 return 1;
1325 }
1326
1327 for (i = 16; i < 32; i++)
1328 {
1329 grub_file_seek(file, i * 2048);
1330 grub_file_read(file, buf, sizeof(buf));
1331 if (buf[0] == 255)
1332 {
1333 break;
1334 }
1335 }
1336
1337 i++;
1338 grub_file_seek(file, i * 2048);
1339 grub_file_read(file, buf, sizeof(buf));
1340
1341 if (grub_memcmp(buf + 1, "BEA01", 5) == 0)
1342 {
1343 i++;
1344 grub_file_seek(file, i * 2048);
1345 grub_file_read(file, buf, sizeof(buf));
1346
1347 if (grub_memcmp(buf + 1, "NSR02", 5) == 0 ||
1348 grub_memcmp(buf + 1, "NSR03", 5) == 0)
1349 {
1350 rc = 0;
1351 }
1352 }
1353
1354 grub_file_close(file);
1355
1356 debug("ISO UDF: %s\n", rc ? "NO" : "YES");
1357
1358 return rc;
1359 }
1360
1361 static grub_err_t ventoy_cmd_cmp(grub_extcmd_context_t ctxt, int argc, char **args)
1362 {
1363 long value_long1 = 0;
1364 long value_long2 = 0;
1365
1366 if ((argc != 3) || (!ventoy_is_decimal(args[0])) || (!ventoy_is_decimal(args[2])))
1367 {
1368 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name);
1369 }
1370
1371 value_long1 = grub_strtol(args[0], NULL, 10);
1372 value_long2 = grub_strtol(args[2], NULL, 10);
1373
1374 if (0 == grub_strcmp(args[1], "eq"))
1375 {
1376 grub_errno = (value_long1 == value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1377 }
1378 else if (0 == grub_strcmp(args[1], "ne"))
1379 {
1380 grub_errno = (value_long1 != value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1381 }
1382 else if (0 == grub_strcmp(args[1], "gt"))
1383 {
1384 grub_errno = (value_long1 > value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1385 }
1386 else if (0 == grub_strcmp(args[1], "lt"))
1387 {
1388 grub_errno = (value_long1 < value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1389 }
1390 else if (0 == grub_strcmp(args[1], "ge"))
1391 {
1392 grub_errno = (value_long1 >= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1393 }
1394 else if (0 == grub_strcmp(args[1], "le"))
1395 {
1396 grub_errno = (value_long1 <= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1397 }
1398 else
1399 {
1400 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name);
1401 }
1402
1403 return grub_errno;
1404 }
1405
1406 static grub_err_t ventoy_cmd_device(grub_extcmd_context_t ctxt, int argc, char **args)
1407 {
1408 char *pos = NULL;
1409 char buf[128] = {0};
1410
1411 if (argc != 2)
1412 {
1413 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s path var", cmd_raw_name);
1414 }
1415
1416 grub_strncpy(buf, (args[0][0] == '(') ? args[0] + 1 : args[0], sizeof(buf) - 1);
1417 pos = grub_strstr(buf, ",");
1418 if (pos)
1419 {
1420 *pos = 0;
1421 }
1422
1423 grub_env_set(args[1], buf);
1424
1425 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1426 }
1427
1428 static grub_err_t ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt, int argc, char **args)
1429 {
1430 int i;
1431 char buf[256];
1432 grub_disk_t disk;
1433 char *pos = NULL;
1434 const char *files[] = { "ventoy.dat", "VENTOY.DAT" };
1435
1436 (void)ctxt;
1437
1438 if (argc != 1)
1439 {
1440 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s (loop)", cmd_raw_name);
1441 }
1442
1443 for (i = 0; i < (int)ARRAY_SIZE(files); i++)
1444 {
1445 grub_snprintf(buf, sizeof(buf) - 1, "[ -e \"%s/%s\" ]", args[0], files[i]);
1446 if (0 == grub_script_execute_sourcecode(buf))
1447 {
1448 debug("file %s exist, ventoy_compatible YES\n", buf);
1449 grub_env_set("ventoy_compatible", "YES");
1450 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1451 }
1452 else
1453 {
1454 debug("file %s NOT exist\n", buf);
1455 }
1456 }
1457
1458 grub_snprintf(buf, sizeof(buf) - 1, "%s", args[0][0] == '(' ? (args[0] + 1) : args[0]);
1459 pos = grub_strstr(buf, ")");
1460 if (pos)
1461 {
1462 *pos = 0;
1463 }
1464
1465 disk = grub_disk_open(buf);
1466 if (disk)
1467 {
1468 grub_disk_read(disk, 16 << 2, 0, 1024, g_img_swap_tmp_buf);
1469 grub_disk_close(disk);
1470
1471 g_img_swap_tmp_buf[703] = 0;
1472 for (i = 318; i < 703; i++)
1473 {
1474 if (g_img_swap_tmp_buf[i] == 'V' &&
1475 0 == grub_strncmp(g_img_swap_tmp_buf + i, VENTOY_COMPATIBLE_STR, VENTOY_COMPATIBLE_STR_LEN))
1476 {
1477 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i);
1478 grub_env_set("ventoy_compatible", "YES");
1479 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1480 }
1481 }
1482 }
1483 else
1484 {
1485 debug("failed to open disk <%s>\n", buf);
1486 }
1487
1488 grub_env_set("ventoy_compatible", "NO");
1489 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1490 }
1491
1492 int ventoy_cmp_img(img_info *img1, img_info *img2)
1493 {
1494 char *s1, *s2;
1495 int c1 = 0;
1496 int c2 = 0;
1497
1498 if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
1499 {
1500 return (img1->plugin_list_index - img2->plugin_list_index);
1501 }
1502
1503 for (s1 = img1->name, s2 = img2->name; *s1 && *s2; s1++, s2++)
1504 {
1505 c1 = *s1;
1506 c2 = *s2;
1507
1508 if (0 == g_sort_case_sensitive)
1509 {
1510 if (grub_islower(c1))
1511 {
1512 c1 = c1 - 'a' + 'A';
1513 }
1514
1515 if (grub_islower(c2))
1516 {
1517 c2 = c2 - 'a' + 'A';
1518 }
1519 }
1520
1521 if (c1 != c2)
1522 {
1523 break;
1524 }
1525 }
1526
1527 return (c1 - c2);
1528 }
1529
1530 static int ventoy_cmp_subdir(img_iterator_node *node1, img_iterator_node *node2)
1531 {
1532 char *s1, *s2;
1533 int c1 = 0;
1534 int c2 = 0;
1535
1536 if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
1537 {
1538 return (node1->plugin_list_index - node2->plugin_list_index);
1539 }
1540
1541 for (s1 = node1->dir, s2 = node2->dir; *s1 && *s2; s1++, s2++)
1542 {
1543 c1 = *s1;
1544 c2 = *s2;
1545
1546 if (0 == g_sort_case_sensitive)
1547 {
1548 if (grub_islower(c1))
1549 {
1550 c1 = c1 - 'a' + 'A';
1551 }
1552
1553 if (grub_islower(c2))
1554 {
1555 c2 = c2 - 'a' + 'A';
1556 }
1557 }
1558
1559 if (c1 != c2)
1560 {
1561 break;
1562 }
1563 }
1564
1565 return (c1 - c2);
1566 }
1567
1568 void ventoy_swap_img(img_info *img1, img_info *img2)
1569 {
1570 grub_memcpy(&g_img_swap_tmp, img1, sizeof(img_info));
1571
1572 grub_memcpy(img1, img2, sizeof(img_info));
1573 img1->next = g_img_swap_tmp.next;
1574 img1->prev = g_img_swap_tmp.prev;
1575
1576 g_img_swap_tmp.next = img2->next;
1577 g_img_swap_tmp.prev = img2->prev;
1578 grub_memcpy(img2, &g_img_swap_tmp, sizeof(img_info));
1579 }
1580
1581 int ventoy_img_name_valid(const char *filename, grub_size_t namelen)
1582 {
1583 (void)namelen;
1584
1585 if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
1586 {
1587 return 0;
1588 }
1589
1590 return 1;
1591 }
1592
1593 static int ventoy_vlnk_iterate_partition(struct grub_disk *disk, const grub_partition_t partition, void *data)
1594 {
1595 ventoy_vlnk_part *node = NULL;
1596 grub_uint32_t SelfSig;
1597 grub_uint32_t *pSig = (grub_uint32_t *)data;
1598
1599 /* skip Ventoy partition 1/2 */
1600 grub_memcpy(&SelfSig, g_ventoy_part_info->MBR.BootCode + 0x1b8, 4);
1601 if (partition->number < 2 && SelfSig == *pSig)
1602 {
1603 return 0;
1604 }
1605
1606 node = grub_zalloc(sizeof(ventoy_vlnk_part));
1607 if (node)
1608 {
1609 node->disksig = *pSig;
1610 node->partoffset = (partition->start << GRUB_DISK_SECTOR_BITS);
1611 grub_snprintf(node->disk, sizeof(node->disk) - 1, "%s", disk->name);
1612 grub_snprintf(node->device, sizeof(node->device) - 1, "%s,%d", disk->name, partition->number + 1);
1613
1614 node->next = g_vlnk_part_list;
1615 g_vlnk_part_list = node;
1616 }
1617
1618 return 0;
1619 }
1620
1621 static int ventoy_vlnk_iterate_disk(const char *name, void *data)
1622 {
1623 grub_disk_t disk;
1624 grub_uint32_t sig;
1625
1626 (void)data;
1627
1628 disk = grub_disk_open(name);
1629 if (disk)
1630 {
1631 grub_disk_read(disk, 0, 0x1b8, 4, &sig);
1632 grub_partition_iterate(disk, ventoy_vlnk_iterate_partition, &sig);
1633 grub_disk_close(disk);
1634 }
1635
1636 return 0;
1637 }
1638
1639 static int ventoy_vlnk_probe_fs(ventoy_vlnk_part *cur)
1640 {
1641 const char *fs[ventoy_fs_max + 1] =
1642 {
1643 "exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
1644 };
1645
1646 if (!cur->dev)
1647 {
1648 cur->dev = grub_device_open(cur->device);
1649 }
1650
1651 if (cur->dev)
1652 {
1653 cur->fs = grub_fs_list_probe(cur->dev, fs);
1654 }
1655
1656 return 0;
1657 }
1658
1659 static int ventoy_check_vlnk_data(ventoy_vlnk *vlnk, int print, char *dst, int size)
1660 {
1661 int diskfind = 0;
1662 int partfind = 0;
1663 int filefind = 0;
1664 char *disk, *device;
1665 grub_uint32_t readcrc, calccrc;
1666 ventoy_vlnk_part *cur;
1667 grub_fs_t fs = NULL;
1668
1669 if (grub_memcmp(&(vlnk->guid), &g_ventoy_guid, sizeof(ventoy_guid)))
1670 {
1671 if (print)
1672 {
1673 grub_printf("VLNK invalid guid\n");
1674 grub_refresh();
1675 }
1676 return 1;
1677 }
1678
1679 readcrc = vlnk->crc32;
1680 vlnk->crc32 = 0;
1681 calccrc = grub_getcrc32c(0, vlnk, sizeof(ventoy_vlnk));
1682 if (readcrc != calccrc)
1683 {
1684 if (print)
1685 {
1686 grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc, readcrc);
1687 grub_refresh();
1688 }
1689 return 1;
1690 }
1691
1692 if (!g_vlnk_part_list)
1693 {
1694 grub_disk_dev_iterate(ventoy_vlnk_iterate_disk, NULL);
1695 }
1696
1697 for (cur = g_vlnk_part_list; cur && filefind == 0; cur = cur->next)
1698 {
1699 if (cur->disksig == vlnk->disk_signature)
1700 {
1701 diskfind = 1;
1702 disk = cur->disk;
1703 if (cur->partoffset == vlnk->part_offset)
1704 {
1705 partfind = 1;
1706 device = cur->device;
1707
1708 if (cur->probe == 0)
1709 {
1710 cur->probe = 1;
1711 ventoy_vlnk_probe_fs(cur);
1712 }
1713
1714 if (!fs)
1715 {
1716 fs = cur->fs;
1717 }
1718
1719 if (cur->fs)
1720 {
1721 struct grub_file file;
1722
1723 grub_memset(&file, 0, sizeof(file));
1724 file.device = cur->dev;
1725 if (cur->fs->fs_open(&file, vlnk->filepath) == GRUB_ERR_NONE)
1726 {
1727 filefind = 1;
1728 cur->fs->fs_close(&file);
1729 grub_snprintf(dst, size - 1, "(%s)%s", cur->device, vlnk->filepath);
1730 }
1731 }
1732 }
1733 }
1734 }
1735
1736 if (print)
1737 {
1738 grub_printf("\n==== VLNK Information ====\n"
1739 "Disk Signature: %08x\n"
1740 "Partition Offset: %llu\n"
1741 "File Path: <%s>\n\n",
1742 vlnk->disk_signature, (ulonglong)vlnk->part_offset, vlnk->filepath);
1743
1744 if (diskfind)
1745 {
1746 grub_printf("Disk Find: [ YES ] [ %s ]\n", disk);
1747 }
1748 else
1749 {
1750 grub_printf("Disk Find: [ NO ]\n");
1751 }
1752
1753 if (partfind)
1754 {
1755 grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device, fs ? fs->name : "N/A");
1756 }
1757 else
1758 {
1759 grub_printf("Part Find: [ NO ]\n");
1760 }
1761 grub_printf("File Find: [ %s ]\n", filefind ? "YES" : "NO");
1762 if (filefind)
1763 {
1764 grub_printf("VLNK File: <%s>\n", dst);
1765 }
1766
1767 grub_printf("\n");
1768 grub_refresh();
1769 }
1770
1771 return (1 - filefind);
1772 }
1773
1774 int ventoy_add_vlnk_file(char *dir, const char *name)
1775 {
1776 int rc = 1;
1777 char src[512];
1778 char dst[512];
1779 grub_file_t file = NULL;
1780 ventoy_vlnk vlnk;
1781
1782 if (!dir)
1783 {
1784 grub_snprintf(src, sizeof(src), "%s%s", g_iso_path, name);
1785 }
1786 else if (dir[0] == '/')
1787 {
1788 grub_snprintf(src, sizeof(src), "%s%s%s", g_iso_path, dir, name);
1789 }
1790 else
1791 {
1792 grub_snprintf(src, sizeof(src), "%s/%s%s", g_iso_path, dir, name);
1793 }
1794
1795 file = grub_file_open(src, VENTOY_FILE_TYPE);
1796 if (!file)
1797 {
1798 return 1;
1799 }
1800
1801 grub_memset(&vlnk, 0, sizeof(vlnk));
1802 grub_file_read(file, &vlnk, sizeof(vlnk));
1803 grub_file_close(file);
1804
1805 if (ventoy_check_vlnk_data(&vlnk, 0, dst, sizeof(dst)) == 0)
1806 {
1807 rc = grub_file_add_vlnk(src, dst);
1808 }
1809
1810 return rc;
1811 }
1812
1813 static int ventoy_collect_img_files(const char *filename, const struct grub_dirhook_info *info, void *data)
1814 {
1815 //int i = 0;
1816 int type = 0;
1817 int ignore = 0;
1818 int index = 0;
1819 int vlnk = 0;
1820 grub_size_t len;
1821 img_info *img;
1822 img_info *tail;
1823 const menu_tip *tip;
1824 img_iterator_node *tmp;
1825 img_iterator_node *new_node;
1826 img_iterator_node *node = (img_iterator_node *)data;
1827
1828 if (g_enumerate_time_checked == 0)
1829 {
1830 g_enumerate_finish_time_ms = grub_get_time_ms();
1831 if ((g_enumerate_finish_time_ms - g_enumerate_start_time_ms) >= 3000)
1832 {
1833 grub_cls();
1834 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1835 grub_refresh();
1836 g_enumerate_time_checked = 1;
1837 }
1838 }
1839
1840 len = grub_strlen(filename);
1841
1842 if (info->dir)
1843 {
1844 if (node->level + 1 > g_img_max_search_level)
1845 {
1846 return 0;
1847 }
1848
1849 if ((len == 1 && filename[0] == '.') ||
1850 (len == 2 && filename[0] == '.' && filename[1] == '.'))
1851 {
1852 return 0;
1853 }
1854
1855 if (!ventoy_img_name_valid(filename, len))
1856 {
1857 return 0;
1858 }
1859
1860 if (filename[0] == '$' && 0 == grub_strncmp(filename, "$RECYCLE.BIN", 12))
1861 {
1862 return 0;
1863 }
1864
1865 if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
1866 {
1867 grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s/", node->dir, filename);
1868 index = ventoy_plugin_get_image_list_index(vtoy_class_directory, g_img_swap_tmp_buf);
1869 if (index == 0)
1870 {
1871 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
1872 return 0;
1873 }
1874 }
1875
1876 new_node = grub_zalloc(sizeof(img_iterator_node));
1877 if (new_node)
1878 {
1879 new_node->level = node->level + 1;
1880 new_node->plugin_list_index = index;
1881 new_node->dirlen = grub_snprintf(new_node->dir, sizeof(new_node->dir), "%s%s/", node->dir, filename);
1882
1883 g_enum_fs->fs_dir(g_enum_dev, new_node->dir, ventoy_check_ignore_flag, &ignore);
1884 if (ignore)
1885 {
1886 debug("Directory %s ignored...\n", new_node->dir);
1887 grub_free(new_node);
1888 return 0;
1889 }
1890
1891 new_node->tail = node->tail;
1892
1893 new_node->parent = node;
1894 if (!node->firstchild)
1895 {
1896 node->firstchild = new_node;
1897 }
1898
1899 if (g_img_iterator_tail)
1900 {
1901 g_img_iterator_tail->next = new_node;
1902 g_img_iterator_tail = new_node;
1903 }
1904 else
1905 {
1906 g_img_iterator_head.next = new_node;
1907 g_img_iterator_tail = new_node;
1908 }
1909 }
1910 }
1911 else
1912 {
1913 debug("Find a file %s\n", filename);
1914 if (len < 4)
1915 {
1916 return 0;
1917 }
1918
1919 if (FILE_FLT(ISO) && 0 == grub_strcasecmp(filename + len - 4, ".iso"))
1920 {
1921 type = img_type_iso;
1922 }
1923 else if (FILE_FLT(WIM) && g_wimboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".wim")))
1924 {
1925 type = img_type_wim;
1926 }
1927 else if (FILE_FLT(VHD) && g_vhdboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".vhd") ||
1928 (len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vhdx"))))
1929 {
1930 type = img_type_vhd;
1931 }
1932 #ifdef GRUB_MACHINE_EFI
1933 else if (FILE_FLT(EFI) && 0 == grub_strcasecmp(filename + len - 4, ".efi"))
1934 {
1935 type = img_type_efi;
1936 }
1937 #endif
1938 else if (FILE_FLT(IMG) && 0 == grub_strcasecmp(filename + len - 4, ".img"))
1939 {
1940 if (len == 18 && grub_strncmp(filename, "ventoy_", 7) == 0)
1941 {
1942 if (grub_strncmp(filename + 7, "wimboot", 7) == 0 ||
1943 grub_strncmp(filename + 7, "vhdboot", 7) == 0)
1944 {
1945 return 0;
1946 }
1947 }
1948 type = img_type_img;
1949 }
1950 else if (FILE_FLT(VTOY) && len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vtoy"))
1951 {
1952 type = img_type_vtoy;
1953 }
1954 else if (len >= 9 && 0 == grub_strcasecmp(filename + len - 5, ".vcfg"))
1955 {
1956 if (filename[len - 9] == '.' || (len >= 10 && filename[len - 10] == '.'))
1957 {
1958 grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
1959 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf);
1960 }
1961 return 0;
1962 }
1963 else
1964 {
1965 return 0;
1966 }
1967
1968 if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
1969 {
1970 return 0;
1971 }
1972
1973 if (g_plugin_image_list)
1974 {
1975 grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
1976 index = ventoy_plugin_get_image_list_index(vtoy_class_image_file, g_img_swap_tmp_buf);
1977 if (VENTOY_IMG_WHITE_LIST == g_plugin_image_list && index == 0)
1978 {
1979 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
1980 return 0;
1981 }
1982 else if (VENTOY_IMG_BLACK_LIST == g_plugin_image_list && index > 0)
1983 {
1984 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf, index);
1985 return 0;
1986 }
1987 }
1988
1989 if (info->size == VTOY_FILT_MIN_FILE_SIZE || info->size == 0)
1990 {
1991 if (grub_file_is_vlnk_suffix(filename, len))
1992 {
1993 vlnk = 1;
1994 if (ventoy_add_vlnk_file(node->dir, filename) != 0)
1995 {
1996 return 0;
1997 }
1998 }
1999 }
2000
2001 img = grub_zalloc(sizeof(img_info));
2002 if (img)
2003 {
2004 img->type = type;
2005 img->plugin_list_index = index;
2006 grub_snprintf(img->name, sizeof(img->name), "%s", filename);
2007
2008 img->pathlen = grub_snprintf(img->path, sizeof(img->path), "%s%s", node->dir, img->name);
2009
2010 img->size = info->size;
2011 if (vlnk || 0 == img->size)
2012 {
2013 if (node->dir[0] == '/')
2014 {
2015 img->size = ventoy_grub_get_file_size("%s%s%s", g_iso_path, node->dir, filename);
2016 }
2017 else
2018 {
2019 img->size = ventoy_grub_get_file_size("%s/%s%s", g_iso_path, node->dir, filename);
2020 }
2021 }
2022
2023 if (img->size < VTOY_FILT_MIN_FILE_SIZE)
2024 {
2025 debug("img <%s> size too small %llu\n", img->name, (ulonglong)img->size);
2026 grub_free(img);
2027 return 0;
2028 }
2029
2030 if (g_ventoy_img_list)
2031 {
2032 tail = *(node->tail);
2033 img->prev = tail;
2034 tail->next = img;
2035 }
2036 else
2037 {
2038 g_ventoy_img_list = img;
2039 }
2040
2041 img->id = g_ventoy_img_count;
2042 img->parent = node;
2043 if (node && NULL == node->firstiso)
2044 {
2045 node->firstiso = img;
2046 }
2047
2048 node->isocnt++;
2049 tmp = node->parent;
2050 while (tmp)
2051 {
2052 tmp->isocnt++;
2053 tmp = tmp->parent;
2054 }
2055
2056 *((img_info **)(node->tail)) = img;
2057 g_ventoy_img_count++;
2058
2059 img->alias = ventoy_plugin_get_menu_alias(vtoy_alias_image_file, img->path);
2060
2061 tip = ventoy_plugin_get_menu_tip(vtoy_tip_image_file, img->path);
2062 if (tip)
2063 {
2064 img->tip1 = tip->tip1;
2065 img->tip2 = tip->tip2;
2066 }
2067
2068 img->class = ventoy_plugin_get_menu_class(vtoy_class_image_file, img->name, img->path);
2069 if (!img->class)
2070 {
2071 img->class = g_menu_class[type];
2072 }
2073 img->menu_prefix = g_menu_prefix[type];
2074
2075 if (img_type_iso == type)
2076 {
2077 if (ventoy_plugin_check_memdisk(img->path))
2078 {
2079 img->menu_prefix = "miso";
2080 }
2081 }
2082
2083 debug("Add %s%s to list %d\n", node->dir, filename, g_ventoy_img_count);
2084 }
2085 }
2086
2087 return 0;
2088 }
2089
2090 int ventoy_fill_data(grub_uint32_t buflen, char *buffer)
2091 {
2092 int len = GRUB_UINT_MAX;
2093 const char *value = NULL;
2094 char name[32] = {0};
2095 char plat[32] = {0};
2096 char guidstr[32] = {0};
2097 ventoy_guid guid = VENTOY_GUID;
2098 const char *fmt1 = NULL;
2099 const char *fmt2 = NULL;
2100 const char *fmt3 = NULL;
2101 grub_uint32_t *puint = (grub_uint32_t *)name;
2102 grub_uint32_t *puint2 = (grub_uint32_t *)plat;
2103 const char fmtdata[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
2104 const char fmtcode[]={
2105 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
2106 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
2107 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
2108 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
2109 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
2110 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
2111 };
2112
2113 grub_memset(name, 0, sizeof(name));
2114 puint[0] = grub_swap_bytes32(0x56454e54);
2115 puint[3] = grub_swap_bytes32(0x4f4e0000);
2116 puint[2] = grub_swap_bytes32(0x45525349);
2117 puint[1] = grub_swap_bytes32(0x4f595f56);
2118 value = ventoy_get_env(name);
2119
2120 grub_memset(name, 0, sizeof(name));
2121 puint[1] = grub_swap_bytes32(0x5f544f50);
2122 puint[0] = grub_swap_bytes32(0x56544c45);
2123 fmt1 = ventoy_get_env(name);
2124 if (!fmt1)
2125 {
2126 fmt1 = fmtdata;
2127 }
2128
2129 grub_memset(name, 0, sizeof(name));
2130 puint[1] = grub_swap_bytes32(0x5f4c4654);
2131 puint[0] = grub_swap_bytes32(0x56544c45);
2132 fmt2 = ventoy_get_env(name);
2133
2134 grub_memset(name, 0, sizeof(name));
2135 puint[1] = grub_swap_bytes32(0x5f434c52);
2136 puint[0] = grub_swap_bytes32(0x56544c45);
2137 fmt3 = ventoy_get_env(name);
2138
2139 grub_memcpy(guidstr, &guid, sizeof(guid));
2140
2141 puint2[0] = grub_swap_bytes32(g_ventoy_plat_data);
2142
2143 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
2144 #pragma GCC diagnostic push
2145 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
2146 len = grub_snprintf(buffer, buflen, fmtcode,
2147 fmt1 ? fmt1 : fmtdata,
2148 fmt2 ? fmt2 : fmtdata + 4,
2149 value ? value : "", plat, guidstr,
2150 fmt3 ? fmt3 : fmtdata + 6);
2151 #pragma GCC diagnostic pop
2152
2153 grub_memset(name, 0, sizeof(name));
2154 puint[0] = grub_swap_bytes32(0x76746f79);
2155 puint[2] = grub_swap_bytes32(0x656e7365);
2156 puint[1] = grub_swap_bytes32(0x5f6c6963);
2157 ventoy_set_env(name, guidstr);
2158
2159 return len;
2160 }
2161
2162 static int
2163 ventoy_password_get (char buf[], unsigned buf_size)
2164 {
2165 unsigned i, cur_len = 0;
2166 int key;
2167 struct grub_term_coordinate *pos = grub_term_save_pos ();
2168
2169 while (1)
2170 {
2171 key = grub_getkey ();
2172 if (key == '\n' || key == '\r')
2173 break;
2174
2175 if (key == GRUB_TERM_ESC)
2176 {
2177 cur_len = 0;
2178 break;
2179 }
2180
2181 if (key == '\b')
2182 {
2183 if (cur_len)
2184 {
2185 grub_term_restore_pos (pos);
2186 for (i = 0; i < cur_len; i++)
2187 grub_xputs (" ");
2188 grub_term_restore_pos (pos);
2189 cur_len--;
2190 for (i = 0; i < cur_len; i++)
2191 grub_xputs ("*");
2192 grub_refresh ();
2193 }
2194 continue;
2195 }
2196
2197 if (!grub_isprint (key))
2198 continue;
2199
2200 if (cur_len + 2 < buf_size)
2201 buf[cur_len++] = key;
2202 grub_xputs ("*");
2203 grub_refresh ();
2204 }
2205
2206 grub_memset (buf + cur_len, 0, buf_size - cur_len);
2207
2208 grub_xputs ("\n");
2209 grub_refresh ();
2210 grub_free (pos);
2211
2212 return (key != GRUB_TERM_ESC);
2213 }
2214
2215 static int ventoy_get_password(char buf[], unsigned buf_size)
2216 {
2217 const char *env = NULL;
2218
2219 env = grub_env_get("VTOY_SHOW_PASSWORD_ASTERISK");
2220 if (env && env[0] == '0' && env[1] == 0)
2221 {
2222 return grub_password_get(buf, buf_size);
2223 }
2224 else
2225 {
2226 return ventoy_password_get(buf, buf_size);
2227 }
2228 }
2229
2230 int ventoy_check_password(const vtoy_password *pwd, int retry)
2231 {
2232 int offset;
2233 char input[256];
2234 grub_uint8_t md5[16];
2235
2236 while (retry--)
2237 {
2238 grub_memset(input, 0, sizeof(input));
2239
2240 grub_printf("Enter password: ");
2241 grub_refresh();
2242
2243 if (pwd->type == VTOY_PASSWORD_TXT)
2244 {
2245 ventoy_get_password(input, 128);
2246 if (grub_strcmp(pwd->text, input) == 0)
2247 {
2248 return 0;
2249 }
2250 }
2251 else if (pwd->type == VTOY_PASSWORD_MD5)
2252 {
2253 ventoy_get_password(input, 128);
2254 grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
2255 if (grub_memcmp(pwd->md5, md5, 16) == 0)
2256 {
2257 return 0;
2258 }
2259 }
2260 else if (pwd->type == VTOY_PASSWORD_SALT_MD5)
2261 {
2262 offset = (int)grub_snprintf(input, 128, "%s", pwd->salt);
2263 ventoy_get_password(input + offset, 128);
2264
2265 grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
2266 if (grub_memcmp(pwd->md5, md5, 16) == 0)
2267 {
2268 return 0;
2269 }
2270 }
2271
2272 grub_printf("Invalid password!\n\n");
2273 grub_refresh();
2274 }
2275
2276 return 1;
2277 }
2278
2279 static img_info * ventoy_get_min_iso(img_iterator_node *node)
2280 {
2281 img_info *minimg = NULL;
2282 img_info *img = (img_info *)(node->firstiso);
2283
2284 while (img && (img_iterator_node *)(img->parent) == node)
2285 {
2286 if (img->select == 0 && (NULL == minimg || ventoy_cmp_img(img, minimg) < 0))
2287 {
2288 minimg = img;
2289 }
2290 img = img->next;
2291 }
2292
2293 if (minimg)
2294 {
2295 minimg->select = 1;
2296 }
2297
2298 return minimg;
2299 }
2300
2301 static img_iterator_node * ventoy_get_min_child(img_iterator_node *node)
2302 {
2303 img_iterator_node *Minchild = NULL;
2304 img_iterator_node *child = node->firstchild;
2305
2306 while (child && child->parent == node)
2307 {
2308 if (child->select == 0 && (NULL == Minchild || ventoy_cmp_subdir(child, Minchild) < 0))
2309 {
2310 Minchild = child;
2311 }
2312 child = child->next;
2313 }
2314
2315 if (Minchild)
2316 {
2317 Minchild->select = 1;
2318 }
2319
2320 return Minchild;
2321 }
2322
2323 static int ventoy_dynamic_tree_menu(img_iterator_node *node)
2324 {
2325 int offset = 1;
2326 img_info *img = NULL;
2327 const char *dir_class = NULL;
2328 const char *dir_alias = NULL;
2329 img_iterator_node *child = NULL;
2330 const menu_tip *tip = NULL;
2331
2332 if (node->isocnt == 0 || node->done == 1)
2333 {
2334 return 0;
2335 }
2336
2337 if (node->parent && node->parent->dirlen < node->dirlen)
2338 {
2339 offset = node->parent->dirlen;
2340 }
2341
2342 if (node == &g_img_iterator_head)
2343 {
2344 if (g_default_menu_mode == 0)
2345 {
2346 if (g_tree_view_menu_style == 0)
2347 {
2348 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2349 "menuentry \"%-10s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2350 " echo 'return ...' \n"
2351 "}\n", "<--", ventoy_get_vmenu_title("VTMENU_RET_TO_LISTVIEW"));
2352 }
2353 else
2354 {
2355 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2356 "menuentry \"[%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2357 " echo 'return ...' \n"
2358 "}\n", ventoy_get_vmenu_title("VTMENU_RET_TO_LISTVIEW"));
2359 }
2360 }
2361
2362 g_tree_script_pre = g_tree_script_pos;
2363 }
2364 else
2365 {
2366 node->dir[node->dirlen - 1] = 0;
2367 dir_class = ventoy_plugin_get_menu_class(vtoy_class_directory, node->dir, node->dir);
2368 if (!dir_class)
2369 {
2370 dir_class = "vtoydir";
2371 }
2372
2373 tip = ventoy_plugin_get_menu_tip(vtoy_tip_directory, node->dir);
2374
2375 dir_alias = ventoy_plugin_get_menu_alias(vtoy_alias_directory, node->dir);
2376 if (dir_alias)
2377 {
2378 if (g_tree_view_menu_style == 0)
2379 {
2380 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2381 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2382 "DIR", dir_alias, dir_class, node->dir + offset, tip);
2383 }
2384 else
2385 {
2386 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2387 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2388 dir_alias, dir_class, node->dir + offset, tip);
2389 }
2390 }
2391 else
2392 {
2393 dir_alias = node->dir + offset;
2394
2395 if (g_tree_view_menu_style == 0)
2396 {
2397 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2398 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2399 "DIR", dir_alias, dir_class, node->dir + offset, tip);
2400 }
2401 else
2402 {
2403 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2404 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" _VTIP_%p {\n",
2405 dir_alias, dir_class, node->dir + offset, tip);
2406 }
2407 }
2408
2409 if (g_tree_view_menu_style == 0)
2410 {
2411 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2412 "menuentry \"%-10s [%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2413 " echo 'return ...' \n"
2414 "}\n", "<--", node->dir);
2415 }
2416 else
2417 {
2418 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2419 "menuentry \"[%s/..]\" --class=\"vtoyret\" VTOY_RET {\n "
2420 " echo 'return ...' \n"
2421 "}\n", node->dir);
2422 }
2423 }
2424
2425 while ((child = ventoy_get_min_child(node)) != NULL)
2426 {
2427 ventoy_dynamic_tree_menu(child);
2428 }
2429
2430 while ((img = ventoy_get_min_iso(node)) != NULL)
2431 {
2432 if (g_tree_view_menu_style == 0)
2433 {
2434 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2435 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2436 " %s_%s \n"
2437 "}\n",
2438 grub_get_human_size(img->size, GRUB_HUMAN_SIZE_SHORT),
2439 img->unsupport ? "[***********] " : "",
2440 img->alias ? img->alias : img->name, img->class, img,
2441 img->menu_prefix,
2442 img->unsupport ? "unsupport_menuentry" : "common_menuentry");
2443 }
2444 else
2445 {
2446 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
2447 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2448 " %s_%s \n"
2449 "}\n",
2450 img->unsupport ? "[***********] " : "",
2451 img->alias ? img->alias : img->name, img->class, img,
2452 img->menu_prefix,
2453 img->unsupport ? "unsupport_menuentry" : "common_menuentry");
2454 }
2455 }
2456
2457 if (node != &g_img_iterator_head)
2458 {
2459 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "}\n");
2460 }
2461
2462 node->done = 1;
2463 return 0;
2464 }
2465
2466 static int ventoy_set_default_menu(void)
2467 {
2468 int img_len = 0;
2469 char *pos = NULL;
2470 char *end = NULL;
2471 char *def = NULL;
2472 const char *strdata = NULL;
2473 img_info *cur = NULL;
2474 img_info *default_node = NULL;
2475 const char *default_image = NULL;
2476
2477 default_image = ventoy_get_env("VTOY_DEFAULT_IMAGE");
2478 if (default_image && default_image[0] == '/')
2479 {
2480 img_len = grub_strlen(default_image);
2481
2482 for (cur = g_ventoy_img_list; cur; cur = cur->next)
2483 {
2484 if (img_len == cur->pathlen && grub_strcmp(default_image, cur->path) == 0)
2485 {
2486 default_node = cur;
2487 break;
2488 }
2489 }
2490
2491 if (!default_node)
2492 {
2493 return 1;
2494 }
2495
2496 if (0 == g_default_menu_mode)
2497 {
2498 vtoy_ssprintf(g_list_script_buf, g_list_script_pos, "set default='VID_%p'\n", default_node);
2499 }
2500 else
2501 {
2502 def = grub_strdup(default_image);
2503 if (!def)
2504 {
2505 return 1;
2506 }
2507
2508 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "set default=%c", '\'');
2509
2510 strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2511 if (strdata && strdata[0] == '/')
2512 {
2513 pos = def + grub_strlen(strdata);
2514 if (*pos == '/')
2515 {
2516 pos++;
2517 }
2518 }
2519 else
2520 {
2521 pos = def + 1;
2522 }
2523
2524 while ((end = grub_strchr(pos, '/')) != NULL)
2525 {
2526 *end = 0;
2527 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "DIR_%s>", pos);
2528 pos = end + 1;
2529 }
2530
2531 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "VID_%p'\n", default_node);
2532 grub_free(def);
2533 }
2534 }
2535
2536 return 0;
2537 }
2538
2539 static grub_err_t ventoy_cmd_clear_img(grub_extcmd_context_t ctxt, int argc, char **args)
2540 {
2541 img_info *next = NULL;
2542 img_info *cur = g_ventoy_img_list;
2543
2544 (void)ctxt;
2545 (void)argc;
2546 (void)args;
2547
2548 while (cur)
2549 {
2550 next = cur->next;
2551 grub_free(cur);
2552 cur = next;
2553 }
2554
2555 g_ventoy_img_list = NULL;
2556 g_ventoy_img_count = 0;
2557
2558 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2559 }
2560
2561 static grub_err_t ventoy_cmd_img_name(grub_extcmd_context_t ctxt, int argc, char **args)
2562 {
2563 long img_id = 0;
2564 img_info *cur = g_ventoy_img_list;
2565
2566 (void)ctxt;
2567
2568 if (argc != 2 || (!ventoy_is_decimal(args[0])))
2569 {
2570 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {imageID} {var}", cmd_raw_name);
2571 }
2572
2573 img_id = grub_strtol(args[0], NULL, 10);
2574 if (img_id >= g_ventoy_img_count)
2575 {
2576 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images %ld %ld", img_id, g_ventoy_img_count);
2577 }
2578
2579 debug("Find image %ld name \n", img_id);
2580
2581 while (cur && img_id > 0)
2582 {
2583 img_id--;
2584 cur = cur->next;
2585 }
2586
2587 if (!cur)
2588 {
2589 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images");
2590 }
2591
2592 debug("image name is %s\n", cur->name);
2593
2594 grub_env_set(args[1], cur->name);
2595
2596 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2597 }
2598
2599 static grub_err_t ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
2600 {
2601 int len = 0;
2602 char id[32] = {0};
2603 img_info *cur = g_ventoy_img_list;
2604
2605 (void)ctxt;
2606
2607 if (argc != 1)
2608 {
2609 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
2610 }
2611
2612 len = (int)grub_strlen(args[0]);
2613
2614 while (cur)
2615 {
2616 if (len == cur->pathlen && 0 == grub_strcmp(args[0], cur->path))
2617 {
2618 break;
2619 }
2620 cur = cur->next;
2621 }
2622
2623 if (!cur)
2624 {
2625 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
2626 }
2627
2628 grub_snprintf(id, sizeof(id), "VID_%p", cur);
2629 grub_env_set("chosen", id);
2630 grub_env_export("chosen");
2631
2632 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2633 }
2634
2635 static char g_fake_vlnk_src[512];
2636 static char g_fake_vlnk_dst[512];
2637 static grub_uint64_t g_fake_vlnk_size;
2638 static grub_err_t ventoy_cmd_set_fake_vlnk(grub_extcmd_context_t ctxt, int argc, char **args)
2639 {
2640 (void)ctxt;
2641 (void)argc;
2642 (void)args;
2643
2644 g_fake_vlnk_size = (grub_uint64_t)grub_strtoull(args[2], NULL, 10);
2645
2646 grub_strncpy(g_fake_vlnk_dst, args[0], sizeof(g_fake_vlnk_dst));
2647 grub_snprintf(g_fake_vlnk_src, sizeof(g_fake_vlnk_src), "%s/________VENTOYVLNK.vlnk.%s", g_iso_path, args[1]);
2648
2649 grub_file_vtoy_vlnk(g_fake_vlnk_src, g_fake_vlnk_dst);
2650
2651 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2652 }
2653
2654 static grub_err_t ventoy_cmd_reset_fake_vlnk(grub_extcmd_context_t ctxt, int argc, char **args)
2655 {
2656 (void)ctxt;
2657 (void)argc;
2658 (void)args;
2659
2660 g_fake_vlnk_src[0] = 0;
2661 g_fake_vlnk_dst[0] = 0;
2662 g_fake_vlnk_size = 0;
2663 grub_file_vtoy_vlnk(NULL, NULL);
2664
2665 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2666 }
2667
2668
2669 static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
2670 {
2671 char value[32];
2672 char *pos = NULL;
2673 char *last = NULL;
2674 const char *id = NULL;
2675 img_info *cur = NULL;
2676
2677 (void)ctxt;
2678
2679 if (argc < 1 || argc > 3)
2680 {
2681 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
2682 }
2683
2684 if (g_fake_vlnk_src[0] && g_fake_vlnk_dst[0])
2685 {
2686 pos = grub_strchr(g_fake_vlnk_src, '/');
2687 grub_env_set(args[0], pos);
2688 if (argc > 1)
2689 {
2690 grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(g_fake_vlnk_size));
2691 grub_env_set(args[1], value);
2692 }
2693
2694 if (argc > 2)
2695 {
2696 for (last = pos; *pos; pos++)
2697 {
2698 if (*pos == '/')
2699 {
2700 last = pos;
2701 }
2702 }
2703 grub_env_set(args[2], last + 1);
2704 }
2705
2706 goto end;
2707 }
2708
2709 id = grub_env_get("chosen");
2710
2711 pos = grub_strstr(id, "VID_");
2712 if (pos)
2713 {
2714 cur = (img_info *)(void *)grub_strtoul(pos + 4, NULL, 16);
2715 }
2716 else
2717 {
2718 cur = g_ventoy_img_list;
2719 }
2720
2721 if (!cur)
2722 {
2723 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
2724 }
2725
2726 grub_env_set(args[0], cur->path);
2727
2728 if (argc > 1)
2729 {
2730 grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size));
2731 grub_env_set(args[1], value);
2732 }
2733
2734 if (argc > 2)
2735 {
2736 grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size));
2737 grub_env_set(args[2], cur->name);
2738 }
2739
2740 end:
2741 g_svd_replace_offset = 0;
2742
2743 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2744 }
2745
2746
2747 static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char **args)
2748 {
2749 int len;
2750 grub_fs_t fs;
2751 grub_device_t dev = NULL;
2752 img_info *cur = NULL;
2753 img_info *tail = NULL;
2754 img_info *min = NULL;
2755 img_info *head = NULL;
2756 const char *strdata = NULL;
2757 char *device_name = NULL;
2758 char buf[32];
2759 img_iterator_node *node = NULL;
2760 img_iterator_node *tmp = NULL;
2761
2762 (void)ctxt;
2763
2764 if (argc != 2)
2765 {
2766 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {device} {cntvar}", cmd_raw_name);
2767 }
2768
2769 if (g_ventoy_img_list || g_ventoy_img_count)
2770 {
2771 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Must clear image before list");
2772 }
2773
2774 VTOY_CMD_CHECK(1);
2775
2776 g_enumerate_time_checked = 0;
2777 g_enumerate_start_time_ms = grub_get_time_ms();
2778
2779 strdata = ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2780 if (strdata && strdata[0] == '1' && strdata[1] == 0)
2781 {
2782 g_filt_dot_underscore_file = 1;
2783 }
2784
2785 strdata = ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2786 if (strdata && strdata[0] == '1' && strdata[1] == 0)
2787 {
2788 g_sort_case_sensitive = 1;
2789 }
2790
2791 device_name = grub_file_get_device_name(args[0]);
2792 if (!device_name)
2793 {
2794 goto fail;
2795 }
2796
2797 g_enum_dev = dev = grub_device_open(device_name);
2798 if (!dev)
2799 {
2800 goto fail;
2801 }
2802
2803 g_enum_fs = fs = grub_fs_probe(dev);
2804 if (!fs)
2805 {
2806 goto fail;
2807 }
2808
2809 if (ventoy_get_fs_type(fs->name) >= ventoy_fs_max)
2810 {
2811 debug("unsupported fs:<%s>\n", fs->name);
2812 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2813 goto fail;
2814 }
2815
2816 ventoy_set_env("vtoy_iso_fs", fs->name);
2817
2818 strdata = ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2819 if (strdata && strdata[0] == '1')
2820 {
2821 g_default_menu_mode = 1;
2822 }
2823
2824 grub_memset(&g_img_iterator_head, 0, sizeof(g_img_iterator_head));
2825
2826 grub_snprintf(g_iso_path, sizeof(g_iso_path), "%s", args[0]);
2827
2828 strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2829 if (strdata && strdata[0] == '/')
2830 {
2831 len = grub_snprintf(g_img_iterator_head.dir, sizeof(g_img_iterator_head.dir) - 1, "%s", strdata);
2832 if (g_img_iterator_head.dir[len - 1] != '/')
2833 {
2834 g_img_iterator_head.dir[len++] = '/';
2835 }
2836 g_img_iterator_head.dirlen = len;
2837 }
2838 else
2839 {
2840 g_img_iterator_head.dirlen = 1;
2841 grub_strcpy(g_img_iterator_head.dir, "/");
2842 }
2843
2844 g_img_iterator_head.tail = &tail;
2845
2846 if (g_img_max_search_level < 0)
2847 {
2848 g_img_max_search_level = GRUB_INT_MAX;
2849 strdata = ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2850 if (strdata && ventoy_is_decimal(strdata))
2851 {
2852 g_img_max_search_level = (int)grub_strtoul(strdata, NULL, 10);
2853 }
2854 }
2855
2856 g_vtoy_file_flt[VTOY_FILE_FLT_ISO] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2857 g_vtoy_file_flt[VTOY_FILE_FLT_WIM] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2858 g_vtoy_file_flt[VTOY_FILE_FLT_EFI] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2859 g_vtoy_file_flt[VTOY_FILE_FLT_IMG] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2860 g_vtoy_file_flt[VTOY_FILE_FLT_VHD] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2861 g_vtoy_file_flt[VTOY_FILE_FLT_VTOY] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2862
2863 for (node = &g_img_iterator_head; node; node = node->next)
2864 {
2865 fs->fs_dir(dev, node->dir, ventoy_collect_img_files, node);
2866 }
2867
2868 strdata = ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2869 if (strdata && strdata[0] == '1' && strdata[1] == 0)
2870 {
2871 g_tree_view_menu_style = 1;
2872 }
2873
2874 ventoy_set_default_menu();
2875
2876 for (node = &g_img_iterator_head; node; node = node->next)
2877 {
2878 ventoy_dynamic_tree_menu(node);
2879 }
2880
2881 /* free node */
2882 node = g_img_iterator_head.next;
2883 while (node)
2884 {
2885 tmp = node->next;
2886 grub_free(node);
2887 node = tmp;
2888 }
2889
2890 /* sort image list by image name */
2891 while (g_ventoy_img_list)
2892 {
2893 min = g_ventoy_img_list;
2894 for (cur = g_ventoy_img_list->next; cur; cur = cur->next)
2895 {
2896 if (ventoy_cmp_img(min, cur) > 0)
2897 {
2898 min = cur;
2899 }
2900 }
2901
2902 if (min->prev)
2903 {
2904 min->prev->next = min->next;
2905 }
2906
2907 if (min->next)
2908 {
2909 min->next->prev = min->prev;
2910 }
2911
2912 if (min == g_ventoy_img_list)
2913 {
2914 g_ventoy_img_list = min->next;
2915 }
2916
2917 if (head == NULL)
2918 {
2919 head = tail = min;
2920 min->prev = NULL;
2921 min->next = NULL;
2922 }
2923 else
2924 {
2925 tail->next = min;
2926 min->prev = tail;
2927 min->next = NULL;
2928 tail = min;
2929 }
2930 }
2931
2932 g_ventoy_img_list = head;
2933
2934 if (g_default_menu_mode == 1)
2935 {
2936 vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
2937 "menuentry \"%s [%s]\" --class=\"vtoyret\" VTOY_RET {\n "
2938 " echo 'return ...' \n"
2939 "}\n", "<--", ventoy_get_vmenu_title("VTMENU_RET_TO_TREEVIEW"));
2940 }
2941
2942 for (cur = g_ventoy_img_list; cur; cur = cur->next)
2943 {
2944 vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
2945 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%p\" {\n"
2946 " %s_%s \n"
2947 "}\n",
2948 cur->unsupport ? "[***********] " : "",
2949 cur->alias ? cur->alias : cur->name, cur->class, cur,
2950 cur->menu_prefix,
2951 cur->unsupport ? "unsupport_menuentry" : "common_menuentry");
2952 }
2953
2954 g_tree_script_buf[g_tree_script_pos] = 0;
2955 g_list_script_buf[g_list_script_pos] = 0;
2956
2957 grub_snprintf(buf, sizeof(buf), "%d", g_ventoy_img_count);
2958 grub_env_set(args[1], buf);
2959
2960 fail:
2961
2962 check_free(device_name, grub_free);
2963 check_free(dev, grub_device_close);
2964
2965 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2966 }
2967
2968 int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t *signature)
2969 {
2970 grub_disk_t disk;
2971 char *device_name;
2972 char *pos;
2973 char *pos2;
2974
2975 device_name = grub_file_get_device_name(filename);
2976 if (!device_name)
2977 {
2978 return 1;
2979 }
2980
2981 pos = device_name;
2982 if (pos[0] == '(')
2983 {
2984 pos++;
2985 }
2986
2987 pos2 = grub_strstr(pos, ",");
2988 if (!pos2)
2989 {
2990 pos2 = grub_strstr(pos, ")");
2991 }
2992
2993 if (pos2)
2994 {
2995 *pos2 = 0;
2996 }
2997
2998 disk = grub_disk_open(pos);
2999 if (disk)
3000 {
3001 grub_disk_read(disk, 0, 0x180, 16, guid);
3002 grub_disk_read(disk, 0, 0x1b8, 4, signature);
3003 grub_disk_close(disk);
3004 }
3005 else
3006 {
3007 return 1;
3008 }
3009
3010 grub_free(device_name);
3011 return 0;
3012 }
3013
3014 grub_uint32_t ventoy_get_iso_boot_catlog(grub_file_t file)
3015 {
3016 eltorito_descriptor desc;
3017
3018 grub_memset(&desc, 0, sizeof(desc));
3019 grub_file_seek(file, 17 * 2048);
3020 grub_file_read(file, &desc, sizeof(desc));
3021
3022 if (desc.type != 0 || desc.version != 1)
3023 {
3024 return 0;
3025 }
3026
3027 if (grub_strncmp((char *)desc.id, "CD001", 5) != 0 ||
3028 grub_strncmp((char *)desc.system_id, "EL TORITO SPECIFICATION", 23) != 0)
3029 {
3030 return 0;
3031 }
3032
3033 return desc.sector;
3034 }
3035
3036 static grub_uint32_t ventoy_get_bios_eltorito_rba(grub_file_t file, grub_uint32_t sector)
3037 {
3038 grub_uint8_t buf[512];
3039
3040 grub_file_seek(file, sector * 2048);
3041 grub_file_read(file, buf, sizeof(buf));
3042
3043 if (buf[0] == 0x01 && buf[1] == 0x00 &&
3044 buf[30] == 0x55 && buf[31] == 0xaa && buf[32] == 0x88)
3045 {
3046 return *((grub_uint32_t *)(buf + 40));
3047 }
3048
3049 return 0;
3050 }
3051
3052 int ventoy_has_efi_eltorito(grub_file_t file, grub_uint32_t sector)
3053 {
3054 int i;
3055 int x86count = 0;
3056 grub_uint8_t buf[512];
3057 grub_uint8_t parttype[] = { 0x04, 0x06, 0x0B, 0x0C };
3058
3059 grub_file_seek(file, sector * 2048);
3060 grub_file_read(file, buf, sizeof(buf));
3061
3062 if (buf[0] == 0x01 && buf[1] == 0xEF)
3063 {
3064 debug("%s efi eltorito in Validation Entry\n", file->name);
3065 return 1;
3066 }
3067
3068 if (buf[0] == 0x01 && buf[1] == 0x00)
3069 {
3070 x86count++;
3071 }
3072
3073 for (i = 64; i < (int)sizeof(buf); i += 32)
3074 {
3075 if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF)
3076 {
3077 debug("%s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
3078 return 1;
3079 }
3080
3081 if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0x00 && x86count == 1)
3082 {
3083 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
3084 return 1;
3085 }
3086 }
3087
3088 if (x86count && buf[32] == 0x88 && buf[33] == 0x04)
3089 {
3090 for (i = 0; i < (int)(ARRAY_SIZE(parttype)); i++)
3091 {
3092 if (buf[36] == parttype[i])
3093 {
3094 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file->name, buf[36]);
3095 return 1;
3096 }
3097 }
3098 }
3099
3100 debug("%s does not contain efi eltorito\n", file->name);
3101 return 0;
3102 }
3103
3104 void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
3105 {
3106 char *pos;
3107 const char *fs = NULL;
3108 const char *val = NULL;
3109 const char *cdprompt = NULL;
3110 grub_uint32_t i;
3111 grub_uint8_t chksum = 0;
3112 grub_disk_t disk;
3113
3114 disk = file->device->disk;
3115 grub_memcpy(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid));
3116
3117 param->vtoy_disk_size = disk->total_sectors * (1 << disk->log_sector_size);
3118 param->vtoy_disk_part_id = disk->partition->number + 1;
3119 param->vtoy_disk_part_type = ventoy_get_fs_type(file->fs->name);
3120
3121 pos = grub_strstr(file->name, "/");
3122 if (!pos)
3123 {
3124 pos = file->name;
3125 }
3126
3127 grub_snprintf(param->vtoy_img_path, sizeof(param->vtoy_img_path), "%s", pos);
3128
3129 ventoy_get_disk_guid(file->name, param->vtoy_disk_guid, param->vtoy_disk_signature);
3130
3131 param->vtoy_img_size = file->size;
3132
3133 param->vtoy_reserved[0] = g_ventoy_break_level;
3134 param->vtoy_reserved[1] = g_ventoy_debug_level;
3135
3136 param->vtoy_reserved[2] = g_ventoy_chain_type;
3137
3138 /* Windows CD/DVD prompt 0:suppress 1:reserved */
3139 param->vtoy_reserved[4] = 0;
3140 if (g_ventoy_chain_type == 1) /* Windows */
3141 {
3142 cdprompt = ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
3143 if (cdprompt && cdprompt[0] == '1' && cdprompt[1] == 0)
3144 {
3145 param->vtoy_reserved[4] = 1;
3146 }
3147 }
3148
3149 fs = ventoy_get_env("ventoy_fs_probe");
3150 if (fs && grub_strcmp(fs, "udf") == 0)
3151 {
3152 param->vtoy_reserved[3] = 1;
3153 }
3154
3155 param->vtoy_reserved[5] = 0;
3156 val = ventoy_get_env("VTOY_LINUX_REMOUNT");
3157 if (val && val[0] == '1' && val[1] == 0)
3158 {
3159 param->vtoy_reserved[5] = 1;
3160 }
3161
3162 /* ventoy_disk_signature used for vlnk */
3163 param->vtoy_reserved[6] = file->vlnk;
3164 grub_memcpy(param->vtoy_reserved + 7, g_ventoy_part_info->MBR.BootCode + 0x1b8, 4);
3165
3166 /* calculate checksum */
3167 for (i = 0; i < sizeof(ventoy_os_param); i++)
3168 {
3169 chksum += *((grub_uint8_t *)param + i);
3170 }
3171 param->chksum = (grub_uint8_t)(0x100 - chksum);
3172
3173 return;
3174 }
3175
3176 int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
3177 {
3178 grub_uint32_t i = 0;
3179 grub_uint64_t total = 0;
3180 grub_uint64_t fileblk = 0;
3181 ventoy_img_chunk *chunk = NULL;
3182
3183 for (i = 0; i < chunklist->cur_chunk; i++)
3184 {
3185 chunk = chunklist->chunk + i;
3186
3187 if (chunk->disk_start_sector <= start)
3188 {
3189 debug("%u disk start invalid %lu\n", i, (ulong)start);
3190 return 1;
3191 }
3192
3193 total += chunk->disk_end_sector + 1 - chunk->disk_start_sector;
3194 }
3195
3196 fileblk = (file->size + 511) / 512;
3197
3198 if (total != fileblk)
3199 {
3200 debug("Invalid total: %llu %llu\n", (ulonglong)total, (ulonglong)fileblk);
3201 if ((file->size % 512) && (total + 1 == fileblk))
3202 {
3203 debug("maybe img file to be processed.\n");
3204 return 0;
3205 }
3206
3207 return 1;
3208 }
3209
3210 return 0;
3211 }
3212
3213 int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
3214 {
3215 int fs_type;
3216 int len;
3217 grub_uint32_t i = 0;
3218 grub_uint32_t sector = 0;
3219 grub_uint32_t count = 0;
3220 grub_off_t size = 0;
3221 grub_off_t read = 0;
3222
3223 fs_type = ventoy_get_fs_type(file->fs->name);
3224 if (fs_type == ventoy_fs_exfat)
3225 {
3226 grub_fat_get_file_chunk(start, file, chunklist);
3227 }
3228 else if (fs_type == ventoy_fs_ext)
3229 {
3230 grub_ext_get_file_chunk(start, file, chunklist);
3231 }
3232 else
3233 {
3234 file->read_hook = (grub_disk_read_hook_t)(void *)grub_disk_blocklist_read;
3235 file->read_hook_data = chunklist;
3236
3237 for (size = file->size; size > 0; size -= read)
3238 {
3239 read = (size > VTOY_SIZE_1GB) ? VTOY_SIZE_1GB : size;
3240 grub_file_read(file, NULL, read);
3241 }
3242
3243 for (i = 0; start > 0 && i < chunklist->cur_chunk; i++)
3244 {
3245 chunklist->chunk[i].disk_start_sector += start;
3246 chunklist->chunk[i].disk_end_sector += start;
3247 }
3248
3249 if (ventoy_fs_udf == fs_type)
3250 {
3251 for (i = 0; i < chunklist->cur_chunk; i++)
3252 {
3253 count = (chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector) >> 2;
3254 chunklist->chunk[i].img_start_sector = sector;
3255 chunklist->chunk[i].img_end_sector = sector + count - 1;
3256 sector += count;
3257 }
3258 }
3259 }
3260
3261 len = (int)grub_strlen(file->name);
3262 if ((len > 4 && grub_strncasecmp(file->name + len - 4, ".img", 4) == 0) ||
3263 (len > 4 && grub_strncasecmp(file->name + len - 4, ".vhd", 4) == 0) ||
3264 (len > 5 && grub_strncasecmp(file->name + len - 5, ".vhdx", 5) == 0) ||
3265 (len > 5 && grub_strncasecmp(file->name + len - 5, ".vtoy", 5) == 0))
3266 {
3267 for (i = 0; i < chunklist->cur_chunk; i++)
3268 {
3269 count = chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector;
3270 if (count < 4)
3271 {
3272 count = 1;
3273 }
3274 else
3275 {
3276 count >>= 2;
3277 }
3278
3279 chunklist->chunk[i].img_start_sector = sector;
3280 chunklist->chunk[i].img_end_sector = sector + count - 1;
3281 sector += count;
3282 }
3283 }
3284
3285 return 0;
3286 }
3287
3288 static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
3289 {
3290 int rc;
3291 grub_file_t file;
3292 grub_disk_addr_t start;
3293
3294 (void)ctxt;
3295 (void)argc;
3296
3297 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3298 if (!file)
3299 {
3300 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
3301 }
3302
3303 g_conf_replace_count = 0;
3304 grub_memset(g_conf_replace_node, 0, sizeof(g_conf_replace_node ));
3305 grub_memset(g_conf_replace_offset, 0, sizeof(g_conf_replace_offset ));
3306
3307 if (g_img_chunk_list.chunk)
3308 {
3309 grub_free(g_img_chunk_list.chunk);
3310 }
3311
3312 if (ventoy_get_fs_type(file->fs->name) >= ventoy_fs_max)
3313 {
3314 grub_file_close(file);
3315 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Unsupported filesystem %s\n", file->fs->name);
3316 }
3317
3318 /* get image chunk data */
3319 grub_memset(&g_img_chunk_list, 0, sizeof(g_img_chunk_list));
3320 g_img_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
3321 if (NULL == g_img_chunk_list.chunk)
3322 {
3323 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
3324 }
3325
3326 g_img_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
3327 g_img_chunk_list.cur_chunk = 0;
3328
3329 start = file->device->disk->partition->start;
3330
3331 ventoy_get_block_list(file, &g_img_chunk_list, start);
3332
3333 rc = ventoy_check_block_list(file, &g_img_chunk_list, start);
3334 grub_file_close(file);
3335
3336 if (rc)
3337 {
3338 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported chunk list.\n");
3339 }
3340
3341 grub_memset(&g_grub_param->file_replace, 0, sizeof(g_grub_param->file_replace));
3342 grub_memset(&g_grub_param->img_replace, 0, sizeof(g_grub_param->img_replace));
3343 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3344 }
3345
3346 static grub_err_t ventoy_select_conf_replace(grub_extcmd_context_t ctxt, int argc, char **args)
3347 {
3348 int i;
3349 int n;
3350 grub_uint64_t offset = 0;
3351 grub_uint32_t align = 0;
3352 grub_file_t file = NULL;
3353 conf_replace *node = NULL;
3354 conf_replace *nodes[VTOY_MAX_CONF_REPLACE] = { NULL };
3355 ventoy_grub_param_file_replace *replace = NULL;
3356
3357 (void)ctxt;
3358 (void)argc;
3359 (void)args;
3360
3361 debug("select conf replace argc:%d\n", argc);
3362
3363 if (argc < 2)
3364 {
3365 return 0;
3366 }
3367
3368 n = ventoy_plugin_find_conf_replace(args[1], nodes);
3369 if (!n)
3370 {
3371 debug("Conf replace not found for %s\n", args[1]);
3372 goto end;
3373 }
3374
3375 debug("Find %d conf replace for %s\n", n, args[1]);
3376
3377 g_conf_replace_count = n;
3378 for (i = 0; i < n; i++)
3379 {
3380 node = nodes[i];
3381
3382 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", node->orgconf);
3383 if (file)
3384 {
3385 offset = grub_iso9660_get_last_file_dirent_pos(file);
3386 grub_file_close(file);
3387 }
3388 else if (node->img > 0)
3389 {
3390 offset = 0;
3391 }
3392 else
3393 {
3394 debug("<(loop)%s> NOT exist\n", node->orgconf);
3395 continue;
3396 }
3397
3398 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], node->newconf);
3399 if (!file)
3400 {
3401 debug("New config file <%s%s> NOT exist\n", args[0], node->newconf);
3402 continue;
3403 }
3404
3405 align = ((int)file->size + 2047) / 2048 * 2048;
3406
3407 if (align > vtoy_max_replace_file_size)
3408 {
3409 debug("New config file <%s%s> too big\n", args[0], node->newconf);
3410 grub_file_close(file);
3411 continue;
3412 }
3413
3414 grub_file_read(file, g_conf_replace_new_buf[i], file->size);
3415 grub_file_close(file);
3416 g_conf_replace_new_len[i] = (int)file->size;
3417 g_conf_replace_new_len_align[i] = align;
3418
3419 g_conf_replace_node[i] = node;
3420 g_conf_replace_offset[i] = offset + 2;
3421
3422 if (node->img > 0)
3423 {
3424 replace = &(g_grub_param->img_replace[i]);
3425 replace->magic = GRUB_IMG_REPLACE_MAGIC;
3426 grub_snprintf(replace->old_file_name[replace->old_name_cnt], 256, "%s", node->orgconf);
3427 replace->old_name_cnt++;
3428 }
3429
3430 debug("conf_replace OK: newlen[%d]: %d img:%d\n", i, g_conf_replace_new_len[i], node->img);
3431 }
3432
3433 end:
3434 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3435 }
3436
3437 static int ventoy_var_expand(int *record, int *flag, const char *var, char *expand, int len)
3438 {
3439 int i = 0;
3440 int n = 0;
3441 char c;
3442 const char *ch = var;
3443
3444 *record = 0;
3445 expand[0] = 0;
3446
3447 while (*ch)
3448 {
3449 if (*ch == '_' || (*ch >= '0' && *ch <= '9') || (*ch >= 'A' && *ch <= 'Z') || (*ch >= 'a' && *ch <= 'z'))
3450 {
3451 ch++;
3452 n++;
3453 }
3454 else
3455 {
3456 debug("Invalid variable letter <%c>\n", *ch);
3457 goto end;
3458 }
3459 }
3460
3461 if (n > 32)
3462 {
3463 debug("Invalid variable length:%d <%s>\n", n, var);
3464 goto end;
3465 }
3466
3467 if (grub_strncmp(var, "VT_", 3) == 0) /* built-in variables */
3468 {
3469
3470 }
3471 else
3472 {
3473 if (*flag == 0)
3474 {
3475 *flag = 1;
3476 grub_printf("\n=================== Variables Expansion ===================\n\n");
3477 }
3478
3479 grub_printf("<%s>: ", var);
3480 grub_refresh();
3481
3482 while (i < (len - 1))
3483 {
3484 c = grub_getkey();
3485 if ((c == '\n') || (c == '\r'))
3486 {
3487 if (i > 0)
3488 {
3489 grub_printf("\n");
3490 grub_refresh();
3491 *record = 1;
3492 break;
3493 }
3494 }
3495 else if (grub_isprint(c))
3496 {
3497 if (i + 1 < (len - 1))
3498 {
3499 grub_printf("%c", c);
3500 grub_refresh();
3501 expand[i++] = c;
3502 expand[i] = 0;
3503 }
3504 }
3505 else if (c == '\b')
3506 {
3507 if (i > 0)
3508 {
3509 expand[i - 1] = ' ';
3510 grub_printf("\r<%s>: %s", var, expand);
3511
3512 expand[i - 1] = 0;
3513 grub_printf("\r<%s>: %s", var, expand);
3514
3515 grub_refresh();
3516 i--;
3517 }
3518 }
3519 }
3520 }
3521
3522 end:
3523 if (expand[0] == 0)
3524 {
3525 grub_snprintf(expand, len, "$$%s$$", var);
3526 }
3527
3528 return 0;
3529 }
3530
3531 static int ventoy_auto_install_var_expand(install_template *node)
3532 {
3533 int pos = 0;
3534 int flag = 0;
3535 int record = 0;
3536 int newlen = 0;
3537 char *start = NULL;
3538 char *end = NULL;
3539 char *newbuf = NULL;
3540 char *curline = NULL;
3541 char *nextline = NULL;
3542 grub_uint8_t *code = NULL;
3543 char value[512];
3544 var_node *CurNode = NULL;
3545 var_node *pVarList = NULL;
3546
3547 code = (grub_uint8_t *)node->filebuf;
3548
3549 if (node->filelen >= VTOY_SIZE_1MB)
3550 {
3551 debug("auto install script too long %d\n", node->filelen);
3552 return 0;
3553 }
3554
3555 if ((code[0] == 0xff && code[1] == 0xfe) || (code[0] == 0xfe && code[1] == 0xff))
3556 {
3557 debug("UCS-2 encoding NOT supported\n");
3558 return 0;
3559 }
3560
3561 start = grub_strstr(node->filebuf, "$$");
3562 if (!start)
3563 {
3564 debug("no need to expand variable, no start.\n");
3565 return 0;
3566 }
3567
3568 end = grub_strstr(start + 2, "$$");
3569 if (!end)
3570 {
3571 debug("no need to expand variable, no end.\n");
3572 return 0;
3573 }
3574
3575 newlen = grub_max(node->filelen * 10, VTOY_SIZE_128KB);
3576 newbuf = grub_malloc(newlen);
3577 if (!newbuf)
3578 {
3579 debug("Failed to alloc newbuf %d\n", newlen);
3580 return 0;
3581 }
3582
3583 for (curline = node->filebuf; curline; curline = nextline)
3584 {
3585 nextline = ventoy_get_line(curline);
3586
3587 start = grub_strstr(curline, "$$");
3588 if (start)
3589 {
3590 end = grub_strstr(start + 2, "$$");
3591 }
3592
3593 if (start && end)
3594 {
3595 *start = *end = 0;
3596 VTOY_APPEND_NEWBUF(curline);
3597
3598 for (CurNode = pVarList; CurNode; CurNode = CurNode->next)
3599 {
3600 if (grub_strcmp(start + 2, CurNode->var) == 0)
3601 {
3602 grub_snprintf(value, sizeof(value) - 1, "%s", CurNode->val);
3603 break;
3604 }
3605 }
3606
3607 if (!CurNode)
3608 {
3609 value[sizeof(value) - 1] = 0;
3610 ventoy_var_expand(&record, &flag, start + 2, value, sizeof(value) - 1);
3611
3612 if (record)
3613 {
3614 CurNode = grub_zalloc(sizeof(var_node));
3615 if (CurNode)
3616 {
3617 grub_snprintf(CurNode->var, sizeof(CurNode->var), "%s", start + 2);
3618 grub_snprintf(CurNode->val, sizeof(CurNode->val), "%s", value);
3619 CurNode->next = pVarList;
3620 pVarList = CurNode;
3621 }
3622 }
3623 }
3624
3625 VTOY_APPEND_NEWBUF(value);
3626
3627 VTOY_APPEND_NEWBUF(end + 2);
3628 }
3629 else
3630 {
3631 VTOY_APPEND_NEWBUF(curline);
3632 }
3633
3634 if (pos > 0 && newbuf[pos - 1] == '\r')
3635 {
3636 newbuf[pos - 1] = '\n';
3637 }
3638 else
3639 {
3640 newbuf[pos++] = '\n';
3641 }
3642 }
3643
3644 grub_free(node->filebuf);
3645 node->filebuf = newbuf;
3646 node->filelen = pos;
3647
3648 while (pVarList)
3649 {
3650 CurNode = pVarList->next;
3651 grub_free(pVarList);
3652 pVarList = CurNode;
3653 }
3654
3655 return 0;
3656 }
3657
3658 static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
3659 {
3660 int i = 0;
3661 int pos = 0;
3662 int defidx = 1;
3663 char *buf = NULL;
3664 grub_file_t file = NULL;
3665 char configfile[128];
3666 install_template *node = NULL;
3667
3668 (void)ctxt;
3669 (void)argc;
3670 (void)args;
3671
3672 debug("select auto installation argc:%d\n", argc);
3673
3674 if (argc < 1)
3675 {
3676 return 0;
3677 }
3678
3679 node = ventoy_plugin_find_install_template(args[0]);
3680 if (!node)
3681 {
3682 debug("Auto install template not found for %s\n", args[0]);
3683 return 0;
3684 }
3685
3686 if (node->autosel >= 0 && node->autosel <= node->templatenum)
3687 {
3688 defidx = node->autosel;
3689 if (node->timeout < 0)
3690 {
3691 node->cursel = node->autosel - 1;
3692 debug("Auto install template auto select %d\n", node->autosel);
3693 goto load;
3694 }
3695 }
3696
3697 buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
3698 if (!buf)
3699 {
3700 return 0;
3701 }
3702
3703 if (node->timeout > 0)
3704 {
3705 vtoy_ssprintf(buf, pos, "set timeout=%d\n", node->timeout);
3706 }
3707
3708 vtoy_ssprintf(buf, pos, "menuentry \"@VTMENU_NO_AUTOINS_SCRIPT\" --class=\"sel_auto_install\" {\n"
3709 " echo %s\n}\n", "");
3710
3711 for (i = 0; i < node->templatenum; i++)
3712 {
3713 vtoy_ssprintf(buf, pos, "menuentry \"%s %s\" --class=\"sel_auto_install\" {\n"
3714 " echo \"\"\n}\n",
3715 ventoy_get_vmenu_title("VTMENU_AUTOINS_USE"),
3716 node->templatepath[i].path);
3717 }
3718
3719 g_ventoy_menu_esc = 1;
3720 g_ventoy_suppress_esc = 1;
3721 g_ventoy_suppress_esc_default = defidx;
3722
3723 grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
3724 grub_script_execute_sourcecode(configfile);
3725
3726 g_ventoy_menu_esc = 0;
3727 g_ventoy_suppress_esc = 0;
3728 g_ventoy_suppress_esc_default = 1;
3729
3730 grub_free(buf);
3731
3732 node->cursel = g_ventoy_last_entry - 1;
3733
3734 load:
3735 grub_check_free(node->filebuf);
3736 node->filelen = 0;
3737
3738 if (node->cursel >= 0 && node->cursel < node->templatenum)
3739 {
3740 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", ventoy_get_env("vtoy_iso_part"),
3741 node->templatepath[node->cursel].path);
3742 if (file)
3743 {
3744 node->filebuf = grub_malloc(file->size + 8);
3745 if (node->filebuf)
3746 {
3747 grub_file_read(file, node->filebuf, file->size);
3748 grub_file_close(file);
3749
3750 grub_memset(node->filebuf + file->size, 0, 8);
3751 node->filelen = (int)file->size;
3752
3753 ventoy_auto_install_var_expand(node);
3754 }
3755 }
3756 else
3757 {
3758 debug("Failed to open auto install script <%s%s>\n",
3759 ventoy_get_env("vtoy_iso_part"), node->templatepath[node->cursel].path);
3760 }
3761 }
3762
3763 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3764 }
3765
3766 static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
3767 {
3768 int i = 0;
3769 int pos = 0;
3770 int defidx = 1;
3771 char *buf = NULL;
3772 char configfile[128];
3773 persistence_config *node;
3774
3775 (void)ctxt;
3776 (void)argc;
3777 (void)args;
3778
3779 debug("select persistence argc:%d\n", argc);
3780
3781 if (argc < 1)
3782 {
3783 return 0;
3784 }
3785
3786 node = ventoy_plugin_find_persistent(args[0]);
3787 if (!node)
3788 {
3789 debug("Persistence image not found for %s\n", args[0]);
3790 return 0;
3791 }
3792
3793 if (node->autosel >= 0 && node->autosel <= node->backendnum)
3794 {
3795 defidx = node->autosel;
3796 if (node->timeout < 0)
3797 {
3798 node->cursel = node->autosel - 1;
3799 debug("Persistence image auto select %d\n", node->autosel);
3800 return 0;
3801 }
3802 }
3803
3804 buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
3805 if (!buf)
3806 {
3807 return 0;
3808 }
3809
3810 if (node->timeout > 0)
3811 {
3812 vtoy_ssprintf(buf, pos, "set timeout=%d\n", node->timeout);
3813 }
3814
3815 vtoy_ssprintf(buf, pos, "menuentry \"@VTMENU_NO_PERSISTENCE\" --class=\"sel_persistence\" {\n"
3816 " echo %s\n}\n", "");
3817
3818 for (i = 0; i < node->backendnum; i++)
3819 {
3820 vtoy_ssprintf(buf, pos, "menuentry \"%s %s\" --class=\"sel_persistence\" {\n"
3821 " echo \"\"\n}\n",
3822 ventoy_get_vmenu_title("VTMENU_PERSIST_USE"),
3823 node->backendpath[i].path);
3824
3825 }
3826
3827 g_ventoy_menu_esc = 1;
3828 g_ventoy_suppress_esc = 1;
3829 g_ventoy_suppress_esc_default = defidx;
3830
3831 grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
3832 grub_script_execute_sourcecode(configfile);
3833
3834 g_ventoy_menu_esc = 0;
3835 g_ventoy_suppress_esc = 0;
3836 g_ventoy_suppress_esc_default = 1;
3837
3838 grub_free(buf);
3839
3840 node->cursel = g_ventoy_last_entry - 1;
3841
3842 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3843 }
3844
3845 static grub_err_t ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
3846 {
3847 grub_uint32_t i;
3848 ventoy_img_chunk *cur;
3849
3850 (void)ctxt;
3851 (void)argc;
3852 (void)args;
3853
3854 for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
3855 {
3856 cur = g_img_chunk_list.chunk + i;
3857 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
3858 cur->img_start_sector, cur->img_end_sector,
3859 (unsigned long long)cur->disk_start_sector, (unsigned long long)cur->disk_end_sector
3860 );
3861 }
3862
3863 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3864 }
3865
3866 static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int argc, char **args)
3867 {
3868 grub_uint32_t i;
3869 grub_file_t file;
3870 ventoy_img_chunk_list chunklist;
3871
3872 (void)ctxt;
3873 (void)argc;
3874
3875 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3876 if (!file)
3877 {
3878 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
3879 }
3880
3881 /* get image chunk data */
3882 grub_memset(&chunklist, 0, sizeof(chunklist));
3883 chunklist.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
3884 if (NULL == chunklist.chunk)
3885 {
3886 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
3887 }
3888
3889 chunklist.max_chunk = DEFAULT_CHUNK_NUM;
3890 chunklist.cur_chunk = 0;
3891
3892 ventoy_get_block_list(file, &chunklist, 0);
3893
3894 if (0 != ventoy_check_block_list(file, &chunklist, 0))
3895 {
3896 grub_printf("########## UNSUPPORTED ###############\n");
3897 }
3898
3899 grub_printf("filesystem: <%s> entry number:<%u>\n", file->fs->name, chunklist.cur_chunk);
3900
3901 for (i = 0; i < chunklist.cur_chunk; i++)
3902 {
3903 grub_printf("%llu+%llu,", (ulonglong)chunklist.chunk[i].disk_start_sector,
3904 (ulonglong)(chunklist.chunk[i].disk_end_sector + 1 - chunklist.chunk[i].disk_start_sector));
3905 }
3906
3907 grub_printf("\n==================================\n");
3908
3909 for (i = 0; i < chunklist.cur_chunk; i++)
3910 {
3911 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i,
3912 (ulonglong)chunklist.chunk[i].img_start_sector,
3913 (ulonglong)chunklist.chunk[i].img_end_sector,
3914 (ulonglong)chunklist.chunk[i].disk_start_sector,
3915 (ulonglong)chunklist.chunk[i].disk_end_sector
3916 );
3917 }
3918
3919 grub_free(chunklist.chunk);
3920 grub_file_close(file);
3921
3922 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3923 }
3924
3925 static grub_err_t ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt, int argc, char **args)
3926 {
3927 int i;
3928 ventoy_grub_param_file_replace *replace = NULL;
3929
3930 (void)ctxt;
3931 (void)argc;
3932 (void)args;
3933
3934 if (argc >= 2)
3935 {
3936 replace = &(g_grub_param->file_replace);
3937 replace->magic = GRUB_FILE_REPLACE_MAGIC;
3938
3939 replace->old_name_cnt = 0;
3940 for (i = 0; i < 4 && i + 1 < argc; i++)
3941 {
3942 replace->old_name_cnt++;
3943 grub_snprintf(replace->old_file_name[i], sizeof(replace->old_file_name[i]), "%s", args[i + 1]);
3944 }
3945
3946 replace->new_file_virtual_id = (grub_uint32_t)grub_strtoul(args[0], NULL, 10);
3947 }
3948
3949 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3950 }
3951
3952 static grub_err_t ventoy_cmd_get_replace_file_cnt(grub_extcmd_context_t ctxt, int argc, char **args)
3953 {
3954 char buf[32];
3955 ventoy_grub_param_file_replace *replace = &(g_grub_param->file_replace);
3956
3957 (void)ctxt;
3958
3959 if (argc >= 1)
3960 {
3961 grub_snprintf(buf, sizeof(buf), "%u", replace->old_name_cnt);
3962 grub_env_set(args[0], buf);
3963 }
3964
3965 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3966 }
3967
3968 static grub_err_t ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt, int argc, char **args)
3969 {
3970 (void)ctxt;
3971 (void)argc;
3972 (void)args;
3973
3974 if (argc == 0)
3975 {
3976 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos, VTOY_MAX_SCRIPT_BUF);
3977 grub_printf("%s", g_list_script_buf);
3978 }
3979 else
3980 {
3981 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos, VTOY_MAX_SCRIPT_BUF);
3982 grub_printf("%s", g_tree_script_buf);
3983 }
3984
3985 return 0;
3986 }
3987
3988 static grub_err_t ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt, int argc, char **args)
3989 {
3990 img_info *cur = g_ventoy_img_list;
3991
3992 (void)ctxt;
3993 (void)argc;
3994 (void)args;
3995
3996 while (cur)
3997 {
3998 grub_printf("path:<%s> id=%d list_index=%d\n", cur->path, cur->id, cur->plugin_list_index);
3999 grub_printf("name:<%s>\n\n", cur->name);
4000 cur = cur->next;
4001 }
4002
4003 return 0;
4004 }
4005
4006 static grub_err_t ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt, int argc, char **args)
4007 {
4008 (void)ctxt;
4009 (void)argc;
4010 (void)args;
4011
4012 ventoy_plugin_dump_injection();
4013
4014 return 0;
4015 }
4016
4017 static grub_err_t ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
4018 {
4019 (void)ctxt;
4020 (void)argc;
4021 (void)args;
4022
4023 ventoy_plugin_dump_auto_install();
4024
4025 return 0;
4026 }
4027
4028 static grub_err_t ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
4029 {
4030 (void)ctxt;
4031 (void)argc;
4032 (void)args;
4033
4034 ventoy_plugin_dump_persistence();
4035
4036 return 0;
4037 }
4038
4039 static int ventoy_check_mode_by_name(char *filename, const char *suffix)
4040 {
4041 int i;
4042 int len1;
4043 int len2;
4044
4045 len1 = (int)grub_strlen(filename);
4046 len2 = (int)grub_strlen(suffix);
4047
4048 if (len1 <= len2)
4049 {
4050 return 0;
4051 }
4052
4053 for (i = len1 - 1; i >= 0; i--)
4054 {
4055 if (filename[i] == '.')
4056 {
4057 break;
4058 }
4059 }
4060
4061 if (i < len2 + 1)
4062 {
4063 return 0;
4064 }
4065
4066 if (filename[i - len2 - 1] != '_')
4067 {
4068 return 0;
4069 }
4070
4071 if (grub_strncasecmp(filename + (i - len2), suffix, len2) == 0)
4072 {
4073 return 1;
4074 }
4075
4076 return 0;
4077 }
4078
4079 static grub_err_t ventoy_cmd_check_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4080 {
4081 (void)ctxt;
4082 (void)argc;
4083 (void)args;
4084
4085 if (argc != 1 && argc != 2)
4086 {
4087 return 1;
4088 }
4089
4090 if (args[0][0] == '0')
4091 {
4092 if (g_ventoy_memdisk_mode)
4093 {
4094 return 0;
4095 }
4096
4097 if (argc == 2 && ventoy_check_mode_by_name(args[1], "vtmemdisk"))
4098 {
4099 return 0;
4100 }
4101
4102 return 1;
4103 }
4104 else if (args[0][0] == '1')
4105 {
4106 return g_ventoy_iso_raw ? 0 : 1;
4107 }
4108 else if (args[0][0] == '2')
4109 {
4110 return g_ventoy_iso_uefi_drv ? 0 : 1;
4111 }
4112 else if (args[0][0] == '3')
4113 {
4114 if (g_ventoy_grub2_mode)
4115 {
4116 return 0;
4117 }
4118
4119 if (argc == 2 && ventoy_check_mode_by_name(args[1], "vtgrub2"))
4120 {
4121 return 0;
4122 }
4123
4124 return 1;
4125 }
4126 else if (args[0][0] == '4')
4127 {
4128 if (g_ventoy_wimboot_mode)
4129 {
4130 return 0;
4131 }
4132
4133 if (argc == 2 && ventoy_check_mode_by_name(args[1], "vtwimboot"))
4134 {
4135 return 0;
4136 }
4137
4138 return 1;
4139 }
4140
4141 return 1;
4142 }
4143
4144 static grub_err_t ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt, int argc, char **args)
4145 {
4146 static int configfile_mode = 0;
4147 char memfile[128] = {0};
4148
4149 (void)ctxt;
4150 (void)argc;
4151 (void)args;
4152
4153 /*
4154 * args[0]: 0:normal 1:configfile
4155 * args[1]: 0:list_buf 1:tree_buf
4156 */
4157
4158 if (argc != 2)
4159 {
4160 debug("Invalid argc %d\n", argc);
4161 return 0;
4162 }
4163
4164 VTOY_CMD_CHECK(1);
4165
4166 if (args[0][0] == '0')
4167 {
4168 if (args[1][0] == '0')
4169 {
4170 grub_script_execute_sourcecode(g_list_script_buf);
4171 }
4172 else
4173 {
4174 grub_script_execute_sourcecode(g_tree_script_buf);
4175 }
4176 }
4177 else
4178 {
4179 if (configfile_mode)
4180 {
4181 debug("Now already in F3 mode %d\n", configfile_mode);
4182 return 0;
4183 }
4184
4185 if (args[1][0] == '0')
4186 {
4187 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
4188 (ulonglong)(ulong)g_list_script_buf, g_list_script_pos);
4189 }
4190 else
4191 {
4192 g_ventoy_last_entry = -1;
4193 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
4194 (ulonglong)(ulong)g_tree_script_buf, g_tree_script_pos);
4195 }
4196
4197 configfile_mode = 1;
4198 grub_script_execute_sourcecode(memfile);
4199 configfile_mode = 0;
4200 }
4201
4202 return 0;
4203 }
4204
4205 static grub_err_t ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt, int argc, char **args)
4206 {
4207 grub_file_t file;
4208
4209 (void)ctxt;
4210
4211 if (argc != 1)
4212 {
4213 return 1;
4214 }
4215
4216 g_ventoy_case_insensitive = 1;
4217 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
4218 g_ventoy_case_insensitive = 0;
4219
4220 grub_errno = 0;
4221
4222 if (file)
4223 {
4224 grub_file_close(file);
4225 return 0;
4226 }
4227 return 1;
4228 }
4229
4230 static grub_err_t ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt, int argc, char **args)
4231 {
4232 int id = 0;
4233 int find = 0;
4234 grub_disk_t disk;
4235 const char *isopath = NULL;
4236 char hdname[32];
4237 ventoy_mbr_head mbr;
4238
4239 (void)ctxt;
4240 (void)argc;
4241
4242 if (argc != 1)
4243 {
4244 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s variable\n", cmd_raw_name);
4245 }
4246
4247 isopath = grub_env_get("vtoy_iso_part");
4248 if (!isopath)
4249 {
4250 debug("isopath is null %p\n", isopath);
4251 return 0;
4252 }
4253
4254 debug("isopath is %s\n", isopath);
4255
4256 for (id = 0; id < 30 && (find == 0); id++)
4257 {
4258 grub_snprintf(hdname, sizeof(hdname), "hd%d,", id);
4259 if (grub_strstr(isopath, hdname))
4260 {
4261 debug("skip %s ...\n", hdname);
4262 continue;
4263 }
4264
4265 grub_snprintf(hdname, sizeof(hdname), "hd%d", id);
4266
4267 disk = grub_disk_open(hdname);
4268 if (!disk)
4269 {
4270 debug("%s not exist\n", hdname);
4271 break;
4272 }
4273
4274 grub_memset(&mbr, 0, sizeof(mbr));
4275 if (0 == grub_disk_read(disk, 0, 0, 512, &mbr))
4276 {
4277 if (mbr.Byte55 == 0x55 && mbr.ByteAA == 0xAA)
4278 {
4279 if (mbr.PartTbl[0].Active == 0x80 || mbr.PartTbl[1].Active == 0x80 ||
4280 mbr.PartTbl[2].Active == 0x80 || mbr.PartTbl[3].Active == 0x80)
4281 {
4282
4283 grub_env_set(args[0], hdname);
4284 find = 1;
4285 }
4286 }
4287 debug("%s is %s\n", hdname, find ? "bootable" : "NOT bootable");
4288 }
4289 else
4290 {
4291 debug("read %s failed\n", hdname);
4292 }
4293
4294 grub_disk_close(disk);
4295 }
4296
4297 return 0;
4298 }
4299
4300 static grub_err_t ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt, int argc, char **args)
4301 {
4302 int len = 1024;
4303 grub_file_t file;
4304 char *buf = NULL;
4305
4306 (void)ctxt;
4307 (void)argc;
4308
4309 if (argc != 2)
4310 {
4311 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file var \n", cmd_raw_name);
4312 }
4313
4314 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
4315 if (!file)
4316 {
4317 debug("failed to open file %s\n", args[0]);
4318 return 0;
4319 }
4320
4321 buf = grub_malloc(len);
4322 if (!buf)
4323 {
4324 goto end;
4325 }
4326
4327 buf[len - 1] = 0;
4328 grub_file_read(file, buf, len - 1);
4329
4330 ventoy_get_line(buf);
4331 ventoy_set_env(args[1], buf);
4332
4333 end:
4334
4335 grub_check_free(buf);
4336 grub_file_close(file);
4337
4338 return 0;
4339 }
4340
4341 static int ventoy_img_partition_callback (struct grub_disk *disk, const grub_partition_t partition, void *data)
4342 {
4343 grub_uint64_t end_max = 0;
4344 int *pCnt = (int *)data;
4345
4346 (void)disk;
4347
4348 (*pCnt)++;
4349 g_part_list_pos += grub_snprintf(g_part_list_buf + g_part_list_pos, VTOY_MAX_SCRIPT_BUF - g_part_list_pos,
4350 "0 %llu linear /dev/ventoy %llu\n",
4351 (ulonglong)partition->len, (ulonglong)partition->start);
4352
4353 end_max = (partition->len + partition->start) * 512;
4354 if (end_max > g_part_end_max)
4355 {
4356 g_part_end_max = end_max;
4357 }
4358
4359 return 0;
4360 }
4361
4362 static grub_err_t ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt, int argc, char **args)
4363 {
4364 int cnt = 0;
4365 char *device_name = NULL;
4366 grub_device_t dev = NULL;
4367 char buf[64];
4368
4369 (void)ctxt;
4370
4371 g_part_list_pos = 0;
4372 g_part_end_max = 0;
4373 grub_env_unset("vtoy_img_part_file");
4374
4375 if (argc != 1)
4376 {
4377 return 1;
4378 }
4379
4380 device_name = grub_file_get_device_name(args[0]);
4381 if (!device_name)
4382 {
4383 debug("ventoy_cmd_img_part_info failed, %s\n", args[0]);
4384 goto end;
4385 }
4386
4387 dev = grub_device_open(device_name);
4388 if (!dev)
4389 {
4390 debug("grub_device_open failed, %s\n", device_name);
4391 goto end;
4392 }
4393
4394 grub_partition_iterate(dev->disk, ventoy_img_partition_callback, &cnt);
4395
4396 grub_snprintf(buf, sizeof(buf), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong)(ulong)g_part_list_buf, g_part_list_pos);
4397 grub_env_set("vtoy_img_part_file", buf);
4398
4399 grub_snprintf(buf, sizeof(buf), "%d", cnt);
4400 grub_env_set("vtoy_img_part_cnt", buf);
4401
4402 grub_snprintf(buf, sizeof(buf), "%llu", (ulonglong)g_part_end_max);
4403 grub_env_set("vtoy_img_max_part_end", buf);
4404
4405 end:
4406
4407 check_free(device_name, grub_free);
4408 check_free(dev, grub_device_close);
4409
4410 return 0;
4411 }
4412
4413
4414 static grub_err_t ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
4415 {
4416 int rc = 1;
4417 grub_file_t file;
4418 char *buf = NULL;
4419
4420 (void)ctxt;
4421 (void)argc;
4422
4423 if (argc != 2)
4424 {
4425 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file str \n", cmd_raw_name);
4426 }
4427
4428 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
4429 if (!file)
4430 {
4431 debug("failed to open file %s\n", args[0]);
4432 return 1;
4433 }
4434
4435 buf = grub_malloc(file->size + 1);
4436 if (!buf)
4437 {
4438 goto end;
4439 }
4440
4441 buf[file->size] = 0;
4442 grub_file_read(file, buf, file->size);
4443
4444 if (grub_strstr(buf, args[1]))
4445 {
4446 rc = 0;
4447 }
4448
4449 end:
4450
4451 grub_check_free(buf);
4452 grub_file_close(file);
4453
4454 return rc;
4455 }
4456
4457 static grub_err_t ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt, int argc, char **args)
4458 {
4459 int len;
4460 grub_file_t file;
4461 char buf[64];
4462 grub_uint64_t size;
4463 ventoy_iso9660_vd pvd;
4464
4465 (void)ctxt;
4466 (void)argc;
4467
4468 if (argc != 4)
4469 {
4470 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s sysid volid space \n", cmd_raw_name);
4471 }
4472
4473 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
4474 if (!file)
4475 {
4476 debug("failed to open file %s\n", args[0]);
4477 return 0;
4478 }
4479
4480 grub_file_seek(file, 16 * 2048);
4481 len = (int)grub_file_read(file, &pvd, sizeof(pvd));
4482 if (len != sizeof(pvd))
4483 {
4484 debug("failed to read pvd %d\n", len);
4485 goto end;
4486 }
4487
4488 grub_memset(buf, 0, sizeof(buf));
4489 grub_memcpy(buf, pvd.sys, sizeof(pvd.sys));
4490 ventoy_set_env(args[1], buf);
4491
4492 grub_memset(buf, 0, sizeof(buf));
4493 grub_memcpy(buf, pvd.vol, sizeof(pvd.vol));
4494 ventoy_set_env(args[2], buf);
4495
4496 size = pvd.space;
4497 size *= 2048;
4498 grub_snprintf(buf, sizeof(buf), "%llu", (ulonglong)size);
4499 ventoy_set_env(args[3], buf);
4500
4501 end:
4502 grub_file_close(file);
4503
4504 return 0;
4505 }
4506
4507 static grub_err_t ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt, int argc, char **args)
4508 {
4509 int len;
4510 grub_file_t file;
4511 char buf[64];
4512
4513 (void)ctxt;
4514 (void)argc;
4515
4516 if (argc != 2)
4517 {
4518 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s var \n", cmd_raw_name);
4519 }
4520
4521 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
4522 if (!file)
4523 {
4524 debug("failed to open file %s\n", args[0]);
4525 return 0;
4526 }
4527
4528 grub_memset(buf, 0, sizeof(buf));
4529 grub_file_seek(file, 16 * 2048 + 813);
4530 len = (int)grub_file_read(file, buf, 17);
4531 if (len != 17)
4532 {
4533 debug("failed to read create date %d\n", len);
4534 goto end;
4535 }
4536
4537 ventoy_set_env(args[1], buf);
4538
4539 end:
4540 grub_file_close(file);
4541
4542 return 0;
4543 }
4544
4545 static grub_err_t ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt, int argc, char **args)
4546 {
4547 (void)ctxt;
4548 (void)argc;
4549 (void)args;
4550
4551 ventoy_env_hook_root(1);
4552
4553 return 0;
4554 }
4555
4556 static grub_err_t ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt, int argc, char **args)
4557 {
4558 (void)ctxt;
4559 (void)argc;
4560 (void)args;
4561
4562 ventoy_env_hook_root(0);
4563
4564 return 0;
4565 }
4566
4567 #ifdef GRUB_MACHINE_EFI
4568 static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
4569 {
4570 int ret = 1;
4571 grub_uint8_t *var;
4572 grub_size_t size;
4573 grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
4574
4575 (void)ctxt;
4576 (void)argc;
4577 (void)args;
4578
4579 var = grub_efi_get_variable("SecureBoot", &global, &size);
4580 if (var && *var == 1)
4581 {
4582 return 0;
4583 }
4584
4585 return ret;
4586 }
4587 #else
4588 static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
4589 {
4590 (void)ctxt;
4591 (void)argc;
4592 (void)args;
4593 return 1;
4594 }
4595 #endif
4596
4597 static grub_err_t ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt, int argc, char **args)
4598 {
4599 int i;
4600 int ret = 1;
4601 grub_file_t file;
4602 grub_uint64_t FileSectors = 0;
4603 ventoy_gpt_info *gpt = NULL;
4604 ventoy_part_table *pt = NULL;
4605 grub_uint8_t zeroguid[16] = {0};
4606
4607 (void)ctxt;
4608 (void)argc;
4609
4610 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
4611 if (!file)
4612 {
4613 debug("failed to open file %s\n", args[0]);
4614 return 1;
4615 }
4616
4617 if (file->size % 512)
4618 {
4619 debug("unaligned file size: %llu\n", (ulonglong)file->size);
4620 goto out;
4621 }
4622
4623 gpt = grub_zalloc(sizeof(ventoy_gpt_info));
4624 if (!gpt)
4625 {
4626 goto out;
4627 }
4628
4629 FileSectors = file->size / 512;
4630
4631 grub_file_read(file, gpt, sizeof(ventoy_gpt_info));
4632 if (grub_strncmp(gpt->Head.Signature, "EFI PART", 8) == 0)
4633 {
4634 debug("This is EFI partition table\n");
4635
4636 for (i = 0; i < 128; i++)
4637 {
4638 if (grub_memcmp(gpt->PartTbl[i].PartGuid, zeroguid, 16))
4639 {
4640 if (FileSectors < gpt->PartTbl[i].LastLBA)
4641 {
4642 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
4643 (ulonglong)gpt->PartTbl[i].LastLBA, (ulonglong)FileSectors);
4644 goto out;
4645 }
4646 }
4647 }
4648 }
4649 else
4650 {
4651 debug("This is MBR partition table\n");
4652
4653 for (i = 0; i < 4; i++)
4654 {
4655 pt = gpt->MBR.PartTbl + i;
4656 if (FileSectors < pt->StartSectorId + pt->SectorCount)
4657 {
4658 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
4659 (ulonglong)(pt->StartSectorId + pt->SectorCount),
4660 (ulonglong)FileSectors);
4661 goto out;
4662 }
4663 }
4664 }
4665
4666 ret = 0;
4667
4668 out:
4669 grub_file_close(file);
4670 grub_check_free(gpt);
4671 grub_errno = GRUB_ERR_NONE;
4672 return ret;
4673 }
4674
4675 static grub_err_t ventoy_cmd_clear_key(grub_extcmd_context_t ctxt, int argc, char **args)
4676 {
4677 int i;
4678 int ret;
4679
4680 (void)ctxt;
4681 (void)argc;
4682 (void)args;
4683
4684 for (i = 0; i < 500; i++)
4685 {
4686 ret = grub_getkey_noblock();
4687 if (ret == GRUB_TERM_NO_KEY)
4688 {
4689 break;
4690 }
4691 }
4692
4693 if (i >= 500)
4694 {
4695 grub_cls();
4696 grub_printf("\n\n Still have key input after clear.\n");
4697 grub_refresh();
4698 grub_sleep(5);
4699 }
4700
4701 return 0;
4702 }
4703
4704 static grub_err_t ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt, int argc, char **args)
4705 {
4706 int i;
4707 int buflen;
4708 int datalen;
4709 int loclen;
4710 int img_chunk_num;
4711 int image_sector_size;
4712 char cmd[64];
4713 ventoy_chain_head *chain;
4714 ventoy_img_chunk *chunk;
4715 ventoy_os_param *osparam;
4716 ventoy_image_location *location;
4717 ventoy_image_disk_region *region;
4718 struct grub_acpi_table_header *acpi;
4719
4720 (void)ctxt;
4721
4722 if (argc != 2)
4723 {
4724 return 1;
4725 }
4726
4727 debug("ventoy_cmd_acpi_param %s %s\n", args[0], args[1]);
4728
4729 chain = (ventoy_chain_head *)(ulong)grub_strtoul(args[0], NULL, 16);
4730 if (!chain)
4731 {
4732 return 1;
4733 }
4734
4735 image_sector_size = (int)grub_strtol(args[1], NULL, 10);
4736
4737 if (grub_memcmp(&g_ventoy_guid, &(chain->os_param.guid), 16))
4738 {
4739 debug("Invalid ventoy guid 0x%x\n", chain->os_param.guid.data1);
4740 return 1;
4741 }
4742
4743 img_chunk_num = chain->img_chunk_num;
4744
4745 loclen = sizeof(ventoy_image_location) + (img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
4746 datalen = sizeof(ventoy_os_param) + loclen;
4747
4748 buflen = sizeof(struct grub_acpi_table_header) + datalen;
4749 acpi = grub_zalloc(buflen);
4750 if (!acpi)
4751 {
4752 return 1;
4753 }
4754
4755 /* Step1: Fill acpi table header */
4756 grub_memcpy(acpi->signature, "VTOY", 4);
4757 acpi->length = buflen;
4758 acpi->revision = 1;
4759 grub_memcpy(acpi->oemid, "VENTOY", 6);
4760 grub_memcpy(acpi->oemtable, "OSPARAMS", 8);
4761 acpi->oemrev = 1;
4762 acpi->creator_id[0] = 1;
4763 acpi->creator_rev = 1;
4764
4765 /* Step2: Fill data */
4766 osparam = (ventoy_os_param *)(acpi + 1);
4767 grub_memcpy(osparam, &chain->os_param, sizeof(ventoy_os_param));
4768 osparam->vtoy_img_location_addr = 0;
4769 osparam->vtoy_img_location_len = loclen;
4770 osparam->chksum = 0;
4771 osparam->chksum = 0x100 - grub_byte_checksum(osparam, sizeof(ventoy_os_param));
4772
4773 location = (ventoy_image_location *)(osparam + 1);
4774 grub_memcpy(&location->guid, &osparam->guid, sizeof(ventoy_guid));
4775 location->image_sector_size = image_sector_size;
4776 location->disk_sector_size = chain->disk_sector_size;
4777 location->region_count = img_chunk_num;
4778
4779 region = location->regions;
4780 chunk = (ventoy_img_chunk *)((char *)chain + chain->img_chunk_offset);
4781 if (512 == image_sector_size)
4782 {
4783 for (i = 0; i < img_chunk_num; i++)
4784 {
4785 region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
4786 region->image_start_sector = chunk->img_start_sector * 4;
4787 region->disk_start_sector = chunk->disk_start_sector;
4788 region++;
4789 chunk++;
4790 }
4791 }
4792 else
4793 {
4794 for (i = 0; i < img_chunk_num; i++)
4795 {
4796 region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
4797 region->image_start_sector = chunk->img_start_sector;
4798 region->disk_start_sector = chunk->disk_start_sector;
4799 region++;
4800 chunk++;
4801 }
4802 }
4803
4804 /* Step3: Fill acpi checksum */
4805 acpi->checksum = 0;
4806 acpi->checksum = 0x100 - grub_byte_checksum(acpi, acpi->length);
4807
4808 /* load acpi table */
4809 grub_snprintf(cmd, sizeof(cmd), "acpi mem:0x%lx:size:%d", (ulong)acpi, acpi->length);
4810 grub_script_execute_sourcecode(cmd);
4811
4812 grub_free(acpi);
4813
4814 VENTOY_CMD_RETURN(0);
4815 }
4816
4817 static grub_err_t ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
4818 {
4819 (void)ctxt;
4820 (void)argc;
4821 (void)args;
4822
4823 g_ventoy_last_entry_back = g_ventoy_last_entry;
4824 g_ventoy_last_entry = -1;
4825
4826 return 0;
4827 }
4828
4829 static grub_err_t ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
4830 {
4831 (void)ctxt;
4832 (void)argc;
4833 (void)args;
4834
4835 g_ventoy_last_entry = g_ventoy_last_entry_back;
4836
4837 return 0;
4838 }
4839
4840 static int ventoy_lib_module_callback(const char *filename, const struct grub_dirhook_info *info, void *data)
4841 {
4842 const char *pos = filename + 1;
4843
4844 if (info->dir)
4845 {
4846 while (*pos)
4847 {
4848 if (*pos == '.')
4849 {
4850 if ((*(pos - 1) >= '0' && *(pos - 1) <= '9') && (*(pos + 1) >= '0' && *(pos + 1) <= '9'))
4851 {
4852 grub_strncpy((char *)data, filename, 128);
4853 return 1;
4854 }
4855 }
4856 pos++;
4857 }
4858 }
4859
4860 return 0;
4861 }
4862
4863 static grub_err_t ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt, int argc, char **args)
4864 {
4865 int rc = 1;
4866 char *device_name = NULL;
4867 grub_device_t dev = NULL;
4868 grub_fs_t fs = NULL;
4869 char buf[128] = {0};
4870
4871 (void)ctxt;
4872
4873 if (argc != 3)
4874 {
4875 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc);
4876 return 1;
4877 }
4878
4879 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args[0], args[1], args[2]);
4880
4881 device_name = grub_file_get_device_name(args[0]);
4882 if (!device_name)
4883 {
4884 debug("grub_file_get_device_name failed, %s\n", args[0]);
4885 goto end;
4886 }
4887
4888 dev = grub_device_open(device_name);
4889 if (!dev)
4890 {
4891 debug("grub_device_open failed, %s\n", device_name);
4892 goto end;
4893 }
4894
4895 fs = grub_fs_probe(dev);
4896 if (!fs)
4897 {
4898 debug("grub_fs_probe failed, %s\n", device_name);
4899 goto end;
4900 }
4901
4902 fs->fs_dir(dev, args[1], ventoy_lib_module_callback, buf);
4903
4904 if (buf[0])
4905 {
4906 ventoy_set_env(args[2], buf);
4907 }
4908
4909 rc = 0;
4910
4911 end:
4912
4913 check_free(device_name, grub_free);
4914 check_free(dev, grub_device_close);
4915
4916 return rc;
4917 }
4918
4919 int ventoy_load_part_table(const char *diskname)
4920 {
4921 char name[64];
4922 int ret;
4923 grub_disk_t disk;
4924 grub_device_t dev;
4925
4926 g_ventoy_part_info = grub_zalloc(sizeof(ventoy_gpt_info));
4927 if (!g_ventoy_part_info)
4928 {
4929 return 1;
4930 }
4931
4932 disk = grub_disk_open(diskname);
4933 if (!disk)
4934 {
4935 debug("Failed to open disk %s\n", diskname);
4936 return 1;
4937 }
4938
4939 g_ventoy_disk_size = disk->total_sectors * (1U << disk->log_sector_size);
4940
4941 g_ventoy_disk_bios_id = disk->id;
4942
4943 grub_disk_read(disk, 0, 0, sizeof(ventoy_gpt_info), g_ventoy_part_info);
4944 grub_disk_close(disk);
4945
4946 grub_snprintf(name, sizeof(name), "%s,1", diskname);
4947 dev = grub_device_open(name);
4948 if (dev)
4949 {
4950 /* Check for official Ventoy device */
4951 ret = ventoy_check_official_device(dev);
4952 grub_device_close(dev);
4953
4954 if (ret)
4955 {
4956 return 1;
4957 }
4958 }
4959
4960 g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
4961 g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
4962
4963 return 0;
4964 }
4965
4966 static grub_err_t ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt, int argc, char **args)
4967 {
4968 int ret;
4969
4970 (void)argc;
4971 (void)ctxt;
4972
4973 ret = ventoy_load_part_table(args[0]);
4974 if (ret)
4975 {
4976 grub_exit();
4977 }
4978
4979 g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
4980 g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
4981
4982 return 0;
4983 }
4984
4985 static grub_err_t ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
4986 {
4987 int ret = 1;
4988 const char *vcfg = NULL;
4989
4990 (void)argc;
4991 (void)ctxt;
4992
4993 vcfg = ventoy_plugin_get_custom_boot(args[0]);
4994 if (vcfg)
4995 {
4996 debug("custom boot <%s>:<%s>\n", args[0], vcfg);
4997 grub_env_set(args[1], vcfg);
4998 ret = 0;
4999 }
5000 else
5001 {
5002 debug("custom boot <%s>:<NOT FOUND>\n", args[0]);
5003 }
5004
5005 grub_errno = 0;
5006 return ret;
5007 }
5008
5009
5010 static grub_err_t ventoy_cmd_part_exist(grub_extcmd_context_t ctxt, int argc, char **args)
5011 {
5012 int id;
5013 grub_uint8_t zeroguid[16] = {0};
5014
5015 (void)argc;
5016 (void)ctxt;
5017
5018 id = (int)grub_strtoul(args[0], NULL, 10);
5019 grub_errno = 0;
5020
5021 if (grub_memcmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
5022 {
5023 if (id >= 1 && id <= 128)
5024 {
5025 if (grub_memcmp(g_ventoy_part_info->PartTbl[id - 1].PartGuid, zeroguid, 16))
5026 {
5027 return 0;
5028 }
5029 }
5030 }
5031 else
5032 {
5033 if (id >= 1 && id <= 4)
5034 {
5035 if (g_ventoy_part_info->MBR.PartTbl[id - 1].FsFlag)
5036 {
5037 return 0;
5038 }
5039 }
5040 }
5041
5042 return 1;
5043 }
5044
5045 static grub_err_t ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt, int argc, char **args)
5046 {
5047 int rc = 1;
5048 char *device_name = NULL;
5049 grub_device_t dev = NULL;
5050 grub_fs_t fs = NULL;
5051 char *label = NULL;
5052
5053 (void)ctxt;
5054
5055 debug("get fs label for %s\n", args[0]);
5056
5057 if (argc != 2)
5058 {
5059 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc);
5060 return 1;
5061 }
5062
5063 device_name = grub_file_get_device_name(args[0]);
5064 if (!device_name)
5065 {
5066 debug("grub_file_get_device_name failed, %s\n", args[0]);
5067 goto end;
5068 }
5069
5070 dev = grub_device_open(device_name);
5071 if (!dev)
5072 {
5073 debug("grub_device_open failed, %s\n", device_name);
5074 goto end;
5075 }
5076
5077 fs = grub_fs_probe(dev);
5078 if (NULL == fs || NULL == fs->fs_label)
5079 {
5080 debug("grub_fs_probe failed, %s %p %p\n", device_name, fs, fs->fs_label);
5081 goto end;
5082 }
5083
5084 fs->fs_label(dev, &label);
5085 if (label)
5086 {
5087 debug("label=<%s>\n", label);
5088 ventoy_set_env(args[1], label);
5089 grub_free(label);
5090 }
5091
5092 rc = 0;
5093
5094 end:
5095
5096 check_free(device_name, grub_free);
5097 check_free(dev, grub_device_close);
5098
5099 return rc;
5100 }
5101
5102 static int ventoy_fs_enum_1st_file(const char *filename, const struct grub_dirhook_info *info, void *data)
5103 {
5104 if (!info->dir)
5105 {
5106 grub_snprintf((char *)data, 256, "%s", filename);
5107 return 1;
5108 }
5109
5110 return 0;
5111 }
5112
5113 static int ventoy_fs_enum_1st_dir(const char *filename, const struct grub_dirhook_info *info, void *data)
5114 {
5115 if (info->dir && filename && filename[0] != '.')
5116 {
5117 grub_snprintf((char *)data, 256, "%s", filename);
5118 return 1;
5119 }
5120
5121 return 0;
5122 }
5123
5124 static grub_err_t ventoy_fs_enum_1st_child(int argc, char **args, grub_fs_dir_hook_t hook)
5125 {
5126 int rc = 1;
5127 char *device_name = NULL;
5128 grub_device_t dev = NULL;
5129 grub_fs_t fs = NULL;
5130 char name[256] ={0};
5131
5132 if (argc != 3)
5133 {
5134 debug("ventoy_fs_enum_1st_child, invalid param num %d\n", argc);
5135 return 1;
5136 }
5137
5138 device_name = grub_file_get_device_name(args[0]);
5139 if (!device_name)
5140 {
5141 debug("grub_file_get_device_name failed, %s\n", args[0]);
5142 goto end;
5143 }
5144
5145 dev = grub_device_open(device_name);
5146 if (!dev)
5147 {
5148 debug("grub_device_open failed, %s\n", device_name);
5149 goto end;
5150 }
5151
5152 fs = grub_fs_probe(dev);
5153 if (!fs)
5154 {
5155 debug("grub_fs_probe failed, %s\n", device_name);
5156 goto end;
5157 }
5158
5159 fs->fs_dir(dev, args[1], hook, name);
5160 if (name[0])
5161 {
5162 ventoy_set_env(args[2], name);
5163 }
5164
5165 rc = 0;
5166
5167 end:
5168
5169 check_free(device_name, grub_free);
5170 check_free(dev, grub_device_close);
5171
5172 return rc;
5173 }
5174
5175 static grub_err_t ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt, int argc, char **args)
5176 {
5177 (void)ctxt;
5178 return ventoy_fs_enum_1st_child(argc, args, ventoy_fs_enum_1st_file);
5179 }
5180
5181 static grub_err_t ventoy_cmd_fs_enum_1st_dir(grub_extcmd_context_t ctxt, int argc, char **args)
5182 {
5183 (void)ctxt;
5184 return ventoy_fs_enum_1st_child(argc, args, ventoy_fs_enum_1st_dir);
5185 }
5186
5187 static grub_err_t ventoy_cmd_basename(grub_extcmd_context_t ctxt, int argc, char **args)
5188 {
5189 char c;
5190 char *pos = NULL;
5191 char *end = NULL;
5192
5193 (void)ctxt;
5194
5195 if (argc != 2)
5196 {
5197 debug("ventoy_cmd_basename, invalid param num %d\n", argc);
5198 return 1;
5199 }
5200
5201 for (pos = args[0]; *pos; pos++)
5202 {
5203 if (*pos == '.')
5204 {
5205 end = pos;
5206 }
5207 }
5208
5209 if (end)
5210 {
5211 c = *end;
5212 *end = 0;
5213 }
5214
5215 grub_env_set(args[1], args[0]);
5216
5217 if (end)
5218 {
5219 *end = c;
5220 }
5221
5222 return 0;
5223 }
5224
5225 static grub_err_t ventoy_cmd_basefile(grub_extcmd_context_t ctxt, int argc, char **args)
5226 {
5227 int i;
5228 int len;
5229 const char *buf;
5230
5231 (void)ctxt;
5232
5233 if (argc != 2)
5234 {
5235 debug("ventoy_cmd_basefile, invalid param num %d\n", argc);
5236 return 1;
5237 }
5238
5239 buf = args[0];
5240 len = (int)grub_strlen(buf);
5241 for (i = len; i > 0; i--)
5242 {
5243 if (buf[i - 1] == '/')
5244 {
5245 grub_env_set(args[1], buf + i);
5246 return 0;
5247 }
5248 }
5249
5250 grub_env_set(args[1], buf);
5251
5252 return 0;
5253 }
5254
5255 static grub_err_t ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
5256 {
5257 struct grub_video_mode_info info;
5258 char buf[32];
5259
5260 (void)ctxt;
5261 (void)argc;
5262 (void)args;
5263
5264 if (!g_video_mode_list)
5265 {
5266 ventoy_enum_video_mode();
5267 }
5268
5269 if (grub_video_get_info(&info) == GRUB_ERR_NONE)
5270 {
5271 grub_snprintf(buf, sizeof(buf), "Resolution (%ux%u)", info.width, info.height);
5272 }
5273 else
5274 {
5275 grub_snprintf(buf, sizeof(buf), "Resolution (0x0)");
5276 }
5277
5278 grub_env_set("VTOY_CUR_VIDEO_MODE", buf);
5279
5280 grub_snprintf(buf, sizeof(buf), "%d", g_video_mode_num);
5281 grub_env_set("VTOY_VIDEO_MODE_NUM", buf);
5282
5283 VENTOY_CMD_RETURN(0);
5284 }
5285
5286 static grub_err_t vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
5287 {
5288 struct grub_video_mode_info info;
5289 char buf[32];
5290
5291 (void)ctxt;
5292 (void)argc;
5293 (void)args;
5294
5295 if (grub_video_get_info(&info) == GRUB_ERR_NONE)
5296 {
5297 grub_snprintf(buf, sizeof(buf), "%ux%ux%u", info.width, info.height, info.bpp);
5298 }
5299 else
5300 {
5301 grub_snprintf(buf, sizeof(buf), "0x0x0");
5302 }
5303
5304 grub_env_set(args[0], buf);
5305
5306 VENTOY_CMD_RETURN(0);
5307 }
5308
5309 static grub_err_t ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
5310 {
5311 int id;
5312 char buf[32];
5313
5314 (void)ctxt;
5315 (void)argc;
5316
5317 if (!g_video_mode_list)
5318 {
5319 return 0;
5320 }
5321
5322 id = (int)grub_strtoul(args[0], NULL, 10);
5323 if (id < g_video_mode_num)
5324 {
5325 grub_snprintf(buf, sizeof(buf), "%ux%ux%u",
5326 g_video_mode_list[id].width, g_video_mode_list[id].height, g_video_mode_list[id].bpp);
5327 }
5328
5329 grub_env_set(args[1], buf);
5330
5331 VENTOY_CMD_RETURN(0);
5332 }
5333
5334 static grub_err_t ventoy_cmd_get_efivdisk_offset(grub_extcmd_context_t ctxt, int argc, char **args)
5335 {
5336 grub_uint32_t i;
5337 grub_uint32_t loadsector = 0;
5338 grub_file_t file;
5339 char value[32];
5340 grub_uint32_t boot_catlog = 0;
5341 grub_uint8_t buf[512];
5342
5343 (void)ctxt;
5344
5345 if (argc != 2)
5346 {
5347 debug("ventoy_cmd_get_efivdisk_offset, invalid param num %d\n", argc);
5348 return 1;
5349 }
5350
5351 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
5352 if (!file)
5353 {
5354 debug("failed to open %s\n", args[0]);
5355 return 1;
5356 }
5357
5358 boot_catlog = ventoy_get_iso_boot_catlog(file);
5359 if (boot_catlog == 0)
5360 {
5361 debug("No bootcatlog found\n");
5362 grub_file_close(file);
5363 return 1;
5364 }
5365
5366 grub_memset(buf, 0, sizeof(buf));
5367 grub_file_seek(file, boot_catlog * 2048);
5368 grub_file_read(file, buf, sizeof(buf));
5369 grub_file_close(file);
5370
5371 for (i = 0; i < sizeof(buf); i += 32)
5372 {
5373 if ((buf[i] == 0 || buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF)
5374 {
5375 if (buf[i + 32] == 0x88)
5376 {
5377 loadsector = *(grub_uint32_t *)(buf + i + 32 + 8);
5378 grub_snprintf(value, sizeof(value), "%u", loadsector * 4); //change to sector size 512
5379 break;
5380 }
5381 }
5382 }
5383
5384 if (loadsector == 0)
5385 {
5386 debug("No EFI eltorito info found\n");
5387 return 1;
5388 }
5389
5390 debug("ventoy_cmd_get_efivdisk_offset <%s>\n", value);
5391 grub_env_set(args[1], value);
5392 VENTOY_CMD_RETURN(0);
5393 }
5394
5395 static int ventoy_collect_replace_initrd(const char *filename, const struct grub_dirhook_info *info, void *data)
5396 {
5397 int curpos;
5398 int printlen;
5399 grub_size_t len;
5400 replace_fs_dir *pfsdir = (replace_fs_dir *)data;
5401
5402 if (pfsdir->initrd[0])
5403 {
5404 return 1;
5405 }
5406
5407 curpos = pfsdir->curpos;
5408 len = grub_strlen(filename);
5409
5410 if (info->dir)
5411 {
5412 if ((len == 1 && filename[0] == '.') ||
5413 (len == 2 && filename[0] == '.' && filename[1] == '.'))
5414 {
5415 return 0;
5416 }
5417
5418 //debug("#### [DIR] <%s> <%s>\n", pfsdir->fullpath, filename);
5419 pfsdir->dircnt++;
5420
5421 printlen = grub_snprintf(pfsdir->fullpath + curpos, 512 - curpos, "%s/", filename);
5422 pfsdir->curpos = curpos + printlen;
5423 pfsdir->fs->fs_dir(pfsdir->dev, pfsdir->fullpath, ventoy_collect_replace_initrd, pfsdir);
5424 pfsdir->curpos = curpos;
5425 pfsdir->fullpath[curpos] = 0;
5426 }
5427 else
5428 {
5429 //debug("#### [FILE] <%s> <%s>\n", pfsdir->fullpath, filename);
5430 pfsdir->filecnt++;
5431
5432 /* We consider the xxx.img file bigger than 32MB is the initramfs file */
5433 if (len > 4 && grub_strncmp(filename + len - 4, ".img", 4) == 0)
5434 {
5435 if (info->size > 32 * VTOY_SIZE_1MB)
5436 {
5437 grub_snprintf(pfsdir->initrd, sizeof(pfsdir->initrd), "%s%s", pfsdir->fullpath, filename);
5438 return 1;
5439 }
5440 }
5441 }
5442
5443 return 0;
5444 }
5445
5446 static grub_err_t ventoy_cmd_search_replace_initrd(grub_extcmd_context_t ctxt, int argc, char **args)
5447 {
5448 int i;
5449 char *pos = NULL;
5450 char *device_name = NULL;
5451 grub_device_t dev = NULL;
5452 grub_fs_t fs = NULL;
5453 replace_fs_dir *pfsdir = NULL;
5454
5455 (void)ctxt;
5456
5457 if (argc != 2)
5458 {
5459 debug("ventoy_cmd_search_replace_initrd, invalid param num %d\n", argc);
5460 return 1;
5461 }
5462
5463 pfsdir = grub_zalloc(sizeof(replace_fs_dir));
5464 if (!pfsdir)
5465 {
5466 return 1;
5467 }
5468
5469 device_name = grub_file_get_device_name(args[0]);
5470 if (!device_name)
5471 {
5472 goto fail;
5473 }
5474
5475 dev = grub_device_open(device_name);
5476 if (!dev)
5477 {
5478 goto fail;
5479 }
5480
5481 fs = grub_fs_probe(dev);
5482 if (!fs)
5483 {
5484 goto fail;
5485 }
5486
5487 pfsdir->dev = dev;
5488 pfsdir->fs = fs;
5489 pfsdir->curpos = 1;
5490 pfsdir->fullpath[0] = '/';
5491 fs->fs_dir(dev, "/", ventoy_collect_replace_initrd, pfsdir);
5492
5493 if (pfsdir->initrd[0])
5494 {
5495 debug("Replace initrd <%s> <%d %d>\n", pfsdir->initrd, pfsdir->dircnt, pfsdir->filecnt);
5496
5497 for (i = 0; i < (int)sizeof(pfsdir->initrd) && pfsdir->initrd[i]; i++)
5498 {
5499 if (pfsdir->initrd[i] == '/')
5500 {
5501 pfsdir->initrd[i] = '\\';
5502 }
5503 }
5504
5505 pos = (pfsdir->initrd[0] == '\\') ? pfsdir->initrd + 1 : pfsdir->initrd;
5506 grub_env_set(args[1], pos);
5507 }
5508 else
5509 {
5510 debug("Replace initrd NOT found <%s> <%d %d>\n", args[0], pfsdir->dircnt, pfsdir->filecnt);
5511 }
5512
5513 fail:
5514
5515 grub_check_free(pfsdir);
5516 grub_check_free(device_name);
5517 check_free(dev, grub_device_close);
5518
5519 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
5520 }
5521
5522 static grub_err_t ventoy_cmd_push_pager(grub_extcmd_context_t ctxt, int argc, char **args)
5523 {
5524 const char *pager = NULL;
5525
5526 (void)ctxt;
5527 (void)argc;
5528 (void)args;
5529
5530 pager = grub_env_get("pager");
5531 if (NULL == pager)
5532 {
5533 g_pager_flag = 1;
5534 grub_env_set("pager", "1");
5535 }
5536 else if (pager[0] == '1')
5537 {
5538 g_pager_flag = 0;
5539 }
5540 else
5541 {
5542 grub_snprintf(g_old_pager, sizeof(g_old_pager), "%s", pager);
5543 g_pager_flag = 2;
5544 grub_env_set("pager", "1");
5545 }
5546
5547 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
5548 }
5549
5550 static grub_err_t ventoy_cmd_pop_pager(grub_extcmd_context_t ctxt, int argc, char **args)
5551 {
5552 (void)ctxt;
5553 (void)argc;
5554 (void)args;
5555
5556 if (g_pager_flag == 1)
5557 {
5558 grub_env_unset("pager");
5559 }
5560 else if (g_pager_flag == 2)
5561 {
5562 grub_env_set("pager", g_old_pager);
5563 }
5564
5565 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
5566 }
5567
5568 static int ventoy_chk_case_file(const char *filename, const struct grub_dirhook_info *info, void *data)
5569 {
5570 if (g_json_case_mis_path[0])
5571 {
5572 return 1;
5573 }
5574
5575 if (0 == info->dir && grub_strcasecmp(filename, "ventoy.json") == 0)
5576 {
5577 grub_snprintf(g_json_case_mis_path, 32, "%s/%s", (char *)data, filename);
5578 return 1;
5579 }
5580 return 0;
5581 }
5582
5583 static int ventoy_chk_case_dir(const char *filename, const struct grub_dirhook_info *info, void *data)
5584 {
5585 char path[16];
5586 chk_case_fs_dir *fs_dir = (chk_case_fs_dir *)data;
5587
5588 if (g_json_case_mis_path[0])
5589 {
5590 return 1;
5591 }
5592
5593 if (info->dir && (filename[0] == 'v' || filename[0] == 'V'))
5594 {
5595 if (grub_strcasecmp(filename, "ventoy") == 0)
5596 {
5597 grub_snprintf(path, sizeof(path), "/%s", filename);
5598 fs_dir->fs->fs_dir(fs_dir->dev, path, ventoy_chk_case_file, path);
5599 if (g_json_case_mis_path[0])
5600 {
5601 return 1;
5602 }
5603 }
5604 }
5605
5606 return 0;
5607 }
5608
5609 static grub_err_t ventoy_cmd_chk_json_pathcase(grub_extcmd_context_t ctxt, int argc, char **args)
5610 {
5611 int fstype = 0;
5612 char *device_name = NULL;
5613 grub_device_t dev = NULL;
5614 grub_fs_t fs = NULL;
5615 chk_case_fs_dir fs_dir;
5616
5617 (void)ctxt;
5618 (void)argc;
5619 (void)args;
5620
5621 device_name = grub_file_get_device_name(args[0]);
5622 if (!device_name)
5623 {
5624 goto out;
5625 }
5626
5627 dev = grub_device_open(device_name);
5628 if (!dev)
5629 {
5630 goto out;
5631 }
5632
5633 fs = grub_fs_probe(dev);
5634 if (!fs)
5635 {
5636 goto out;
5637 }
5638
5639 fstype = ventoy_get_fs_type(fs->name);
5640 if (fstype == ventoy_fs_fat || fstype == ventoy_fs_exfat || fstype >= ventoy_fs_max)
5641 {
5642 goto out;
5643 }
5644
5645 g_json_case_mis_path[0] = 0;
5646 fs_dir.dev = dev;
5647 fs_dir.fs = fs;
5648 fs->fs_dir(dev, "/", ventoy_chk_case_dir, &fs_dir);
5649
5650 if (g_json_case_mis_path[0])
5651 {
5652 grub_env_set("VTOY_PLUGIN_PATH_CASE_MISMATCH", g_json_case_mis_path);
5653 }
5654
5655 out:
5656
5657 grub_check_free(device_name);
5658 check_free(dev, grub_device_close);
5659
5660 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
5661 }
5662
5663 static grub_err_t grub_cmd_gptpriority(grub_extcmd_context_t ctxt, int argc, char **args)
5664 {
5665 grub_disk_t disk;
5666 grub_partition_t part;
5667 char priority_str[3]; /* Maximum value 15 */
5668
5669 (void)ctxt;
5670
5671 if (argc < 2 || argc > 3)
5672 return grub_error (GRUB_ERR_BAD_ARGUMENT,
5673 "gptpriority DISKNAME PARTITIONNUM [VARNAME]");
5674
5675 /* Open the disk if it exists */
5676 disk = grub_disk_open (args[0]);
5677 if (!disk)
5678 {
5679 return grub_error (GRUB_ERR_BAD_ARGUMENT,
5680 "Not a disk");
5681 }
5682
5683 part = grub_partition_probe (disk, args[1]);
5684 if (!part)
5685 {
5686 grub_disk_close (disk);
5687 return grub_error (GRUB_ERR_BAD_ARGUMENT,
5688 "No such partition");
5689 }
5690
5691 if (grub_strcmp (part->partmap->name, "gpt"))
5692 {
5693 grub_disk_close (disk);
5694 return grub_error (GRUB_ERR_BAD_PART_TABLE,
5695 "Not a GPT partition");
5696 }
5697
5698 grub_snprintf (priority_str, sizeof(priority_str), "%u",
5699 (grub_uint32_t)((part->gpt_attrib >> 48) & 0xfULL));
5700
5701 if (argc == 3)
5702 {
5703 grub_env_set (args[2], priority_str);
5704 grub_env_export (args[2]);
5705 }
5706 else
5707 {
5708 grub_printf ("Priority is %s\n", priority_str);
5709 }
5710
5711 grub_disk_close (disk);
5712 return GRUB_ERR_NONE;
5713 }
5714
5715
5716 static grub_err_t grub_cmd_syslinux_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
5717 {
5718 int ret = 1;
5719 int joliet = 0;
5720 grub_file_t file = NULL;
5721 grub_uint32_t loadrba = 0;
5722 grub_uint32_t boot_catlog = 0;
5723 grub_uint8_t sector[512];
5724 boot_info_table *info = NULL;
5725
5726 (void)ctxt;
5727 (void)argc;
5728
5729 /* This also trigger a iso9660 fs parse */
5730 if (ventoy_check_file_exist("(loop)/isolinux/isolinux.cfg"))
5731 {
5732 return 0;
5733 }
5734
5735 joliet = grub_iso9660_is_joliet();
5736 if (joliet == 0)
5737 {
5738 return 1;
5739 }
5740
5741 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
5742 if (!file)
5743 {
5744 debug("failed to open %s\n", args[0]);
5745 return 1;
5746 }
5747
5748 boot_catlog = ventoy_get_iso_boot_catlog(file);
5749 if (boot_catlog == 0)
5750 {
5751 debug("no bootcatlog found %u\n", boot_catlog);
5752 goto out;
5753 }
5754
5755 loadrba = ventoy_get_bios_eltorito_rba(file, boot_catlog);
5756 if (loadrba == 0)
5757 {
5758 debug("no bios eltorito rba found %u\n", loadrba);
5759 goto out;
5760 }
5761
5762 grub_file_seek(file, loadrba * 2048);
5763 grub_file_read(file, sector, 512);
5764
5765 info = (boot_info_table *)sector;
5766 if (info->bi_data0 == 0x7c6ceafa &&
5767 info->bi_data1 == 0x90900000 &&
5768 info->bi_PrimaryVolumeDescriptor == 16 &&
5769 info->bi_BootFileLocation == loadrba)
5770 {
5771 debug("bootloader is syslinux, %u.\n", loadrba);
5772 ret = 0;
5773 }
5774
5775 out:
5776
5777 grub_file_close(file);
5778 grub_errno = GRUB_ERR_NONE;
5779 return ret;
5780 }
5781
5782 static grub_err_t grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt, int argc, char **args)
5783 {
5784 int n = 0;
5785 ventoy_vlnk_part *node;
5786
5787 (void)ctxt;
5788 (void)argc;
5789 (void)args;
5790
5791 for (node = g_vlnk_part_list; node; node = node->next)
5792 {
5793 grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
5794 ++n, node->device, node->disksig,
5795 (ulonglong)node->partoffset, (node->fs ? node->fs->name : "N/A"));
5796 }
5797
5798 return 0;
5799 }
5800
5801 static grub_err_t grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt, int argc, char **args)
5802 {
5803 int len = 0;
5804
5805 (void)ctxt;
5806
5807 if (argc == 1)
5808 {
5809 len = (int)grub_strlen(args[0]);
5810 if (grub_file_is_vlnk_suffix(args[0], len))
5811 {
5812 return 0;
5813 }
5814 }
5815
5816 return 1;
5817 }
5818
5819 static grub_err_t grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt, int argc, char **args)
5820 {
5821 int vlnk = 0;
5822 const char *name = NULL;
5823
5824 (void)ctxt;
5825
5826 if (argc == 2)
5827 {
5828 grub_env_unset(args[1]);
5829 name = grub_file_get_vlnk(args[0], &vlnk);
5830 if (vlnk)
5831 {
5832 debug("VLNK SRC: <%s>\n", args[0]);
5833 debug("VLNK DST: <%s>\n", name);
5834 grub_env_set(args[1], name);
5835 return 0;
5836 }
5837 }
5838
5839 return 1;
5840 }
5841
5842 static grub_err_t grub_cmd_check_vlnk(grub_extcmd_context_t ctxt, int argc, char **args)
5843 {
5844 int ret = 1;
5845 int len = 0;
5846 grub_file_t file = NULL;
5847 ventoy_vlnk vlnk;
5848 char dst[512];
5849
5850 (void)ctxt;
5851
5852 if (argc != 1)
5853 {
5854 goto out;
5855 }
5856
5857 len = (int)grub_strlen(args[0]);
5858 if (!grub_file_is_vlnk_suffix(args[0], len))
5859 {
5860 grub_printf("Invalid vlnk suffix\n");
5861 goto out;
5862 }
5863
5864 file = grub_file_open(args[0], VENTOY_FILE_TYPE | GRUB_FILE_TYPE_NO_VLNK);
5865 if (!file)
5866 {
5867 grub_printf("Failed to open %s\n", args[0]);
5868 goto out;
5869 }
5870
5871 if (file->size != 32768)
5872 {
5873 grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong)file->size);
5874 goto out;
5875 }
5876
5877 grub_memset(&vlnk, 0, sizeof(vlnk));
5878 grub_file_read(file, &vlnk, sizeof(vlnk));
5879
5880 ret = ventoy_check_vlnk_data(&vlnk, 1, dst, sizeof(dst));
5881
5882 out:
5883
5884 grub_refresh();
5885 check_free(file, grub_file_close);
5886 grub_errno = GRUB_ERR_NONE;
5887 return ret;
5888 }
5889
5890 static grub_err_t ventoy_iso_vd_id_clear(grub_extcmd_context_t ctxt, int argc, char **args)
5891 {
5892 (void)ctxt;
5893 (void)argc;
5894 (void)args;
5895
5896 g_iso_vd_id_publisher[0] = 0;
5897 g_iso_vd_id_prepare[0] = 0;
5898 g_iso_vd_id_application[0] = 0;
5899
5900 return 0;
5901 }
5902
5903 static grub_err_t ventoy_cmd_iso_vd_id_parse(grub_extcmd_context_t ctxt, int argc, char **args)
5904 {
5905 int ret = 1;
5906 int offset = 318;
5907 grub_file_t file = NULL;
5908
5909 (void)ctxt;
5910 (void)argc;
5911
5912 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
5913 if (!file)
5914 {
5915 grub_printf("Failed to open %s\n", args[0]);
5916 goto out;
5917 }
5918
5919 grub_file_seek(file, 16 * 2048 + offset);
5920 grub_file_read(file, g_iso_vd_id_publisher, 128);
5921
5922 offset += 128;
5923 grub_file_seek(file, 16 * 2048 + offset);
5924 grub_file_read(file, g_iso_vd_id_prepare, 128);
5925
5926 offset += 128;
5927 grub_file_seek(file, 16 * 2048 + offset);
5928 grub_file_read(file, g_iso_vd_id_application, 128);
5929
5930 out:
5931
5932 check_free(file, grub_file_close);
5933 grub_errno = GRUB_ERR_NONE;
5934 return ret;
5935 }
5936
5937 static grub_err_t ventoy_cmd_iso_vd_id_begin(grub_extcmd_context_t ctxt, int argc, char **args)
5938 {
5939 int ret = 1;
5940 char *id = g_iso_vd_id_publisher;
5941
5942 (void)ctxt;
5943 (void)argc;
5944
5945 if (args[0][0] == '1')
5946 {
5947 id = g_iso_vd_id_prepare;
5948 }
5949 else if (args[0][0] == '2')
5950 {
5951 id = g_iso_vd_id_application;
5952 }
5953
5954 if (args[1][0] == '0' && grub_strncasecmp(id, args[2], grub_strlen(args[2])) == 0)
5955 {
5956 ret = 0;
5957 }
5958
5959 if (args[1][0] == '1' && grub_strncmp(id, args[2], grub_strlen(args[2])) == 0)
5960 {
5961 ret = 0;
5962 }
5963
5964 grub_errno = GRUB_ERR_NONE;
5965 return ret;
5966 }
5967
5968 static grub_err_t ventoy_cmd_fn_mutex_lock(grub_extcmd_context_t ctxt, int argc, char **args)
5969 {
5970 (void)ctxt;
5971 (void)argc;
5972
5973 g_ventoy_fn_mutex = 0;
5974 if (argc == 1 && args[0][0] == '1' && args[0][1] == 0)
5975 {
5976 g_ventoy_fn_mutex = 1;
5977 }
5978
5979 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
5980 }
5981
5982 static grub_err_t ventoy_cmd_dump_rsv_page(grub_extcmd_context_t ctxt, int argc, char **args)
5983 {
5984 grub_uint64_t total;
5985 grub_uint64_t org_required;
5986 grub_uint64_t new_required;
5987
5988 (void)ctxt;
5989 (void)argc;
5990 (void)args;
5991
5992 #ifdef GRUB_MACHINE_EFI
5993 grub_efi_get_reserved_page_num(&total, &org_required, &new_required);
5994 grub_printf("Total pages: %llu\n", (unsigned long long)total);
5995 grub_printf("OrgReq pages: %llu\n", (unsigned long long)org_required);
5996 grub_printf("NewReq pages: %llu\n", (unsigned long long)new_required);
5997 #else
5998 (void)total;
5999 (void)org_required;
6000 (void)new_required;
6001 grub_printf("Non EFI mode!\n");
6002 #endif
6003
6004 grub_refresh();
6005
6006 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
6007 }
6008
6009 static grub_err_t ventoy_cmd_need_secondary_menu(grub_extcmd_context_t ctxt, int argc, char **args)
6010 {
6011 const char *env = NULL;
6012
6013 (void)ctxt;
6014 (void)argc;
6015
6016 if (g_ventoy_memdisk_mode || g_ventoy_grub2_mode || g_ventoy_wimboot_mode || g_ventoy_iso_raw)
6017 {
6018 return 1;
6019 }
6020
6021 if (ventoy_check_mode_by_name(args[0], "vtgrub2") ||
6022 ventoy_check_mode_by_name(args[0], "vtwimboot") ||
6023 ventoy_check_mode_by_name(args[0], "vtmemdisk") ||
6024 ventoy_check_mode_by_name(args[0], "vtnormal")
6025 )
6026 {
6027 return 1;
6028 }
6029
6030 env = grub_env_get("VTOY_SECONDARY_BOOT_MENU");
6031 if (env && env[0] == '0' && env[1] == 0)
6032 {
6033 return 1;
6034 }
6035
6036 return 0;
6037 }
6038
6039 static grub_err_t ventoy_cmd_show_secondary_menu(grub_extcmd_context_t ctxt, int argc, char **args)
6040 {
6041 int n = 0;
6042 int pos = 0;
6043 int len = 0;
6044 int select = 0;
6045 int timeout = 0;
6046 char *cmd = NULL;
6047 const char *env = NULL;
6048 ulonglong fsize = 0;
6049 char cfgfile[128];
6050 int seldata[16] = {0};
6051
6052 (void)ctxt;
6053 (void)argc;
6054
6055 len = 8 * VTOY_SIZE_1KB;
6056 cmd = (char *)grub_malloc(len);
6057 if (!cmd)
6058 {
6059 return 1;
6060 }
6061
6062 g_vtoy_secondary_need_recover = 0;
6063 grub_env_unset("VTOY_CHKSUM_FILE_PATH");
6064
6065 env = grub_env_get("VTOY_SECONDARY_TIMEOUT");
6066 if (env)
6067 {
6068 timeout = (int)grub_strtol(env, NULL, 10);
6069 }
6070
6071 if (timeout > 0)
6072 {
6073 vtoy_len_ssprintf(cmd, pos, len, "set timeout=%d\n", timeout);
6074 }
6075
6076 fsize = grub_strtoull(args[2], NULL, 10);
6077
6078 vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_NORMAL_MODE", "second_normal"); seldata[n++] = 1;
6079
6080 if (grub_strcmp(args[1], "Unix") != 0)
6081 {
6082 if (grub_strcmp(args[1], "Windows") == 0)
6083 {
6084 vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_WIMBOOT_MODE", "second_wimboot"); seldata[n++] = 2;
6085 }
6086 else
6087 {
6088 vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_GRUB2_MODE", "second_grub2"); seldata[n++] = 3;
6089 }
6090
6091 if (fsize <= VTOY_SIZE_1GB)
6092 {
6093 vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_MEMDISK_MODE", "second_memdisk"); seldata[n++] = 4;
6094 }
6095 }
6096
6097 vtoy_dummy_menuentry(cmd, pos, len, "@VTMENU_FILE_CHKSUM", "second_checksum"); seldata[n++] = 5;
6098
6099 do {
6100 g_ventoy_menu_esc = 1;
6101 g_ventoy_suppress_esc = 1;
6102 g_ventoy_suppress_esc_default = 0;
6103 g_ventoy_secondary_menu_on = 1;
6104 grub_snprintf(cfgfile, sizeof(cfgfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)cmd, pos);
6105 grub_script_execute_sourcecode(cfgfile);
6106 g_ventoy_menu_esc = 0;
6107 g_ventoy_suppress_esc = 0;
6108 g_ventoy_suppress_esc_default = 1;
6109 g_ventoy_secondary_menu_on = 0;
6110
6111 select = seldata[g_ventoy_last_entry];
6112
6113 if (select == 2)
6114 {
6115 g_ventoy_wimboot_mode = 1;
6116 g_vtoy_secondary_need_recover = 1;
6117 }
6118 else if (select == 3)
6119 {
6120 g_ventoy_grub2_mode = 1;
6121 g_vtoy_secondary_need_recover = 2;
6122 }
6123 else if (select == 4)
6124 {
6125 g_ventoy_memdisk_mode = 1;
6126 g_vtoy_secondary_need_recover = 3;
6127 }
6128 else if (select == 5)
6129 {
6130 grub_env_set("VTOY_CHKSUM_FILE_PATH", args[0]);
6131 grub_script_execute_sourcecode("configfile $vtoy_efi_part/grub/checksum.cfg");
6132 }
6133 }while (select == 5);
6134
6135 grub_free(cmd);
6136 return 0;
6137 }
6138
6139 static grub_err_t ventoy_cmd_secondary_recover_mode(grub_extcmd_context_t ctxt, int argc, char **args)
6140 {
6141 (void)ctxt;
6142 (void)argc;
6143 (void)args;
6144
6145 if (g_vtoy_secondary_need_recover == 1)
6146 {
6147 g_ventoy_wimboot_mode = 0;
6148 }
6149 else if (g_vtoy_secondary_need_recover == 2)
6150 {
6151 g_ventoy_grub2_mode = 0;
6152 }
6153 else if (g_vtoy_secondary_need_recover == 3)
6154 {
6155 g_ventoy_memdisk_mode = 0;
6156 }
6157
6158 g_vtoy_secondary_need_recover = 0;
6159
6160 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
6161 }
6162
6163 static grub_err_t ventoy_cmd_fs_ignore_case(grub_extcmd_context_t ctxt, int argc, char **args)
6164 {
6165 (void)ctxt;
6166 (void)argc;
6167
6168 if (args[0][0] == '0')
6169 {
6170 g_ventoy_case_insensitive = 0;
6171 }
6172 else
6173 {
6174 g_ventoy_case_insensitive = 1;
6175 }
6176
6177 return 0;
6178 }
6179
6180 static grub_err_t ventoy_cmd_init_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args)
6181 {
6182 (void)ctxt;
6183 (void)argc;
6184
6185 ventoy_plugin_load_menu_lang(1, args[0]);
6186 VENTOY_CMD_RETURN(0);
6187 }
6188
6189 static grub_err_t ventoy_cmd_load_menu_lang(grub_extcmd_context_t ctxt, int argc, char **args)
6190 {
6191 (void)ctxt;
6192 (void)argc;
6193
6194 ventoy_plugin_load_menu_lang(0, args[0]);
6195 VENTOY_CMD_RETURN(0);
6196 }
6197
6198 int ventoy_env_init(void)
6199 {
6200 int i;
6201 char buf[64];
6202
6203 grub_env_set("vtdebug_flag", "");
6204
6205 g_part_list_buf = grub_malloc(VTOY_PART_BUF_LEN);
6206 g_tree_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
6207 g_list_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
6208 for (i = 0; i < VTOY_MAX_CONF_REPLACE; i++)
6209 {
6210 g_conf_replace_new_buf[i] = grub_malloc(vtoy_max_replace_file_size);
6211 }
6212
6213 ventoy_filt_register(0, ventoy_wrapper_open);
6214
6215 g_grub_param = (ventoy_grub_param *)grub_zalloc(sizeof(ventoy_grub_param));
6216 if (g_grub_param)
6217 {
6218 g_grub_param->grub_env_get = grub_env_get;
6219 g_grub_param->grub_env_set = (grub_env_set_pf)grub_env_set;
6220 g_grub_param->grub_env_printf = (grub_env_printf_pf)grub_printf;
6221 grub_snprintf(buf, sizeof(buf), "%p", g_grub_param);
6222 grub_env_set("env_param", buf);
6223 grub_env_set("ventoy_env_param", buf);
6224
6225 grub_env_export("env_param");
6226 grub_env_export("ventoy_env_param");
6227 }
6228
6229 grub_env_export("vtoy_winpeshl_ini_addr");
6230 grub_env_export("vtoy_winpeshl_ini_size");
6231
6232 grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)ventoy_chain_file_size);
6233 grub_env_set("vtoy_chain_file_size", buf);
6234 grub_env_export("vtoy_chain_file_size");
6235
6236 grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)ventoy_chain_file_read);
6237 grub_env_set("vtoy_chain_file_read", buf);
6238 grub_env_export("vtoy_chain_file_read");
6239
6240 grub_snprintf(buf, sizeof(buf), "0x%lx", (ulong)ventoy_get_vmenu_title);
6241 grub_env_set("VTOY_VMENU_FUNC_ADDR", buf);
6242 grub_env_export("VTOY_VMENU_FUNC_ADDR");
6243
6244 return 0;
6245 }
6246
6247
6248
6249 static cmd_para ventoy_cmds[] =
6250 {
6251 { "vt_browser_disk", ventoy_cmd_browser_disk, 0, NULL, "", "", NULL },
6252 { "vt_browser_dir", ventoy_cmd_browser_dir, 0, NULL, "", "", NULL },
6253 { "vt_incr", ventoy_cmd_incr, 0, NULL, "{Var} {INT}", "Increase integer variable", NULL },
6254 { "vt_mod", ventoy_cmd_mod, 0, NULL, "{Int} {Int} {Var}", "mod integer variable", NULL },
6255 { "vt_strstr", ventoy_cmd_strstr, 0, NULL, "", "", NULL },
6256 { "vt_str_begin", ventoy_cmd_strbegin, 0, NULL, "", "", NULL },
6257 { "vt_str_casebegin", ventoy_cmd_strcasebegin, 0, NULL, "", "", NULL },
6258 { "vt_debug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
6259 { "vtdebug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
6260 { "vtbreak", ventoy_cmd_break, 0, NULL, "{level}", "set debug break", NULL },
6261 { "vt_cmp", ventoy_cmd_cmp, 0, NULL, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL },
6262 { "vt_device", ventoy_cmd_device, 0, NULL, "path var", "", NULL },
6263 { "vt_check_compatible", ventoy_cmd_check_compatible, 0, NULL, "", "", NULL },
6264 { "vt_list_img", ventoy_cmd_list_img, 0, NULL, "{device} {cntvar}", "find all iso file in device", NULL },
6265 { "vt_clear_img", ventoy_cmd_clear_img, 0, NULL, "", "clear image list", NULL },
6266 { "vt_img_name", ventoy_cmd_img_name, 0, NULL, "{imageID} {var}", "get image name", NULL },
6267 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path, 0, NULL, "{var}", "get chosen img path", NULL },
6268 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path, 0, NULL, "{var}", "select chosen img path", NULL },
6269 { "vt_img_sector", ventoy_cmd_img_sector, 0, NULL, "{imageName}", "", NULL },
6270 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector, 0, NULL, "", "", NULL },
6271 { "vt_load_wimboot", ventoy_cmd_load_wimboot, 0, NULL, "", "", NULL },
6272 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot, 0, NULL, "", "", NULL },
6273 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot, 0, NULL, "", "", NULL },
6274 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data, 0, NULL, "", "", NULL },
6275 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type, 0, NULL, "", "", NULL },
6276 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot, 0, NULL, "", "", NULL },
6277 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot, 0, NULL, "", "", NULL },
6278
6279 { "vt_skip_svd", ventoy_cmd_skip_svd, 0, NULL, "", "", NULL },
6280 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64, 0, NULL, "", "", NULL },
6281 { "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
6282 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio, 0, NULL, "", "", NULL },
6283 { "vt_push_last_entry", ventoy_cmd_push_last_entry, 0, NULL, "", "", NULL },
6284 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry, 0, NULL, "", "", NULL },
6285 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver, 0, NULL, "", "", NULL },
6286
6287 { "vt_load_part_table", ventoy_cmd_load_part_table, 0, NULL, "", "", NULL },
6288 { "vt_check_part_exist", ventoy_cmd_part_exist, 0, NULL, "", "", NULL },
6289 { "vt_get_fs_label", ventoy_cmd_get_fs_label, 0, NULL, "", "", NULL },
6290 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file, 0, NULL, "", "", NULL },
6291 { "vt_fs_enum_1st_dir", ventoy_cmd_fs_enum_1st_dir, 0, NULL, "", "", NULL },
6292 { "vt_file_basename", ventoy_cmd_basename, 0, NULL, "", "", NULL },
6293 { "vt_file_basefile", ventoy_cmd_basefile, 0, NULL, "", "", NULL },
6294 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode, 0, NULL, "", "", NULL },
6295 { "vt_get_video_mode", ventoy_cmd_get_video_mode, 0, NULL, "", "", NULL },
6296 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode, 0, NULL, "", "", NULL },
6297
6298
6299 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd, 0, NULL, "", "", NULL },
6300 { "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
6301 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
6302 { "vt_check_mode", ventoy_cmd_check_mode, 0, NULL, "", "", NULL },
6303 { "vt_dump_img_list", ventoy_cmd_dump_img_list, 0, NULL, "", "", NULL },
6304 { "vt_dump_injection", ventoy_cmd_dump_injection, 0, NULL, "", "", NULL },
6305 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install, 0, NULL, "", "", NULL },
6306 { "vt_dump_persistence", ventoy_cmd_dump_persistence, 0, NULL, "", "", NULL },
6307 { "vt_select_auto_install", ventoy_cmd_sel_auto_install, 0, NULL, "", "", NULL },
6308 { "vt_select_persistence", ventoy_cmd_sel_persistence, 0, NULL, "", "", NULL },
6309 { "vt_select_conf_replace", ventoy_select_conf_replace, 0, NULL, "", "", NULL },
6310
6311 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
6312 { "vt_iso9660_isjoliet", ventoy_cmd_iso9660_is_joliet, 0, NULL, "", "", NULL },
6313 { "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
6314 { "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
6315 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem, 0, NULL, "", "", NULL },
6316 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk, 0, NULL, "", "", NULL },
6317 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso, 0, NULL, "", "", NULL },
6318
6319 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
6320 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
6321 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file, 0, NULL, "", "", NULL },
6322 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list, 0, NULL, "", "", NULL },
6323 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list, 0, NULL, "", "", NULL },
6324 { "vt_linux_initrd_count", ventoy_cmd_initrd_count, 0, NULL, "", "", NULL },
6325 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count, 0, NULL, "", "", NULL },
6326 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd, 0, NULL, "", "", NULL },
6327 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data, 0, NULL, "", "", NULL },
6328 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index, 0, NULL, "", "", NULL },
6329
6330 { "vt_windows_reset", ventoy_cmd_wimdows_reset, 0, NULL, "", "", NULL },
6331 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data, 0, NULL, "", "", NULL },
6332 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data, 0, NULL, "", "", NULL },
6333 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch, 0, NULL, "", "", NULL },
6334 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch, 0, NULL, "", "", NULL },
6335 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count, 0, NULL, "", "", NULL },
6336 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch, 0, NULL, "", "", NULL },
6337 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable, 0, NULL, "", "", NULL },
6338 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data, 0, NULL, "", "", NULL },
6339
6340 { "vt_add_replace_file", ventoy_cmd_add_replace_file, 0, NULL, "", "", NULL },
6341 { "vt_get_replace_file_cnt", ventoy_cmd_get_replace_file_cnt, 0, NULL, "", "", NULL },
6342 { "vt_test_block_list", ventoy_cmd_test_block_list, 0, NULL, "", "", NULL },
6343 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase, 0, NULL, "", "", NULL },
6344
6345
6346 { "vt_load_plugin", ventoy_cmd_load_plugin, 0, NULL, "", "", NULL },
6347 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json, 0, NULL, "", "", NULL },
6348 { "vt_check_password", ventoy_cmd_check_password, 0, NULL, "", "", NULL },
6349
6350 { "vt_1st_line", ventoy_cmd_read_1st_line, 0, NULL, "", "", NULL },
6351 { "vt_file_strstr", ventoy_cmd_file_strstr, 0, NULL, "", "", NULL },
6352 { "vt_img_part_info", ventoy_cmd_img_part_info, 0, NULL, "", "", NULL },
6353
6354
6355 { "vt_parse_iso_volume", ventoy_cmd_parse_volume, 0, NULL, "", "", NULL },
6356 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date, 0, NULL, "", "", NULL },
6357 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver, 0, NULL, "", "", NULL },
6358 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver, 0, NULL, "", "", NULL },
6359 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf, 0, NULL, "", "", NULL },
6360 { "vt_unix_reset", ventoy_cmd_unix_reset, 0, NULL, "", "", NULL },
6361 { "vt_unix_check_vlnk", ventoy_cmd_unix_check_vlnk, 0, NULL, "", "", NULL },
6362 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf, 0, NULL, "", "", NULL },
6363 { "vt_unix_replace_grub_conf", ventoy_cmd_unix_replace_grub_conf, 0, NULL, "", "", NULL },
6364 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko, 0, NULL, "", "", NULL },
6365 { "vt_unix_ko_fillmap", ventoy_cmd_unix_ko_fillmap, 0, NULL, "", "", NULL },
6366 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc, 0, NULL, "", "", NULL },
6367 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko, 0, NULL, "", "", NULL },
6368 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data, 0, NULL, "", "", NULL },
6369
6370 { "vt_img_hook_root", ventoy_cmd_img_hook_root, 0, NULL, "", "", NULL },
6371 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root, 0, NULL, "", "", NULL },
6372 { "vt_acpi_param", ventoy_cmd_acpi_param, 0, NULL, "", "", NULL },
6373 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var, 0, NULL, "", "", NULL },
6374 { "vt_clear_key", ventoy_cmd_clear_key, 0, NULL, "", "", NULL },
6375 { "vt_img_check_range", ventoy_cmd_img_check_range, 0, NULL, "", "", NULL },
6376 { "vt_is_pe64", ventoy_cmd_is_pe64, 0, NULL, "", "", NULL },
6377 { "vt_sel_wimboot", ventoy_cmd_sel_wimboot, 0, NULL, "", "", NULL },
6378 { "vt_set_wim_load_prompt", ventoy_cmd_set_wim_prompt, 0, NULL, "", "", NULL },
6379 { "vt_set_theme", ventoy_cmd_set_theme, 0, NULL, "", "", NULL },
6380 { "vt_set_theme_path", ventoy_cmd_set_theme_path, 0, NULL, "", "", NULL },
6381 { "vt_select_theme_cfg", ventoy_cmd_select_theme_cfg, 0, NULL, "", "", NULL },
6382
6383 { "vt_get_efi_vdisk_offset", ventoy_cmd_get_efivdisk_offset, 0, NULL, "", "", NULL },
6384 { "vt_search_replace_initrd", ventoy_cmd_search_replace_initrd, 0, NULL, "", "", NULL },
6385 { "vt_push_pager", ventoy_cmd_push_pager, 0, NULL, "", "", NULL },
6386 { "vt_pop_pager", ventoy_cmd_pop_pager, 0, NULL, "", "", NULL },
6387 { "vt_check_json_path_case", ventoy_cmd_chk_json_pathcase, 0, NULL, "", "", NULL },
6388 { "vt_append_extra_sector", ventoy_cmd_append_ext_sector, 0, NULL, "", "", NULL },
6389 { "gptpriority", grub_cmd_gptpriority, 0, NULL, "", "", NULL },
6390 { "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet, 0, NULL, "", "", NULL },
6391 { "vt_vlnk_check", grub_cmd_check_vlnk, 0, NULL, "", "", NULL },
6392 { "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part, 0, NULL, "", "", NULL },
6393 { "vt_is_vlnk_name", grub_cmd_is_vlnk_name, 0, NULL, "", "", NULL },
6394 { "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst, 0, NULL, "", "", NULL },
6395 { "vt_set_fake_vlnk", ventoy_cmd_set_fake_vlnk, 0, NULL, "", "", NULL },
6396 { "vt_reset_fake_vlnk", ventoy_cmd_reset_fake_vlnk, 0, NULL, "", "", NULL },
6397 { "vt_iso_vd_id_parse", ventoy_cmd_iso_vd_id_parse, 0, NULL, "", "", NULL },
6398 { "vt_iso_vd_id_clear", ventoy_iso_vd_id_clear, 0, NULL, "", "", NULL },
6399 { "vt_iso_vd_id_begin", ventoy_cmd_iso_vd_id_begin, 0, NULL, "", "", NULL },
6400 { "vt_fn_mutex_lock", ventoy_cmd_fn_mutex_lock, 0, NULL, "", "", NULL },
6401 { "vt_efi_dump_rsv_page", ventoy_cmd_dump_rsv_page, 0, NULL, "", "", NULL },
6402 { "vt_is_standard_winiso", ventoy_cmd_is_standard_winiso, 0, NULL, "", "", NULL },
6403 { "vt_sel_winpe_wim", ventoy_cmd_sel_winpe_wim, 0, NULL, "", "", NULL },
6404 { "vt_need_secondary_menu", ventoy_cmd_need_secondary_menu, 0, NULL, "", "", NULL },
6405 { "vt_show_secondary_menu", ventoy_cmd_show_secondary_menu, 0, NULL, "", "", NULL },
6406 { "vt_fs_ignore_case", ventoy_cmd_fs_ignore_case, 0, NULL, "", "", NULL },
6407 { "vt_systemd_menu", ventoy_cmd_linux_systemd_menu, 0, NULL, "", "", NULL },
6408 { "vt_limine_menu", ventoy_cmd_linux_limine_menu, 0, NULL, "", "", NULL },
6409 { "vt_secondary_recover_mode", ventoy_cmd_secondary_recover_mode, 0, NULL, "", "", NULL },
6410 { "vt_load_menu_lang", ventoy_cmd_load_menu_lang, 0, NULL, "", "", NULL },
6411 { "vt_init_menu_lang", ventoy_cmd_init_menu_lang, 0, NULL, "", "", NULL },
6412 { "vt_cur_menu_lang", ventoy_cmd_cur_menu_lang, 0, NULL, "", "", NULL },
6413 };
6414
6415 int ventoy_register_all_cmd(void)
6416 {
6417 grub_uint32_t i;
6418 cmd_para *cur = NULL;
6419
6420 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
6421 {
6422 cur = ventoy_cmds + i;
6423 cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags,
6424 cur->summary, cur->description, cur->parser);
6425 }
6426
6427 return 0;
6428 }
6429
6430 int ventoy_unregister_all_cmd(void)
6431 {
6432 grub_uint32_t i;
6433
6434 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
6435 {
6436 grub_unregister_extcmd(ventoy_cmds[i].cmd);
6437 }
6438
6439 return 0;
6440 }
6441
6442