]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c
9f0a8b8ffdbdf8b0dcacb2a2e069643c0b126e71
[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/ventoy.h>
49 #include "ventoy_def.h"
50 #include "miniz.h"
51
52 GRUB_MOD_LICENSE ("GPLv3+");
53
54 initrd_info *g_initrd_img_list = NULL;
55 initrd_info *g_initrd_img_tail = NULL;
56 int g_initrd_img_count = 0;
57 int g_valid_initrd_count = 0;
58 int g_default_menu_mode = 0;
59 int g_filt_dot_underscore_file = 0;
60 int g_sort_case_sensitive = 0;
61 int g_tree_view_menu_style = 0;
62 static grub_file_t g_old_file;
63 static int g_ventoy_last_entry_back;
64
65 char g_iso_path[256];
66 char g_img_swap_tmp_buf[1024];
67 img_info g_img_swap_tmp;
68 img_info *g_ventoy_img_list = NULL;
69
70 int g_ventoy_img_count = 0;
71
72 grub_device_t g_enum_dev = NULL;
73 grub_fs_t g_enum_fs = NULL;
74 int g_img_max_search_level = -1;
75 img_iterator_node g_img_iterator_head;
76 img_iterator_node *g_img_iterator_tail = NULL;
77
78 grub_uint8_t g_ventoy_break_level = 0;
79 grub_uint8_t g_ventoy_debug_level = 0;
80 grub_uint8_t g_ventoy_chain_type = 0;
81
82 grub_uint8_t *g_ventoy_cpio_buf = NULL;
83 grub_uint32_t g_ventoy_cpio_size = 0;
84 cpio_newc_header *g_ventoy_initrd_head = NULL;
85 grub_uint8_t *g_ventoy_runtime_buf = NULL;
86
87 int g_plugin_image_list = 0;
88
89 ventoy_grub_param *g_grub_param = NULL;
90
91 ventoy_guid g_ventoy_guid = VENTOY_GUID;
92
93 ventoy_img_chunk_list g_img_chunk_list;
94
95 int g_wimboot_enable = 0;
96 ventoy_img_chunk_list g_wimiso_chunk_list;
97 char *g_wimiso_path = NULL;
98
99 int g_vhdboot_enable = 0;
100
101 grub_uint64_t g_conf_replace_offset = 0;
102 grub_uint64_t g_svd_replace_offset = 0;
103 conf_replace *g_conf_replace_node = NULL;
104 grub_uint8_t *g_conf_replace_new_buf = NULL;
105 int g_conf_replace_new_len = 0;
106 int g_conf_replace_new_len_align = 0;
107
108 ventoy_gpt_info *g_ventoy_part_info = NULL;
109 grub_uint64_t g_ventoy_disk_size = 0;
110 grub_uint64_t g_ventoy_disk_part_size[2];
111
112 static char *g_tree_script_buf = NULL;
113 static int g_tree_script_pos = 0;
114
115 static char *g_list_script_buf = NULL;
116 static int g_list_script_pos = 0;
117
118 static char *g_part_list_buf = NULL;
119 static int g_part_list_pos = 0;
120
121 static int g_video_mode_max = 0;
122 static int g_video_mode_num = 0;
123 static ventoy_video_mode *g_video_mode_list = NULL;
124
125 static int g_enumerate_time_checked = 0;
126 static grub_uint64_t g_enumerate_start_time_ms;
127 static grub_uint64_t g_enumerate_finish_time_ms;
128 static int g_vtoy_file_flt[VTOY_FILE_FLT_BUTT] = {0};
129
130 static const char *g_menu_class[] =
131 {
132 "vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
133 };
134
135 static const char *g_menu_prefix[] =
136 {
137 "iso", "wim", "efi", "img", "vhd", "vtoy"
138 };
139
140 static int ventoy_get_fs_type(const char *fs)
141 {
142 if (NULL == fs)
143 {
144 return ventoy_fs_max;
145 }
146 else if (grub_strncmp(fs, "exfat", 5) == 0)
147 {
148 return ventoy_fs_exfat;
149 }
150 else if (grub_strncmp(fs, "ntfs", 4) == 0)
151 {
152 return ventoy_fs_ntfs;
153 }
154 else if (grub_strncmp(fs, "ext", 3) == 0)
155 {
156 return ventoy_fs_ext;
157 }
158 else if (grub_strncmp(fs, "xfs", 3) == 0)
159 {
160 return ventoy_fs_xfs;
161 }
162 else if (grub_strncmp(fs, "udf", 3) == 0)
163 {
164 return ventoy_fs_udf;
165 }
166 else if (grub_strncmp(fs, "fat", 3) == 0)
167 {
168 return ventoy_fs_fat;
169 }
170
171 return ventoy_fs_max;
172 }
173
174 static int ventoy_string_check(const char *str, grub_char_check_func check)
175 {
176 if (!str)
177 {
178 return 0;
179 }
180
181 for ( ; *str; str++)
182 {
183 if (!check(*str))
184 {
185 return 0;
186 }
187 }
188
189 return 1;
190 }
191
192
193 static grub_ssize_t ventoy_fs_read(grub_file_t file, char *buf, grub_size_t len)
194 {
195 grub_memcpy(buf, (char *)file->data + file->offset, len);
196 return len;
197 }
198
199 static int ventoy_control_get_flag(const char *key)
200 {
201 const char *val = ventoy_get_env(key);
202
203 if (val && val[0] == '1' && val[1] == 0)
204 {
205 return 1;
206 }
207 return 0;
208 }
209
210 static grub_err_t ventoy_fs_close(grub_file_t file)
211 {
212 grub_file_close(g_old_file);
213 grub_free(file->data);
214
215 file->device = 0;
216 file->name = 0;
217
218 return 0;
219 }
220
221 static int ventoy_video_hook(const struct grub_video_mode_info *info, void *hook_arg)
222 {
223 int i;
224
225 (void)hook_arg;
226
227 if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
228 {
229 return 0;
230 }
231
232 for (i = 0; i < g_video_mode_num; i++)
233 {
234 if (g_video_mode_list[i].width == info->width &&
235 g_video_mode_list[i].height == info->height &&
236 g_video_mode_list[i].bpp == info->bpp)
237 {
238 return 0;
239 }
240 }
241
242 g_video_mode_list[g_video_mode_num].width = info->width;
243 g_video_mode_list[g_video_mode_num].height = info->height;
244 g_video_mode_list[g_video_mode_num].bpp = info->bpp;
245 g_video_mode_num++;
246
247 if (g_video_mode_num == g_video_mode_max)
248 {
249 g_video_mode_max *= 2;
250 g_video_mode_list = grub_realloc(g_video_mode_list, g_video_mode_max * sizeof(ventoy_video_mode));
251 }
252
253 return 0;
254 }
255
256 static int ventoy_video_mode_cmp(ventoy_video_mode *v1, ventoy_video_mode *v2)
257 {
258 if (v1->bpp == v2->bpp)
259 {
260 if (v1->width == v2->width)
261 {
262 if (v1->height == v2->height)
263 {
264 return 0;
265 }
266 else
267 {
268 return (v1->height < v2->height) ? -1 : 1;
269 }
270 }
271 else
272 {
273 return (v1->width < v2->width) ? -1 : 1;
274 }
275 }
276 else
277 {
278 return (v1->bpp < v2->bpp) ? -1 : 1;
279 }
280 }
281
282 static int ventoy_enum_video_mode(void)
283 {
284 int i, j;
285 grub_video_adapter_t adapter;
286 grub_video_driver_id_t id;
287 ventoy_video_mode mode;
288
289 g_video_mode_num = 0;
290 g_video_mode_max = 1024;
291 g_video_mode_list = grub_malloc(sizeof(ventoy_video_mode) * g_video_mode_max);
292 if (!g_video_mode_list)
293 {
294 return 0;
295 }
296
297 #ifdef GRUB_MACHINE_PCBIOS
298 grub_dl_load ("vbe");
299 #endif
300
301 id = grub_video_get_driver_id ();
302
303 FOR_VIDEO_ADAPTERS (adapter)
304 {
305 if (!adapter->iterate ||
306 (adapter->id != id && (id != GRUB_VIDEO_DRIVER_NONE ||
307 adapter->init() != GRUB_ERR_NONE)))
308 {
309 continue;
310 }
311
312 adapter->iterate(ventoy_video_hook, NULL);
313
314 if (adapter->id != id)
315 {
316 adapter->fini();
317 }
318 }
319
320 /* sort video mode */
321 for (i = 0; i < g_video_mode_num; i++)
322 for (j = i + 1; j < g_video_mode_num; j++)
323 {
324 if (ventoy_video_mode_cmp(g_video_mode_list + i, g_video_mode_list + j) < 0)
325 {
326 grub_memcpy(&mode, g_video_mode_list + i, sizeof(ventoy_video_mode));
327 grub_memcpy(g_video_mode_list + i, g_video_mode_list + j, sizeof(ventoy_video_mode));
328 grub_memcpy(g_video_mode_list + j, &mode, sizeof(ventoy_video_mode));
329 }
330 }
331
332 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
333 }
334
335 static grub_file_t ventoy_wrapper_open(grub_file_t rawFile, enum grub_file_type type)
336 {
337 int len;
338 grub_file_t file;
339 static struct grub_fs vtoy_fs =
340 {
341 .name = "vtoy",
342 .fs_dir = 0,
343 .fs_open = 0,
344 .fs_read = ventoy_fs_read,
345 .fs_close = ventoy_fs_close,
346 .fs_label = 0,
347 .next = 0
348 };
349
350 if (type != 52)
351 {
352 return rawFile;
353 }
354
355 file = (grub_file_t)grub_zalloc(sizeof (*file));
356 if (!file)
357 {
358 return 0;
359 }
360
361 file->data = grub_malloc(rawFile->size + 4096);
362 if (!file->data)
363 {
364 return 0;
365 }
366
367 grub_file_read(rawFile, file->data, rawFile->size);
368 len = ventoy_fill_data(4096, (char *)file->data + rawFile->size);
369
370 g_old_file = rawFile;
371
372 file->size = rawFile->size + len;
373 file->device = rawFile->device;
374 file->fs = &vtoy_fs;
375 file->not_easily_seekable = 1;
376
377 return file;
378 }
379
380 static int ventoy_check_decimal_var(const char *name, long *value)
381 {
382 const char *value_str = NULL;
383
384 value_str = grub_env_get(name);
385 if (NULL == value_str)
386 {
387 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s not found", name);
388 }
389
390 if (!ventoy_is_decimal(value_str))
391 {
392 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s value '%s' is not an integer", name, value_str);
393 }
394
395 *value = grub_strtol(value_str, NULL, 10);
396
397 return GRUB_ERR_NONE;
398 }
399
400 grub_uint64_t ventoy_get_vtoy_partsize(int part)
401 {
402 grub_uint64_t sectors;
403
404 if (grub_strncmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
405 {
406 sectors = g_ventoy_part_info->PartTbl[part].LastLBA + 1 - g_ventoy_part_info->PartTbl[part].StartLBA;
407 }
408 else
409 {
410 sectors = g_ventoy_part_info->MBR.PartTbl[part].SectorCount;
411 }
412
413 return sectors * 512;
414 }
415
416 static int ventoy_load_efiboot_template(char **buf, int *datalen, int *direntoff)
417 {
418 int len;
419 grub_file_t file;
420 char exec[128];
421 char *data = NULL;
422 grub_uint32_t offset;
423
424 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
425 if (file == NULL)
426 {
427 debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
428 return 1;
429 }
430
431 len = (int)file->size;
432
433 data = (char *)grub_malloc(file->size);
434 if (!data)
435 {
436 return 1;
437 }
438
439 grub_file_read(file, data, file->size);
440 grub_file_close(file);
441
442 grub_snprintf(exec, sizeof(exec), "loopback efiboot mem:0x%llx:size:%d", (ulonglong)(ulong)data, len);
443 grub_script_execute_sourcecode(exec);
444
445 file = grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD);
446 offset = (grub_uint32_t)grub_iso9660_get_last_file_dirent_pos(file);
447 grub_file_close(file);
448
449 grub_script_execute_sourcecode("loopback -d efiboot");
450
451 *buf = data;
452 *datalen = len;
453 *direntoff = offset + 2;
454
455 return 0;
456 }
457
458 static int ventoy_set_check_result(int ret)
459 {
460 char buf[32];
461
462 grub_snprintf(buf, sizeof(buf), "%d", (ret & 0x7FFF));
463 grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf);
464 grub_env_export("VTOY_CHKDEV_RESULT_STRING");
465
466 if (ret)
467 {
468 grub_printf(VTOY_WARNING"\n");
469 grub_printf(VTOY_WARNING"\n");
470 grub_printf(VTOY_WARNING"\n\n\n");
471
472 grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret);
473 grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
474
475 grub_printf("\n\nWill exit after 10 seconds ...... ");
476 grub_refresh();
477 grub_sleep(10);
478 }
479
480 return ret;
481 }
482
483 static int ventoy_check_official_device(grub_device_t dev)
484 {
485 int workaround = 0;
486 grub_file_t file;
487 grub_uint64_t offset;
488 char devname[64];
489 grub_fs_t fs;
490 grub_device_t dev2;
491 char *label = NULL;
492 struct grub_partition *partition;
493
494 if (dev->disk == NULL || dev->disk->partition == NULL)
495 {
496 return ventoy_set_check_result(1 | 0x1000);
497 }
498
499 if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev->disk->name) ||
500 0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev->disk->name) ||
501 0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
502 {
503 #ifndef GRUB_MACHINE_EFI
504 if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev->disk->name) ||
505 0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev->disk->name) ||
506 0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
507 {
508 return ventoy_set_check_result(2 | 0x1000);
509 }
510 else
511 {
512 workaround = 1;
513 }
514 #endif
515 }
516
517 /* We must have partition 2 */
518 if (workaround)
519 {
520 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
521 }
522 else
523 {
524 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(%s,2)/ventoy/ventoy.cpio", dev->disk->name);
525 }
526 if (!file)
527 {
528 return ventoy_set_check_result(3 | 0x1000);
529 }
530
531 if (NULL == grub_strstr(file->fs->name, "fat"))
532 {
533 grub_file_close(file);
534 return ventoy_set_check_result(4 | 0x1000);
535 }
536
537 partition = dev->disk->partition;
538 if (partition->number != 0 || partition->start != 2048)
539 {
540 return ventoy_set_check_result(5);
541 }
542
543 if (workaround)
544 {
545 if (grub_strncmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
546 {
547 ventoy_gpt_part_tbl *PartTbl = g_ventoy_part_info->PartTbl;
548 if (PartTbl[1].StartLBA != PartTbl[0].LastLBA + 1 ||
549 (PartTbl[1].LastLBA + 1 - PartTbl[1].StartLBA) != 65536)
550 {
551 grub_file_close(file);
552 return ventoy_set_check_result(6);
553 }
554 }
555 else
556 {
557 ventoy_part_table *PartTbl = g_ventoy_part_info->MBR.PartTbl;
558 if (PartTbl[1].StartSectorId != PartTbl[0].StartSectorId + PartTbl[0].SectorCount ||
559 PartTbl[1].SectorCount != 65536)
560 {
561 grub_file_close(file);
562 return ventoy_set_check_result(6);
563 }
564 }
565 }
566 else
567 {
568 offset = partition->start + partition->len;
569 partition = file->device->disk->partition;
570 if ((partition->number != 1) || (partition->len != 65536) || (offset != partition->start))
571 {
572 grub_file_close(file);
573 return ventoy_set_check_result(7);
574 }
575 }
576
577 grub_file_close(file);
578
579 if (workaround == 0)
580 {
581 grub_snprintf(devname, sizeof(devname), "%s,2", dev->disk->name);
582 dev2 = grub_device_open(devname);
583 if (!dev2)
584 {
585 return ventoy_set_check_result(8);
586 }
587
588 fs = grub_fs_probe(dev2);
589 if (!fs)
590 {
591 grub_device_close(dev2);
592 return ventoy_set_check_result(9);
593 }
594
595 fs->fs_label(dev2, &label);
596 if ((!label) || grub_strncmp("VTOYEFI", label, 7))
597 {
598 grub_device_close(dev2);
599 return ventoy_set_check_result(10);
600 }
601
602 grub_device_close(dev2);
603 }
604
605 return ventoy_set_check_result(0);
606 }
607
608 static int ventoy_check_ignore_flag(const char *filename, const struct grub_dirhook_info *info, void *data)
609 {
610 if (0 == info->dir)
611 {
612 if (filename && filename[0] == '.' && 0 == grub_strncmp(filename, ".ventoyignore", 13))
613 {
614 *((int *)data) = 1;
615 return 0;
616 }
617 }
618
619 return 0;
620 }
621
622 grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...)
623 {
624 grub_uint64_t size = 0;
625 grub_file_t file;
626 va_list ap;
627 char fullpath[256] = {0};
628
629 va_start (ap, fmt);
630 grub_vsnprintf(fullpath, 255, fmt, ap);
631 va_end (ap);
632
633 file = grub_file_open(fullpath, VENTOY_FILE_TYPE);
634 if (!file)
635 {
636 debug("grub_file_open failed <%s>\n", fullpath);
637 grub_errno = 0;
638 return 0;
639 }
640
641 size = file->size;
642 grub_file_close(file);
643 return size;
644 }
645
646 grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...)
647 {
648 va_list ap;
649 grub_file_t file;
650 char fullpath[256] = {0};
651
652 va_start (ap, fmt);
653 grub_vsnprintf(fullpath, 255, fmt, ap);
654 va_end (ap);
655
656 file = grub_file_open(fullpath, type);
657 if (!file)
658 {
659 debug("grub_file_open failed <%s> %d\n", fullpath, grub_errno);
660 grub_errno = 0;
661 }
662
663 return file;
664 }
665
666 int ventoy_is_file_exist(const char *fmt, ...)
667 {
668 va_list ap;
669 int len;
670 char *pos = NULL;
671 char buf[256] = {0};
672
673 grub_snprintf(buf, sizeof(buf), "%s", "[ -f \"");
674 pos = buf + 6;
675
676 va_start (ap, fmt);
677 len = grub_vsnprintf(pos, 255, fmt, ap);
678 va_end (ap);
679
680 grub_strncpy(pos + len, "\" ]", 3);
681
682 debug("script exec %s\n", buf);
683
684 if (0 == grub_script_execute_sourcecode(buf))
685 {
686 return 1;
687 }
688
689 return 0;
690 }
691
692 int ventoy_is_dir_exist(const char *fmt, ...)
693 {
694 va_list ap;
695 int len;
696 char *pos = NULL;
697 char buf[256] = {0};
698
699 grub_snprintf(buf, sizeof(buf), "%s", "[ -d \"");
700 pos = buf + 6;
701
702 va_start (ap, fmt);
703 len = grub_vsnprintf(pos, 255, fmt, ap);
704 va_end (ap);
705
706 grub_strncpy(pos + len, "\" ]", 3);
707
708 debug("script exec %s\n", buf);
709
710 if (0 == grub_script_execute_sourcecode(buf))
711 {
712 return 1;
713 }
714
715 return 0;
716 }
717
718 int ventoy_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len)
719 {
720 mz_stream s;
721 grub_uint8_t *outbuf;
722 grub_uint8_t gzHdr[10] =
723 {
724 0x1F, 0x8B, /* magic */
725 8, /* z method */
726 0, /* flags */
727 0,0,0,0, /* mtime */
728 4, /* xfl */
729 3, /* OS */
730 };
731
732 grub_memset(&s, 0, sizeof(mz_stream));
733
734 mz_deflateInit2(&s, 1, MZ_DEFLATED, -MZ_DEFAULT_WINDOW_BITS, 6, MZ_DEFAULT_STRATEGY);
735
736 outbuf = (grub_uint8_t *)mem_out;
737
738 mem_out_len -= sizeof(gzHdr) + 8;
739 grub_memcpy(outbuf, gzHdr, sizeof(gzHdr));
740 outbuf += sizeof(gzHdr);
741
742 s.avail_in = mem_in_len;
743 s.next_in = mem_in;
744
745 s.avail_out = mem_out_len;
746 s.next_out = outbuf;
747
748 mz_deflate(&s, MZ_FINISH);
749
750 mz_deflateEnd(&s);
751
752 outbuf += s.total_out;
753 *(grub_uint32_t *)outbuf = grub_getcrc32c(0, outbuf, s.total_out);
754 *(grub_uint32_t *)(outbuf + 4) = (grub_uint32_t)(s.total_out);
755
756 return s.total_out + sizeof(gzHdr) + 8;
757 }
758
759
760 #if 0
761 ventoy grub cmds
762 #endif
763
764 static grub_err_t ventoy_cmd_debug(grub_extcmd_context_t ctxt, int argc, char **args)
765 {
766 if (argc != 1)
767 {
768 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {on|off}", cmd_raw_name);
769 }
770
771 if (0 == grub_strcmp(args[0], "on"))
772 {
773 g_ventoy_debug = 1;
774 grub_env_set("vtdebug_flag", "debug");
775 }
776 else
777 {
778 g_ventoy_debug = 0;
779 grub_env_set("vtdebug_flag", "");
780 }
781
782 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
783 }
784
785 static grub_err_t ventoy_cmd_break(grub_extcmd_context_t ctxt, int argc, char **args)
786 {
787 (void)ctxt;
788
789 if (argc < 1 || (args[0][0] != '0' && args[0][0] != '1'))
790 {
791 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name);
792 grub_printf(" level:\r\n");
793 grub_printf(" 01/11: busybox / (+cat log)\r\n");
794 grub_printf(" 02/12: initrd / (+cat log)\r\n");
795 grub_printf(" 03/13: hook / (+cat log)\r\n");
796 grub_printf("\r\n");
797 grub_printf(" debug:\r\n");
798 grub_printf(" 0: debug is off\r\n");
799 grub_printf(" 1: debug is on\r\n");
800 grub_printf("\r\n");
801 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
802 }
803
804 g_ventoy_break_level = (grub_uint8_t)grub_strtoul(args[0], NULL, 16);
805
806 if (argc > 1 && grub_strtoul(args[1], NULL, 10) > 0)
807 {
808 g_ventoy_debug_level = 1;
809 }
810
811 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
812 }
813
814 static grub_err_t ventoy_cmd_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
815 {
816 (void)ctxt;
817
818 if (argc != 2)
819 {
820 return 1;
821 }
822
823 return (grub_strstr(args[0], args[1])) ? 0 : 1;
824 }
825
826 static grub_err_t ventoy_cmd_strbegin(grub_extcmd_context_t ctxt, int argc, char **args)
827 {
828 char *c0, *c1;
829
830 (void)ctxt;
831
832 if (argc != 2)
833 {
834 return 1;
835 }
836
837 c0 = args[0];
838 c1 = args[1];
839
840 while (*c0 && *c1)
841 {
842 if (*c0 != *c1)
843 {
844 return 1;
845 }
846 c0++;
847 c1++;
848 }
849
850 if (*c1)
851 {
852 return 1;
853 }
854
855 return 0;
856 }
857
858 static grub_err_t ventoy_cmd_incr(grub_extcmd_context_t ctxt, int argc, char **args)
859 {
860 long value_long = 0;
861 char buf[32];
862
863 if ((argc != 2) || (!ventoy_is_decimal(args[1])))
864 {
865 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Variable} {Int}", cmd_raw_name);
866 }
867
868 if (GRUB_ERR_NONE != ventoy_check_decimal_var(args[0], &value_long))
869 {
870 return grub_errno;
871 }
872
873 value_long += grub_strtol(args[1], NULL, 10);
874
875 grub_snprintf(buf, sizeof(buf), "%ld", value_long);
876 grub_env_set(args[0], buf);
877
878 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
879 }
880
881 static grub_err_t ventoy_cmd_mod(grub_extcmd_context_t ctxt, int argc, char **args)
882 {
883 ulonglong value1 = 0;
884 ulonglong value2 = 0;
885 char buf[32];
886
887 if (argc != 3)
888 {
889 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name);
890 }
891
892 value1 = grub_strtoull(args[0], NULL, 10);
893 value2 = grub_strtoull(args[1], NULL, 10);
894
895 grub_snprintf(buf, sizeof(buf), "%llu", (value1 & (value2 - 1)));
896 grub_env_set(args[2], buf);
897
898 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
899 }
900
901 static grub_err_t ventoy_cmd_file_size(grub_extcmd_context_t ctxt, int argc, char **args)
902 {
903 int rc = 1;
904 char buf[32];
905 grub_file_t file;
906
907 (void)ctxt;
908 (void)argc;
909 (void)args;
910
911 if (argc != 2)
912 {
913 return rc;
914 }
915
916 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
917 if (file == NULL)
918 {
919 debug("failed to open file <%s> for udf check\n", args[0]);
920 return 1;
921 }
922
923 grub_snprintf(buf, sizeof(buf), "%llu", (unsigned long long)file->size);
924
925 grub_env_set(args[1], buf);
926
927 grub_file_close(file);
928 rc = 0;
929
930 return rc;
931 }
932
933 static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc, char **args)
934 {
935 grub_file_t file;
936
937 (void)ctxt;
938 (void)argc;
939 (void)args;
940
941 g_wimboot_enable = 0;
942 grub_check_free(g_wimiso_path);
943 grub_check_free(g_wimiso_chunk_list.chunk);
944
945 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
946 if (!file)
947 {
948 return 0;
949 }
950
951 grub_memset(&g_wimiso_chunk_list, 0, sizeof(g_wimiso_chunk_list));
952 g_wimiso_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
953 if (NULL == g_wimiso_chunk_list.chunk)
954 {
955 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
956 }
957
958 g_wimiso_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
959 g_wimiso_chunk_list.cur_chunk = 0;
960
961 ventoy_get_block_list(file, &g_wimiso_chunk_list, file->device->disk->partition->start);
962
963 g_wimboot_enable = 1;
964 g_wimiso_path = grub_strdup(args[0]);
965
966 grub_file_close(file);
967
968 return 0;
969 }
970
971 static grub_err_t ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc, char **args)
972 {
973 int len = 0;
974 int totlen = 0;
975 int offset = 0;
976 grub_file_t file;
977 char name[32];
978 char value[32];
979 char *buf = NULL;
980 char *data = NULL;
981 ventoy_iso9660_override *dirent;
982
983 (void)ctxt;
984
985 if (argc != 2)
986 {
987 return 1;
988 }
989
990 totlen = sizeof(ventoy_chain_head);
991
992 if (ventoy_load_efiboot_template(&buf, &len, &offset))
993 {
994 debug("failed to load efiboot template %d\n", len);
995 return 1;
996 }
997
998 totlen += len;
999
1000 debug("efiboot template len:%d offset:%d\n", len, offset);
1001
1002 file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
1003 if (file == NULL)
1004 {
1005 debug("failed to open file <%s>\n", args[0]);
1006 return 1;
1007 }
1008
1009 totlen += ventoy_align_2k(file->size);
1010
1011 dirent = (ventoy_iso9660_override *)(buf + offset);
1012 dirent->first_sector = len / 2048;
1013 dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
1014 dirent->size = (grub_uint32_t)file->size;
1015 dirent->size_be = grub_swap_bytes32(dirent->size);
1016
1017 debug("rawiso len:%d efilen:%d total:%d\n", len, (int)file->size, totlen);
1018
1019 #ifdef GRUB_MACHINE_EFI
1020 data = (char *)grub_efi_allocate_iso_buf(totlen);
1021 #else
1022 data = (char *)grub_malloc(totlen);
1023 #endif
1024
1025 ventoy_fill_os_param(file, (ventoy_os_param *)data);
1026
1027 grub_memcpy(data + sizeof(ventoy_chain_head), buf, len);
1028 grub_check_free(buf);
1029
1030 grub_file_read(file, data + sizeof(ventoy_chain_head) + len, file->size);
1031 grub_file_close(file);
1032
1033 grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
1034 grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)data);
1035 grub_env_set(name, value);
1036
1037 grub_snprintf(name, sizeof(name), "%s_size", args[1]);
1038 grub_snprintf(value, sizeof(value), "%d", (int)(totlen));
1039 grub_env_set(name, value);
1040
1041 return 0;
1042 }
1043
1044 static grub_err_t ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
1045 {
1046 int rc = 1;
1047 char name[32];
1048 char value[32];
1049 char *buf = NULL;
1050 grub_file_t file;
1051
1052 (void)ctxt;
1053 (void)argc;
1054 (void)args;
1055
1056 if (argc != 2)
1057 {
1058 return rc;
1059 }
1060
1061 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1062 if (file == NULL)
1063 {
1064 debug("failed to open file <%s>\n", args[0]);
1065 return 1;
1066 }
1067
1068 #ifdef GRUB_MACHINE_EFI
1069 buf = (char *)grub_efi_allocate_iso_buf(file->size);
1070 #else
1071 buf = (char *)grub_malloc(file->size);
1072 #endif
1073
1074 grub_file_read(file, buf, file->size);
1075
1076 grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
1077 grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
1078 grub_env_set(name, value);
1079
1080 grub_snprintf(name, sizeof(name), "%s_size", args[1]);
1081 grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
1082 grub_env_set(name, value);
1083
1084 grub_file_close(file);
1085 rc = 0;
1086
1087 return rc;
1088 }
1089
1090 static grub_err_t ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt, int argc, char **args)
1091 {
1092 int rc = 1;
1093 int headlen;
1094 char name[32];
1095 char value[32];
1096 char *buf = NULL;
1097 grub_file_t file;
1098
1099 (void)ctxt;
1100 (void)argc;
1101 (void)args;
1102
1103 if (argc != 2)
1104 {
1105 return rc;
1106 }
1107
1108 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1109 if (file == NULL)
1110 {
1111 debug("failed to open file <%s> for udf check\n", args[0]);
1112 return 1;
1113 }
1114
1115 headlen = sizeof(ventoy_chain_head);
1116
1117 #ifdef GRUB_MACHINE_EFI
1118 buf = (char *)grub_efi_allocate_iso_buf(headlen + file->size);
1119 #else
1120 buf = (char *)grub_malloc(headlen + file->size);
1121 #endif
1122
1123 ventoy_fill_os_param(file, (ventoy_os_param *)buf);
1124
1125 grub_file_read(file, buf + headlen, file->size);
1126
1127 grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
1128 grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
1129 grub_env_set(name, value);
1130
1131 grub_snprintf(name, sizeof(name), "%s_size", args[1]);
1132 grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
1133 grub_env_set(name, value);
1134
1135 grub_file_close(file);
1136 rc = 0;
1137
1138 return rc;
1139 }
1140
1141 static grub_err_t ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
1142 {
1143 (void)ctxt;
1144
1145 if (argc != 1)
1146 {
1147 return 1;
1148 }
1149
1150 if (args[0][0] == '1')
1151 {
1152 grub_iso9660_set_nojoliet(1);
1153 }
1154 else
1155 {
1156 grub_iso9660_set_nojoliet(0);
1157 }
1158
1159 return 0;
1160 }
1161
1162 static grub_err_t ventoy_cmd_is_udf(grub_extcmd_context_t ctxt, int argc, char **args)
1163 {
1164 int i;
1165 int rc = 1;
1166 grub_file_t file;
1167 grub_uint8_t buf[32];
1168
1169 (void)ctxt;
1170 (void)argc;
1171 (void)args;
1172
1173 if (argc != 1)
1174 {
1175 return rc;
1176 }
1177
1178 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1179 if (file == NULL)
1180 {
1181 debug("failed to open file <%s> for udf check\n", args[0]);
1182 return 1;
1183 }
1184
1185 for (i = 16; i < 32; i++)
1186 {
1187 grub_file_seek(file, i * 2048);
1188 grub_file_read(file, buf, sizeof(buf));
1189 if (buf[0] == 255)
1190 {
1191 break;
1192 }
1193 }
1194
1195 i++;
1196 grub_file_seek(file, i * 2048);
1197 grub_file_read(file, buf, sizeof(buf));
1198
1199 if (grub_memcmp(buf + 1, "BEA01", 5) == 0)
1200 {
1201 i++;
1202 grub_file_seek(file, i * 2048);
1203 grub_file_read(file, buf, sizeof(buf));
1204
1205 if (grub_memcmp(buf + 1, "NSR02", 5) == 0 ||
1206 grub_memcmp(buf + 1, "NSR03", 5) == 0)
1207 {
1208 rc = 0;
1209 }
1210 }
1211
1212 grub_file_close(file);
1213
1214 debug("ISO UDF: %s\n", rc ? "NO" : "YES");
1215
1216 return rc;
1217 }
1218
1219 static grub_err_t ventoy_cmd_cmp(grub_extcmd_context_t ctxt, int argc, char **args)
1220 {
1221 long value_long1 = 0;
1222 long value_long2 = 0;
1223
1224 if ((argc != 3) || (!ventoy_is_decimal(args[0])) || (!ventoy_is_decimal(args[2])))
1225 {
1226 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name);
1227 }
1228
1229 value_long1 = grub_strtol(args[0], NULL, 10);
1230 value_long2 = grub_strtol(args[2], NULL, 10);
1231
1232 if (0 == grub_strcmp(args[1], "eq"))
1233 {
1234 grub_errno = (value_long1 == value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1235 }
1236 else if (0 == grub_strcmp(args[1], "ne"))
1237 {
1238 grub_errno = (value_long1 != value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1239 }
1240 else if (0 == grub_strcmp(args[1], "gt"))
1241 {
1242 grub_errno = (value_long1 > value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1243 }
1244 else if (0 == grub_strcmp(args[1], "lt"))
1245 {
1246 grub_errno = (value_long1 < value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1247 }
1248 else if (0 == grub_strcmp(args[1], "ge"))
1249 {
1250 grub_errno = (value_long1 >= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1251 }
1252 else if (0 == grub_strcmp(args[1], "le"))
1253 {
1254 grub_errno = (value_long1 <= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
1255 }
1256 else
1257 {
1258 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name);
1259 }
1260
1261 return grub_errno;
1262 }
1263
1264 static grub_err_t ventoy_cmd_device(grub_extcmd_context_t ctxt, int argc, char **args)
1265 {
1266 char *pos = NULL;
1267 char buf[128] = {0};
1268
1269 if (argc != 2)
1270 {
1271 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s path var", cmd_raw_name);
1272 }
1273
1274 grub_strncpy(buf, (args[0][0] == '(') ? args[0] + 1 : args[0], sizeof(buf) - 1);
1275 pos = grub_strstr(buf, ",");
1276 if (pos)
1277 {
1278 *pos = 0;
1279 }
1280
1281 grub_env_set(args[1], buf);
1282
1283 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1284 }
1285
1286 static grub_err_t ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt, int argc, char **args)
1287 {
1288 int i;
1289 char buf[256];
1290 grub_disk_t disk;
1291 char *pos = NULL;
1292 const char *files[] = { "ventoy.dat", "VENTOY.DAT" };
1293
1294 (void)ctxt;
1295
1296 if (argc != 1)
1297 {
1298 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s (loop)", cmd_raw_name);
1299 }
1300
1301 for (i = 0; i < (int)ARRAY_SIZE(files); i++)
1302 {
1303 grub_snprintf(buf, sizeof(buf) - 1, "[ -e \"%s/%s\" ]", args[0], files[i]);
1304 if (0 == grub_script_execute_sourcecode(buf))
1305 {
1306 debug("file %s exist, ventoy_compatible YES\n", buf);
1307 grub_env_set("ventoy_compatible", "YES");
1308 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1309 }
1310 else
1311 {
1312 debug("file %s NOT exist\n", buf);
1313 }
1314 }
1315
1316 grub_snprintf(buf, sizeof(buf) - 1, "%s", args[0][0] == '(' ? (args[0] + 1) : args[0]);
1317 pos = grub_strstr(buf, ")");
1318 if (pos)
1319 {
1320 *pos = 0;
1321 }
1322
1323 disk = grub_disk_open(buf);
1324 if (disk)
1325 {
1326 grub_disk_read(disk, 16 << 2, 0, 1024, g_img_swap_tmp_buf);
1327 grub_disk_close(disk);
1328
1329 g_img_swap_tmp_buf[703] = 0;
1330 for (i = 318; i < 703; i++)
1331 {
1332 if (g_img_swap_tmp_buf[i] == 'V' &&
1333 0 == grub_strncmp(g_img_swap_tmp_buf + i, VENTOY_COMPATIBLE_STR, VENTOY_COMPATIBLE_STR_LEN))
1334 {
1335 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i);
1336 grub_env_set("ventoy_compatible", "YES");
1337 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1338 }
1339 }
1340 }
1341 else
1342 {
1343 debug("failed to open disk <%s>\n", buf);
1344 }
1345
1346 grub_env_set("ventoy_compatible", "NO");
1347 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1348 }
1349
1350 int ventoy_cmp_img(img_info *img1, img_info *img2)
1351 {
1352 char *s1, *s2;
1353 int c1 = 0;
1354 int c2 = 0;
1355
1356 if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
1357 {
1358 return (img1->plugin_list_index - img2->plugin_list_index);
1359 }
1360
1361 for (s1 = img1->name, s2 = img2->name; *s1 && *s2; s1++, s2++)
1362 {
1363 c1 = *s1;
1364 c2 = *s2;
1365
1366 if (0 == g_sort_case_sensitive)
1367 {
1368 if (grub_islower(c1))
1369 {
1370 c1 = c1 - 'a' + 'A';
1371 }
1372
1373 if (grub_islower(c2))
1374 {
1375 c2 = c2 - 'a' + 'A';
1376 }
1377 }
1378
1379 if (c1 != c2)
1380 {
1381 break;
1382 }
1383 }
1384
1385 return (c1 - c2);
1386 }
1387
1388 static int ventoy_cmp_subdir(img_iterator_node *node1, img_iterator_node *node2)
1389 {
1390 char *s1, *s2;
1391 int c1 = 0;
1392 int c2 = 0;
1393
1394 if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
1395 {
1396 return (node1->plugin_list_index - node2->plugin_list_index);
1397 }
1398
1399 for (s1 = node1->dir, s2 = node2->dir; *s1 && *s2; s1++, s2++)
1400 {
1401 c1 = *s1;
1402 c2 = *s2;
1403
1404 if (0 == g_sort_case_sensitive)
1405 {
1406 if (grub_islower(c1))
1407 {
1408 c1 = c1 - 'a' + 'A';
1409 }
1410
1411 if (grub_islower(c2))
1412 {
1413 c2 = c2 - 'a' + 'A';
1414 }
1415 }
1416
1417 if (c1 != c2)
1418 {
1419 break;
1420 }
1421 }
1422
1423 return (c1 - c2);
1424 }
1425
1426 void ventoy_swap_img(img_info *img1, img_info *img2)
1427 {
1428 grub_memcpy(&g_img_swap_tmp, img1, sizeof(img_info));
1429
1430 grub_memcpy(img1, img2, sizeof(img_info));
1431 img1->next = g_img_swap_tmp.next;
1432 img1->prev = g_img_swap_tmp.prev;
1433
1434 g_img_swap_tmp.next = img2->next;
1435 g_img_swap_tmp.prev = img2->prev;
1436 grub_memcpy(img2, &g_img_swap_tmp, sizeof(img_info));
1437 }
1438
1439 static int ventoy_img_name_valid(const char *filename, grub_size_t namelen)
1440 {
1441 (void)namelen;
1442
1443 if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
1444 {
1445 return 0;
1446 }
1447
1448 return 1;
1449 }
1450
1451 static int ventoy_collect_img_files(const char *filename, const struct grub_dirhook_info *info, void *data)
1452 {
1453 //int i = 0;
1454 int type = 0;
1455 int ignore = 0;
1456 int index = 0;
1457 grub_size_t len;
1458 img_info *img;
1459 img_info *tail;
1460 img_iterator_node *tmp;
1461 img_iterator_node *new_node;
1462 img_iterator_node *node = (img_iterator_node *)data;
1463
1464 if (g_enumerate_time_checked == 0)
1465 {
1466 g_enumerate_finish_time_ms = grub_get_time_ms();
1467 if ((g_enumerate_finish_time_ms - g_enumerate_start_time_ms) >= 3000)
1468 {
1469 grub_cls();
1470 grub_printf("\n\n Ventoy scanning files, please wait...\n");
1471 grub_refresh();
1472 g_enumerate_time_checked = 1;
1473 }
1474 }
1475
1476 len = grub_strlen(filename);
1477
1478 if (info->dir)
1479 {
1480 if (node->level + 1 > g_img_max_search_level)
1481 {
1482 return 0;
1483 }
1484
1485 if ((len == 1 && filename[0] == '.') ||
1486 (len == 2 && filename[0] == '.' && filename[1] == '.'))
1487 {
1488 return 0;
1489 }
1490
1491 if (!ventoy_img_name_valid(filename, len))
1492 {
1493 return 0;
1494 }
1495
1496 if (filename[0] == '$' && 0 == grub_strncmp(filename, "$RECYCLE.BIN", 12))
1497 {
1498 return 0;
1499 }
1500
1501 if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
1502 {
1503 grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s/", node->dir, filename);
1504 index = ventoy_plugin_get_image_list_index(vtoy_class_directory, g_img_swap_tmp_buf);
1505 if (index == 0)
1506 {
1507 debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
1508 return 0;
1509 }
1510 }
1511
1512 new_node = grub_zalloc(sizeof(img_iterator_node));
1513 if (new_node)
1514 {
1515 new_node->level = node->level + 1;
1516 new_node->plugin_list_index = index;
1517 new_node->dirlen = grub_snprintf(new_node->dir, sizeof(new_node->dir), "%s%s/", node->dir, filename);
1518
1519 g_enum_fs->fs_dir(g_enum_dev, new_node->dir, ventoy_check_ignore_flag, &ignore);
1520 if (ignore)
1521 {
1522 debug("Directory %s ignored...\n", new_node->dir);
1523 grub_free(new_node);
1524 return 0;
1525 }
1526
1527 new_node->tail = node->tail;
1528
1529 new_node->parent = node;
1530 if (!node->firstchild)
1531 {
1532 node->firstchild = new_node;
1533 }
1534
1535 if (g_img_iterator_tail)
1536 {
1537 g_img_iterator_tail->next = new_node;
1538 g_img_iterator_tail = new_node;
1539 }
1540 else
1541 {
1542 g_img_iterator_head.next = new_node;
1543 g_img_iterator_tail = new_node;
1544 }
1545 }
1546 }
1547 else
1548 {
1549 debug("Find a file %s\n", filename);
1550 if (len < 4)
1551 {
1552 return 0;
1553 }
1554
1555 if (FILE_FLT(ISO) && 0 == grub_strcasecmp(filename + len - 4, ".iso"))
1556 {
1557 type = img_type_iso;
1558 }
1559 else if (FILE_FLT(WIM) && g_wimboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".wim")))
1560 {
1561 type = img_type_wim;
1562 }
1563 else if (FILE_FLT(VHD) && g_vhdboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".vhd") ||
1564 (len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vhdx"))))
1565 {
1566 type = img_type_vhd;
1567 }
1568 #ifdef GRUB_MACHINE_EFI
1569 else if (FILE_FLT(EFI) && 0 == grub_strcasecmp(filename + len - 4, ".efi"))
1570 {
1571 type = img_type_efi;
1572 }
1573 #endif
1574 else if (FILE_FLT(IMG) && 0 == grub_strcasecmp(filename + len - 4, ".img"))
1575 {
1576 if (len == 18 && grub_strncmp(filename, "ventoy_", 7) == 0)
1577 {
1578 if (grub_strncmp(filename + 7, "wimboot", 7) == 0 ||
1579 grub_strncmp(filename + 7, "vhdboot", 7) == 0)
1580 {
1581 return 0;
1582 }
1583 }
1584 type = img_type_img;
1585 }
1586 else if (FILE_FLT(VTOY) && len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vtoy"))
1587 {
1588 type = img_type_vtoy;
1589 }
1590 else if (len >= 9 && 0 == grub_strcasecmp(filename + len - 5, ".vcfg"))
1591 {
1592 if (filename[len - 9] == '.' || (len >= 10 && filename[len - 10] == '.'))
1593 {
1594 grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
1595 ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf);
1596 }
1597 return 0;
1598 }
1599 else
1600 {
1601 return 0;
1602 }
1603
1604 if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
1605 {
1606 return 0;
1607 }
1608
1609 if (g_plugin_image_list)
1610 {
1611 grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
1612 index = ventoy_plugin_get_image_list_index(vtoy_class_image_file, g_img_swap_tmp_buf);
1613 if (VENTOY_IMG_WHITE_LIST == g_plugin_image_list && index == 0)
1614 {
1615 debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
1616 return 0;
1617 }
1618 else if (VENTOY_IMG_BLACK_LIST == g_plugin_image_list && index > 0)
1619 {
1620 debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf, index);
1621 return 0;
1622 }
1623 }
1624
1625 img = grub_zalloc(sizeof(img_info));
1626 if (img)
1627 {
1628 img->type = type;
1629 img->plugin_list_index = index;
1630 grub_snprintf(img->name, sizeof(img->name), "%s", filename);
1631
1632 img->pathlen = grub_snprintf(img->path, sizeof(img->path), "%s%s", node->dir, img->name);
1633
1634 img->size = info->size;
1635 if (0 == img->size)
1636 {
1637 img->size = ventoy_grub_get_file_size("%s/%s%s", g_iso_path, node->dir, filename);
1638 }
1639
1640 if (img->size < VTOY_FILT_MIN_FILE_SIZE)
1641 {
1642 debug("img <%s> size too small %llu\n", img->name, (ulonglong)img->size);
1643 grub_free(img);
1644 return 0;
1645 }
1646
1647 if (g_ventoy_img_list)
1648 {
1649 tail = *(node->tail);
1650 img->prev = tail;
1651 tail->next = img;
1652 }
1653 else
1654 {
1655 g_ventoy_img_list = img;
1656 }
1657
1658 img->id = g_ventoy_img_count;
1659 img->parent = node;
1660 if (node && NULL == node->firstiso)
1661 {
1662 node->firstiso = img;
1663 }
1664
1665 node->isocnt++;
1666 tmp = node->parent;
1667 while (tmp)
1668 {
1669 tmp->isocnt++;
1670 tmp = tmp->parent;
1671 }
1672
1673 *((img_info **)(node->tail)) = img;
1674 g_ventoy_img_count++;
1675
1676 img->alias = ventoy_plugin_get_menu_alias(vtoy_alias_image_file, img->path);
1677 img->class = ventoy_plugin_get_menu_class(vtoy_class_image_file, img->name, img->path);
1678 if (!img->class)
1679 {
1680 img->class = g_menu_class[type];
1681 }
1682 img->menu_prefix = g_menu_prefix[type];
1683
1684 if (img_type_iso == type)
1685 {
1686 if (ventoy_plugin_check_memdisk(img->path))
1687 {
1688 img->menu_prefix = "miso";
1689 }
1690 }
1691
1692 debug("Add %s%s to list %d\n", node->dir, filename, g_ventoy_img_count);
1693 }
1694 }
1695
1696 return 0;
1697 }
1698
1699 int ventoy_fill_data(grub_uint32_t buflen, char *buffer)
1700 {
1701 int len = GRUB_UINT_MAX;
1702 const char *value = NULL;
1703 char name[32] = {0};
1704 char plat[32] = {0};
1705 char guidstr[32] = {0};
1706 ventoy_guid guid = VENTOY_GUID;
1707 const char *fmt1 = NULL;
1708 const char *fmt2 = NULL;
1709 const char *fmt3 = NULL;
1710 grub_uint32_t *puint = (grub_uint32_t *)name;
1711 grub_uint32_t *puint2 = (grub_uint32_t *)plat;
1712 const char fmtdata[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
1713 const char fmtcode[]={
1714 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
1715 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
1716 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
1717 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
1718 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
1719 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
1720 };
1721
1722 grub_memset(name, 0, sizeof(name));
1723 puint[0] = grub_swap_bytes32(0x56454e54);
1724 puint[3] = grub_swap_bytes32(0x4f4e0000);
1725 puint[2] = grub_swap_bytes32(0x45525349);
1726 puint[1] = grub_swap_bytes32(0x4f595f56);
1727 value = ventoy_get_env(name);
1728
1729 grub_memset(name, 0, sizeof(name));
1730 puint[1] = grub_swap_bytes32(0x5f544f50);
1731 puint[0] = grub_swap_bytes32(0x56544c45);
1732 fmt1 = ventoy_get_env(name);
1733 if (!fmt1)
1734 {
1735 fmt1 = fmtdata;
1736 }
1737
1738 grub_memset(name, 0, sizeof(name));
1739 puint[1] = grub_swap_bytes32(0x5f4c4654);
1740 puint[0] = grub_swap_bytes32(0x56544c45);
1741 fmt2 = ventoy_get_env(name);
1742
1743 grub_memset(name, 0, sizeof(name));
1744 puint[1] = grub_swap_bytes32(0x5f434c52);
1745 puint[0] = grub_swap_bytes32(0x56544c45);
1746 fmt3 = ventoy_get_env(name);
1747
1748 grub_memcpy(guidstr, &guid, sizeof(guid));
1749
1750 puint2[0] = grub_swap_bytes32(g_ventoy_plat_data);
1751
1752 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
1753 #pragma GCC diagnostic push
1754 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
1755 len = grub_snprintf(buffer, buflen, fmtcode,
1756 fmt1 ? fmt1 : fmtdata,
1757 fmt2 ? fmt2 : fmtdata + 4,
1758 value ? value : "", plat, guidstr,
1759 fmt3 ? fmt3 : fmtdata + 6);
1760 #pragma GCC diagnostic pop
1761
1762 grub_memset(name, 0, sizeof(name));
1763 puint[0] = grub_swap_bytes32(0x76746f79);
1764 puint[2] = grub_swap_bytes32(0x656e7365);
1765 puint[1] = grub_swap_bytes32(0x5f6c6963);
1766 ventoy_set_env(name, guidstr);
1767
1768 return len;
1769 }
1770
1771 int ventoy_check_password(const vtoy_password *pwd, int retry)
1772 {
1773 int offset;
1774 char input[256];
1775 grub_uint8_t md5[16];
1776
1777 while (retry--)
1778 {
1779 grub_memset(input, 0, sizeof(input));
1780
1781 grub_printf("Enter password: ");
1782 grub_refresh();
1783
1784 if (pwd->type == VTOY_PASSWORD_TXT)
1785 {
1786 grub_password_get(input, 128);
1787 if (grub_strcmp(pwd->text, input) == 0)
1788 {
1789 return 0;
1790 }
1791 }
1792 else if (pwd->type == VTOY_PASSWORD_MD5)
1793 {
1794 grub_password_get(input, 128);
1795 grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
1796 if (grub_memcmp(pwd->md5, md5, 16) == 0)
1797 {
1798 return 0;
1799 }
1800 }
1801 else if (pwd->type == VTOY_PASSWORD_SALT_MD5)
1802 {
1803 offset = (int)grub_snprintf(input, 128, "%s", pwd->salt);
1804 grub_password_get(input + offset, 128);
1805
1806 grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
1807 if (grub_memcmp(pwd->md5, md5, 16) == 0)
1808 {
1809 return 0;
1810 }
1811 }
1812
1813 grub_printf("Invalid password!\n\n");
1814 grub_refresh();
1815 }
1816
1817 return 1;
1818 }
1819
1820 static img_info * ventoy_get_min_iso(img_iterator_node *node)
1821 {
1822 img_info *minimg = NULL;
1823 img_info *img = (img_info *)(node->firstiso);
1824
1825 while (img && (img_iterator_node *)(img->parent) == node)
1826 {
1827 if (img->select == 0 && (NULL == minimg || ventoy_cmp_img(img, minimg) < 0))
1828 {
1829 minimg = img;
1830 }
1831 img = img->next;
1832 }
1833
1834 if (minimg)
1835 {
1836 minimg->select = 1;
1837 }
1838
1839 return minimg;
1840 }
1841
1842 static img_iterator_node * ventoy_get_min_child(img_iterator_node *node)
1843 {
1844 img_iterator_node *Minchild = NULL;
1845 img_iterator_node *child = node->firstchild;
1846
1847 while (child && child->parent == node)
1848 {
1849 if (child->select == 0 && (NULL == Minchild || ventoy_cmp_subdir(child, Minchild) < 0))
1850 {
1851 Minchild = child;
1852 }
1853 child = child->next;
1854 }
1855
1856 if (Minchild)
1857 {
1858 Minchild->select = 1;
1859 }
1860
1861 return Minchild;
1862 }
1863
1864 static int ventoy_dynamic_tree_menu(img_iterator_node *node)
1865 {
1866 int offset = 1;
1867 img_info *img = NULL;
1868 const char *dir_class = NULL;
1869 const char *dir_alias = NULL;
1870 img_iterator_node *child = NULL;
1871
1872 if (node->isocnt == 0 || node->done == 1)
1873 {
1874 return 0;
1875 }
1876
1877 if (node->parent && node->parent->dirlen < node->dirlen)
1878 {
1879 offset = node->parent->dirlen;
1880 }
1881
1882 if (node == &g_img_iterator_head)
1883 {
1884 if (g_default_menu_mode == 0)
1885 {
1886 if (g_tree_view_menu_style == 0)
1887 {
1888 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1889 "menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1890 " echo 'return ...' \n"
1891 "}\n", "<--");
1892 }
1893 else
1894 {
1895 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1896 "menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
1897 " echo '%s ...' \n"
1898 "}\n", "return");
1899 }
1900 }
1901 }
1902 else
1903 {
1904 node->dir[node->dirlen - 1] = 0;
1905 dir_class = ventoy_plugin_get_menu_class(vtoy_class_directory, node->dir, node->dir);
1906 if (!dir_class)
1907 {
1908 dir_class = "vtoydir";
1909 }
1910
1911 dir_alias = ventoy_plugin_get_menu_alias(vtoy_alias_directory, node->dir);
1912 if (dir_alias)
1913 {
1914 if (g_tree_view_menu_style == 0)
1915 {
1916 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1917 "submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1918 "DIR", dir_alias, dir_class, node->dir + offset);
1919 }
1920 else
1921 {
1922 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1923 "submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1924 dir_alias, dir_class, node->dir + offset);
1925 }
1926 }
1927 else
1928 {
1929 dir_alias = node->dir + offset;
1930
1931 if (g_tree_view_menu_style == 0)
1932 {
1933 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1934 "submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1935 "DIR", dir_alias, dir_class, node->dir + offset);
1936 }
1937 else
1938 {
1939 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1940 "submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
1941 dir_alias, dir_class, node->dir + offset);
1942 }
1943 }
1944
1945 if (g_tree_view_menu_style == 0)
1946 {
1947 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1948 "menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
1949 " echo 'return ...' \n"
1950 "}\n", "<--");
1951 }
1952 else
1953 {
1954 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1955 "menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
1956 " echo '%s ...' \n"
1957 "}\n", "return");
1958 }
1959 }
1960
1961 while ((child = ventoy_get_min_child(node)) != NULL)
1962 {
1963 ventoy_dynamic_tree_menu(child);
1964 }
1965
1966 while ((img = ventoy_get_min_iso(node)) != NULL)
1967 {
1968 if (g_tree_view_menu_style == 0)
1969 {
1970 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1971 "menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1972 " %s_%s \n"
1973 "}\n",
1974 grub_get_human_size(img->size, GRUB_HUMAN_SIZE_SHORT),
1975 img->unsupport ? "[***********] " : "",
1976 img->alias ? img->alias : img->name, img->class, img->id,
1977 img->menu_prefix,
1978 img->unsupport ? "unsupport_menuentry" : "common_menuentry");
1979 }
1980 else
1981 {
1982 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1983 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
1984 " %s_%s \n"
1985 "}\n",
1986 img->unsupport ? "[***********] " : "",
1987 img->alias ? img->alias : img->name, img->class, img->id,
1988 img->menu_prefix,
1989 img->unsupport ? "unsupport_menuentry" : "common_menuentry");
1990 }
1991 }
1992
1993 if (node != &g_img_iterator_head)
1994 {
1995 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "%s", "}\n");
1996 }
1997
1998 node->done = 1;
1999 return 0;
2000 }
2001
2002 static int ventoy_set_default_menu(void)
2003 {
2004 int img_len = 0;
2005 char *pos = NULL;
2006 char *end = NULL;
2007 char *def = NULL;
2008 const char *strdata = NULL;
2009 img_info *cur = NULL;
2010 img_info *default_node = NULL;
2011 const char *default_image = NULL;
2012
2013 default_image = ventoy_get_env("VTOY_DEFAULT_IMAGE");
2014 if (default_image && default_image[0] == '/')
2015 {
2016 img_len = grub_strlen(default_image);
2017
2018 for (cur = g_ventoy_img_list; cur; cur = cur->next)
2019 {
2020 if (img_len == cur->pathlen && grub_strcmp(default_image, cur->path) == 0)
2021 {
2022 default_node = cur;
2023 break;
2024 }
2025 }
2026
2027 if (!default_node)
2028 {
2029 return 1;
2030 }
2031
2032 if (0 == g_default_menu_mode)
2033 {
2034 vtoy_ssprintf(g_list_script_buf, g_list_script_pos, "set default='VID_%d'\n", default_node->id);
2035 }
2036 else
2037 {
2038 def = grub_strdup(default_image);
2039 if (!def)
2040 {
2041 return 1;
2042 }
2043
2044 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "set default=%c", '\'');
2045
2046 strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2047 if (strdata && strdata[0] == '/')
2048 {
2049 pos = def + grub_strlen(strdata);
2050 if (*pos == '/')
2051 {
2052 pos++;
2053 }
2054 }
2055 else
2056 {
2057 pos = def + 1;
2058 }
2059
2060 while ((end = grub_strchr(pos, '/')) != NULL)
2061 {
2062 *end = 0;
2063 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "DIR_%s>", pos);
2064 pos = end + 1;
2065 }
2066
2067 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "VID_%d'\n", default_node->id);
2068 grub_free(def);
2069 }
2070 }
2071
2072 return 0;
2073 }
2074
2075 static grub_err_t ventoy_cmd_clear_img(grub_extcmd_context_t ctxt, int argc, char **args)
2076 {
2077 img_info *next = NULL;
2078 img_info *cur = g_ventoy_img_list;
2079
2080 (void)ctxt;
2081 (void)argc;
2082 (void)args;
2083
2084 while (cur)
2085 {
2086 next = cur->next;
2087 grub_free(cur);
2088 cur = next;
2089 }
2090
2091 g_ventoy_img_list = NULL;
2092 g_ventoy_img_count = 0;
2093
2094 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2095 }
2096
2097 static grub_err_t ventoy_cmd_img_name(grub_extcmd_context_t ctxt, int argc, char **args)
2098 {
2099 long img_id = 0;
2100 img_info *cur = g_ventoy_img_list;
2101
2102 (void)ctxt;
2103
2104 if (argc != 2 || (!ventoy_is_decimal(args[0])))
2105 {
2106 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {imageID} {var}", cmd_raw_name);
2107 }
2108
2109 img_id = grub_strtol(args[0], NULL, 10);
2110 if (img_id >= g_ventoy_img_count)
2111 {
2112 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images %ld %ld", img_id, g_ventoy_img_count);
2113 }
2114
2115 debug("Find image %ld name \n", img_id);
2116
2117 while (cur && img_id > 0)
2118 {
2119 img_id--;
2120 cur = cur->next;
2121 }
2122
2123 if (!cur)
2124 {
2125 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images");
2126 }
2127
2128 debug("image name is %s\n", cur->name);
2129
2130 grub_env_set(args[1], cur->name);
2131
2132 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2133 }
2134
2135 static grub_err_t ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
2136 {
2137 int len = 0;
2138 char id[32] = {0};
2139 img_info *cur = g_ventoy_img_list;
2140
2141 (void)ctxt;
2142
2143 if (argc != 1)
2144 {
2145 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
2146 }
2147
2148 len = (int)grub_strlen(args[0]);
2149
2150 while (cur)
2151 {
2152 if (len == cur->pathlen && 0 == grub_strcmp(args[0], cur->path))
2153 {
2154 break;
2155 }
2156 cur = cur->next;
2157 }
2158
2159 if (!cur)
2160 {
2161 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
2162 }
2163
2164 grub_snprintf(id, sizeof(id), "VID_%d", cur->id);
2165 grub_env_set("chosen", id);
2166 grub_env_export("chosen");
2167
2168 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2169 }
2170
2171 static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
2172 {
2173 int img_id = 0;
2174 char value[32];
2175 char *pos = NULL;
2176 const char *id = NULL;
2177 img_info *cur = g_ventoy_img_list;
2178
2179 (void)ctxt;
2180
2181 if (argc < 1 || argc > 2)
2182 {
2183 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
2184 }
2185
2186 id = grub_env_get("chosen");
2187
2188 pos = grub_strstr(id, "VID_");
2189 if (pos)
2190 {
2191 img_id = (int)grub_strtoul(pos + 4, NULL, 10);
2192 }
2193 else
2194 {
2195 img_id = (int)grub_strtoul(id, NULL, 10);
2196 }
2197
2198 while (cur)
2199 {
2200 if (img_id == cur->id)
2201 {
2202 break;
2203 }
2204 cur = cur->next;
2205 }
2206
2207 if (!cur)
2208 {
2209 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
2210 }
2211
2212 grub_env_set(args[0], cur->path);
2213
2214 if (argc > 1)
2215 {
2216 grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size));
2217 grub_env_set(args[1], value);
2218 }
2219
2220 g_svd_replace_offset = 0;
2221
2222 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2223 }
2224
2225
2226 static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char **args)
2227 {
2228 int len;
2229 grub_fs_t fs;
2230 grub_device_t dev = NULL;
2231 img_info *cur = NULL;
2232 img_info *tail = NULL;
2233 const char *strdata = NULL;
2234 char *device_name = NULL;
2235 char buf[32];
2236 img_iterator_node *node = NULL;
2237 img_iterator_node *tmp = NULL;
2238
2239 (void)ctxt;
2240
2241 if (argc != 2)
2242 {
2243 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {device} {cntvar}", cmd_raw_name);
2244 }
2245
2246 if (g_ventoy_img_list || g_ventoy_img_count)
2247 {
2248 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Must clear image before list");
2249 }
2250
2251 VTOY_CMD_CHECK(1);
2252
2253 g_enumerate_time_checked = 0;
2254 g_enumerate_start_time_ms = grub_get_time_ms();
2255
2256 strdata = ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
2257 if (strdata && strdata[0] == '1' && strdata[1] == 0)
2258 {
2259 g_filt_dot_underscore_file = 1;
2260 }
2261
2262 strdata = ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
2263 if (strdata && strdata[0] == '1' && strdata[1] == 0)
2264 {
2265 g_sort_case_sensitive = 1;
2266 }
2267
2268 device_name = grub_file_get_device_name(args[0]);
2269 if (!device_name)
2270 {
2271 goto fail;
2272 }
2273
2274 g_enum_dev = dev = grub_device_open(device_name);
2275 if (!dev)
2276 {
2277 goto fail;
2278 }
2279
2280 g_enum_fs = fs = grub_fs_probe(dev);
2281 if (!fs)
2282 {
2283 goto fail;
2284 }
2285
2286 if (ventoy_get_fs_type(fs->name) >= ventoy_fs_max)
2287 {
2288 debug("unsupported fs:<%s>\n", fs->name);
2289 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
2290 goto fail;
2291 }
2292
2293 ventoy_set_env("vtoy_iso_fs", fs->name);
2294
2295 strdata = ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
2296 if (strdata && strdata[0] == '1')
2297 {
2298 g_default_menu_mode = 1;
2299 }
2300
2301 grub_memset(&g_img_iterator_head, 0, sizeof(g_img_iterator_head));
2302
2303 grub_snprintf(g_iso_path, sizeof(g_iso_path), "%s", args[0]);
2304
2305 strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
2306 if (strdata && strdata[0] == '/')
2307 {
2308 len = grub_snprintf(g_img_iterator_head.dir, sizeof(g_img_iterator_head.dir) - 1, "%s", strdata);
2309 if (g_img_iterator_head.dir[len - 1] != '/')
2310 {
2311 g_img_iterator_head.dir[len++] = '/';
2312 }
2313 g_img_iterator_head.dirlen = len;
2314 }
2315 else
2316 {
2317 g_img_iterator_head.dirlen = 1;
2318 grub_strcpy(g_img_iterator_head.dir, "/");
2319 }
2320
2321 g_img_iterator_head.tail = &tail;
2322
2323 if (g_img_max_search_level < 0)
2324 {
2325 g_img_max_search_level = GRUB_INT_MAX;
2326 strdata = ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
2327 if (strdata && ventoy_is_decimal(strdata))
2328 {
2329 g_img_max_search_level = (int)grub_strtoul(strdata, NULL, 10);
2330 }
2331 }
2332
2333 g_vtoy_file_flt[VTOY_FILE_FLT_ISO] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
2334 g_vtoy_file_flt[VTOY_FILE_FLT_WIM] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
2335 g_vtoy_file_flt[VTOY_FILE_FLT_EFI] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
2336 g_vtoy_file_flt[VTOY_FILE_FLT_IMG] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
2337 g_vtoy_file_flt[VTOY_FILE_FLT_VHD] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
2338 g_vtoy_file_flt[VTOY_FILE_FLT_VTOY] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
2339
2340 for (node = &g_img_iterator_head; node; node = node->next)
2341 {
2342 fs->fs_dir(dev, node->dir, ventoy_collect_img_files, node);
2343 }
2344
2345 strdata = ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
2346 if (strdata && strdata[0] == '1' && strdata[1] == 0)
2347 {
2348 g_tree_view_menu_style = 1;
2349 }
2350
2351 ventoy_set_default_menu();
2352
2353 for (node = &g_img_iterator_head; node; node = node->next)
2354 {
2355 ventoy_dynamic_tree_menu(node);
2356 }
2357
2358 /* free node */
2359 node = g_img_iterator_head.next;
2360 while (node)
2361 {
2362 tmp = node->next;
2363 grub_free(node);
2364 node = tmp;
2365 }
2366
2367 /* sort image list by image name */
2368 for (cur = g_ventoy_img_list; cur; cur = cur->next)
2369 {
2370 for (tail = cur->next; tail; tail = tail->next)
2371 {
2372 if (ventoy_cmp_img(cur, tail) > 0)
2373 {
2374 ventoy_swap_img(cur, tail);
2375 }
2376 }
2377 }
2378
2379 if (g_default_menu_mode == 1)
2380 {
2381 vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
2382 "menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
2383 " echo 'return ...' \n"
2384 "}\n", "<--");
2385 }
2386
2387 for (cur = g_ventoy_img_list; cur; cur = cur->next)
2388 {
2389 vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
2390 "menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
2391 " %s_%s \n"
2392 "}\n",
2393 cur->unsupport ? "[***********] " : "",
2394 cur->alias ? cur->alias : cur->name, cur->class, cur->id,
2395 cur->menu_prefix,
2396 cur->unsupport ? "unsupport_menuentry" : "common_menuentry");
2397 }
2398
2399 g_tree_script_buf[g_tree_script_pos] = 0;
2400 g_list_script_buf[g_list_script_pos] = 0;
2401
2402 grub_snprintf(buf, sizeof(buf), "%d", g_ventoy_img_count);
2403 grub_env_set(args[1], buf);
2404
2405 fail:
2406
2407 check_free(device_name, grub_free);
2408 check_free(dev, grub_device_close);
2409
2410 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2411 }
2412
2413 int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t *signature)
2414 {
2415 grub_disk_t disk;
2416 char *device_name;
2417 char *pos;
2418 char *pos2;
2419
2420 device_name = grub_file_get_device_name(filename);
2421 if (!device_name)
2422 {
2423 return 1;
2424 }
2425
2426 pos = device_name;
2427 if (pos[0] == '(')
2428 {
2429 pos++;
2430 }
2431
2432 pos2 = grub_strstr(pos, ",");
2433 if (!pos2)
2434 {
2435 pos2 = grub_strstr(pos, ")");
2436 }
2437
2438 if (pos2)
2439 {
2440 *pos2 = 0;
2441 }
2442
2443 disk = grub_disk_open(pos);
2444 if (disk)
2445 {
2446 grub_disk_read(disk, 0, 0x180, 16, guid);
2447 grub_disk_read(disk, 0, 0x1b8, 4, signature);
2448 grub_disk_close(disk);
2449 }
2450 else
2451 {
2452 return 1;
2453 }
2454
2455 grub_free(device_name);
2456 return 0;
2457 }
2458
2459 grub_uint32_t ventoy_get_iso_boot_catlog(grub_file_t file)
2460 {
2461 eltorito_descriptor desc;
2462
2463 grub_memset(&desc, 0, sizeof(desc));
2464 grub_file_seek(file, 17 * 2048);
2465 grub_file_read(file, &desc, sizeof(desc));
2466
2467 if (desc.type != 0 || desc.version != 1)
2468 {
2469 return 0;
2470 }
2471
2472 if (grub_strncmp((char *)desc.id, "CD001", 5) != 0 ||
2473 grub_strncmp((char *)desc.system_id, "EL TORITO SPECIFICATION", 23) != 0)
2474 {
2475 return 0;
2476 }
2477
2478 return desc.sector;
2479 }
2480
2481 int ventoy_has_efi_eltorito(grub_file_t file, grub_uint32_t sector)
2482 {
2483 int i;
2484 int x86count = 0;
2485 grub_uint8_t buf[512];
2486 grub_uint8_t parttype[] = { 0x04, 0x06, 0x0B, 0x0C };
2487
2488 grub_file_seek(file, sector * 2048);
2489 grub_file_read(file, buf, sizeof(buf));
2490
2491 if (buf[0] == 0x01 && buf[1] == 0xEF)
2492 {
2493 debug("%s efi eltorito in Validation Entry\n", file->name);
2494 return 1;
2495 }
2496
2497 if (buf[0] == 0x01 && buf[1] == 0x00)
2498 {
2499 x86count++;
2500 }
2501
2502 for (i = 64; i < (int)sizeof(buf); i += 32)
2503 {
2504 if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF)
2505 {
2506 debug("%s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
2507 return 1;
2508 }
2509
2510 if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0x00 && x86count == 1)
2511 {
2512 debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
2513 return 1;
2514 }
2515 }
2516
2517 if (x86count && buf[32] == 0x88 && buf[33] == 0x04)
2518 {
2519 for (i = 0; i < (int)(ARRAY_SIZE(parttype)); i++)
2520 {
2521 if (buf[36] == parttype[i])
2522 {
2523 debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file->name, buf[36]);
2524 return 1;
2525 }
2526 }
2527 }
2528
2529 debug("%s does not contain efi eltorito\n", file->name);
2530 return 0;
2531 }
2532
2533 void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
2534 {
2535 char *pos;
2536 const char *fs = NULL;
2537 const char *cdprompt = NULL;
2538 grub_uint32_t i;
2539 grub_uint8_t chksum = 0;
2540 grub_disk_t disk;
2541
2542 disk = file->device->disk;
2543 grub_memcpy(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid));
2544
2545 param->vtoy_disk_size = disk->total_sectors * (1 << disk->log_sector_size);
2546 param->vtoy_disk_part_id = disk->partition->number + 1;
2547 param->vtoy_disk_part_type = ventoy_get_fs_type(file->fs->name);
2548
2549 pos = grub_strstr(file->name, "/");
2550 if (!pos)
2551 {
2552 pos = file->name;
2553 }
2554
2555 grub_snprintf(param->vtoy_img_path, sizeof(param->vtoy_img_path), "%s", pos);
2556
2557 ventoy_get_disk_guid(file->name, param->vtoy_disk_guid, param->vtoy_disk_signature);
2558
2559 param->vtoy_img_size = file->size;
2560
2561 param->vtoy_reserved[0] = g_ventoy_break_level;
2562 param->vtoy_reserved[1] = g_ventoy_debug_level;
2563
2564 param->vtoy_reserved[2] = g_ventoy_chain_type;
2565
2566 /* Windows CD/DVD prompt 0:suppress 1:reserved */
2567 param->vtoy_reserved[4] = 0;
2568 if (g_ventoy_chain_type == 1) /* Windows */
2569 {
2570 cdprompt = ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
2571 if (cdprompt && cdprompt[0] == '1' && cdprompt[1] == 0)
2572 {
2573 param->vtoy_reserved[4] = 1;
2574 }
2575 }
2576
2577 fs = ventoy_get_env("ventoy_fs_probe");
2578 if (fs && grub_strcmp(fs, "udf") == 0)
2579 {
2580 param->vtoy_reserved[3] = 1;
2581 }
2582
2583 /* calculate checksum */
2584 for (i = 0; i < sizeof(ventoy_os_param); i++)
2585 {
2586 chksum += *((grub_uint8_t *)param + i);
2587 }
2588 param->chksum = (grub_uint8_t)(0x100 - chksum);
2589
2590 return;
2591 }
2592
2593 int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
2594 {
2595 grub_uint32_t i = 0;
2596 grub_uint64_t total = 0;
2597 grub_uint64_t fileblk = 0;
2598 ventoy_img_chunk *chunk = NULL;
2599
2600 for (i = 0; i < chunklist->cur_chunk; i++)
2601 {
2602 chunk = chunklist->chunk + i;
2603
2604 if (chunk->disk_start_sector <= start)
2605 {
2606 debug("%u disk start invalid %lu\n", i, (ulong)start);
2607 return 1;
2608 }
2609
2610 total += chunk->disk_end_sector + 1 - chunk->disk_start_sector;
2611 }
2612
2613 fileblk = (file->size + 511) / 512;
2614
2615 if (total != fileblk)
2616 {
2617 debug("Invalid total: %llu %llu\n", (ulonglong)total, (ulonglong)fileblk);
2618 if ((file->size % 512) && (total + 1 == fileblk))
2619 {
2620 debug("maybe img file to be processed.\n");
2621 return 0;
2622 }
2623
2624 return 1;
2625 }
2626
2627 return 0;
2628 }
2629
2630 int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
2631 {
2632 int fs_type;
2633 int len;
2634 grub_uint32_t i = 0;
2635 grub_uint32_t sector = 0;
2636 grub_uint32_t count = 0;
2637 grub_off_t size = 0;
2638 grub_off_t read = 0;
2639
2640 fs_type = ventoy_get_fs_type(file->fs->name);
2641 if (fs_type == ventoy_fs_exfat)
2642 {
2643 grub_fat_get_file_chunk(start, file, chunklist);
2644 }
2645 else if (fs_type == ventoy_fs_ext)
2646 {
2647 grub_ext_get_file_chunk(start, file, chunklist);
2648 }
2649 else
2650 {
2651 file->read_hook = (grub_disk_read_hook_t)grub_disk_blocklist_read;
2652 file->read_hook_data = chunklist;
2653
2654 for (size = file->size; size > 0; size -= read)
2655 {
2656 read = (size > VTOY_SIZE_1GB) ? VTOY_SIZE_1GB : size;
2657 grub_file_read(file, NULL, read);
2658 }
2659
2660 for (i = 0; start > 0 && i < chunklist->cur_chunk; i++)
2661 {
2662 chunklist->chunk[i].disk_start_sector += start;
2663 chunklist->chunk[i].disk_end_sector += start;
2664 }
2665
2666 if (ventoy_fs_udf == fs_type)
2667 {
2668 for (i = 0; i < chunklist->cur_chunk; i++)
2669 {
2670 count = (chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector) >> 2;
2671 chunklist->chunk[i].img_start_sector = sector;
2672 chunklist->chunk[i].img_end_sector = sector + count - 1;
2673 sector += count;
2674 }
2675 }
2676 }
2677
2678 len = (int)grub_strlen(file->name);
2679 if ((len > 4 && grub_strncasecmp(file->name + len - 4, ".img", 4) == 0) ||
2680 (len > 4 && grub_strncasecmp(file->name + len - 4, ".vhd", 4) == 0) ||
2681 (len > 5 && grub_strncasecmp(file->name + len - 5, ".vhdx", 5) == 0) ||
2682 (len > 5 && grub_strncasecmp(file->name + len - 5, ".vtoy", 5) == 0))
2683 {
2684 for (i = 0; i < chunklist->cur_chunk; i++)
2685 {
2686 count = chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector;
2687 if (count < 4)
2688 {
2689 count = 1;
2690 }
2691 else
2692 {
2693 count >>= 2;
2694 }
2695
2696 chunklist->chunk[i].img_start_sector = sector;
2697 chunklist->chunk[i].img_end_sector = sector + count - 1;
2698 sector += count;
2699 }
2700 }
2701
2702 return 0;
2703 }
2704
2705 static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
2706 {
2707 int rc;
2708 grub_file_t file;
2709 grub_disk_addr_t start;
2710
2711 (void)ctxt;
2712 (void)argc;
2713
2714 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
2715 if (!file)
2716 {
2717 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
2718 }
2719
2720 g_conf_replace_node = NULL;
2721 g_conf_replace_offset = 0;
2722
2723 if (g_img_chunk_list.chunk)
2724 {
2725 grub_free(g_img_chunk_list.chunk);
2726 }
2727
2728 if (ventoy_get_fs_type(file->fs->name) >= ventoy_fs_max)
2729 {
2730 grub_file_close(file);
2731 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Unsupported filesystem %s\n", file->fs->name);
2732 }
2733
2734 /* get image chunk data */
2735 grub_memset(&g_img_chunk_list, 0, sizeof(g_img_chunk_list));
2736 g_img_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
2737 if (NULL == g_img_chunk_list.chunk)
2738 {
2739 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
2740 }
2741
2742 g_img_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
2743 g_img_chunk_list.cur_chunk = 0;
2744
2745 start = file->device->disk->partition->start;
2746
2747 ventoy_get_block_list(file, &g_img_chunk_list, start);
2748
2749 rc = ventoy_check_block_list(file, &g_img_chunk_list, start);
2750 grub_file_close(file);
2751
2752 if (rc)
2753 {
2754 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported chunk list.\n");
2755 }
2756
2757 grub_memset(&g_grub_param->file_replace, 0, sizeof(g_grub_param->file_replace));
2758 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2759 }
2760
2761 static grub_err_t ventoy_select_conf_replace(grub_extcmd_context_t ctxt, int argc, char **args)
2762 {
2763 grub_uint64_t offset = 0;
2764 grub_uint32_t align = 0;
2765 grub_file_t file = NULL;
2766 conf_replace *node = NULL;
2767
2768 (void)ctxt;
2769 (void)argc;
2770 (void)args;
2771
2772 debug("select conf replace argc:%d\n", argc);
2773
2774 if (argc < 2)
2775 {
2776 return 0;
2777 }
2778
2779 node = ventoy_plugin_find_conf_replace(args[1]);
2780 if (!node)
2781 {
2782 debug("Conf replace not found for %s\n", args[1]);
2783 goto end;
2784 }
2785
2786 debug("Find conf replace for %s\n", args[1]);
2787
2788 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", node->orgconf);
2789 if (!file)
2790 {
2791 debug("<(loop)%s> NOT exist\n", node->orgconf);
2792 goto end;
2793 }
2794
2795 offset = grub_iso9660_get_last_file_dirent_pos(file);
2796 grub_file_close(file);
2797
2798 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], node->newconf);
2799 if (!file)
2800 {
2801 debug("New config file <%s%s> NOT exist\n", args[0], node->newconf);
2802 goto end;
2803 }
2804
2805 align = ((int)file->size + 2047) / 2048 * 2048;
2806
2807 if (align > vtoy_max_replace_file_size)
2808 {
2809 debug("New config file <%s%s> too big\n", args[0], node->newconf);
2810 goto end;
2811 }
2812
2813 grub_file_read(file, g_conf_replace_new_buf, file->size);
2814 g_conf_replace_new_len = (int)file->size;
2815 g_conf_replace_new_len_align = align;
2816
2817 g_conf_replace_node = node;
2818 g_conf_replace_offset = offset + 2;
2819
2820 debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len);
2821
2822 end:
2823 if (file)
2824 {
2825 grub_file_close(file);
2826 }
2827 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2828 }
2829
2830 static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
2831 {
2832 int i = 0;
2833 int pos = 0;
2834 char *buf = NULL;
2835 char configfile[128];
2836 install_template *node = NULL;
2837
2838 (void)ctxt;
2839 (void)argc;
2840 (void)args;
2841
2842 debug("select auto installation argc:%d\n", argc);
2843
2844 if (argc < 1)
2845 {
2846 return 0;
2847 }
2848
2849 node = ventoy_plugin_find_install_template(args[0]);
2850 if (!node)
2851 {
2852 debug("Auto install template not found for %s\n", args[0]);
2853 return 0;
2854 }
2855
2856 if (node->autosel >= 0 && node->autosel <= node->templatenum)
2857 {
2858 node->cursel = node->autosel - 1;
2859 debug("Auto install template auto select %d\n", node->autosel);
2860 return 0;
2861 }
2862
2863 buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
2864 if (!buf)
2865 {
2866 return 0;
2867 }
2868
2869 vtoy_ssprintf(buf, pos, "menuentry \"Boot without auto installation template\" {\n"
2870 " echo %s\n}\n", "123");
2871
2872 for (i = 0; i < node->templatenum; i++)
2873 {
2874 vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" {\n"
2875 " echo 123\n}\n",
2876 node->templatepath[i].path);
2877 }
2878
2879 g_ventoy_menu_esc = 1;
2880 g_ventoy_suppress_esc = 1;
2881
2882 grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
2883 grub_script_execute_sourcecode(configfile);
2884
2885 g_ventoy_menu_esc = 0;
2886 g_ventoy_suppress_esc = 0;
2887
2888 grub_free(buf);
2889
2890 node->cursel = g_ventoy_last_entry - 1;
2891
2892 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2893 }
2894
2895 static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
2896 {
2897 int i = 0;
2898 int pos = 0;
2899 char *buf = NULL;
2900 char configfile[128];
2901 persistence_config *node;
2902
2903 (void)ctxt;
2904 (void)argc;
2905 (void)args;
2906
2907 debug("select persistence argc:%d\n", argc);
2908
2909 if (argc < 1)
2910 {
2911 return 0;
2912 }
2913
2914 node = ventoy_plugin_find_persistent(args[0]);
2915 if (!node)
2916 {
2917 debug("Persistence image not found for %s\n", args[0]);
2918 return 0;
2919 }
2920
2921 if (node->autosel >= 0 && node->autosel <= node->backendnum)
2922 {
2923 node->cursel = node->autosel - 1;
2924 debug("Persistence image auto select %d\n", node->autosel);
2925 return 0;
2926 }
2927
2928 buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
2929 if (!buf)
2930 {
2931 return 0;
2932 }
2933
2934 vtoy_ssprintf(buf, pos, "menuentry \"Boot without persistence\" {\n"
2935 " echo %s\n}\n", "123");
2936
2937 for (i = 0; i < node->backendnum; i++)
2938 {
2939 vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" {\n"
2940 " echo 123\n}\n",
2941 node->backendpath[i].path);
2942
2943 }
2944
2945 g_ventoy_menu_esc = 1;
2946 g_ventoy_suppress_esc = 1;
2947
2948 grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
2949 grub_script_execute_sourcecode(configfile);
2950
2951 g_ventoy_menu_esc = 0;
2952 g_ventoy_suppress_esc = 0;
2953
2954 grub_free(buf);
2955
2956 node->cursel = g_ventoy_last_entry - 1;
2957
2958 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2959 }
2960
2961 static grub_err_t ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
2962 {
2963 grub_uint32_t i;
2964 ventoy_img_chunk *cur;
2965
2966 (void)ctxt;
2967 (void)argc;
2968 (void)args;
2969
2970 for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
2971 {
2972 cur = g_img_chunk_list.chunk + i;
2973 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
2974 cur->img_start_sector, cur->img_end_sector,
2975 (unsigned long long)cur->disk_start_sector, (unsigned long long)cur->disk_end_sector
2976 );
2977 }
2978
2979 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
2980 }
2981
2982 static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int argc, char **args)
2983 {
2984 grub_uint32_t i;
2985 grub_file_t file;
2986 ventoy_img_chunk_list chunklist;
2987
2988 (void)ctxt;
2989 (void)argc;
2990
2991 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
2992 if (!file)
2993 {
2994 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
2995 }
2996
2997 /* get image chunk data */
2998 grub_memset(&chunklist, 0, sizeof(chunklist));
2999 chunklist.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
3000 if (NULL == chunklist.chunk)
3001 {
3002 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
3003 }
3004
3005 chunklist.max_chunk = DEFAULT_CHUNK_NUM;
3006 chunklist.cur_chunk = 0;
3007
3008 ventoy_get_block_list(file, &chunklist, 0);
3009
3010 if (0 != ventoy_check_block_list(file, &chunklist, 0))
3011 {
3012 grub_printf("########## UNSUPPORTED ###############\n");
3013 }
3014
3015 grub_printf("filesystem: <%s> entry number:<%u>\n", file->fs->name, chunklist.cur_chunk);
3016
3017 for (i = 0; i < chunklist.cur_chunk; i++)
3018 {
3019 grub_printf("%llu+%llu,", (ulonglong)chunklist.chunk[i].disk_start_sector,
3020 (ulonglong)(chunklist.chunk[i].disk_end_sector + 1 - chunklist.chunk[i].disk_start_sector));
3021 }
3022
3023 grub_printf("\n==================================\n");
3024
3025 for (i = 0; i < chunklist.cur_chunk; i++)
3026 {
3027 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i,
3028 (ulonglong)chunklist.chunk[i].img_start_sector,
3029 (ulonglong)chunklist.chunk[i].img_end_sector,
3030 (ulonglong)chunklist.chunk[i].disk_start_sector,
3031 (ulonglong)chunklist.chunk[i].disk_end_sector
3032 );
3033 }
3034
3035 grub_free(chunklist.chunk);
3036 grub_file_close(file);
3037
3038 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3039 }
3040
3041 static grub_err_t ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt, int argc, char **args)
3042 {
3043 int i;
3044 ventoy_grub_param_file_replace *replace = NULL;
3045
3046 (void)ctxt;
3047 (void)argc;
3048 (void)args;
3049
3050 if (argc >= 2)
3051 {
3052 replace = &(g_grub_param->file_replace);
3053 replace->magic = GRUB_FILE_REPLACE_MAGIC;
3054
3055 replace->old_name_cnt = 0;
3056 for (i = 0; i < 4 && i + 1 < argc; i++)
3057 {
3058 replace->old_name_cnt++;
3059 grub_snprintf(replace->old_file_name[i], sizeof(replace->old_file_name[i]), "%s", args[i + 1]);
3060 }
3061
3062 replace->new_file_virtual_id = (grub_uint32_t)grub_strtoul(args[0], NULL, 10);
3063 }
3064
3065 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
3066 }
3067
3068 static grub_err_t ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt, int argc, char **args)
3069 {
3070 (void)ctxt;
3071 (void)argc;
3072 (void)args;
3073
3074 if (argc == 0)
3075 {
3076 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos, VTOY_MAX_SCRIPT_BUF);
3077 grub_printf("%s", g_list_script_buf);
3078 }
3079 else
3080 {
3081 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos, VTOY_MAX_SCRIPT_BUF);
3082 grub_printf("%s", g_tree_script_buf);
3083 }
3084
3085 return 0;
3086 }
3087
3088 static grub_err_t ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt, int argc, char **args)
3089 {
3090 img_info *cur = g_ventoy_img_list;
3091
3092 (void)ctxt;
3093 (void)argc;
3094 (void)args;
3095
3096 while (cur)
3097 {
3098 grub_printf("path:<%s> id=%d list_index=%d\n", cur->path, cur->id, cur->plugin_list_index);
3099 grub_printf("name:<%s>\n\n", cur->name);
3100 cur = cur->next;
3101 }
3102
3103 return 0;
3104 }
3105
3106 static grub_err_t ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt, int argc, char **args)
3107 {
3108 (void)ctxt;
3109 (void)argc;
3110 (void)args;
3111
3112 ventoy_plugin_dump_injection();
3113
3114 return 0;
3115 }
3116
3117 static grub_err_t ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
3118 {
3119 (void)ctxt;
3120 (void)argc;
3121 (void)args;
3122
3123 ventoy_plugin_dump_auto_install();
3124
3125 return 0;
3126 }
3127
3128 static grub_err_t ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
3129 {
3130 (void)ctxt;
3131 (void)argc;
3132 (void)args;
3133
3134 ventoy_plugin_dump_persistence();
3135
3136 return 0;
3137 }
3138
3139 static grub_err_t ventoy_cmd_check_mode(grub_extcmd_context_t ctxt, int argc, char **args)
3140 {
3141 (void)ctxt;
3142 (void)argc;
3143 (void)args;
3144
3145 if (argc != 1)
3146 {
3147 return 1;
3148 }
3149
3150 if (args[0][0] == '0')
3151 {
3152 return g_ventoy_memdisk_mode ? 0 : 1;
3153 }
3154 else if (args[0][0] == '1')
3155 {
3156 return g_ventoy_iso_raw ? 0 : 1;
3157 }
3158 else if (args[0][0] == '2')
3159 {
3160 return g_ventoy_iso_uefi_drv ? 0 : 1;
3161 }
3162 else if (args[0][0] == '3')
3163 {
3164 return g_ventoy_grub2_mode ? 0 : 1;
3165 }
3166
3167 return 1;
3168 }
3169
3170 static grub_err_t ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt, int argc, char **args)
3171 {
3172 static int configfile_mode = 0;
3173 char memfile[128] = {0};
3174
3175 (void)ctxt;
3176 (void)argc;
3177 (void)args;
3178
3179 /*
3180 * args[0]: 0:normal 1:configfile
3181 * args[1]: 0:list_buf 1:tree_buf
3182 */
3183
3184 if (argc != 2)
3185 {
3186 debug("Invalid argc %d\n", argc);
3187 return 0;
3188 }
3189
3190 VTOY_CMD_CHECK(1);
3191
3192 if (args[0][0] == '0')
3193 {
3194 if (args[1][0] == '0')
3195 {
3196 grub_script_execute_sourcecode(g_list_script_buf);
3197 }
3198 else
3199 {
3200 grub_script_execute_sourcecode(g_tree_script_buf);
3201 }
3202 }
3203 else
3204 {
3205 if (configfile_mode)
3206 {
3207 debug("Now already in F3 mode %d\n", configfile_mode);
3208 return 0;
3209 }
3210
3211 if (args[1][0] == '0')
3212 {
3213 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
3214 (ulonglong)(ulong)g_list_script_buf, g_list_script_pos);
3215 }
3216 else
3217 {
3218 g_ventoy_last_entry = -1;
3219 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
3220 (ulonglong)(ulong)g_tree_script_buf, g_tree_script_pos);
3221 }
3222
3223 configfile_mode = 1;
3224 grub_script_execute_sourcecode(memfile);
3225 configfile_mode = 0;
3226 }
3227
3228 return 0;
3229 }
3230
3231 static grub_err_t ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt, int argc, char **args)
3232 {
3233 grub_file_t file;
3234
3235 (void)ctxt;
3236
3237 if (argc != 1)
3238 {
3239 return 1;
3240 }
3241
3242 g_ventoy_case_insensitive = 1;
3243 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
3244 g_ventoy_case_insensitive = 0;
3245
3246 grub_errno = 0;
3247
3248 if (file)
3249 {
3250 grub_file_close(file);
3251 return 0;
3252 }
3253 return 1;
3254 }
3255
3256 static grub_err_t ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt, int argc, char **args)
3257 {
3258 int id = 0;
3259 int find = 0;
3260 grub_disk_t disk;
3261 const char *isopath = NULL;
3262 char hdname[32];
3263 ventoy_mbr_head mbr;
3264
3265 (void)ctxt;
3266 (void)argc;
3267
3268 if (argc != 1)
3269 {
3270 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s variable\n", cmd_raw_name);
3271 }
3272
3273 isopath = grub_env_get("vtoy_iso_part");
3274 if (!isopath)
3275 {
3276 debug("isopath is null %p\n", isopath);
3277 return 0;
3278 }
3279
3280 debug("isopath is %s\n", isopath);
3281
3282 for (id = 0; id < 30 && (find == 0); id++)
3283 {
3284 grub_snprintf(hdname, sizeof(hdname), "hd%d,", id);
3285 if (grub_strstr(isopath, hdname))
3286 {
3287 debug("skip %s ...\n", hdname);
3288 continue;
3289 }
3290
3291 grub_snprintf(hdname, sizeof(hdname), "hd%d", id);
3292
3293 disk = grub_disk_open(hdname);
3294 if (!disk)
3295 {
3296 debug("%s not exist\n", hdname);
3297 break;
3298 }
3299
3300 grub_memset(&mbr, 0, sizeof(mbr));
3301 if (0 == grub_disk_read(disk, 0, 0, 512, &mbr))
3302 {
3303 if (mbr.Byte55 == 0x55 && mbr.ByteAA == 0xAA)
3304 {
3305 if (mbr.PartTbl[0].Active == 0x80 || mbr.PartTbl[1].Active == 0x80 ||
3306 mbr.PartTbl[2].Active == 0x80 || mbr.PartTbl[3].Active == 0x80)
3307 {
3308
3309 grub_env_set(args[0], hdname);
3310 find = 1;
3311 }
3312 }
3313 debug("%s is %s\n", hdname, find ? "bootable" : "NOT bootable");
3314 }
3315 else
3316 {
3317 debug("read %s failed\n", hdname);
3318 }
3319
3320 grub_disk_close(disk);
3321 }
3322
3323 return 0;
3324 }
3325
3326 static grub_err_t ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt, int argc, char **args)
3327 {
3328 int len = 1024;
3329 grub_file_t file;
3330 char *buf = NULL;
3331
3332 (void)ctxt;
3333 (void)argc;
3334
3335 if (argc != 2)
3336 {
3337 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file var \n", cmd_raw_name);
3338 }
3339
3340 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3341 if (!file)
3342 {
3343 debug("failed to open file %s\n", args[0]);
3344 return 0;
3345 }
3346
3347 buf = grub_malloc(len);
3348 if (!buf)
3349 {
3350 goto end;
3351 }
3352
3353 buf[len - 1] = 0;
3354 grub_file_read(file, buf, len - 1);
3355
3356 ventoy_get_line(buf);
3357 ventoy_set_env(args[1], buf);
3358
3359 end:
3360
3361 grub_check_free(buf);
3362 grub_file_close(file);
3363
3364 return 0;
3365 }
3366
3367 static int ventoy_img_partition_callback (struct grub_disk *disk, const grub_partition_t partition, void *data)
3368 {
3369 (void)disk;
3370 (void)data;
3371
3372 g_part_list_pos += grub_snprintf(g_part_list_buf + g_part_list_pos, VTOY_MAX_SCRIPT_BUF - g_part_list_pos,
3373 "0 %llu linear /dev/ventoy %llu\n",
3374 (ulonglong)partition->len, (ulonglong)partition->start);
3375
3376 return 0;
3377 }
3378
3379 static grub_err_t ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt, int argc, char **args)
3380 {
3381 char *device_name = NULL;
3382 grub_device_t dev = NULL;
3383 char buf[64];
3384
3385 (void)ctxt;
3386
3387 g_part_list_pos = 0;
3388 grub_env_unset("vtoy_img_part_file");
3389
3390 if (argc != 1)
3391 {
3392 return 1;
3393 }
3394
3395 device_name = grub_file_get_device_name(args[0]);
3396 if (!device_name)
3397 {
3398 debug("ventoy_cmd_img_part_info failed, %s\n", args[0]);
3399 goto end;
3400 }
3401
3402 dev = grub_device_open(device_name);
3403 if (!dev)
3404 {
3405 debug("grub_device_open failed, %s\n", device_name);
3406 goto end;
3407 }
3408
3409 grub_partition_iterate(dev->disk, ventoy_img_partition_callback, NULL);
3410
3411 grub_snprintf(buf, sizeof(buf), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong)(ulong)g_part_list_buf, g_part_list_pos);
3412 grub_env_set("vtoy_img_part_file", buf);
3413
3414 end:
3415
3416 check_free(device_name, grub_free);
3417 check_free(dev, grub_device_close);
3418
3419 return 0;
3420 }
3421
3422
3423 static grub_err_t ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
3424 {
3425 int rc = 1;
3426 grub_file_t file;
3427 char *buf = NULL;
3428
3429 (void)ctxt;
3430 (void)argc;
3431
3432 if (argc != 2)
3433 {
3434 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file str \n", cmd_raw_name);
3435 }
3436
3437 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3438 if (!file)
3439 {
3440 debug("failed to open file %s\n", args[0]);
3441 return 1;
3442 }
3443
3444 buf = grub_malloc(file->size + 1);
3445 if (!buf)
3446 {
3447 goto end;
3448 }
3449
3450 buf[file->size] = 0;
3451 grub_file_read(file, buf, file->size);
3452
3453 if (grub_strstr(buf, args[1]))
3454 {
3455 rc = 0;
3456 }
3457
3458 end:
3459
3460 grub_check_free(buf);
3461 grub_file_close(file);
3462
3463 return rc;
3464 }
3465
3466 static grub_err_t ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt, int argc, char **args)
3467 {
3468 int len;
3469 grub_file_t file;
3470 char buf[64];
3471 grub_uint64_t size;
3472 ventoy_iso9660_vd pvd;
3473
3474 (void)ctxt;
3475 (void)argc;
3476
3477 if (argc != 4)
3478 {
3479 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s sysid volid space \n", cmd_raw_name);
3480 }
3481
3482 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3483 if (!file)
3484 {
3485 debug("failed to open file %s\n", args[0]);
3486 return 0;
3487 }
3488
3489 grub_file_seek(file, 16 * 2048);
3490 len = (int)grub_file_read(file, &pvd, sizeof(pvd));
3491 if (len != sizeof(pvd))
3492 {
3493 debug("failed to read pvd %d\n", len);
3494 goto end;
3495 }
3496
3497 grub_memset(buf, 0, sizeof(buf));
3498 grub_memcpy(buf, pvd.sys, sizeof(pvd.sys));
3499 ventoy_set_env(args[1], buf);
3500
3501 grub_memset(buf, 0, sizeof(buf));
3502 grub_memcpy(buf, pvd.vol, sizeof(pvd.vol));
3503 ventoy_set_env(args[2], buf);
3504
3505 size = pvd.space;
3506 size *= 2048;
3507 grub_snprintf(buf, sizeof(buf), "%llu", (ulonglong)size);
3508 ventoy_set_env(args[3], buf);
3509
3510 end:
3511 grub_file_close(file);
3512
3513 return 0;
3514 }
3515
3516 static grub_err_t ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt, int argc, char **args)
3517 {
3518 int len;
3519 grub_file_t file;
3520 char buf[64];
3521
3522 (void)ctxt;
3523 (void)argc;
3524
3525 if (argc != 2)
3526 {
3527 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s var \n", cmd_raw_name);
3528 }
3529
3530 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3531 if (!file)
3532 {
3533 debug("failed to open file %s\n", args[0]);
3534 return 0;
3535 }
3536
3537 grub_memset(buf, 0, sizeof(buf));
3538 grub_file_seek(file, 16 * 2048 + 813);
3539 len = (int)grub_file_read(file, buf, 17);
3540 if (len != 17)
3541 {
3542 debug("failed to read create date %d\n", len);
3543 goto end;
3544 }
3545
3546 ventoy_set_env(args[1], buf);
3547
3548 end:
3549 grub_file_close(file);
3550
3551 return 0;
3552 }
3553
3554 static grub_err_t ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt, int argc, char **args)
3555 {
3556 (void)ctxt;
3557 (void)argc;
3558 (void)args;
3559
3560 ventoy_env_hook_root(1);
3561
3562 return 0;
3563 }
3564
3565 static grub_err_t ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt, int argc, char **args)
3566 {
3567 (void)ctxt;
3568 (void)argc;
3569 (void)args;
3570
3571 ventoy_env_hook_root(0);
3572
3573 return 0;
3574 }
3575
3576 #ifdef GRUB_MACHINE_EFI
3577 static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
3578 {
3579 int ret = 1;
3580 grub_uint8_t *var;
3581 grub_size_t size;
3582 grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
3583
3584 (void)ctxt;
3585 (void)argc;
3586 (void)args;
3587
3588 var = grub_efi_get_variable("SecureBoot", &global, &size);
3589 if (var && *var == 1)
3590 {
3591 return 0;
3592 }
3593
3594 return ret;
3595 }
3596 #else
3597 static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
3598 {
3599 (void)ctxt;
3600 (void)argc;
3601 (void)args;
3602 return 1;
3603 }
3604 #endif
3605
3606 static grub_err_t ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt, int argc, char **args)
3607 {
3608 int i;
3609 int ret = 1;
3610 grub_file_t file;
3611 grub_uint64_t FileSectors = 0;
3612 ventoy_gpt_info *gpt = NULL;
3613 ventoy_part_table *pt = NULL;
3614 grub_uint8_t zeroguid[16] = {0};
3615
3616 (void)ctxt;
3617 (void)argc;
3618
3619 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3620 if (!file)
3621 {
3622 debug("failed to open file %s\n", args[0]);
3623 return 1;
3624 }
3625
3626 if (file->size % 512)
3627 {
3628 debug("unaligned file size: %llu\n", (ulonglong)file->size);
3629 goto out;
3630 }
3631
3632 gpt = grub_zalloc(sizeof(ventoy_gpt_info));
3633 if (!gpt)
3634 {
3635 goto out;
3636 }
3637
3638 FileSectors = file->size / 512;
3639
3640 grub_file_read(file, gpt, sizeof(ventoy_gpt_info));
3641 if (grub_strncmp(gpt->Head.Signature, "EFI PART", 8) == 0)
3642 {
3643 debug("This is EFI partition table\n");
3644
3645 for (i = 0; i < 128; i++)
3646 {
3647 if (grub_memcmp(gpt->PartTbl[i].PartGuid, zeroguid, 16))
3648 {
3649 if (FileSectors < gpt->PartTbl[i].LastLBA)
3650 {
3651 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
3652 (ulonglong)gpt->PartTbl[i].LastLBA, (ulonglong)FileSectors);
3653 goto out;
3654 }
3655 }
3656 }
3657 }
3658 else
3659 {
3660 debug("This is MBR partition table\n");
3661
3662 for (i = 0; i < 4; i++)
3663 {
3664 pt = gpt->MBR.PartTbl + i;
3665 if (FileSectors < pt->StartSectorId + pt->SectorCount)
3666 {
3667 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
3668 (ulonglong)(pt->StartSectorId + pt->SectorCount),
3669 (ulonglong)FileSectors);
3670 goto out;
3671 }
3672 }
3673 }
3674
3675 ret = 0;
3676
3677 out:
3678 grub_file_close(file);
3679 grub_check_free(gpt);
3680 grub_errno = GRUB_ERR_NONE;
3681 return ret;
3682 }
3683
3684 static grub_err_t ventoy_cmd_clear_key(grub_extcmd_context_t ctxt, int argc, char **args)
3685 {
3686 int i;
3687 int ret;
3688
3689 (void)ctxt;
3690 (void)argc;
3691 (void)args;
3692
3693 for (i = 0; i < 500; i++)
3694 {
3695 ret = grub_getkey_noblock();
3696 if (ret == GRUB_TERM_NO_KEY)
3697 {
3698 break;
3699 }
3700 }
3701
3702 if (i >= 500)
3703 {
3704 grub_cls();
3705 grub_printf("\n\n Still have key input after clear.\n");
3706 grub_refresh();
3707 grub_sleep(5);
3708 }
3709
3710 return 0;
3711 }
3712
3713 static grub_err_t ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt, int argc, char **args)
3714 {
3715 int i;
3716 int buflen;
3717 int datalen;
3718 int loclen;
3719 int img_chunk_num;
3720 int image_sector_size;
3721 char cmd[64];
3722 ventoy_chain_head *chain;
3723 ventoy_img_chunk *chunk;
3724 ventoy_os_param *osparam;
3725 ventoy_image_location *location;
3726 ventoy_image_disk_region *region;
3727 struct grub_acpi_table_header *acpi;
3728
3729 (void)ctxt;
3730
3731 if (argc != 2)
3732 {
3733 return 1;
3734 }
3735
3736 debug("ventoy_cmd_acpi_param %s %s\n", args[0], args[1]);
3737
3738 chain = (ventoy_chain_head *)(ulong)grub_strtoul(args[0], NULL, 16);
3739 if (!chain)
3740 {
3741 return 1;
3742 }
3743
3744 image_sector_size = (int)grub_strtol(args[1], NULL, 10);
3745
3746 if (grub_memcmp(&g_ventoy_guid, &(chain->os_param.guid), 16))
3747 {
3748 debug("Invalid ventoy guid 0x%x\n", chain->os_param.guid.data1);
3749 return 1;
3750 }
3751
3752 img_chunk_num = chain->img_chunk_num;
3753
3754 loclen = sizeof(ventoy_image_location) + (img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
3755 datalen = sizeof(ventoy_os_param) + loclen;
3756
3757 buflen = sizeof(struct grub_acpi_table_header) + datalen;
3758 acpi = grub_zalloc(buflen);
3759 if (!acpi)
3760 {
3761 return 1;
3762 }
3763
3764 /* Step1: Fill acpi table header */
3765 grub_memcpy(acpi->signature, "VTOY", 4);
3766 acpi->length = buflen;
3767 acpi->revision = 1;
3768 grub_memcpy(acpi->oemid, "VENTOY", 6);
3769 grub_memcpy(acpi->oemtable, "OSPARAMS", 8);
3770 acpi->oemrev = 1;
3771 acpi->creator_id[0] = 1;
3772 acpi->creator_rev = 1;
3773
3774 /* Step2: Fill data */
3775 osparam = (ventoy_os_param *)(acpi + 1);
3776 grub_memcpy(osparam, &chain->os_param, sizeof(ventoy_os_param));
3777 osparam->vtoy_img_location_addr = 0;
3778 osparam->vtoy_img_location_len = loclen;
3779 osparam->chksum = 0;
3780 osparam->chksum = 0x100 - grub_byte_checksum(osparam, sizeof(ventoy_os_param));
3781
3782 location = (ventoy_image_location *)(osparam + 1);
3783 grub_memcpy(&location->guid, &osparam->guid, sizeof(ventoy_guid));
3784 location->image_sector_size = image_sector_size;
3785 location->disk_sector_size = chain->disk_sector_size;
3786 location->region_count = img_chunk_num;
3787
3788 region = location->regions;
3789 chunk = (ventoy_img_chunk *)((char *)chain + chain->img_chunk_offset);
3790 if (512 == image_sector_size)
3791 {
3792 for (i = 0; i < img_chunk_num; i++)
3793 {
3794 region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
3795 region->image_start_sector = chunk->img_start_sector * 4;
3796 region->disk_start_sector = chunk->disk_start_sector;
3797 region++;
3798 chunk++;
3799 }
3800 }
3801 else
3802 {
3803 for (i = 0; i < img_chunk_num; i++)
3804 {
3805 region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
3806 region->image_start_sector = chunk->img_start_sector;
3807 region->disk_start_sector = chunk->disk_start_sector;
3808 region++;
3809 chunk++;
3810 }
3811 }
3812
3813 /* Step3: Fill acpi checksum */
3814 acpi->checksum = 0;
3815 acpi->checksum = 0x100 - grub_byte_checksum(acpi, acpi->length);
3816
3817 /* load acpi table */
3818 grub_snprintf(cmd, sizeof(cmd), "acpi mem:0x%lx:size:%d", (ulong)acpi, acpi->length);
3819 grub_script_execute_sourcecode(cmd);
3820
3821 grub_free(acpi);
3822
3823 VENTOY_CMD_RETURN(0);
3824 }
3825
3826 static grub_err_t ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
3827 {
3828 (void)ctxt;
3829 (void)argc;
3830 (void)args;
3831
3832 g_ventoy_last_entry_back = g_ventoy_last_entry;
3833 g_ventoy_last_entry = -1;
3834
3835 return 0;
3836 }
3837
3838 static grub_err_t ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
3839 {
3840 (void)ctxt;
3841 (void)argc;
3842 (void)args;
3843
3844 g_ventoy_last_entry = g_ventoy_last_entry_back;
3845
3846 return 0;
3847 }
3848
3849 static int ventoy_lib_module_callback(const char *filename, const struct grub_dirhook_info *info, void *data)
3850 {
3851 const char *pos = filename + 1;
3852
3853 if (info->dir)
3854 {
3855 while (*pos)
3856 {
3857 if (*pos == '.')
3858 {
3859 if ((*(pos - 1) >= '0' && *(pos - 1) <= '9') && (*(pos + 1) >= '0' && *(pos + 1) <= '9'))
3860 {
3861 grub_strncpy((char *)data, filename, 128);
3862 return 1;
3863 }
3864 }
3865 pos++;
3866 }
3867 }
3868
3869 return 0;
3870 }
3871
3872 static grub_err_t ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt, int argc, char **args)
3873 {
3874 int rc = 1;
3875 char *device_name = NULL;
3876 grub_device_t dev = NULL;
3877 grub_fs_t fs = NULL;
3878 char buf[128] = {0};
3879
3880 (void)ctxt;
3881
3882 if (argc != 3)
3883 {
3884 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc);
3885 return 1;
3886 }
3887
3888 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args[0], args[1], args[2]);
3889
3890 device_name = grub_file_get_device_name(args[0]);
3891 if (!device_name)
3892 {
3893 debug("grub_file_get_device_name failed, %s\n", args[0]);
3894 goto end;
3895 }
3896
3897 dev = grub_device_open(device_name);
3898 if (!dev)
3899 {
3900 debug("grub_device_open failed, %s\n", device_name);
3901 goto end;
3902 }
3903
3904 fs = grub_fs_probe(dev);
3905 if (!fs)
3906 {
3907 debug("grub_fs_probe failed, %s\n", device_name);
3908 goto end;
3909 }
3910
3911 fs->fs_dir(dev, args[1], ventoy_lib_module_callback, buf);
3912
3913 if (buf[0])
3914 {
3915 ventoy_set_env(args[2], buf);
3916 }
3917
3918 rc = 0;
3919
3920 end:
3921
3922 check_free(device_name, grub_free);
3923 check_free(dev, grub_device_close);
3924
3925 return rc;
3926 }
3927
3928 int ventoy_load_part_table(const char *diskname)
3929 {
3930 char name[64];
3931 int ret;
3932 grub_disk_t disk;
3933 grub_device_t dev;
3934
3935 g_ventoy_part_info = grub_zalloc(sizeof(ventoy_gpt_info));
3936 if (!g_ventoy_part_info)
3937 {
3938 return 1;
3939 }
3940
3941 disk = grub_disk_open(diskname);
3942 if (!disk)
3943 {
3944 debug("Failed to open disk %s\n", diskname);
3945 return 1;
3946 }
3947
3948 g_ventoy_disk_size = disk->total_sectors * (1U << disk->log_sector_size);
3949
3950 grub_disk_read(disk, 0, 0, sizeof(ventoy_gpt_info), g_ventoy_part_info);
3951 grub_disk_close(disk);
3952
3953 grub_snprintf(name, sizeof(name), "%s,1", diskname);
3954 dev = grub_device_open(name);
3955 if (dev)
3956 {
3957 /* Check for official Ventoy device */
3958 ret = ventoy_check_official_device(dev);
3959 grub_device_close(dev);
3960
3961 if (ret)
3962 {
3963 return 1;
3964 }
3965 }
3966
3967 g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
3968 g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
3969
3970 return 0;
3971 }
3972
3973 static grub_err_t ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt, int argc, char **args)
3974 {
3975 int ret;
3976
3977 (void)argc;
3978 (void)ctxt;
3979
3980 ret = ventoy_load_part_table(args[0]);
3981 if (ret)
3982 {
3983 grub_exit();
3984 }
3985
3986 g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
3987 g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
3988
3989 return 0;
3990 }
3991
3992 static grub_err_t ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
3993 {
3994 int ret = 1;
3995 const char *vcfg = NULL;
3996
3997 (void)argc;
3998 (void)ctxt;
3999
4000 vcfg = ventoy_plugin_get_custom_boot(args[0]);
4001 if (vcfg)
4002 {
4003 debug("custom boot <%s>:<%s>\n", args[0], vcfg);
4004 grub_env_set(args[1], vcfg);
4005 ret = 0;
4006 }
4007 else
4008 {
4009 debug("custom boot <%s>:<NOT FOUND>\n", args[0]);
4010 }
4011
4012 grub_errno = 0;
4013 return ret;
4014 }
4015
4016
4017 static grub_err_t ventoy_cmd_part_exist(grub_extcmd_context_t ctxt, int argc, char **args)
4018 {
4019 int id;
4020 grub_uint8_t zeroguid[16] = {0};
4021
4022 (void)argc;
4023 (void)ctxt;
4024
4025 id = (int)grub_strtoul(args[0], NULL, 10);
4026 grub_errno = 0;
4027
4028 if (grub_memcmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
4029 {
4030 if (id >= 1 && id <= 128)
4031 {
4032 if (grub_memcmp(g_ventoy_part_info->PartTbl[id - 1].PartGuid, zeroguid, 16))
4033 {
4034 return 0;
4035 }
4036 }
4037 }
4038 else
4039 {
4040 if (id >= 1 && id <= 4)
4041 {
4042 if (g_ventoy_part_info->MBR.PartTbl[id - 1].FsFlag)
4043 {
4044 return 0;
4045 }
4046 }
4047 }
4048
4049 return 1;
4050 }
4051
4052 static grub_err_t ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt, int argc, char **args)
4053 {
4054 int rc = 1;
4055 char *device_name = NULL;
4056 grub_device_t dev = NULL;
4057 grub_fs_t fs = NULL;
4058 char *label = NULL;
4059
4060 (void)ctxt;
4061
4062 debug("get fs label for %s\n", args[0]);
4063
4064 if (argc != 2)
4065 {
4066 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc);
4067 return 1;
4068 }
4069
4070 device_name = grub_file_get_device_name(args[0]);
4071 if (!device_name)
4072 {
4073 debug("grub_file_get_device_name failed, %s\n", args[0]);
4074 goto end;
4075 }
4076
4077 dev = grub_device_open(device_name);
4078 if (!dev)
4079 {
4080 debug("grub_device_open failed, %s\n", device_name);
4081 goto end;
4082 }
4083
4084 fs = grub_fs_probe(dev);
4085 if (NULL == fs || NULL == fs->fs_label)
4086 {
4087 debug("grub_fs_probe failed, %s %p %p\n", device_name, fs, fs->fs_label);
4088 goto end;
4089 }
4090
4091 fs->fs_label(dev, &label);
4092 if (label)
4093 {
4094 debug("label=<%s>\n", label);
4095 ventoy_set_env(args[1], label);
4096 grub_free(label);
4097 }
4098
4099 rc = 0;
4100
4101 end:
4102
4103 check_free(device_name, grub_free);
4104 check_free(dev, grub_device_close);
4105
4106 return rc;
4107 }
4108
4109 static int ventoy_fs_enum_1st_file(const char *filename, const struct grub_dirhook_info *info, void *data)
4110 {
4111 if (!info->dir)
4112 {
4113 grub_snprintf((char *)data, 256, "%s", filename);
4114 return 1;
4115 }
4116
4117 return 0;
4118 }
4119
4120
4121 static grub_err_t ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt, int argc, char **args)
4122 {
4123 int rc = 1;
4124 char *device_name = NULL;
4125 grub_device_t dev = NULL;
4126 grub_fs_t fs = NULL;
4127 char name[256] ={0};
4128
4129 (void)ctxt;
4130
4131 if (argc != 3)
4132 {
4133 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc);
4134 return 1;
4135 }
4136
4137 device_name = grub_file_get_device_name(args[0]);
4138 if (!device_name)
4139 {
4140 debug("grub_file_get_device_name failed, %s\n", args[0]);
4141 goto end;
4142 }
4143
4144 dev = grub_device_open(device_name);
4145 if (!dev)
4146 {
4147 debug("grub_device_open failed, %s\n", device_name);
4148 goto end;
4149 }
4150
4151 fs = grub_fs_probe(dev);
4152 if (!fs)
4153 {
4154 debug("grub_fs_probe failed, %s\n", device_name);
4155 goto end;
4156 }
4157
4158 fs->fs_dir(dev, args[1], ventoy_fs_enum_1st_file, name);
4159 if (name[0])
4160 {
4161 ventoy_set_env(args[2], name);
4162 }
4163
4164 rc = 0;
4165
4166 end:
4167
4168 check_free(device_name, grub_free);
4169 check_free(dev, grub_device_close);
4170
4171 return rc;
4172 }
4173
4174 static grub_err_t ventoy_cmd_basename(grub_extcmd_context_t ctxt, int argc, char **args)
4175 {
4176 char c;
4177 char *pos = NULL;
4178 char *end = NULL;
4179
4180 (void)ctxt;
4181
4182 if (argc != 2)
4183 {
4184 debug("ventoy_cmd_basename, invalid param num %d\n", argc);
4185 return 1;
4186 }
4187
4188 for (pos = args[0]; *pos; pos++)
4189 {
4190 if (*pos == '.')
4191 {
4192 end = pos;
4193 }
4194 }
4195
4196 if (end)
4197 {
4198 c = *end;
4199 *end = 0;
4200 }
4201
4202 grub_env_set(args[1], args[0]);
4203
4204 if (end)
4205 {
4206 *end = c;
4207 }
4208
4209 return 0;
4210 }
4211
4212 static grub_err_t ventoy_cmd_basefile(grub_extcmd_context_t ctxt, int argc, char **args)
4213 {
4214 int i;
4215 int len;
4216 const char *buf;
4217
4218 (void)ctxt;
4219
4220 if (argc != 2)
4221 {
4222 debug("ventoy_cmd_basefile, invalid param num %d\n", argc);
4223 return 1;
4224 }
4225
4226 buf = args[0];
4227 len = (int)grub_strlen(buf);
4228 for (i = len; i > 0; i--)
4229 {
4230 if (buf[i - 1] == '/')
4231 {
4232 grub_env_set(args[1], buf + i);
4233 return 0;
4234 }
4235 }
4236
4237 grub_env_set(args[1], buf);
4238
4239 return 0;
4240 }
4241
4242 static grub_err_t ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4243 {
4244 struct grub_video_mode_info info;
4245 char buf[32];
4246
4247 (void)ctxt;
4248 (void)argc;
4249 (void)args;
4250
4251 if (!g_video_mode_list)
4252 {
4253 ventoy_enum_video_mode();
4254 }
4255
4256 if (grub_video_get_info(&info) == GRUB_ERR_NONE)
4257 {
4258 grub_snprintf(buf, sizeof(buf), "Resolution (%ux%u)", info.width, info.height);
4259 }
4260 else
4261 {
4262 grub_snprintf(buf, sizeof(buf), "Resolution (0x0)");
4263 }
4264
4265 grub_env_set("VTOY_CUR_VIDEO_MODE", buf);
4266
4267 grub_snprintf(buf, sizeof(buf), "%d", g_video_mode_num);
4268 grub_env_set("VTOY_VIDEO_MODE_NUM", buf);
4269
4270 VENTOY_CMD_RETURN(0);
4271 }
4272
4273 static grub_err_t vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4274 {
4275 struct grub_video_mode_info info;
4276 char buf[32];
4277
4278 (void)ctxt;
4279 (void)argc;
4280 (void)args;
4281
4282 if (grub_video_get_info(&info) == GRUB_ERR_NONE)
4283 {
4284 grub_snprintf(buf, sizeof(buf), "%ux%ux%u", info.width, info.height, info.bpp);
4285 }
4286 else
4287 {
4288 grub_snprintf(buf, sizeof(buf), "0x0x0");
4289 }
4290
4291 grub_env_set(args[0], buf);
4292
4293 VENTOY_CMD_RETURN(0);
4294 }
4295
4296 static grub_err_t ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4297 {
4298 int id;
4299 char buf[32];
4300
4301 (void)ctxt;
4302 (void)argc;
4303
4304 if (!g_video_mode_list)
4305 {
4306 return 0;
4307 }
4308
4309 id = (int)grub_strtoul(args[0], NULL, 10);
4310 if (id < g_video_mode_num)
4311 {
4312 grub_snprintf(buf, sizeof(buf), "%ux%ux%u",
4313 g_video_mode_list[id].width, g_video_mode_list[id].height, g_video_mode_list[id].bpp);
4314 }
4315
4316 grub_env_set(args[1], buf);
4317
4318 VENTOY_CMD_RETURN(0);
4319 }
4320
4321 int ventoy_env_init(void)
4322 {
4323 char buf[64];
4324
4325 grub_env_set("vtdebug_flag", "");
4326
4327 g_part_list_buf = grub_malloc(VTOY_PART_BUF_LEN);
4328 g_tree_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
4329 g_list_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
4330 g_conf_replace_new_buf = grub_malloc(vtoy_max_replace_file_size);
4331
4332 ventoy_filt_register(0, ventoy_wrapper_open);
4333
4334 g_grub_param = (ventoy_grub_param *)grub_zalloc(sizeof(ventoy_grub_param));
4335 if (g_grub_param)
4336 {
4337 g_grub_param->grub_env_get = grub_env_get;
4338 g_grub_param->grub_env_set = (grub_env_set_pf)grub_env_set;
4339 g_grub_param->grub_env_printf = (grub_env_printf_pf)grub_printf;
4340 grub_snprintf(buf, sizeof(buf), "%p", g_grub_param);
4341 grub_env_set("env_param", buf);
4342 grub_env_set("ventoy_env_param", buf);
4343
4344 grub_env_export("env_param");
4345 grub_env_export("ventoy_env_param");
4346 }
4347
4348 return 0;
4349 }
4350
4351 static cmd_para ventoy_cmds[] =
4352 {
4353 { "vt_incr", ventoy_cmd_incr, 0, NULL, "{Var} {INT}", "Increase integer variable", NULL },
4354 { "vt_mod", ventoy_cmd_mod, 0, NULL, "{Int} {Int} {Var}", "mod integer variable", NULL },
4355 { "vt_strstr", ventoy_cmd_strstr, 0, NULL, "", "", NULL },
4356 { "vt_str_begin", ventoy_cmd_strbegin, 0, NULL, "", "", NULL },
4357 { "vt_debug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
4358 { "vtdebug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
4359 { "vtbreak", ventoy_cmd_break, 0, NULL, "{level}", "set debug break", NULL },
4360 { "vt_cmp", ventoy_cmd_cmp, 0, NULL, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL },
4361 { "vt_device", ventoy_cmd_device, 0, NULL, "path var", "", NULL },
4362 { "vt_check_compatible", ventoy_cmd_check_compatible, 0, NULL, "", "", NULL },
4363 { "vt_list_img", ventoy_cmd_list_img, 0, NULL, "{device} {cntvar}", "find all iso file in device", NULL },
4364 { "vt_clear_img", ventoy_cmd_clear_img, 0, NULL, "", "clear image list", NULL },
4365 { "vt_img_name", ventoy_cmd_img_name, 0, NULL, "{imageID} {var}", "get image name", NULL },
4366 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path, 0, NULL, "{var}", "get chosen img path", NULL },
4367 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path, 0, NULL, "{var}", "select chosen img path", NULL },
4368 { "vt_img_sector", ventoy_cmd_img_sector, 0, NULL, "{imageName}", "", NULL },
4369 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector, 0, NULL, "", "", NULL },
4370 { "vt_load_wimboot", ventoy_cmd_load_wimboot, 0, NULL, "", "", NULL },
4371 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot, 0, NULL, "", "", NULL },
4372 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot, 0, NULL, "", "", NULL },
4373 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data, 0, NULL, "", "", NULL },
4374 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type, 0, NULL, "", "", NULL },
4375 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot, 0, NULL, "", "", NULL },
4376 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot, 0, NULL, "", "", NULL },
4377
4378 { "vt_skip_svd", ventoy_cmd_skip_svd, 0, NULL, "", "", NULL },
4379 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64, 0, NULL, "", "", NULL },
4380 { "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
4381 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio, 0, NULL, "", "", NULL },
4382 { "vt_push_last_entry", ventoy_cmd_push_last_entry, 0, NULL, "", "", NULL },
4383 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry, 0, NULL, "", "", NULL },
4384 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver, 0, NULL, "", "", NULL },
4385
4386 { "vt_load_part_table", ventoy_cmd_load_part_table, 0, NULL, "", "", NULL },
4387 { "vt_check_part_exist", ventoy_cmd_part_exist, 0, NULL, "", "", NULL },
4388 { "vt_get_fs_label", ventoy_cmd_get_fs_label, 0, NULL, "", "", NULL },
4389 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file, 0, NULL, "", "", NULL },
4390 { "vt_file_basename", ventoy_cmd_basename, 0, NULL, "", "", NULL },
4391 { "vt_file_basefile", ventoy_cmd_basefile, 0, NULL, "", "", NULL },
4392 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode, 0, NULL, "", "", NULL },
4393 { "vt_get_video_mode", ventoy_cmd_get_video_mode, 0, NULL, "", "", NULL },
4394 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode, 0, NULL, "", "", NULL },
4395
4396
4397 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd, 0, NULL, "", "", NULL },
4398 { "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
4399 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
4400 { "vt_check_mode", ventoy_cmd_check_mode, 0, NULL, "", "", NULL },
4401 { "vt_dump_img_list", ventoy_cmd_dump_img_list, 0, NULL, "", "", NULL },
4402 { "vt_dump_injection", ventoy_cmd_dump_injection, 0, NULL, "", "", NULL },
4403 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install, 0, NULL, "", "", NULL },
4404 { "vt_dump_persistence", ventoy_cmd_dump_persistence, 0, NULL, "", "", NULL },
4405 { "vt_select_auto_install", ventoy_cmd_sel_auto_install, 0, NULL, "", "", NULL },
4406 { "vt_select_persistence", ventoy_cmd_sel_persistence, 0, NULL, "", "", NULL },
4407 { "vt_select_conf_replace", ventoy_select_conf_replace, 0, NULL, "", "", NULL },
4408
4409 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
4410 { "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
4411 { "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
4412 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem, 0, NULL, "", "", NULL },
4413 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk, 0, NULL, "", "", NULL },
4414 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso, 0, NULL, "", "", NULL },
4415
4416 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
4417 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
4418 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file, 0, NULL, "", "", NULL },
4419 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list, 0, NULL, "", "", NULL },
4420 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list, 0, NULL, "", "", NULL },
4421 { "vt_linux_initrd_count", ventoy_cmd_initrd_count, 0, NULL, "", "", NULL },
4422 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count, 0, NULL, "", "", NULL },
4423 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd, 0, NULL, "", "", NULL },
4424 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data, 0, NULL, "", "", NULL },
4425 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index, 0, NULL, "", "", NULL },
4426
4427 { "vt_windows_reset", ventoy_cmd_wimdows_reset, 0, NULL, "", "", NULL },
4428 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data, 0, NULL, "", "", NULL },
4429 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch, 0, NULL, "", "", NULL },
4430 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch, 0, NULL, "", "", NULL },
4431 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count, 0, NULL, "", "", NULL },
4432 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch, 0, NULL, "", "", NULL },
4433 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable, 0, NULL, "", "", NULL },
4434 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data, 0, NULL, "", "", NULL },
4435
4436 { "vt_add_replace_file", ventoy_cmd_add_replace_file, 0, NULL, "", "", NULL },
4437 { "vt_test_block_list", ventoy_cmd_test_block_list, 0, NULL, "", "", NULL },
4438 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase, 0, NULL, "", "", NULL },
4439
4440
4441 { "vt_load_plugin", ventoy_cmd_load_plugin, 0, NULL, "", "", NULL },
4442 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json, 0, NULL, "", "", NULL },
4443 { "vt_check_password", ventoy_cmd_check_password, 0, NULL, "", "", NULL },
4444
4445 { "vt_1st_line", ventoy_cmd_read_1st_line, 0, NULL, "", "", NULL },
4446 { "vt_file_strstr", ventoy_cmd_file_strstr, 0, NULL, "", "", NULL },
4447 { "vt_img_part_info", ventoy_cmd_img_part_info, 0, NULL, "", "", NULL },
4448
4449
4450 { "vt_parse_iso_volume", ventoy_cmd_parse_volume, 0, NULL, "", "", NULL },
4451 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date, 0, NULL, "", "", NULL },
4452 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver, 0, NULL, "", "", NULL },
4453 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver, 0, NULL, "", "", NULL },
4454 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf, 0, NULL, "", "", NULL },
4455 { "vt_unix_reset", ventoy_cmd_unix_reset, 0, NULL, "", "", NULL },
4456 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf, 0, NULL, "", "", NULL },
4457 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko, 0, NULL, "", "", NULL },
4458 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc, 0, NULL, "", "", NULL },
4459 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko, 0, NULL, "", "", NULL },
4460 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data, 0, NULL, "", "", NULL },
4461
4462 { "vt_img_hook_root", ventoy_cmd_img_hook_root, 0, NULL, "", "", NULL },
4463 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root, 0, NULL, "", "", NULL },
4464 { "vt_acpi_param", ventoy_cmd_acpi_param, 0, NULL, "", "", NULL },
4465 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var, 0, NULL, "", "", NULL },
4466 { "vt_clear_key", ventoy_cmd_clear_key, 0, NULL, "", "", NULL },
4467 { "vt_img_check_range", ventoy_cmd_img_check_range, 0, NULL, "", "", NULL },
4468
4469 };
4470
4471 int ventoy_register_all_cmd(void)
4472 {
4473 grub_uint32_t i;
4474 cmd_para *cur = NULL;
4475
4476 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
4477 {
4478 cur = ventoy_cmds + i;
4479 cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags,
4480 cur->summary, cur->description, cur->parser);
4481 }
4482 return 0;
4483 }
4484
4485 int ventoy_unregister_all_cmd(void)
4486 {
4487 grub_uint32_t i;
4488
4489 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
4490 {
4491 grub_unregister_extcmd(ventoy_cmds[i].cmd);
4492 }
4493
4494 return 0;
4495 }
4496
4497