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