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