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