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