]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c
3a9b7718023c297ccb4b7d38793a513def1c396d
[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 else if (args[0][0] == '4')
3167 {
3168 return g_ventoy_wimboot_mode ? 0 : 1;
3169 }
3170
3171 return 1;
3172 }
3173
3174 static grub_err_t ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt, int argc, char **args)
3175 {
3176 static int configfile_mode = 0;
3177 char memfile[128] = {0};
3178
3179 (void)ctxt;
3180 (void)argc;
3181 (void)args;
3182
3183 /*
3184 * args[0]: 0:normal 1:configfile
3185 * args[1]: 0:list_buf 1:tree_buf
3186 */
3187
3188 if (argc != 2)
3189 {
3190 debug("Invalid argc %d\n", argc);
3191 return 0;
3192 }
3193
3194 VTOY_CMD_CHECK(1);
3195
3196 if (args[0][0] == '0')
3197 {
3198 if (args[1][0] == '0')
3199 {
3200 grub_script_execute_sourcecode(g_list_script_buf);
3201 }
3202 else
3203 {
3204 grub_script_execute_sourcecode(g_tree_script_buf);
3205 }
3206 }
3207 else
3208 {
3209 if (configfile_mode)
3210 {
3211 debug("Now already in F3 mode %d\n", configfile_mode);
3212 return 0;
3213 }
3214
3215 if (args[1][0] == '0')
3216 {
3217 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
3218 (ulonglong)(ulong)g_list_script_buf, g_list_script_pos);
3219 }
3220 else
3221 {
3222 g_ventoy_last_entry = -1;
3223 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
3224 (ulonglong)(ulong)g_tree_script_buf, g_tree_script_pos);
3225 }
3226
3227 configfile_mode = 1;
3228 grub_script_execute_sourcecode(memfile);
3229 configfile_mode = 0;
3230 }
3231
3232 return 0;
3233 }
3234
3235 static grub_err_t ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt, int argc, char **args)
3236 {
3237 grub_file_t file;
3238
3239 (void)ctxt;
3240
3241 if (argc != 1)
3242 {
3243 return 1;
3244 }
3245
3246 g_ventoy_case_insensitive = 1;
3247 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
3248 g_ventoy_case_insensitive = 0;
3249
3250 grub_errno = 0;
3251
3252 if (file)
3253 {
3254 grub_file_close(file);
3255 return 0;
3256 }
3257 return 1;
3258 }
3259
3260 static grub_err_t ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt, int argc, char **args)
3261 {
3262 int id = 0;
3263 int find = 0;
3264 grub_disk_t disk;
3265 const char *isopath = NULL;
3266 char hdname[32];
3267 ventoy_mbr_head mbr;
3268
3269 (void)ctxt;
3270 (void)argc;
3271
3272 if (argc != 1)
3273 {
3274 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s variable\n", cmd_raw_name);
3275 }
3276
3277 isopath = grub_env_get("vtoy_iso_part");
3278 if (!isopath)
3279 {
3280 debug("isopath is null %p\n", isopath);
3281 return 0;
3282 }
3283
3284 debug("isopath is %s\n", isopath);
3285
3286 for (id = 0; id < 30 && (find == 0); id++)
3287 {
3288 grub_snprintf(hdname, sizeof(hdname), "hd%d,", id);
3289 if (grub_strstr(isopath, hdname))
3290 {
3291 debug("skip %s ...\n", hdname);
3292 continue;
3293 }
3294
3295 grub_snprintf(hdname, sizeof(hdname), "hd%d", id);
3296
3297 disk = grub_disk_open(hdname);
3298 if (!disk)
3299 {
3300 debug("%s not exist\n", hdname);
3301 break;
3302 }
3303
3304 grub_memset(&mbr, 0, sizeof(mbr));
3305 if (0 == grub_disk_read(disk, 0, 0, 512, &mbr))
3306 {
3307 if (mbr.Byte55 == 0x55 && mbr.ByteAA == 0xAA)
3308 {
3309 if (mbr.PartTbl[0].Active == 0x80 || mbr.PartTbl[1].Active == 0x80 ||
3310 mbr.PartTbl[2].Active == 0x80 || mbr.PartTbl[3].Active == 0x80)
3311 {
3312
3313 grub_env_set(args[0], hdname);
3314 find = 1;
3315 }
3316 }
3317 debug("%s is %s\n", hdname, find ? "bootable" : "NOT bootable");
3318 }
3319 else
3320 {
3321 debug("read %s failed\n", hdname);
3322 }
3323
3324 grub_disk_close(disk);
3325 }
3326
3327 return 0;
3328 }
3329
3330 static grub_err_t ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt, int argc, char **args)
3331 {
3332 int len = 1024;
3333 grub_file_t file;
3334 char *buf = NULL;
3335
3336 (void)ctxt;
3337 (void)argc;
3338
3339 if (argc != 2)
3340 {
3341 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file var \n", cmd_raw_name);
3342 }
3343
3344 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3345 if (!file)
3346 {
3347 debug("failed to open file %s\n", args[0]);
3348 return 0;
3349 }
3350
3351 buf = grub_malloc(len);
3352 if (!buf)
3353 {
3354 goto end;
3355 }
3356
3357 buf[len - 1] = 0;
3358 grub_file_read(file, buf, len - 1);
3359
3360 ventoy_get_line(buf);
3361 ventoy_set_env(args[1], buf);
3362
3363 end:
3364
3365 grub_check_free(buf);
3366 grub_file_close(file);
3367
3368 return 0;
3369 }
3370
3371 static int ventoy_img_partition_callback (struct grub_disk *disk, const grub_partition_t partition, void *data)
3372 {
3373 (void)disk;
3374 (void)data;
3375
3376 g_part_list_pos += grub_snprintf(g_part_list_buf + g_part_list_pos, VTOY_MAX_SCRIPT_BUF - g_part_list_pos,
3377 "0 %llu linear /dev/ventoy %llu\n",
3378 (ulonglong)partition->len, (ulonglong)partition->start);
3379
3380 return 0;
3381 }
3382
3383 static grub_err_t ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt, int argc, char **args)
3384 {
3385 char *device_name = NULL;
3386 grub_device_t dev = NULL;
3387 char buf[64];
3388
3389 (void)ctxt;
3390
3391 g_part_list_pos = 0;
3392 grub_env_unset("vtoy_img_part_file");
3393
3394 if (argc != 1)
3395 {
3396 return 1;
3397 }
3398
3399 device_name = grub_file_get_device_name(args[0]);
3400 if (!device_name)
3401 {
3402 debug("ventoy_cmd_img_part_info failed, %s\n", args[0]);
3403 goto end;
3404 }
3405
3406 dev = grub_device_open(device_name);
3407 if (!dev)
3408 {
3409 debug("grub_device_open failed, %s\n", device_name);
3410 goto end;
3411 }
3412
3413 grub_partition_iterate(dev->disk, ventoy_img_partition_callback, NULL);
3414
3415 grub_snprintf(buf, sizeof(buf), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong)(ulong)g_part_list_buf, g_part_list_pos);
3416 grub_env_set("vtoy_img_part_file", buf);
3417
3418 end:
3419
3420 check_free(device_name, grub_free);
3421 check_free(dev, grub_device_close);
3422
3423 return 0;
3424 }
3425
3426
3427 static grub_err_t ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
3428 {
3429 int rc = 1;
3430 grub_file_t file;
3431 char *buf = NULL;
3432
3433 (void)ctxt;
3434 (void)argc;
3435
3436 if (argc != 2)
3437 {
3438 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file str \n", cmd_raw_name);
3439 }
3440
3441 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3442 if (!file)
3443 {
3444 debug("failed to open file %s\n", args[0]);
3445 return 1;
3446 }
3447
3448 buf = grub_malloc(file->size + 1);
3449 if (!buf)
3450 {
3451 goto end;
3452 }
3453
3454 buf[file->size] = 0;
3455 grub_file_read(file, buf, file->size);
3456
3457 if (grub_strstr(buf, args[1]))
3458 {
3459 rc = 0;
3460 }
3461
3462 end:
3463
3464 grub_check_free(buf);
3465 grub_file_close(file);
3466
3467 return rc;
3468 }
3469
3470 static grub_err_t ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt, int argc, char **args)
3471 {
3472 int len;
3473 grub_file_t file;
3474 char buf[64];
3475 grub_uint64_t size;
3476 ventoy_iso9660_vd pvd;
3477
3478 (void)ctxt;
3479 (void)argc;
3480
3481 if (argc != 4)
3482 {
3483 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s sysid volid space \n", cmd_raw_name);
3484 }
3485
3486 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3487 if (!file)
3488 {
3489 debug("failed to open file %s\n", args[0]);
3490 return 0;
3491 }
3492
3493 grub_file_seek(file, 16 * 2048);
3494 len = (int)grub_file_read(file, &pvd, sizeof(pvd));
3495 if (len != sizeof(pvd))
3496 {
3497 debug("failed to read pvd %d\n", len);
3498 goto end;
3499 }
3500
3501 grub_memset(buf, 0, sizeof(buf));
3502 grub_memcpy(buf, pvd.sys, sizeof(pvd.sys));
3503 ventoy_set_env(args[1], buf);
3504
3505 grub_memset(buf, 0, sizeof(buf));
3506 grub_memcpy(buf, pvd.vol, sizeof(pvd.vol));
3507 ventoy_set_env(args[2], buf);
3508
3509 size = pvd.space;
3510 size *= 2048;
3511 grub_snprintf(buf, sizeof(buf), "%llu", (ulonglong)size);
3512 ventoy_set_env(args[3], buf);
3513
3514 end:
3515 grub_file_close(file);
3516
3517 return 0;
3518 }
3519
3520 static grub_err_t ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt, int argc, char **args)
3521 {
3522 int len;
3523 grub_file_t file;
3524 char buf[64];
3525
3526 (void)ctxt;
3527 (void)argc;
3528
3529 if (argc != 2)
3530 {
3531 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s var \n", cmd_raw_name);
3532 }
3533
3534 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3535 if (!file)
3536 {
3537 debug("failed to open file %s\n", args[0]);
3538 return 0;
3539 }
3540
3541 grub_memset(buf, 0, sizeof(buf));
3542 grub_file_seek(file, 16 * 2048 + 813);
3543 len = (int)grub_file_read(file, buf, 17);
3544 if (len != 17)
3545 {
3546 debug("failed to read create date %d\n", len);
3547 goto end;
3548 }
3549
3550 ventoy_set_env(args[1], buf);
3551
3552 end:
3553 grub_file_close(file);
3554
3555 return 0;
3556 }
3557
3558 static grub_err_t ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt, int argc, char **args)
3559 {
3560 (void)ctxt;
3561 (void)argc;
3562 (void)args;
3563
3564 ventoy_env_hook_root(1);
3565
3566 return 0;
3567 }
3568
3569 static grub_err_t ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt, int argc, char **args)
3570 {
3571 (void)ctxt;
3572 (void)argc;
3573 (void)args;
3574
3575 ventoy_env_hook_root(0);
3576
3577 return 0;
3578 }
3579
3580 #ifdef GRUB_MACHINE_EFI
3581 static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
3582 {
3583 int ret = 1;
3584 grub_uint8_t *var;
3585 grub_size_t size;
3586 grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
3587
3588 (void)ctxt;
3589 (void)argc;
3590 (void)args;
3591
3592 var = grub_efi_get_variable("SecureBoot", &global, &size);
3593 if (var && *var == 1)
3594 {
3595 return 0;
3596 }
3597
3598 return ret;
3599 }
3600 #else
3601 static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
3602 {
3603 (void)ctxt;
3604 (void)argc;
3605 (void)args;
3606 return 1;
3607 }
3608 #endif
3609
3610 static grub_err_t ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt, int argc, char **args)
3611 {
3612 int i;
3613 int ret = 1;
3614 grub_file_t file;
3615 grub_uint64_t FileSectors = 0;
3616 ventoy_gpt_info *gpt = NULL;
3617 ventoy_part_table *pt = NULL;
3618 grub_uint8_t zeroguid[16] = {0};
3619
3620 (void)ctxt;
3621 (void)argc;
3622
3623 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
3624 if (!file)
3625 {
3626 debug("failed to open file %s\n", args[0]);
3627 return 1;
3628 }
3629
3630 if (file->size % 512)
3631 {
3632 debug("unaligned file size: %llu\n", (ulonglong)file->size);
3633 goto out;
3634 }
3635
3636 gpt = grub_zalloc(sizeof(ventoy_gpt_info));
3637 if (!gpt)
3638 {
3639 goto out;
3640 }
3641
3642 FileSectors = file->size / 512;
3643
3644 grub_file_read(file, gpt, sizeof(ventoy_gpt_info));
3645 if (grub_strncmp(gpt->Head.Signature, "EFI PART", 8) == 0)
3646 {
3647 debug("This is EFI partition table\n");
3648
3649 for (i = 0; i < 128; i++)
3650 {
3651 if (grub_memcmp(gpt->PartTbl[i].PartGuid, zeroguid, 16))
3652 {
3653 if (FileSectors < gpt->PartTbl[i].LastLBA)
3654 {
3655 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
3656 (ulonglong)gpt->PartTbl[i].LastLBA, (ulonglong)FileSectors);
3657 goto out;
3658 }
3659 }
3660 }
3661 }
3662 else
3663 {
3664 debug("This is MBR partition table\n");
3665
3666 for (i = 0; i < 4; i++)
3667 {
3668 pt = gpt->MBR.PartTbl + i;
3669 if (FileSectors < pt->StartSectorId + pt->SectorCount)
3670 {
3671 debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
3672 (ulonglong)(pt->StartSectorId + pt->SectorCount),
3673 (ulonglong)FileSectors);
3674 goto out;
3675 }
3676 }
3677 }
3678
3679 ret = 0;
3680
3681 out:
3682 grub_file_close(file);
3683 grub_check_free(gpt);
3684 grub_errno = GRUB_ERR_NONE;
3685 return ret;
3686 }
3687
3688 static grub_err_t ventoy_cmd_clear_key(grub_extcmd_context_t ctxt, int argc, char **args)
3689 {
3690 int i;
3691 int ret;
3692
3693 (void)ctxt;
3694 (void)argc;
3695 (void)args;
3696
3697 for (i = 0; i < 500; i++)
3698 {
3699 ret = grub_getkey_noblock();
3700 if (ret == GRUB_TERM_NO_KEY)
3701 {
3702 break;
3703 }
3704 }
3705
3706 if (i >= 500)
3707 {
3708 grub_cls();
3709 grub_printf("\n\n Still have key input after clear.\n");
3710 grub_refresh();
3711 grub_sleep(5);
3712 }
3713
3714 return 0;
3715 }
3716
3717 static grub_err_t ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt, int argc, char **args)
3718 {
3719 int i;
3720 int buflen;
3721 int datalen;
3722 int loclen;
3723 int img_chunk_num;
3724 int image_sector_size;
3725 char cmd[64];
3726 ventoy_chain_head *chain;
3727 ventoy_img_chunk *chunk;
3728 ventoy_os_param *osparam;
3729 ventoy_image_location *location;
3730 ventoy_image_disk_region *region;
3731 struct grub_acpi_table_header *acpi;
3732
3733 (void)ctxt;
3734
3735 if (argc != 2)
3736 {
3737 return 1;
3738 }
3739
3740 debug("ventoy_cmd_acpi_param %s %s\n", args[0], args[1]);
3741
3742 chain = (ventoy_chain_head *)(ulong)grub_strtoul(args[0], NULL, 16);
3743 if (!chain)
3744 {
3745 return 1;
3746 }
3747
3748 image_sector_size = (int)grub_strtol(args[1], NULL, 10);
3749
3750 if (grub_memcmp(&g_ventoy_guid, &(chain->os_param.guid), 16))
3751 {
3752 debug("Invalid ventoy guid 0x%x\n", chain->os_param.guid.data1);
3753 return 1;
3754 }
3755
3756 img_chunk_num = chain->img_chunk_num;
3757
3758 loclen = sizeof(ventoy_image_location) + (img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
3759 datalen = sizeof(ventoy_os_param) + loclen;
3760
3761 buflen = sizeof(struct grub_acpi_table_header) + datalen;
3762 acpi = grub_zalloc(buflen);
3763 if (!acpi)
3764 {
3765 return 1;
3766 }
3767
3768 /* Step1: Fill acpi table header */
3769 grub_memcpy(acpi->signature, "VTOY", 4);
3770 acpi->length = buflen;
3771 acpi->revision = 1;
3772 grub_memcpy(acpi->oemid, "VENTOY", 6);
3773 grub_memcpy(acpi->oemtable, "OSPARAMS", 8);
3774 acpi->oemrev = 1;
3775 acpi->creator_id[0] = 1;
3776 acpi->creator_rev = 1;
3777
3778 /* Step2: Fill data */
3779 osparam = (ventoy_os_param *)(acpi + 1);
3780 grub_memcpy(osparam, &chain->os_param, sizeof(ventoy_os_param));
3781 osparam->vtoy_img_location_addr = 0;
3782 osparam->vtoy_img_location_len = loclen;
3783 osparam->chksum = 0;
3784 osparam->chksum = 0x100 - grub_byte_checksum(osparam, sizeof(ventoy_os_param));
3785
3786 location = (ventoy_image_location *)(osparam + 1);
3787 grub_memcpy(&location->guid, &osparam->guid, sizeof(ventoy_guid));
3788 location->image_sector_size = image_sector_size;
3789 location->disk_sector_size = chain->disk_sector_size;
3790 location->region_count = img_chunk_num;
3791
3792 region = location->regions;
3793 chunk = (ventoy_img_chunk *)((char *)chain + chain->img_chunk_offset);
3794 if (512 == image_sector_size)
3795 {
3796 for (i = 0; i < img_chunk_num; i++)
3797 {
3798 region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
3799 region->image_start_sector = chunk->img_start_sector * 4;
3800 region->disk_start_sector = chunk->disk_start_sector;
3801 region++;
3802 chunk++;
3803 }
3804 }
3805 else
3806 {
3807 for (i = 0; i < img_chunk_num; i++)
3808 {
3809 region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
3810 region->image_start_sector = chunk->img_start_sector;
3811 region->disk_start_sector = chunk->disk_start_sector;
3812 region++;
3813 chunk++;
3814 }
3815 }
3816
3817 /* Step3: Fill acpi checksum */
3818 acpi->checksum = 0;
3819 acpi->checksum = 0x100 - grub_byte_checksum(acpi, acpi->length);
3820
3821 /* load acpi table */
3822 grub_snprintf(cmd, sizeof(cmd), "acpi mem:0x%lx:size:%d", (ulong)acpi, acpi->length);
3823 grub_script_execute_sourcecode(cmd);
3824
3825 grub_free(acpi);
3826
3827 VENTOY_CMD_RETURN(0);
3828 }
3829
3830 static grub_err_t ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
3831 {
3832 (void)ctxt;
3833 (void)argc;
3834 (void)args;
3835
3836 g_ventoy_last_entry_back = g_ventoy_last_entry;
3837 g_ventoy_last_entry = -1;
3838
3839 return 0;
3840 }
3841
3842 static grub_err_t ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
3843 {
3844 (void)ctxt;
3845 (void)argc;
3846 (void)args;
3847
3848 g_ventoy_last_entry = g_ventoy_last_entry_back;
3849
3850 return 0;
3851 }
3852
3853 static int ventoy_lib_module_callback(const char *filename, const struct grub_dirhook_info *info, void *data)
3854 {
3855 const char *pos = filename + 1;
3856
3857 if (info->dir)
3858 {
3859 while (*pos)
3860 {
3861 if (*pos == '.')
3862 {
3863 if ((*(pos - 1) >= '0' && *(pos - 1) <= '9') && (*(pos + 1) >= '0' && *(pos + 1) <= '9'))
3864 {
3865 grub_strncpy((char *)data, filename, 128);
3866 return 1;
3867 }
3868 }
3869 pos++;
3870 }
3871 }
3872
3873 return 0;
3874 }
3875
3876 static grub_err_t ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt, int argc, char **args)
3877 {
3878 int rc = 1;
3879 char *device_name = NULL;
3880 grub_device_t dev = NULL;
3881 grub_fs_t fs = NULL;
3882 char buf[128] = {0};
3883
3884 (void)ctxt;
3885
3886 if (argc != 3)
3887 {
3888 debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc);
3889 return 1;
3890 }
3891
3892 debug("ventoy_cmd_lib_module_ver %s %s %s\n", args[0], args[1], args[2]);
3893
3894 device_name = grub_file_get_device_name(args[0]);
3895 if (!device_name)
3896 {
3897 debug("grub_file_get_device_name failed, %s\n", args[0]);
3898 goto end;
3899 }
3900
3901 dev = grub_device_open(device_name);
3902 if (!dev)
3903 {
3904 debug("grub_device_open failed, %s\n", device_name);
3905 goto end;
3906 }
3907
3908 fs = grub_fs_probe(dev);
3909 if (!fs)
3910 {
3911 debug("grub_fs_probe failed, %s\n", device_name);
3912 goto end;
3913 }
3914
3915 fs->fs_dir(dev, args[1], ventoy_lib_module_callback, buf);
3916
3917 if (buf[0])
3918 {
3919 ventoy_set_env(args[2], buf);
3920 }
3921
3922 rc = 0;
3923
3924 end:
3925
3926 check_free(device_name, grub_free);
3927 check_free(dev, grub_device_close);
3928
3929 return rc;
3930 }
3931
3932 int ventoy_load_part_table(const char *diskname)
3933 {
3934 char name[64];
3935 int ret;
3936 grub_disk_t disk;
3937 grub_device_t dev;
3938
3939 g_ventoy_part_info = grub_zalloc(sizeof(ventoy_gpt_info));
3940 if (!g_ventoy_part_info)
3941 {
3942 return 1;
3943 }
3944
3945 disk = grub_disk_open(diskname);
3946 if (!disk)
3947 {
3948 debug("Failed to open disk %s\n", diskname);
3949 return 1;
3950 }
3951
3952 g_ventoy_disk_size = disk->total_sectors * (1U << disk->log_sector_size);
3953
3954 grub_disk_read(disk, 0, 0, sizeof(ventoy_gpt_info), g_ventoy_part_info);
3955 grub_disk_close(disk);
3956
3957 grub_snprintf(name, sizeof(name), "%s,1", diskname);
3958 dev = grub_device_open(name);
3959 if (dev)
3960 {
3961 /* Check for official Ventoy device */
3962 ret = ventoy_check_official_device(dev);
3963 grub_device_close(dev);
3964
3965 if (ret)
3966 {
3967 return 1;
3968 }
3969 }
3970
3971 g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
3972 g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
3973
3974 return 0;
3975 }
3976
3977 static grub_err_t ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt, int argc, char **args)
3978 {
3979 int ret;
3980
3981 (void)argc;
3982 (void)ctxt;
3983
3984 ret = ventoy_load_part_table(args[0]);
3985 if (ret)
3986 {
3987 grub_exit();
3988 }
3989
3990 g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
3991 g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
3992
3993 return 0;
3994 }
3995
3996 static grub_err_t ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
3997 {
3998 int ret = 1;
3999 const char *vcfg = NULL;
4000
4001 (void)argc;
4002 (void)ctxt;
4003
4004 vcfg = ventoy_plugin_get_custom_boot(args[0]);
4005 if (vcfg)
4006 {
4007 debug("custom boot <%s>:<%s>\n", args[0], vcfg);
4008 grub_env_set(args[1], vcfg);
4009 ret = 0;
4010 }
4011 else
4012 {
4013 debug("custom boot <%s>:<NOT FOUND>\n", args[0]);
4014 }
4015
4016 grub_errno = 0;
4017 return ret;
4018 }
4019
4020
4021 static grub_err_t ventoy_cmd_part_exist(grub_extcmd_context_t ctxt, int argc, char **args)
4022 {
4023 int id;
4024 grub_uint8_t zeroguid[16] = {0};
4025
4026 (void)argc;
4027 (void)ctxt;
4028
4029 id = (int)grub_strtoul(args[0], NULL, 10);
4030 grub_errno = 0;
4031
4032 if (grub_memcmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
4033 {
4034 if (id >= 1 && id <= 128)
4035 {
4036 if (grub_memcmp(g_ventoy_part_info->PartTbl[id - 1].PartGuid, zeroguid, 16))
4037 {
4038 return 0;
4039 }
4040 }
4041 }
4042 else
4043 {
4044 if (id >= 1 && id <= 4)
4045 {
4046 if (g_ventoy_part_info->MBR.PartTbl[id - 1].FsFlag)
4047 {
4048 return 0;
4049 }
4050 }
4051 }
4052
4053 return 1;
4054 }
4055
4056 static grub_err_t ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt, int argc, char **args)
4057 {
4058 int rc = 1;
4059 char *device_name = NULL;
4060 grub_device_t dev = NULL;
4061 grub_fs_t fs = NULL;
4062 char *label = NULL;
4063
4064 (void)ctxt;
4065
4066 debug("get fs label for %s\n", args[0]);
4067
4068 if (argc != 2)
4069 {
4070 debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc);
4071 return 1;
4072 }
4073
4074 device_name = grub_file_get_device_name(args[0]);
4075 if (!device_name)
4076 {
4077 debug("grub_file_get_device_name failed, %s\n", args[0]);
4078 goto end;
4079 }
4080
4081 dev = grub_device_open(device_name);
4082 if (!dev)
4083 {
4084 debug("grub_device_open failed, %s\n", device_name);
4085 goto end;
4086 }
4087
4088 fs = grub_fs_probe(dev);
4089 if (NULL == fs || NULL == fs->fs_label)
4090 {
4091 debug("grub_fs_probe failed, %s %p %p\n", device_name, fs, fs->fs_label);
4092 goto end;
4093 }
4094
4095 fs->fs_label(dev, &label);
4096 if (label)
4097 {
4098 debug("label=<%s>\n", label);
4099 ventoy_set_env(args[1], label);
4100 grub_free(label);
4101 }
4102
4103 rc = 0;
4104
4105 end:
4106
4107 check_free(device_name, grub_free);
4108 check_free(dev, grub_device_close);
4109
4110 return rc;
4111 }
4112
4113 static int ventoy_fs_enum_1st_file(const char *filename, const struct grub_dirhook_info *info, void *data)
4114 {
4115 if (!info->dir)
4116 {
4117 grub_snprintf((char *)data, 256, "%s", filename);
4118 return 1;
4119 }
4120
4121 return 0;
4122 }
4123
4124
4125 static grub_err_t ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt, int argc, char **args)
4126 {
4127 int rc = 1;
4128 char *device_name = NULL;
4129 grub_device_t dev = NULL;
4130 grub_fs_t fs = NULL;
4131 char name[256] ={0};
4132
4133 (void)ctxt;
4134
4135 if (argc != 3)
4136 {
4137 debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc);
4138 return 1;
4139 }
4140
4141 device_name = grub_file_get_device_name(args[0]);
4142 if (!device_name)
4143 {
4144 debug("grub_file_get_device_name failed, %s\n", args[0]);
4145 goto end;
4146 }
4147
4148 dev = grub_device_open(device_name);
4149 if (!dev)
4150 {
4151 debug("grub_device_open failed, %s\n", device_name);
4152 goto end;
4153 }
4154
4155 fs = grub_fs_probe(dev);
4156 if (!fs)
4157 {
4158 debug("grub_fs_probe failed, %s\n", device_name);
4159 goto end;
4160 }
4161
4162 fs->fs_dir(dev, args[1], ventoy_fs_enum_1st_file, name);
4163 if (name[0])
4164 {
4165 ventoy_set_env(args[2], name);
4166 }
4167
4168 rc = 0;
4169
4170 end:
4171
4172 check_free(device_name, grub_free);
4173 check_free(dev, grub_device_close);
4174
4175 return rc;
4176 }
4177
4178 static grub_err_t ventoy_cmd_basename(grub_extcmd_context_t ctxt, int argc, char **args)
4179 {
4180 char c;
4181 char *pos = NULL;
4182 char *end = NULL;
4183
4184 (void)ctxt;
4185
4186 if (argc != 2)
4187 {
4188 debug("ventoy_cmd_basename, invalid param num %d\n", argc);
4189 return 1;
4190 }
4191
4192 for (pos = args[0]; *pos; pos++)
4193 {
4194 if (*pos == '.')
4195 {
4196 end = pos;
4197 }
4198 }
4199
4200 if (end)
4201 {
4202 c = *end;
4203 *end = 0;
4204 }
4205
4206 grub_env_set(args[1], args[0]);
4207
4208 if (end)
4209 {
4210 *end = c;
4211 }
4212
4213 return 0;
4214 }
4215
4216 static grub_err_t ventoy_cmd_basefile(grub_extcmd_context_t ctxt, int argc, char **args)
4217 {
4218 int i;
4219 int len;
4220 const char *buf;
4221
4222 (void)ctxt;
4223
4224 if (argc != 2)
4225 {
4226 debug("ventoy_cmd_basefile, invalid param num %d\n", argc);
4227 return 1;
4228 }
4229
4230 buf = args[0];
4231 len = (int)grub_strlen(buf);
4232 for (i = len; i > 0; i--)
4233 {
4234 if (buf[i - 1] == '/')
4235 {
4236 grub_env_set(args[1], buf + i);
4237 return 0;
4238 }
4239 }
4240
4241 grub_env_set(args[1], buf);
4242
4243 return 0;
4244 }
4245
4246 static grub_err_t ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4247 {
4248 struct grub_video_mode_info info;
4249 char buf[32];
4250
4251 (void)ctxt;
4252 (void)argc;
4253 (void)args;
4254
4255 if (!g_video_mode_list)
4256 {
4257 ventoy_enum_video_mode();
4258 }
4259
4260 if (grub_video_get_info(&info) == GRUB_ERR_NONE)
4261 {
4262 grub_snprintf(buf, sizeof(buf), "Resolution (%ux%u)", info.width, info.height);
4263 }
4264 else
4265 {
4266 grub_snprintf(buf, sizeof(buf), "Resolution (0x0)");
4267 }
4268
4269 grub_env_set("VTOY_CUR_VIDEO_MODE", buf);
4270
4271 grub_snprintf(buf, sizeof(buf), "%d", g_video_mode_num);
4272 grub_env_set("VTOY_VIDEO_MODE_NUM", buf);
4273
4274 VENTOY_CMD_RETURN(0);
4275 }
4276
4277 static grub_err_t vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4278 {
4279 struct grub_video_mode_info info;
4280 char buf[32];
4281
4282 (void)ctxt;
4283 (void)argc;
4284 (void)args;
4285
4286 if (grub_video_get_info(&info) == GRUB_ERR_NONE)
4287 {
4288 grub_snprintf(buf, sizeof(buf), "%ux%ux%u", info.width, info.height, info.bpp);
4289 }
4290 else
4291 {
4292 grub_snprintf(buf, sizeof(buf), "0x0x0");
4293 }
4294
4295 grub_env_set(args[0], buf);
4296
4297 VENTOY_CMD_RETURN(0);
4298 }
4299
4300 static grub_err_t ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
4301 {
4302 int id;
4303 char buf[32];
4304
4305 (void)ctxt;
4306 (void)argc;
4307
4308 if (!g_video_mode_list)
4309 {
4310 return 0;
4311 }
4312
4313 id = (int)grub_strtoul(args[0], NULL, 10);
4314 if (id < g_video_mode_num)
4315 {
4316 grub_snprintf(buf, sizeof(buf), "%ux%ux%u",
4317 g_video_mode_list[id].width, g_video_mode_list[id].height, g_video_mode_list[id].bpp);
4318 }
4319
4320 grub_env_set(args[1], buf);
4321
4322 VENTOY_CMD_RETURN(0);
4323 }
4324
4325 int ventoy_env_init(void)
4326 {
4327 char buf[64];
4328
4329 grub_env_set("vtdebug_flag", "");
4330
4331 g_part_list_buf = grub_malloc(VTOY_PART_BUF_LEN);
4332 g_tree_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
4333 g_list_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
4334 g_conf_replace_new_buf = grub_malloc(vtoy_max_replace_file_size);
4335
4336 ventoy_filt_register(0, ventoy_wrapper_open);
4337
4338 g_grub_param = (ventoy_grub_param *)grub_zalloc(sizeof(ventoy_grub_param));
4339 if (g_grub_param)
4340 {
4341 g_grub_param->grub_env_get = grub_env_get;
4342 g_grub_param->grub_env_set = (grub_env_set_pf)grub_env_set;
4343 g_grub_param->grub_env_printf = (grub_env_printf_pf)grub_printf;
4344 grub_snprintf(buf, sizeof(buf), "%p", g_grub_param);
4345 grub_env_set("env_param", buf);
4346 grub_env_set("ventoy_env_param", buf);
4347
4348 grub_env_export("env_param");
4349 grub_env_export("ventoy_env_param");
4350 }
4351
4352 return 0;
4353 }
4354
4355 static cmd_para ventoy_cmds[] =
4356 {
4357 { "vt_incr", ventoy_cmd_incr, 0, NULL, "{Var} {INT}", "Increase integer variable", NULL },
4358 { "vt_mod", ventoy_cmd_mod, 0, NULL, "{Int} {Int} {Var}", "mod integer variable", NULL },
4359 { "vt_strstr", ventoy_cmd_strstr, 0, NULL, "", "", NULL },
4360 { "vt_str_begin", ventoy_cmd_strbegin, 0, NULL, "", "", NULL },
4361 { "vt_debug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
4362 { "vtdebug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
4363 { "vtbreak", ventoy_cmd_break, 0, NULL, "{level}", "set debug break", NULL },
4364 { "vt_cmp", ventoy_cmd_cmp, 0, NULL, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL },
4365 { "vt_device", ventoy_cmd_device, 0, NULL, "path var", "", NULL },
4366 { "vt_check_compatible", ventoy_cmd_check_compatible, 0, NULL, "", "", NULL },
4367 { "vt_list_img", ventoy_cmd_list_img, 0, NULL, "{device} {cntvar}", "find all iso file in device", NULL },
4368 { "vt_clear_img", ventoy_cmd_clear_img, 0, NULL, "", "clear image list", NULL },
4369 { "vt_img_name", ventoy_cmd_img_name, 0, NULL, "{imageID} {var}", "get image name", NULL },
4370 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path, 0, NULL, "{var}", "get chosen img path", NULL },
4371 { "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path, 0, NULL, "{var}", "select chosen img path", NULL },
4372 { "vt_img_sector", ventoy_cmd_img_sector, 0, NULL, "{imageName}", "", NULL },
4373 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector, 0, NULL, "", "", NULL },
4374 { "vt_load_wimboot", ventoy_cmd_load_wimboot, 0, NULL, "", "", NULL },
4375 { "vt_load_vhdboot", ventoy_cmd_load_vhdboot, 0, NULL, "", "", NULL },
4376 { "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot, 0, NULL, "", "", NULL },
4377 { "vt_raw_chain_data", ventoy_cmd_raw_chain_data, 0, NULL, "", "", NULL },
4378 { "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type, 0, NULL, "", "", NULL },
4379 { "vt_check_custom_boot", ventoy_cmd_check_custom_boot, 0, NULL, "", "", NULL },
4380 { "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot, 0, NULL, "", "", NULL },
4381
4382 { "vt_skip_svd", ventoy_cmd_skip_svd, 0, NULL, "", "", NULL },
4383 { "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64, 0, NULL, "", "", NULL },
4384 { "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
4385 { "vt_trailer_cpio", ventoy_cmd_trailer_cpio, 0, NULL, "", "", NULL },
4386 { "vt_push_last_entry", ventoy_cmd_push_last_entry, 0, NULL, "", "", NULL },
4387 { "vt_pop_last_entry", ventoy_cmd_pop_last_entry, 0, NULL, "", "", NULL },
4388 { "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver, 0, NULL, "", "", NULL },
4389
4390 { "vt_load_part_table", ventoy_cmd_load_part_table, 0, NULL, "", "", NULL },
4391 { "vt_check_part_exist", ventoy_cmd_part_exist, 0, NULL, "", "", NULL },
4392 { "vt_get_fs_label", ventoy_cmd_get_fs_label, 0, NULL, "", "", NULL },
4393 { "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file, 0, NULL, "", "", NULL },
4394 { "vt_file_basename", ventoy_cmd_basename, 0, NULL, "", "", NULL },
4395 { "vt_file_basefile", ventoy_cmd_basefile, 0, NULL, "", "", NULL },
4396 { "vt_enum_video_mode", ventoy_cmd_enum_video_mode, 0, NULL, "", "", NULL },
4397 { "vt_get_video_mode", ventoy_cmd_get_video_mode, 0, NULL, "", "", NULL },
4398 { "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode, 0, NULL, "", "", NULL },
4399
4400
4401 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd, 0, NULL, "", "", NULL },
4402 { "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
4403 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
4404 { "vt_check_mode", ventoy_cmd_check_mode, 0, NULL, "", "", NULL },
4405 { "vt_dump_img_list", ventoy_cmd_dump_img_list, 0, NULL, "", "", NULL },
4406 { "vt_dump_injection", ventoy_cmd_dump_injection, 0, NULL, "", "", NULL },
4407 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install, 0, NULL, "", "", NULL },
4408 { "vt_dump_persistence", ventoy_cmd_dump_persistence, 0, NULL, "", "", NULL },
4409 { "vt_select_auto_install", ventoy_cmd_sel_auto_install, 0, NULL, "", "", NULL },
4410 { "vt_select_persistence", ventoy_cmd_sel_persistence, 0, NULL, "", "", NULL },
4411 { "vt_select_conf_replace", ventoy_select_conf_replace, 0, NULL, "", "", NULL },
4412
4413 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
4414 { "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
4415 { "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
4416 { "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem, 0, NULL, "", "", NULL },
4417 { "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk, 0, NULL, "", "", NULL },
4418 { "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso, 0, NULL, "", "", NULL },
4419
4420 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
4421 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
4422 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file, 0, NULL, "", "", NULL },
4423 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list, 0, NULL, "", "", NULL },
4424 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list, 0, NULL, "", "", NULL },
4425 { "vt_linux_initrd_count", ventoy_cmd_initrd_count, 0, NULL, "", "", NULL },
4426 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count, 0, NULL, "", "", NULL },
4427 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd, 0, NULL, "", "", NULL },
4428 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data, 0, NULL, "", "", NULL },
4429 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index, 0, NULL, "", "", NULL },
4430
4431 { "vt_windows_reset", ventoy_cmd_wimdows_reset, 0, NULL, "", "", NULL },
4432 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data, 0, NULL, "", "", NULL },
4433 { "vt_windows_wimboot_data", ventoy_cmd_windows_wimboot_data, 0, NULL, "", "", NULL },
4434 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch, 0, NULL, "", "", NULL },
4435 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch, 0, NULL, "", "", NULL },
4436 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count, 0, NULL, "", "", NULL },
4437 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch, 0, NULL, "", "", NULL },
4438 { "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable, 0, NULL, "", "", NULL },
4439 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data, 0, NULL, "", "", NULL },
4440
4441 { "vt_add_replace_file", ventoy_cmd_add_replace_file, 0, NULL, "", "", NULL },
4442 { "vt_test_block_list", ventoy_cmd_test_block_list, 0, NULL, "", "", NULL },
4443 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase, 0, NULL, "", "", NULL },
4444
4445
4446 { "vt_load_plugin", ventoy_cmd_load_plugin, 0, NULL, "", "", NULL },
4447 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json, 0, NULL, "", "", NULL },
4448 { "vt_check_password", ventoy_cmd_check_password, 0, NULL, "", "", NULL },
4449
4450 { "vt_1st_line", ventoy_cmd_read_1st_line, 0, NULL, "", "", NULL },
4451 { "vt_file_strstr", ventoy_cmd_file_strstr, 0, NULL, "", "", NULL },
4452 { "vt_img_part_info", ventoy_cmd_img_part_info, 0, NULL, "", "", NULL },
4453
4454
4455 { "vt_parse_iso_volume", ventoy_cmd_parse_volume, 0, NULL, "", "", NULL },
4456 { "vt_parse_iso_create_date", ventoy_cmd_parse_create_date, 0, NULL, "", "", NULL },
4457 { "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver, 0, NULL, "", "", NULL },
4458 { "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver, 0, NULL, "", "", NULL },
4459 { "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf, 0, NULL, "", "", NULL },
4460 { "vt_unix_reset", ventoy_cmd_unix_reset, 0, NULL, "", "", NULL },
4461 { "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf, 0, NULL, "", "", NULL },
4462 { "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko, 0, NULL, "", "", NULL },
4463 { "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc, 0, NULL, "", "", NULL },
4464 { "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko, 0, NULL, "", "", NULL },
4465 { "vt_unix_chain_data", ventoy_cmd_unix_chain_data, 0, NULL, "", "", NULL },
4466
4467 { "vt_img_hook_root", ventoy_cmd_img_hook_root, 0, NULL, "", "", NULL },
4468 { "vt_img_unhook_root", ventoy_cmd_img_unhook_root, 0, NULL, "", "", NULL },
4469 { "vt_acpi_param", ventoy_cmd_acpi_param, 0, NULL, "", "", NULL },
4470 { "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var, 0, NULL, "", "", NULL },
4471 { "vt_clear_key", ventoy_cmd_clear_key, 0, NULL, "", "", NULL },
4472 { "vt_img_check_range", ventoy_cmd_img_check_range, 0, NULL, "", "", NULL },
4473
4474 };
4475
4476 int ventoy_register_all_cmd(void)
4477 {
4478 grub_uint32_t i;
4479 cmd_para *cur = NULL;
4480
4481 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
4482 {
4483 cur = ventoy_cmds + i;
4484 cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags,
4485 cur->summary, cur->description, cur->parser);
4486 }
4487 return 0;
4488 }
4489
4490 int ventoy_unregister_all_cmd(void)
4491 {
4492 grub_uint32_t i;
4493
4494 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
4495 {
4496 grub_unregister_extcmd(ventoy_cmds[i].cmd);
4497 }
4498
4499 return 0;
4500 }
4501
4502