]> glassweightruler.freedombox.rocks Git - Ventoy.git/blob - GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy.c
add docker automated build environment (#235)
[Ventoy.git] / GRUB2 / MOD_SRC / grub-2.04 / grub-core / ventoy / ventoy.c
1 /******************************************************************************
2 * ventoy.c
3 *
4 * Copyright (c) 2020, 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 #ifdef GRUB_MACHINE_EFI
38 #include <grub/efi/efi.h>
39 #endif
40 #include <grub/time.h>
41 #include <grub/relocator.h>
42 #include <grub/ventoy.h>
43 #include "ventoy_def.h"
44
45 GRUB_MOD_LICENSE ("GPLv3+");
46
47 int g_ventoy_debug = 0;
48 static int g_efi_os = 0xFF;
49 initrd_info *g_initrd_img_list = NULL;
50 initrd_info *g_initrd_img_tail = NULL;
51 int g_initrd_img_count = 0;
52 int g_valid_initrd_count = 0;
53 int g_default_menu_mode = 0;
54 int g_filt_dot_underscore_file = 0;
55 static grub_file_t g_old_file;
56
57 char g_iso_path[256];
58 char g_img_swap_tmp_buf[1024];
59 img_info g_img_swap_tmp;
60 img_info *g_ventoy_img_list = NULL;
61
62 int g_ventoy_img_count = 0;
63
64 grub_device_t g_enum_dev = NULL;
65 grub_fs_t g_enum_fs = NULL;
66 img_iterator_node g_img_iterator_head;
67 img_iterator_node *g_img_iterator_tail = NULL;
68
69 grub_uint8_t g_ventoy_break_level = 0;
70 grub_uint8_t g_ventoy_debug_level = 0;
71 grub_uint8_t g_ventoy_chain_type = 0;
72 grub_uint8_t *g_ventoy_cpio_buf = NULL;
73 grub_uint32_t g_ventoy_cpio_size = 0;
74 cpio_newc_header *g_ventoy_initrd_head = NULL;
75 grub_uint8_t *g_ventoy_runtime_buf = NULL;
76
77 ventoy_grub_param *g_grub_param = NULL;
78
79 ventoy_guid g_ventoy_guid = VENTOY_GUID;
80
81 ventoy_img_chunk_list g_img_chunk_list;
82
83 int g_wimboot_enable = 0;
84 ventoy_img_chunk_list g_wimiso_chunk_list;
85 char *g_wimiso_path = NULL;
86
87 static char *g_tree_script_buf = NULL;
88 static int g_tree_script_pos = 0;
89
90 static char *g_list_script_buf = NULL;
91 static int g_list_script_pos = 0;
92
93
94 void ventoy_debug(const char *fmt, ...)
95 {
96 va_list args;
97
98 va_start (args, fmt);
99 grub_vprintf (fmt, args);
100 va_end (args);
101 }
102
103 int ventoy_is_efi_os(void)
104 {
105 if (g_efi_os > 1)
106 {
107 g_efi_os = (grub_strstr(GRUB_PLATFORM, "efi")) ? 1 : 0;
108 }
109
110 return g_efi_os;
111 }
112
113 static int ventoy_get_fs_type(const char *fs)
114 {
115 if (NULL == fs)
116 {
117 return ventoy_fs_max;
118 }
119 else if (grub_strncmp(fs, "exfat", 5) == 0)
120 {
121 return ventoy_fs_exfat;
122 }
123 else if (grub_strncmp(fs, "ntfs", 4) == 0)
124 {
125 return ventoy_fs_ntfs;
126 }
127 else if (grub_strncmp(fs, "ext", 3) == 0)
128 {
129 return ventoy_fs_ext;
130 }
131 else if (grub_strncmp(fs, "xfs", 3) == 0)
132 {
133 return ventoy_fs_xfs;
134 }
135 else if (grub_strncmp(fs, "udf", 3) == 0)
136 {
137 return ventoy_fs_udf;
138 }
139 else if (grub_strncmp(fs, "fat", 3) == 0)
140 {
141 return ventoy_fs_fat;
142 }
143
144 return ventoy_fs_max;
145 }
146
147 static int ventoy_string_check(const char *str, grub_char_check_func check)
148 {
149 if (!str)
150 {
151 return 0;
152 }
153
154 for ( ; *str; str++)
155 {
156 if (!check(*str))
157 {
158 return 0;
159 }
160 }
161
162 return 1;
163 }
164
165
166 static grub_ssize_t ventoy_fs_read(grub_file_t file, char *buf, grub_size_t len)
167 {
168 grub_memcpy(buf, (char *)file->data + file->offset, len);
169 return len;
170 }
171
172 static grub_err_t ventoy_fs_close(grub_file_t file)
173 {
174 grub_file_close(g_old_file);
175 grub_free(file->data);
176
177 file->device = 0;
178 file->name = 0;
179
180 return 0;
181 }
182
183 static grub_file_t ventoy_wrapper_open(grub_file_t rawFile, enum grub_file_type type)
184 {
185 int len;
186 grub_file_t file;
187 static struct grub_fs vtoy_fs =
188 {
189 .name = "vtoy",
190 .fs_dir = 0,
191 .fs_open = 0,
192 .fs_read = ventoy_fs_read,
193 .fs_close = ventoy_fs_close,
194 .fs_label = 0,
195 .next = 0
196 };
197
198 if (type != 52)
199 {
200 return rawFile;
201 }
202
203 file = (grub_file_t)grub_zalloc(sizeof (*file));
204 if (!file)
205 {
206 return 0;
207 }
208
209 file->data = grub_malloc(rawFile->size + 4096);
210 if (!file->data)
211 {
212 return 0;
213 }
214
215 grub_file_read(rawFile, file->data, rawFile->size);
216 len = ventoy_fill_data(4096, (char *)file->data + rawFile->size);
217
218 g_old_file = rawFile;
219
220 file->size = rawFile->size + len;
221 file->device = rawFile->device;
222 file->fs = &vtoy_fs;
223 file->not_easily_seekable = 1;
224
225 return file;
226 }
227
228 static int ventoy_check_decimal_var(const char *name, long *value)
229 {
230 const char *value_str = NULL;
231
232 value_str = grub_env_get(name);
233 if (NULL == value_str)
234 {
235 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s not found", name);
236 }
237
238 if (!ventoy_is_decimal(value_str))
239 {
240 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s value '%s' is not an integer", name, value_str);
241 }
242
243 *value = grub_strtol(value_str, NULL, 10);
244
245 return GRUB_ERR_NONE;
246 }
247
248 static grub_err_t ventoy_cmd_debug(grub_extcmd_context_t ctxt, int argc, char **args)
249 {
250 if (argc != 1)
251 {
252 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {on|off}", cmd_raw_name);
253 }
254
255 if (0 == grub_strcmp(args[0], "on"))
256 {
257 g_ventoy_debug = 1;
258 grub_env_set("vtdebug_flag", "debug");
259 }
260 else
261 {
262 g_ventoy_debug = 0;
263 grub_env_set("vtdebug_flag", "");
264 }
265
266 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
267 }
268
269 static grub_err_t ventoy_cmd_break(grub_extcmd_context_t ctxt, int argc, char **args)
270 {
271 (void)ctxt;
272
273 if (argc < 1 || (args[0][0] != '0' && args[0][0] != '1'))
274 {
275 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name);
276 grub_printf(" level:\r\n");
277 grub_printf(" 01/11: busybox / (+cat log)\r\n");
278 grub_printf(" 02/12: initrd / (+cat log)\r\n");
279 grub_printf(" 03/13: hook / (+cat log)\r\n");
280 grub_printf("\r\n");
281 grub_printf(" debug:\r\n");
282 grub_printf(" 0: debug is on\r\n");
283 grub_printf(" 1: debug is off\r\n");
284 grub_printf("\r\n");
285 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
286 }
287
288 g_ventoy_break_level = (grub_uint8_t)grub_strtoul(args[0], NULL, 16);
289
290 if (argc > 1 && grub_strtoul(args[1], NULL, 10) > 0)
291 {
292 g_ventoy_debug_level = 1;
293 }
294
295 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
296 }
297
298 static grub_err_t ventoy_cmd_incr(grub_extcmd_context_t ctxt, int argc, char **args)
299 {
300 long value_long = 0;
301 char buf[32];
302
303 if ((argc != 2) || (!ventoy_is_decimal(args[1])))
304 {
305 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Variable} {Int}", cmd_raw_name);
306 }
307
308 if (GRUB_ERR_NONE != ventoy_check_decimal_var(args[0], &value_long))
309 {
310 return grub_errno;
311 }
312
313 value_long += grub_strtol(args[1], NULL, 10);
314
315 grub_snprintf(buf, sizeof(buf), "%ld", value_long);
316 grub_env_set(args[0], buf);
317
318 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
319 }
320
321 static grub_err_t ventoy_cmd_file_size(grub_extcmd_context_t ctxt, int argc, char **args)
322 {
323 int rc = 1;
324 char buf[32];
325 grub_file_t file;
326
327 (void)ctxt;
328 (void)argc;
329 (void)args;
330
331 if (argc != 2)
332 {
333 return rc;
334 }
335
336 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
337 if (file == NULL)
338 {
339 debug("failed to open file <%s> for udf check\n", args[0]);
340 return 1;
341 }
342
343 grub_snprintf(buf, sizeof(buf), "%llu", (unsigned long long)file->size);
344
345 grub_env_set(args[1], buf);
346
347 grub_file_close(file);
348 rc = 0;
349
350 return rc;
351 }
352
353 static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc, char **args)
354 {
355 grub_file_t file;
356
357 (void)ctxt;
358 (void)argc;
359 (void)args;
360
361 g_wimboot_enable = 0;
362 grub_check_free(g_wimiso_path);
363 grub_check_free(g_wimiso_chunk_list.chunk);
364
365 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
366 if (!file)
367 {
368 return 0;
369 }
370
371 grub_memset(&g_wimiso_chunk_list, 0, sizeof(g_wimiso_chunk_list));
372 g_wimiso_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
373 if (NULL == g_wimiso_chunk_list.chunk)
374 {
375 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
376 }
377
378 g_wimiso_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
379 g_wimiso_chunk_list.cur_chunk = 0;
380
381 ventoy_get_block_list(file, &g_wimiso_chunk_list, file->device->disk->partition->start);
382
383 g_wimboot_enable = 1;
384 g_wimiso_path = grub_strdup(args[0]);
385
386 grub_file_close(file);
387
388 return 0;
389 }
390
391 static grub_err_t ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
392 {
393 int rc = 1;
394 char name[32];
395 char value[32];
396 char *buf = NULL;
397 grub_file_t file;
398
399 (void)ctxt;
400 (void)argc;
401 (void)args;
402
403 if (argc != 2)
404 {
405 return rc;
406 }
407
408 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
409 if (file == NULL)
410 {
411 debug("failed to open file <%s> for udf check\n", args[0]);
412 return 1;
413 }
414
415 #ifdef GRUB_MACHINE_EFI
416 buf = (char *)grub_efi_allocate_iso_buf(file->size);
417 #else
418 buf = (char *)grub_malloc(file->size);
419 #endif
420
421 grub_file_read(file, buf, file->size);
422
423 grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
424 grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
425 grub_env_set(name, value);
426
427 grub_snprintf(name, sizeof(name), "%s_size", args[1]);
428 grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
429 grub_env_set(name, value);
430
431 grub_file_close(file);
432 rc = 0;
433
434 return rc;
435 }
436
437 static grub_err_t ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
438 {
439 (void)ctxt;
440
441 if (argc != 1)
442 {
443 return 1;
444 }
445
446 if (args[0][0] == '1')
447 {
448 grub_iso9660_set_nojoliet(1);
449 }
450 else
451 {
452 grub_iso9660_set_nojoliet(0);
453 }
454
455 return 0;
456 }
457
458 static grub_err_t ventoy_cmd_is_udf(grub_extcmd_context_t ctxt, int argc, char **args)
459 {
460 int i;
461 int rc = 1;
462 grub_file_t file;
463 grub_uint8_t buf[32];
464
465 (void)ctxt;
466 (void)argc;
467 (void)args;
468
469 if (argc != 1)
470 {
471 return rc;
472 }
473
474 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
475 if (file == NULL)
476 {
477 debug("failed to open file <%s> for udf check\n", args[0]);
478 return 1;
479 }
480
481 for (i = 16; i < 32; i++)
482 {
483 grub_file_seek(file, i * 2048);
484 grub_file_read(file, buf, sizeof(buf));
485 if (buf[0] == 255)
486 {
487 break;
488 }
489 }
490
491 i++;
492 grub_file_seek(file, i * 2048);
493 grub_file_read(file, buf, sizeof(buf));
494
495 if (grub_memcmp(buf + 1, "BEA01", 5) == 0)
496 {
497 i++;
498 grub_file_seek(file, i * 2048);
499 grub_file_read(file, buf, sizeof(buf));
500
501 if (grub_memcmp(buf + 1, "NSR02", 5) == 0 ||
502 grub_memcmp(buf + 1, "NSR03", 5) == 0)
503 {
504 rc = 0;
505 }
506 }
507
508 grub_file_close(file);
509
510 debug("ISO UDF: %s\n", rc ? "NO" : "YES");
511
512 return rc;
513 }
514
515 static grub_err_t ventoy_cmd_cmp(grub_extcmd_context_t ctxt, int argc, char **args)
516 {
517 long value_long1 = 0;
518 long value_long2 = 0;
519
520 if ((argc != 3) || (!ventoy_is_decimal(args[0])) || (!ventoy_is_decimal(args[2])))
521 {
522 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name);
523 }
524
525 value_long1 = grub_strtol(args[0], NULL, 10);
526 value_long2 = grub_strtol(args[2], NULL, 10);
527
528 if (0 == grub_strcmp(args[1], "eq"))
529 {
530 grub_errno = (value_long1 == value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
531 }
532 else if (0 == grub_strcmp(args[1], "ne"))
533 {
534 grub_errno = (value_long1 != value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
535 }
536 else if (0 == grub_strcmp(args[1], "gt"))
537 {
538 grub_errno = (value_long1 > value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
539 }
540 else if (0 == grub_strcmp(args[1], "lt"))
541 {
542 grub_errno = (value_long1 < value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
543 }
544 else if (0 == grub_strcmp(args[1], "ge"))
545 {
546 grub_errno = (value_long1 >= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
547 }
548 else if (0 == grub_strcmp(args[1], "le"))
549 {
550 grub_errno = (value_long1 <= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
551 }
552 else
553 {
554 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name);
555 }
556
557 return grub_errno;
558 }
559
560 static grub_err_t ventoy_cmd_device(grub_extcmd_context_t ctxt, int argc, char **args)
561 {
562 char *pos = NULL;
563 char buf[128] = {0};
564
565 if (argc != 2)
566 {
567 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s path var", cmd_raw_name);
568 }
569
570 grub_strncpy(buf, (args[0][0] == '(') ? args[0] + 1 : args[0], sizeof(buf) - 1);
571 pos = grub_strstr(buf, ",");
572 if (pos)
573 {
574 *pos = 0;
575 }
576
577 grub_env_set(args[1], buf);
578
579 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
580 }
581
582 static grub_err_t ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt, int argc, char **args)
583 {
584 int i;
585 char buf[256];
586 grub_disk_t disk;
587 char *pos = NULL;
588 const char *files[] = { "ventoy.dat", "VENTOY.DAT" };
589
590 (void)ctxt;
591
592 if (argc != 1)
593 {
594 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s (loop)", cmd_raw_name);
595 }
596
597 for (i = 0; i < (int)ARRAY_SIZE(files); i++)
598 {
599 grub_snprintf(buf, sizeof(buf) - 1, "[ -e %s/%s ]", args[0], files[i]);
600 if (0 == grub_script_execute_sourcecode(buf))
601 {
602 debug("file %s exist, ventoy_compatible YES\n", buf);
603 grub_env_set("ventoy_compatible", "YES");
604 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
605 }
606 else
607 {
608 debug("file %s NOT exist\n", buf);
609 }
610 }
611
612 grub_snprintf(buf, sizeof(buf) - 1, "%s", args[0][0] == '(' ? (args[0] + 1) : args[0]);
613 pos = grub_strstr(buf, ")");
614 if (pos)
615 {
616 *pos = 0;
617 }
618
619 disk = grub_disk_open(buf);
620 if (disk)
621 {
622 grub_disk_read(disk, 16 << 2, 0, 1024, g_img_swap_tmp_buf);
623 grub_disk_close(disk);
624
625 g_img_swap_tmp_buf[703] = 0;
626 for (i = 319; i < 703; i++)
627 {
628 if (g_img_swap_tmp_buf[i] == 'V' &&
629 0 == grub_strncmp(g_img_swap_tmp_buf + i, VENTOY_COMPATIBLE_STR, VENTOY_COMPATIBLE_STR_LEN))
630 {
631 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i);
632 grub_env_set("ventoy_compatible", "YES");
633 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
634 }
635 }
636 }
637 else
638 {
639 debug("failed to open disk <%s>\n", buf);
640 }
641
642 grub_env_set("ventoy_compatible", "NO");
643 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
644 }
645
646 int ventoy_cmp_img(img_info *img1, img_info *img2)
647 {
648 char *s1, *s2;
649 int c1 = 0;
650 int c2 = 0;
651
652 for (s1 = img1->name, s2 = img2->name; *s1 && *s2; s1++, s2++)
653 {
654 c1 = *s1;
655 c2 = *s2;
656
657 if (grub_islower(c1))
658 {
659 c1 = c1 - 'a' + 'A';
660 }
661
662 if (grub_islower(c2))
663 {
664 c2 = c2 - 'a' + 'A';
665 }
666
667 if (c1 != c2)
668 {
669 break;
670 }
671 }
672
673 return (c1 - c2);
674 }
675
676 void ventoy_swap_img(img_info *img1, img_info *img2)
677 {
678 grub_memcpy(&g_img_swap_tmp, img1, sizeof(img_info));
679
680 grub_memcpy(img1, img2, sizeof(img_info));
681 img1->next = g_img_swap_tmp.next;
682 img1->prev = g_img_swap_tmp.prev;
683
684 g_img_swap_tmp.next = img2->next;
685 g_img_swap_tmp.prev = img2->prev;
686 grub_memcpy(img2, &g_img_swap_tmp, sizeof(img_info));
687 }
688
689 static int ventoy_img_name_valid(const char *filename, grub_size_t namelen)
690 {
691 grub_size_t i;
692
693 if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
694 {
695 return 0;
696 }
697
698 for (i = 0; i < namelen; i++)
699 {
700 if (filename[i] == ' ' || filename[i] == '\t')
701 {
702 return 0;
703 }
704
705 if ((grub_uint8_t)(filename[i]) >= 127)
706 {
707 return 0;
708 }
709 }
710
711 return 1;
712 }
713
714 static int ventoy_check_ignore_flag(const char *filename, const struct grub_dirhook_info *info, void *data)
715 {
716 if (0 == info->dir)
717 {
718 if (filename && filename[0] == '.' && 0 == grub_strncmp(filename, ".ventoyignore", 13))
719 {
720 *((int *)data) = 1;
721 return 0;
722 }
723 }
724
725 return 0;
726 }
727
728 static int ventoy_colect_img_files(const char *filename, const struct grub_dirhook_info *info, void *data)
729 {
730 int i = 0;
731 int type = 0;
732 int ignore = 0;
733 grub_size_t len;
734 img_info *img;
735 img_info *tail;
736 img_iterator_node *tmp;
737 img_iterator_node *new_node;
738 img_iterator_node *node = (img_iterator_node *)data;
739
740 len = grub_strlen(filename);
741
742 if (info->dir)
743 {
744 if ((len == 1 && filename[0] == '.') ||
745 (len == 2 && filename[0] == '.' && filename[1] == '.'))
746 {
747 return 0;
748 }
749
750 if (!ventoy_img_name_valid(filename, len))
751 {
752 return 0;
753 }
754
755 if (filename[0] == '$' && 0 == grub_strncmp(filename, "$RECYCLE.BIN", 12))
756 {
757 return 0;
758 }
759
760 new_node = grub_zalloc(sizeof(img_iterator_node));
761 if (new_node)
762 {
763 new_node->dirlen = grub_snprintf(new_node->dir, sizeof(new_node->dir), "%s%s/", node->dir, filename);
764
765 g_enum_fs->fs_dir(g_enum_dev, new_node->dir, ventoy_check_ignore_flag, &ignore);
766 if (ignore)
767 {
768 debug("Directory %s ignored...\n", new_node->dir);
769 grub_free(new_node);
770 return 0;
771 }
772
773 new_node->tail = node->tail;
774
775 new_node->parent = node;
776 if (!node->firstchild)
777 {
778 node->firstchild = new_node;
779 }
780
781 if (g_img_iterator_tail)
782 {
783 g_img_iterator_tail->next = new_node;
784 g_img_iterator_tail = new_node;
785 }
786 else
787 {
788 g_img_iterator_head.next = new_node;
789 g_img_iterator_tail = new_node;
790 }
791 }
792 }
793 else
794 {
795 debug("Find a file %s\n", filename);
796 if (len <= 4)
797 {
798 return 0;
799 }
800
801 if (0 == grub_strcasecmp(filename + len - 4, ".iso"))
802 {
803 type = img_type_iso;
804 }
805 else if (g_wimboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".wim")))
806 {
807 type = img_type_wim;
808 }
809 else
810 {
811 return 0;
812 }
813
814 if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
815 {
816 return 0;
817 }
818
819 img = grub_zalloc(sizeof(img_info));
820 if (img)
821 {
822 img->type = type;
823 grub_snprintf(img->name, sizeof(img->name), "%s", filename);
824
825 for (i = 0; i < (int)len; i++)
826 {
827 if (filename[i] == ' ' || filename[i] == '\t' || (0 == grub_isprint(filename[i])))
828 {
829 img->name[i] = '*';
830 img->unsupport = 1;
831 }
832 }
833
834 grub_snprintf(img->path, sizeof(img->path), "%s%s", node->dir, img->name);
835
836 img->size = info->size;
837 if (0 == img->size)
838 {
839 img->size = ventoy_grub_get_file_size("%s/%s", g_iso_path, img->path);
840 }
841
842 if (img->size < VTOY_FILT_MIN_FILE_SIZE)
843 {
844 debug("img <%s> size too small %llu\n", img->name, (ulonglong)img->size);
845 grub_free(img);
846 return 0;
847 }
848
849 if (g_ventoy_img_list)
850 {
851 tail = *(node->tail);
852 img->prev = tail;
853 tail->next = img;
854 }
855 else
856 {
857 g_ventoy_img_list = img;
858 }
859
860 img->id = g_ventoy_img_count;
861 img->parent = node;
862 if (node && NULL == node->firstiso)
863 {
864 node->firstiso = img;
865 }
866
867 node->isocnt++;
868 tmp = node->parent;
869 while (tmp)
870 {
871 tmp->isocnt++;
872 tmp = tmp->parent;
873 }
874
875 *((img_info **)(node->tail)) = img;
876 g_ventoy_img_count++;
877
878 img->alias = ventoy_plugin_get_menu_alias(img->path);
879
880 debug("Add %s%s to list %d\n", node->dir, filename, g_ventoy_img_count);
881 }
882 }
883
884 return 0;
885 }
886
887 int ventoy_fill_data(grub_uint32_t buflen, char *buffer)
888 {
889 int len = GRUB_UINT_MAX;
890 const char *value = NULL;
891 char name[32] = {0};
892 char plat[32] = {0};
893 char guidstr[32] = {0};
894 ventoy_guid guid = VENTOY_GUID;
895 const char *fmt1 = NULL;
896 const char *fmt2 = NULL;
897 const char *fmt3 = NULL;
898 grub_uint32_t *puint = (grub_uint32_t *)name;
899 grub_uint32_t *puint2 = (grub_uint32_t *)plat;
900 const char fmtdata[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
901 const char fmtcode[]={
902 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
903 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
904 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
905 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
906 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
907 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
908 };
909
910 grub_memset(name, 0, sizeof(name));
911 puint[0] = grub_swap_bytes32(0x56454e54);
912 puint[3] = grub_swap_bytes32(0x4f4e0000);
913 puint[2] = grub_swap_bytes32(0x45525349);
914 puint[1] = grub_swap_bytes32(0x4f595f56);
915 value = ventoy_get_env(name);
916
917 grub_memset(name, 0, sizeof(name));
918 puint[1] = grub_swap_bytes32(0x5f544f50);
919 puint[0] = grub_swap_bytes32(0x56544c45);
920 fmt1 = ventoy_get_env(name);
921 if (!fmt1)
922 {
923 fmt1 = fmtdata;
924 }
925
926 grub_memset(name, 0, sizeof(name));
927 puint[1] = grub_swap_bytes32(0x5f4c4654);
928 puint[0] = grub_swap_bytes32(0x56544c45);
929 fmt2 = ventoy_get_env(name);
930
931 grub_memset(name, 0, sizeof(name));
932 puint[1] = grub_swap_bytes32(0x5f434c52);
933 puint[0] = grub_swap_bytes32(0x56544c45);
934 fmt3 = ventoy_get_env(name);
935
936 grub_memcpy(guidstr, &guid, sizeof(guid));
937
938 #if defined (GRUB_MACHINE_EFI)
939 puint2[0] = grub_swap_bytes32(0x55454649);
940 #else
941 puint2[0] = grub_swap_bytes32(0x42494f53);
942 #endif
943
944 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
945 #pragma GCC diagnostic push
946 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
947 len = grub_snprintf(buffer, buflen, fmtcode,
948 fmt1 ? fmt1 : fmtdata,
949 fmt2 ? fmt2 : fmtdata + 4,
950 value ? value : "", plat, guidstr,
951 fmt3 ? fmt3 : fmtdata + 6);
952 #pragma GCC diagnostic pop
953
954 grub_memset(name, 0, sizeof(name));
955 puint[0] = grub_swap_bytes32(0x76746f79);
956 puint[2] = grub_swap_bytes32(0x656e7365);
957 puint[1] = grub_swap_bytes32(0x5f6c6963);
958 ventoy_set_env(name, guidstr);
959
960 return len;
961 }
962
963 static img_info * ventoy_get_min_iso(img_iterator_node *node)
964 {
965 img_info *minimg = NULL;
966 img_info *img = (img_info *)(node->firstiso);
967
968 while (img && (img_iterator_node *)(img->parent) == node)
969 {
970 if (img->select == 0 && (NULL == minimg || grub_strcmp(img->name, minimg->name) < 0))
971 {
972 minimg = img;
973 }
974 img = img->next;
975 }
976
977 if (minimg)
978 {
979 minimg->select = 1;
980 }
981
982 return minimg;
983 }
984
985 static img_iterator_node * ventoy_get_min_child(img_iterator_node *node)
986 {
987 img_iterator_node *Minchild = NULL;
988 img_iterator_node *child = node->firstchild;
989
990 while (child && child->parent == node)
991 {
992 if (child->select == 0 && (NULL == Minchild || grub_strcmp(child->dir, Minchild->dir) < 0))
993 {
994 Minchild = child;
995 }
996 child = child->next;
997 }
998
999 if (Minchild)
1000 {
1001 Minchild->select = 1;
1002 }
1003
1004 return Minchild;
1005 }
1006
1007 static int ventoy_dynamic_tree_menu(img_iterator_node *node)
1008 {
1009 int offset = 1;
1010 img_info *img;
1011 img_iterator_node *child = NULL;
1012
1013 if (node->isocnt == 0 || node->done == 1)
1014 {
1015 return 0;
1016 }
1017
1018 if (node->parent && node->parent->dirlen < node->dirlen)
1019 {
1020 offset = node->parent->dirlen;
1021 }
1022
1023 if (node == &g_img_iterator_head)
1024 {
1025 if (g_default_menu_mode == 0)
1026 {
1027 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1028 "menuentry \"%-10s [Return to ListView]\" VTOY_RET {\n "
1029 " echo 'return ...' \n"
1030 "}\n", "<--");
1031 }
1032 }
1033 else
1034 {
1035 node->dir[node->dirlen - 1] = 0;
1036 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1037 "submenu \"%-10s [%s]\" {\n",
1038 "DIR", node->dir + offset);
1039
1040 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1041 "menuentry \"%-10s [../]\" VTOY_RET {\n "
1042 " echo 'return ...' \n"
1043 "}\n", "<--");
1044 }
1045
1046 while ((child = ventoy_get_min_child(node)) != NULL)
1047 {
1048 ventoy_dynamic_tree_menu(child);
1049 }
1050
1051 while ((img = ventoy_get_min_iso(node)) != NULL)
1052 {
1053 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
1054 "menuentry \"%-10s %s%s\" --id=\"VID_%d\" {\n"
1055 " %s_%s \n"
1056 "}\n",
1057 grub_get_human_size(img->size, GRUB_HUMAN_SIZE_SHORT),
1058 img->unsupport ? "[unsupported] " : "",
1059 img->alias ? img->alias : img->name, img->id,
1060 (img->type == img_type_iso) ? "iso" : "wim",
1061 img->unsupport ? "unsupport_menuentry" : "common_menuentry");
1062 }
1063
1064 if (node != &g_img_iterator_head)
1065 {
1066 vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "%s", "}\n");
1067 }
1068
1069 node->done = 1;
1070 return 0;
1071 }
1072
1073 static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char **args)
1074 {
1075 int len;
1076 grub_fs_t fs;
1077 grub_device_t dev = NULL;
1078 img_info *cur = NULL;
1079 img_info *tail = NULL;
1080 const char *strdata = NULL;
1081 char *device_name = NULL;
1082 char buf[32];
1083 img_iterator_node *node = NULL;
1084 img_iterator_node *tmp = NULL;
1085
1086 (void)ctxt;
1087
1088 if (argc != 2)
1089 {
1090 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {device} {cntvar}", cmd_raw_name);
1091 }
1092
1093 if (g_ventoy_img_list || g_ventoy_img_count)
1094 {
1095 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Must clear image before list");
1096 }
1097
1098 strdata = ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
1099 if (strdata && strdata[0] == '1' && strdata[1] == 0)
1100 {
1101 g_filt_dot_underscore_file = 1;
1102 }
1103
1104 device_name = grub_file_get_device_name(args[0]);
1105 if (!device_name)
1106 {
1107 goto fail;
1108 }
1109
1110 g_enum_dev = dev = grub_device_open(device_name);
1111 if (!dev)
1112 {
1113 goto fail;
1114 }
1115
1116 g_enum_fs = fs = grub_fs_probe(dev);
1117 if (!fs)
1118 {
1119 goto fail;
1120 }
1121
1122 if (ventoy_get_fs_type(fs->name) >= ventoy_fs_max)
1123 {
1124 debug("unsupported fs:<%s>\n", fs->name);
1125 ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
1126 goto fail;
1127 }
1128
1129 strdata = ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
1130 if (strdata && strdata[0] == '1')
1131 {
1132 g_default_menu_mode = 1;
1133 }
1134
1135 grub_memset(&g_img_iterator_head, 0, sizeof(g_img_iterator_head));
1136
1137 grub_snprintf(g_iso_path, sizeof(g_iso_path), "%s", args[0]);
1138
1139 strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
1140 if (strdata && strdata[0] == '/')
1141 {
1142 len = grub_snprintf(g_img_iterator_head.dir, sizeof(g_img_iterator_head.dir) - 1, "%s", strdata);
1143 if (g_img_iterator_head.dir[len - 1] != '/')
1144 {
1145 g_img_iterator_head.dir[len++] = '/';
1146 }
1147 g_img_iterator_head.dirlen = len;
1148 }
1149 else
1150 {
1151 g_img_iterator_head.dirlen = 1;
1152 grub_strcpy(g_img_iterator_head.dir, "/");
1153 }
1154
1155 g_img_iterator_head.tail = &tail;
1156
1157 for (node = &g_img_iterator_head; node; node = node->next)
1158 {
1159 fs->fs_dir(dev, node->dir, ventoy_colect_img_files, node);
1160 }
1161
1162 for (node = &g_img_iterator_head; node; node = node->next)
1163 {
1164 ventoy_dynamic_tree_menu(node);
1165 }
1166
1167 /* free node */
1168 node = g_img_iterator_head.next;
1169 while (node)
1170 {
1171 tmp = node->next;
1172 grub_free(node);
1173 node = tmp;
1174 }
1175
1176 /* sort image list by image name */
1177 for (cur = g_ventoy_img_list; cur; cur = cur->next)
1178 {
1179 for (tail = cur->next; tail; tail = tail->next)
1180 {
1181 if (ventoy_cmp_img(cur, tail) > 0)
1182 {
1183 ventoy_swap_img(cur, tail);
1184 }
1185 }
1186 }
1187
1188 if (g_default_menu_mode == 1)
1189 {
1190 vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
1191 "menuentry \"%s [Return to TreeView]\" VTOY_RET {\n "
1192 " echo 'return ...' \n"
1193 "}\n", "<--");
1194 }
1195
1196 for (cur = g_ventoy_img_list; cur; cur = cur->next)
1197 {
1198 vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
1199 "menuentry \"%s%s\" --id=\"VID_%d\" {\n"
1200 " %s_%s \n"
1201 "}\n",
1202 cur->unsupport ? "[unsupported] " : "",
1203 cur->alias ? cur->alias : cur->name, cur->id,
1204 (cur->type == img_type_iso) ? "iso" : "wim",
1205 cur->unsupport ? "unsupport_menuentry" : "common_menuentry");
1206 }
1207 g_list_script_buf[g_list_script_pos] = 0;
1208
1209 grub_snprintf(buf, sizeof(buf), "%d", g_ventoy_img_count);
1210 grub_env_set(args[1], buf);
1211
1212 fail:
1213
1214 check_free(device_name, grub_free);
1215 check_free(dev, grub_device_close);
1216
1217 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1218 }
1219
1220
1221 static grub_err_t ventoy_cmd_clear_img(grub_extcmd_context_t ctxt, int argc, char **args)
1222 {
1223 img_info *next = NULL;
1224 img_info *cur = g_ventoy_img_list;
1225
1226 (void)ctxt;
1227 (void)argc;
1228 (void)args;
1229
1230 while (cur)
1231 {
1232 next = cur->next;
1233 grub_free(cur);
1234 cur = next;
1235 }
1236
1237 g_ventoy_img_list = NULL;
1238 g_ventoy_img_count = 0;
1239
1240 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1241 }
1242
1243 static grub_err_t ventoy_cmd_img_name(grub_extcmd_context_t ctxt, int argc, char **args)
1244 {
1245 long img_id = 0;
1246 img_info *cur = g_ventoy_img_list;
1247
1248 (void)ctxt;
1249
1250 if (argc != 2 || (!ventoy_is_decimal(args[0])))
1251 {
1252 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {imageID} {var}", cmd_raw_name);
1253 }
1254
1255 img_id = grub_strtol(args[0], NULL, 10);
1256 if (img_id >= g_ventoy_img_count)
1257 {
1258 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images %ld %ld", img_id, g_ventoy_img_count);
1259 }
1260
1261 debug("Find image %ld name \n", img_id);
1262
1263 while (cur && img_id > 0)
1264 {
1265 img_id--;
1266 cur = cur->next;
1267 }
1268
1269 if (!cur)
1270 {
1271 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images");
1272 }
1273
1274 debug("image name is %s\n", cur->name);
1275
1276 grub_env_set(args[1], cur->name);
1277
1278 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1279 }
1280
1281 static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
1282 {
1283 int img_id = 0;
1284 char *pos = NULL;
1285 const char *id = NULL;
1286 img_info *cur = g_ventoy_img_list;
1287
1288 (void)ctxt;
1289
1290 if (argc != 1)
1291 {
1292 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
1293 }
1294
1295 id = grub_env_get("chosen");
1296
1297 pos = grub_strstr(id, "VID_");
1298 if (pos)
1299 {
1300 img_id = (int)grub_strtoul(pos + 4, NULL, 10);
1301 }
1302 else
1303 {
1304 img_id = (int)grub_strtoul(id, NULL, 10);
1305 }
1306
1307 while (cur)
1308 {
1309 if (img_id == cur->id)
1310 {
1311 break;
1312 }
1313 cur = cur->next;
1314 }
1315
1316 if (!cur)
1317 {
1318 return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
1319 }
1320
1321 grub_env_set(args[0], cur->path);
1322
1323 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1324 }
1325
1326 static int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid)
1327 {
1328 grub_disk_t disk;
1329 char *device_name;
1330 char *pos;
1331 char *pos2;
1332
1333 device_name = grub_file_get_device_name(filename);
1334 if (!device_name)
1335 {
1336 return 1;
1337 }
1338
1339 pos = device_name;
1340 if (pos[0] == '(')
1341 {
1342 pos++;
1343 }
1344
1345 pos2 = grub_strstr(pos, ",");
1346 if (!pos2)
1347 {
1348 pos2 = grub_strstr(pos, ")");
1349 }
1350
1351 if (pos2)
1352 {
1353 *pos2 = 0;
1354 }
1355
1356 disk = grub_disk_open(pos);
1357 if (disk)
1358 {
1359 grub_disk_read(disk, 0, 0x180, 16, guid);
1360 grub_disk_close(disk);
1361 }
1362 else
1363 {
1364 return 1;
1365 }
1366
1367 grub_free(device_name);
1368 return 0;
1369 }
1370
1371 grub_uint32_t ventoy_get_iso_boot_catlog(grub_file_t file)
1372 {
1373 eltorito_descriptor desc;
1374
1375 grub_memset(&desc, 0, sizeof(desc));
1376 grub_file_seek(file, 17 * 2048);
1377 grub_file_read(file, &desc, sizeof(desc));
1378
1379 if (desc.type != 0 || desc.version != 1)
1380 {
1381 return 0;
1382 }
1383
1384 if (grub_strncmp((char *)desc.id, "CD001", 5) != 0 ||
1385 grub_strncmp((char *)desc.system_id, "EL TORITO SPECIFICATION", 23) != 0)
1386 {
1387 return 0;
1388 }
1389
1390 return desc.sector;
1391 }
1392
1393 int ventoy_has_efi_eltorito(grub_file_t file, grub_uint32_t sector)
1394 {
1395 int i;
1396 grub_uint8_t buf[512];
1397
1398 grub_file_seek(file, sector * 2048);
1399 grub_file_read(file, buf, sizeof(buf));
1400
1401 if (buf[0] == 0x01 && buf[1] == 0xEF)
1402 {
1403 debug("%s efi eltorito in Validation Entry\n", file->name);
1404 return 1;
1405 }
1406
1407 for (i = 64; i < (int)sizeof(buf); i += 32)
1408 {
1409 if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF)
1410 {
1411 debug("%s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
1412 return 1;
1413 }
1414 }
1415
1416 debug("%s does not contain efi eltorito\n", file->name);
1417 return 0;
1418 }
1419
1420 void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
1421 {
1422 char *pos;
1423 const char *fs = NULL;
1424 grub_uint32_t i;
1425 grub_uint8_t chksum = 0;
1426 grub_disk_t disk;
1427
1428 disk = file->device->disk;
1429 grub_memcpy(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid));
1430
1431 param->vtoy_disk_size = disk->total_sectors * (1 << disk->log_sector_size);
1432 param->vtoy_disk_part_id = disk->partition->number + 1;
1433 param->vtoy_disk_part_type = ventoy_get_fs_type(file->fs->name);
1434
1435 pos = grub_strstr(file->name, "/");
1436 if (!pos)
1437 {
1438 pos = file->name;
1439 }
1440
1441 grub_snprintf(param->vtoy_img_path, sizeof(param->vtoy_img_path), "%s", pos);
1442
1443 ventoy_get_disk_guid(file->name, param->vtoy_disk_guid);
1444
1445 param->vtoy_img_size = file->size;
1446
1447 param->vtoy_reserved[0] = g_ventoy_break_level;
1448 param->vtoy_reserved[1] = g_ventoy_debug_level;
1449
1450 param->vtoy_reserved[2] = g_ventoy_chain_type;
1451
1452 fs = ventoy_get_env("ventoy_fs_probe");
1453 if (fs && grub_strcmp(fs, "udf") == 0)
1454 {
1455 param->vtoy_reserved[3] = 1;
1456 }
1457
1458 /* calculate checksum */
1459 for (i = 0; i < sizeof(ventoy_os_param); i++)
1460 {
1461 chksum += *((grub_uint8_t *)param + i);
1462 }
1463 param->chksum = (grub_uint8_t)(0x100 - chksum);
1464
1465 return;
1466 }
1467
1468 int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
1469 {
1470 grub_uint32_t i = 0;
1471 grub_uint64_t total = 0;
1472 ventoy_img_chunk *chunk = NULL;
1473
1474 for (i = 0; i < chunklist->cur_chunk; i++)
1475 {
1476 chunk = chunklist->chunk + i;
1477
1478 if (chunk->disk_start_sector <= start)
1479 {
1480 debug("%u disk start invalid %lu\n", i, (ulong)start);
1481 return 1;
1482 }
1483
1484 total += chunk->disk_end_sector + 1 - chunk->disk_start_sector;
1485 }
1486
1487 if (total != ((file->size + 511) / 512))
1488 {
1489 debug("Invalid total: %llu %llu\n", (ulonglong)total, (ulonglong)((file->size + 511) / 512));
1490 return 1;
1491 }
1492
1493 return 0;
1494 }
1495
1496 int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
1497 {
1498 int fs_type;
1499 grub_uint32_t i = 0;
1500 grub_uint32_t sector = 0;
1501 grub_uint32_t count = 0;
1502 grub_off_t size = 0;
1503 grub_off_t read = 0;
1504
1505 fs_type = ventoy_get_fs_type(file->fs->name);
1506 if (fs_type == ventoy_fs_exfat)
1507 {
1508 grub_fat_get_file_chunk(start, file, chunklist);
1509 }
1510 else if (fs_type == ventoy_fs_ext)
1511 {
1512 grub_ext_get_file_chunk(start, file, chunklist);
1513 }
1514 else
1515 {
1516 file->read_hook = (grub_disk_read_hook_t)grub_disk_blocklist_read;
1517 file->read_hook_data = chunklist;
1518
1519 for (size = file->size; size > 0; size -= read)
1520 {
1521 read = (size > VTOY_SIZE_1GB) ? VTOY_SIZE_1GB : size;
1522 grub_file_read(file, NULL, read);
1523 }
1524
1525 for (i = 0; start > 0 && i < chunklist->cur_chunk; i++)
1526 {
1527 chunklist->chunk[i].disk_start_sector += start;
1528 chunklist->chunk[i].disk_end_sector += start;
1529 }
1530
1531 if (ventoy_fs_udf == fs_type)
1532 {
1533 for (i = 0; i < chunklist->cur_chunk; i++)
1534 {
1535 count = (chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector) >> 2;
1536 chunklist->chunk[i].img_start_sector = sector;
1537 chunklist->chunk[i].img_end_sector = sector + count - 1;
1538 sector += count;
1539 }
1540 }
1541 }
1542
1543 return 0;
1544 }
1545
1546 static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
1547 {
1548 int rc;
1549 grub_file_t file;
1550 grub_disk_addr_t start;
1551
1552 (void)ctxt;
1553 (void)argc;
1554
1555 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1556 if (!file)
1557 {
1558 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
1559 }
1560
1561 if (g_img_chunk_list.chunk)
1562 {
1563 grub_free(g_img_chunk_list.chunk);
1564 }
1565
1566 /* get image chunk data */
1567 grub_memset(&g_img_chunk_list, 0, sizeof(g_img_chunk_list));
1568 g_img_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
1569 if (NULL == g_img_chunk_list.chunk)
1570 {
1571 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
1572 }
1573
1574 g_img_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
1575 g_img_chunk_list.cur_chunk = 0;
1576
1577 start = file->device->disk->partition->start;
1578
1579 ventoy_get_block_list(file, &g_img_chunk_list, start);
1580
1581 rc = ventoy_check_block_list(file, &g_img_chunk_list, start);
1582 grub_file_close(file);
1583
1584 if (rc)
1585 {
1586 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported chunk list.\n");
1587 }
1588
1589 grub_memset(&g_grub_param->file_replace, 0, sizeof(g_grub_param->file_replace));
1590 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1591 }
1592
1593 static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
1594 {
1595 int i = 0;
1596 int pos = 0;
1597 char *buf = NULL;
1598 char configfile[128];
1599 install_template *node = NULL;
1600
1601 (void)ctxt;
1602 (void)argc;
1603 (void)args;
1604
1605 debug("select auto installation %d\n", argc);
1606
1607 if (argc < 1)
1608 {
1609 return 0;
1610 }
1611
1612 node = ventoy_plugin_find_install_template(args[0]);
1613 if (!node)
1614 {
1615 debug("Install template not found for %s\n", args[0]);
1616 return 0;
1617 }
1618
1619 buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
1620 if (!buf)
1621 {
1622 return 0;
1623 }
1624
1625 vtoy_ssprintf(buf, pos, "menuentry \"Boot without auto installation template\" {\n"
1626 " echo %s\n}\n", "123");
1627
1628 for (i = 0; i < node->templatenum; i++)
1629 {
1630 vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" {\n"
1631 " echo 123\n}\n",
1632 node->templatepath[i].path);
1633 }
1634
1635 g_ventoy_menu_esc = 1;
1636 g_ventoy_suppress_esc = 1;
1637
1638 grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
1639 grub_script_execute_sourcecode(configfile);
1640
1641 g_ventoy_menu_esc = 0;
1642 g_ventoy_suppress_esc = 0;
1643
1644 grub_free(buf);
1645
1646 node->cursel = g_ventoy_last_entry - 1;
1647
1648 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1649 }
1650
1651 static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
1652 {
1653 int i = 0;
1654 int pos = 0;
1655 char *buf = NULL;
1656 char configfile[128];
1657 persistence_config *node;
1658
1659 (void)ctxt;
1660 (void)argc;
1661 (void)args;
1662
1663 debug("select persistece %d\n", argc);
1664
1665 if (argc < 1)
1666 {
1667 return 0;
1668 }
1669
1670 node = ventoy_plugin_find_persistent(args[0]);
1671 if (!node)
1672 {
1673 debug("Persistence image not found for %s\n", args[0]);
1674 return 0;
1675 }
1676
1677 buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
1678 if (!buf)
1679 {
1680 return 0;
1681 }
1682
1683 vtoy_ssprintf(buf, pos, "menuentry \"Boot without persistence\" {\n"
1684 " echo %s\n}\n", "123");
1685
1686 for (i = 0; i < node->backendnum; i++)
1687 {
1688 vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" {\n"
1689 " echo 123\n}\n",
1690 node->backendpath[i].path);
1691
1692 }
1693
1694 g_ventoy_menu_esc = 1;
1695 g_ventoy_suppress_esc = 1;
1696
1697 grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
1698 grub_script_execute_sourcecode(configfile);
1699
1700 g_ventoy_menu_esc = 0;
1701 g_ventoy_suppress_esc = 0;
1702
1703 grub_free(buf);
1704
1705 node->cursel = g_ventoy_last_entry - 1;
1706
1707 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1708 }
1709
1710 static grub_err_t ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
1711 {
1712 grub_uint32_t i;
1713 ventoy_img_chunk *cur;
1714
1715 (void)ctxt;
1716 (void)argc;
1717 (void)args;
1718
1719 for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
1720 {
1721 cur = g_img_chunk_list.chunk + i;
1722 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
1723 cur->img_start_sector, cur->img_end_sector,
1724 (unsigned long long)cur->disk_start_sector, (unsigned long long)cur->disk_end_sector
1725 );
1726 }
1727
1728 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1729 }
1730
1731 #ifdef GRUB_MACHINE_EFI
1732 static grub_err_t ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt, int argc, char **args)
1733 {
1734 (void)ctxt;
1735 (void)argc;
1736 (void)args;
1737 return 0;
1738 }
1739 #else
1740 static grub_err_t ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt, int argc, char **args)
1741 {
1742 int rc = 0;
1743 ulong chain_len = 0;
1744 char *chain_data = NULL;
1745 char *relocator_addr = NULL;
1746 grub_relocator_chunk_t ch;
1747 struct grub_relocator *relocator = NULL;
1748 char envbuf[64] = { 0 };
1749
1750 (void)ctxt;
1751 (void)argc;
1752 (void)args;
1753
1754 if (argc != 2)
1755 {
1756 return 1;
1757 }
1758
1759 chain_data = (char *)grub_strtoul(args[0], NULL, 16);
1760 chain_len = grub_strtoul(args[1], NULL, 10);
1761
1762 relocator = grub_relocator_new ();
1763 if (!relocator)
1764 {
1765 debug("grub_relocator_new failed %p %lu\n", chain_data, chain_len);
1766 return 1;
1767 }
1768
1769 rc = grub_relocator_alloc_chunk_addr (relocator, &ch,
1770 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
1771 chain_len);
1772 if (rc)
1773 {
1774 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc, chain_data, chain_len);
1775 grub_relocator_unload (relocator);
1776 return 1;
1777 }
1778
1779 relocator_addr = get_virtual_current_address(ch);
1780
1781 grub_memcpy(relocator_addr, chain_data, chain_len);
1782
1783 grub_relocator_unload (relocator);
1784
1785 grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)relocator_addr);
1786 grub_env_set("vtoy_chain_relocator_addr", envbuf);
1787
1788 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1789 }
1790 #endif
1791
1792 static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int argc, char **args)
1793 {
1794 grub_uint32_t i;
1795 grub_file_t file;
1796 ventoy_img_chunk_list chunklist;
1797
1798 (void)ctxt;
1799 (void)argc;
1800
1801 file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
1802 if (!file)
1803 {
1804 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
1805 }
1806
1807 /* get image chunk data */
1808 grub_memset(&chunklist, 0, sizeof(chunklist));
1809 chunklist.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
1810 if (NULL == chunklist.chunk)
1811 {
1812 return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
1813 }
1814
1815 chunklist.max_chunk = DEFAULT_CHUNK_NUM;
1816 chunklist.cur_chunk = 0;
1817
1818 ventoy_get_block_list(file, &chunklist, 0);
1819
1820 if (0 != ventoy_check_block_list(file, &chunklist, 0))
1821 {
1822 grub_printf("########## UNSUPPORTED ###############\n");
1823 }
1824
1825 grub_printf("filesystem: <%s> entry number:<%u>\n", file->fs->name, chunklist.cur_chunk);
1826
1827 for (i = 0; i < chunklist.cur_chunk; i++)
1828 {
1829 grub_printf("%llu+%llu,", (ulonglong)chunklist.chunk[i].disk_start_sector,
1830 (ulonglong)(chunklist.chunk[i].disk_end_sector + 1 - chunklist.chunk[i].disk_start_sector));
1831 }
1832
1833 grub_printf("\n==================================\n");
1834
1835 for (i = 0; i < chunklist.cur_chunk; i++)
1836 {
1837 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i,
1838 (ulonglong)chunklist.chunk[i].img_start_sector,
1839 (ulonglong)chunklist.chunk[i].img_end_sector,
1840 (ulonglong)chunklist.chunk[i].disk_start_sector,
1841 (ulonglong)chunklist.chunk[i].disk_end_sector
1842 );
1843 }
1844
1845 grub_free(chunklist.chunk);
1846 grub_file_close(file);
1847
1848 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1849 }
1850
1851 static grub_err_t ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt, int argc, char **args)
1852 {
1853 int i;
1854 ventoy_grub_param_file_replace *replace = NULL;
1855
1856 (void)ctxt;
1857 (void)argc;
1858 (void)args;
1859
1860 if (argc >= 2)
1861 {
1862 replace = &(g_grub_param->file_replace);
1863 replace->magic = GRUB_FILE_REPLACE_MAGIC;
1864
1865 replace->old_name_cnt = 0;
1866 for (i = 0; i < 4 && i + 1 < argc; i++)
1867 {
1868 replace->old_name_cnt++;
1869 grub_snprintf(replace->old_file_name[i], sizeof(replace->old_file_name[i]), "%s", args[i + 1]);
1870 }
1871
1872 replace->new_file_virtual_id = (grub_uint32_t)grub_strtoul(args[0], NULL, 10);
1873 }
1874
1875 VENTOY_CMD_RETURN(GRUB_ERR_NONE);
1876 }
1877
1878 static grub_err_t ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt, int argc, char **args)
1879 {
1880 (void)ctxt;
1881 (void)argc;
1882 (void)args;
1883
1884 if (argc == 0)
1885 {
1886 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos, VTOY_MAX_SCRIPT_BUF);
1887 grub_printf("%s", g_list_script_buf);
1888 }
1889 else
1890 {
1891 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos, VTOY_MAX_SCRIPT_BUF);
1892 grub_printf("%s", g_tree_script_buf);
1893 }
1894
1895 return 0;
1896 }
1897
1898 static grub_err_t ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt, int argc, char **args)
1899 {
1900 img_info *cur = g_ventoy_img_list;
1901
1902 (void)ctxt;
1903 (void)argc;
1904 (void)args;
1905
1906 while (cur)
1907 {
1908 grub_printf("path:<%s>\n", cur->path);
1909 grub_printf("name:<%s>\n\n", cur->name);
1910 cur = cur->next;
1911 }
1912
1913 return 0;
1914 }
1915
1916 static grub_err_t ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
1917 {
1918 (void)ctxt;
1919 (void)argc;
1920 (void)args;
1921
1922 {
1923 grub_file_t file;
1924 char *buf;
1925 char name[128];
1926
1927 file = grub_file_open("(hd0,1)/ventoy/ventoy.disk.img.xz", GRUB_FILE_TYPE_NONE);
1928 if (file)
1929 {
1930 grub_printf("Open File OK (size:%llu)\n", (ulonglong)file->size);
1931
1932 buf = grub_malloc(file->size);
1933 grub_file_read(file, buf, file->size);
1934
1935 grub_file_close(file);
1936
1937 grub_snprintf(name, sizeof(name), "mem:0x%llx:size:%llu", (ulonglong)(ulong)buf, (ulonglong)file->size);
1938 grub_printf("<%s>\n", name);
1939 }
1940 }
1941
1942
1943 ventoy_plugin_dump_auto_install();
1944
1945 return 0;
1946 }
1947
1948 static grub_err_t ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
1949 {
1950 (void)ctxt;
1951 (void)argc;
1952 (void)args;
1953
1954 ventoy_plugin_dump_persistence();
1955
1956 return 0;
1957 }
1958
1959 static grub_err_t ventoy_cmd_check_mode(grub_extcmd_context_t ctxt, int argc, char **args)
1960 {
1961 (void)ctxt;
1962 (void)argc;
1963 (void)args;
1964
1965 if (argc != 1)
1966 {
1967 return 1;
1968 }
1969
1970 if (args[0][0] == '0')
1971 {
1972 return g_ventoy_memdisk_mode ? 0 : 1;
1973 }
1974 else if (args[0][0] == '1')
1975 {
1976 return g_ventoy_iso_raw ? 0 : 1;
1977 }
1978 else if (args[0][0] == '2')
1979 {
1980 return g_ventoy_iso_uefi_drv ? 0 : 1;
1981 }
1982
1983 return 1;
1984 }
1985
1986 static grub_err_t ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt, int argc, char **args)
1987 {
1988 static int configfile_mode = 0;
1989 char memfile[128] = {0};
1990
1991 (void)ctxt;
1992 (void)argc;
1993 (void)args;
1994
1995 /*
1996 * args[0]: 0:normal 1:configfile
1997 * args[1]: 0:list_buf 1:tree_buf
1998 */
1999
2000 if (argc != 2)
2001 {
2002 debug("Invalid argc %d\n", argc);
2003 return 0;
2004 }
2005
2006 if (args[0][0] == '0')
2007 {
2008 if (args[1][0] == '0')
2009 {
2010 grub_script_execute_sourcecode(g_list_script_buf);
2011 }
2012 else
2013 {
2014 grub_script_execute_sourcecode(g_tree_script_buf);
2015 }
2016 }
2017 else
2018 {
2019 if (configfile_mode)
2020 {
2021 debug("Now already in F3 mode %d\n", configfile_mode);
2022 return 0;
2023 }
2024
2025 if (args[1][0] == '0')
2026 {
2027 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
2028 (ulonglong)(ulong)g_list_script_buf, g_list_script_pos);
2029 }
2030 else
2031 {
2032 g_ventoy_last_entry = -1;
2033 grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
2034 (ulonglong)(ulong)g_tree_script_buf, g_tree_script_pos);
2035 }
2036
2037 configfile_mode = 1;
2038 grub_script_execute_sourcecode(memfile);
2039 configfile_mode = 0;
2040 }
2041
2042 return 0;
2043 }
2044
2045 static grub_err_t ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt, int argc, char **args)
2046 {
2047 grub_file_t file;
2048
2049 (void)ctxt;
2050
2051 if (argc != 1)
2052 {
2053 return 1;
2054 }
2055
2056 g_ventoy_case_insensitive = 1;
2057 file = grub_file_open(args[0], VENTOY_FILE_TYPE);
2058 g_ventoy_case_insensitive = 0;
2059
2060 grub_errno = 0;
2061
2062 if (file)
2063 {
2064 grub_file_close(file);
2065 return 0;
2066 }
2067 return 1;
2068 }
2069
2070 static grub_err_t ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt, int argc, char **args)
2071 {
2072 int id = 0;
2073 int find = 0;
2074 grub_disk_t disk;
2075 const char *isopath = NULL;
2076 char hdname[32];
2077 ventoy_mbr_head mbr;
2078
2079 (void)ctxt;
2080 (void)argc;
2081
2082 if (argc != 1)
2083 {
2084 return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s variable\n", cmd_raw_name);
2085 }
2086
2087 isopath = grub_env_get("iso_path");
2088 if (!isopath)
2089 {
2090 debug("isopath is null %p\n", isopath);
2091 return 0;
2092 }
2093
2094 debug("isopath is %s\n", isopath);
2095
2096 for (id = 0; id < 30 && (find == 0); id++)
2097 {
2098 grub_snprintf(hdname, sizeof(hdname), "hd%d,", id);
2099 if (grub_strstr(isopath, hdname))
2100 {
2101 debug("skip %s ...\n", hdname);
2102 continue;
2103 }
2104
2105 grub_snprintf(hdname, sizeof(hdname), "hd%d", id);
2106
2107 disk = grub_disk_open(hdname);
2108 if (!disk)
2109 {
2110 debug("%s not exist\n", hdname);
2111 break;
2112 }
2113
2114 grub_memset(&mbr, 0, sizeof(mbr));
2115 if (0 == grub_disk_read(disk, 0, 0, 512, &mbr))
2116 {
2117 if (mbr.Byte55 == 0x55 && mbr.ByteAA == 0xAA)
2118 {
2119 if (mbr.PartTbl[0].Active == 0x80 || mbr.PartTbl[1].Active == 0x80 ||
2120 mbr.PartTbl[2].Active == 0x80 || mbr.PartTbl[3].Active == 0x80)
2121 {
2122
2123 grub_env_set(args[0], hdname);
2124 find = 1;
2125 }
2126 }
2127 debug("%s is %s\n", hdname, find ? "bootable" : "NOT bootable");
2128 }
2129 else
2130 {
2131 debug("read %s failed\n", hdname);
2132 }
2133
2134 grub_disk_close(disk);
2135 }
2136
2137 return 0;
2138 }
2139
2140 grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...)
2141 {
2142 grub_uint64_t size = 0;
2143 grub_file_t file;
2144 va_list ap;
2145 char fullpath[256] = {0};
2146
2147 va_start (ap, fmt);
2148 grub_vsnprintf(fullpath, 255, fmt, ap);
2149 va_end (ap);
2150
2151 file = grub_file_open(fullpath, VENTOY_FILE_TYPE);
2152 if (!file)
2153 {
2154 debug("grub_file_open failed <%s>\n", fullpath);
2155 grub_errno = 0;
2156 return 0;
2157 }
2158
2159 size = file->size;
2160 grub_file_close(file);
2161 return size;
2162 }
2163
2164 grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...)
2165 {
2166 va_list ap;
2167 grub_file_t file;
2168 char fullpath[256] = {0};
2169
2170 va_start (ap, fmt);
2171 grub_vsnprintf(fullpath, 255, fmt, ap);
2172 va_end (ap);
2173
2174 file = grub_file_open(fullpath, type);
2175 if (!file)
2176 {
2177 debug("grub_file_open failed <%s>\n", fullpath);
2178 grub_errno = 0;
2179 }
2180
2181 return file;
2182 }
2183
2184 int ventoy_is_file_exist(const char *fmt, ...)
2185 {
2186 va_list ap;
2187 int len;
2188 char *pos = NULL;
2189 char buf[256] = {0};
2190
2191 grub_snprintf(buf, sizeof(buf), "%s", "[ -f ");
2192 pos = buf + 5;
2193
2194 va_start (ap, fmt);
2195 len = grub_vsnprintf(pos, 255, fmt, ap);
2196 va_end (ap);
2197
2198 grub_strncpy(pos + len, " ]", 2);
2199
2200 debug("script exec %s\n", buf);
2201
2202 if (0 == grub_script_execute_sourcecode(buf))
2203 {
2204 return 1;
2205 }
2206
2207 return 0;
2208 }
2209
2210 static int ventoy_env_init(void)
2211 {
2212 char buf[64];
2213
2214 grub_env_set("vtdebug_flag", "");
2215 grub_env_export("vtdebug_flag");
2216
2217
2218
2219 g_tree_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
2220 g_list_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
2221
2222 ventoy_filt_register(0, ventoy_wrapper_open);
2223
2224 g_grub_param = (ventoy_grub_param *)grub_zalloc(sizeof(ventoy_grub_param));
2225 if (g_grub_param)
2226 {
2227 g_grub_param->grub_env_get = grub_env_get;
2228 grub_snprintf(buf, sizeof(buf), "%p", g_grub_param);
2229 grub_env_set("env_param", buf);
2230 }
2231
2232 return 0;
2233 }
2234
2235 static cmd_para ventoy_cmds[] =
2236 {
2237 { "vt_incr", ventoy_cmd_incr, 0, NULL, "{Var} {INT}", "Increase integer variable", NULL },
2238 { "vt_debug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
2239 { "vtdebug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
2240 { "vtbreak", ventoy_cmd_break, 0, NULL, "{level}", "set debug break", NULL },
2241 { "vt_cmp", ventoy_cmd_cmp, 0, NULL, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL },
2242 { "vt_device", ventoy_cmd_device, 0, NULL, "path var", "", NULL },
2243 { "vt_check_compatible", ventoy_cmd_check_compatible, 0, NULL, "", "", NULL },
2244 { "vt_list_img", ventoy_cmd_list_img, 0, NULL, "{device} {cntvar}", "find all iso file in device", NULL },
2245 { "vt_clear_img", ventoy_cmd_clear_img, 0, NULL, "", "clear image list", NULL },
2246 { "vt_img_name", ventoy_cmd_img_name, 0, NULL, "{imageID} {var}", "get image name", NULL },
2247 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path, 0, NULL, "{var}", "get chosen img path", NULL },
2248 { "vt_img_sector", ventoy_cmd_img_sector, 0, NULL, "{imageName}", "", NULL },
2249 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector, 0, NULL, "", "", NULL },
2250 { "vt_load_wimboot", ventoy_cmd_load_wimboot, 0, NULL, "", "", NULL },
2251 { "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
2252 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd, 0, NULL, "", "", NULL },
2253 { "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
2254 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
2255 { "vt_check_mode", ventoy_cmd_check_mode, 0, NULL, "", "", NULL },
2256 { "vt_dump_img_list", ventoy_cmd_dump_img_list, 0, NULL, "", "", NULL },
2257 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install, 0, NULL, "", "", NULL },
2258 { "vt_dump_persistence", ventoy_cmd_dump_persistence, 0, NULL, "", "", NULL },
2259 { "vt_select_auto_install", ventoy_cmd_sel_auto_install, 0, NULL, "", "", NULL },
2260 { "vt_select_persistence", ventoy_cmd_sel_persistence, 0, NULL, "", "", NULL },
2261
2262 { "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
2263 { "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
2264 { "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
2265 { "vt_load_iso_to_mem", ventoy_cmd_load_iso_to_mem, 0, NULL, "", "", NULL },
2266
2267 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
2268 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
2269 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file, 0, NULL, "", "", NULL },
2270 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list, 0, NULL, "", "", NULL },
2271 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list, 0, NULL, "", "", NULL },
2272 { "vt_linux_initrd_count", ventoy_cmd_initrd_count, 0, NULL, "", "", NULL },
2273 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count, 0, NULL, "", "", NULL },
2274 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd, 0, NULL, "", "", NULL },
2275 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data, 0, NULL, "", "", NULL },
2276 { "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index, 0, NULL, "", "", NULL },
2277
2278 { "vt_windows_reset", ventoy_cmd_wimdows_reset, 0, NULL, "", "", NULL },
2279 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data, 0, NULL, "", "", NULL },
2280 { "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch, 0, NULL, "", "", NULL },
2281 { "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch, 0, NULL, "", "", NULL },
2282 { "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count, 0, NULL, "", "", NULL },
2283 { "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch, 0, NULL, "", "", NULL },
2284 { "vt_wim_chain_data", ventoy_cmd_wim_chain_data, 0, NULL, "", "", NULL },
2285
2286 { "vt_add_replace_file", ventoy_cmd_add_replace_file, 0, NULL, "", "", NULL },
2287 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata, 0, NULL, "", "", NULL },
2288 { "vt_test_block_list", ventoy_cmd_test_block_list, 0, NULL, "", "", NULL },
2289 { "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase, 0, NULL, "", "", NULL },
2290
2291
2292 { "vt_load_plugin", ventoy_cmd_load_plugin, 0, NULL, "", "", NULL },
2293 { "vt_check_plugin_json", ventoy_cmd_plugin_check_json, 0, NULL, "", "", NULL },
2294
2295 };
2296
2297
2298
2299 GRUB_MOD_INIT(ventoy)
2300 {
2301 grub_uint32_t i;
2302 cmd_para *cur = NULL;
2303
2304 ventoy_env_init();
2305
2306 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
2307 {
2308 cur = ventoy_cmds + i;
2309 cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags,
2310 cur->summary, cur->description, cur->parser);
2311 }
2312 }
2313
2314 GRUB_MOD_FINI(ventoy)
2315 {
2316 grub_uint32_t i;
2317
2318 for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
2319 {
2320 grub_unregister_extcmd(ventoy_cmds[i].cmd);
2321 }
2322 }
2323