1 /******************************************************************************
4 * Copyright (c) 2020, longpanda <admin@ventoy.net>
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.
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.
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/>.
21 #include <grub/types.h>
22 #include <grub/misc.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>
36 #ifdef GRUB_MACHINE_EFI
37 #include <grub/efi/efi.h>
39 #include <grub/time.h>
40 #include <grub/relocator.h>
41 #include <grub/ventoy.h>
42 #include "ventoy_def.h"
44 GRUB_MOD_LICENSE ("GPLv3+");
46 int g_ventoy_debug
= 0;
47 static int g_efi_os
= 0xFF;
48 initrd_info
*g_initrd_img_list
= NULL
;
49 initrd_info
*g_initrd_img_tail
= NULL
;
50 int g_initrd_img_count
= 0;
51 int g_valid_initrd_count
= 0;
53 static grub_file_t g_old_file
;
55 char g_img_swap_tmp_buf
[1024];
56 img_info g_img_swap_tmp
;
57 img_info
*g_ventoy_img_list
= NULL
;
58 int g_ventoy_img_count
= 0;
60 grub_device_t g_enum_dev
= NULL
;
61 grub_fs_t g_enum_fs
= NULL
;
62 img_iterator_node g_img_iterator_head
;
63 img_iterator_node
*g_img_iterator_tail
= NULL
;
65 grub_uint8_t g_ventoy_break_level
= 0;
66 grub_uint8_t g_ventoy_debug_level
= 0;
67 grub_uint8_t
*g_ventoy_cpio_buf
= NULL
;
68 grub_uint32_t g_ventoy_cpio_size
= 0;
69 cpio_newc_header
*g_ventoy_initrd_head
= NULL
;
70 grub_uint8_t
*g_ventoy_runtime_buf
= NULL
;
72 ventoy_grub_param
*g_grub_param
= NULL
;
74 ventoy_guid g_ventoy_guid
= VENTOY_GUID
;
76 ventoy_img_chunk_list g_img_chunk_list
;
78 static char *g_tree_script_buf
= NULL
;
79 static int g_tree_script_pos
= 0;
81 static char *g_list_script_buf
= NULL
;
82 static int g_list_script_pos
= 0;
85 void ventoy_debug(const char *fmt
, ...)
90 grub_vprintf (fmt
, args
);
94 int ventoy_is_efi_os(void)
98 g_efi_os
= (grub_strstr(GRUB_PLATFORM
, "efi")) ? 1 : 0;
104 static int ventoy_get_fs_type(const char *fs
)
108 return ventoy_fs_max
;
110 else if (grub_strncmp(fs
, "exfat", 5) == 0)
112 return ventoy_fs_exfat
;
114 else if (grub_strncmp(fs
, "ntfs", 4) == 0)
116 return ventoy_fs_ntfs
;
118 else if (grub_strncmp(fs
, "ext", 3) == 0)
120 return ventoy_fs_ext
;
122 else if (grub_strncmp(fs
, "xfs", 3) == 0)
124 return ventoy_fs_xfs
;
126 else if (grub_strncmp(fs
, "udf", 3) == 0)
128 return ventoy_fs_udf
;
131 return ventoy_fs_max
;
134 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
153 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
155 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
159 static grub_err_t
ventoy_fs_close(grub_file_t file
)
161 grub_file_close(g_old_file
);
162 grub_free(file
->data
);
170 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
174 static struct grub_fs vtoy_fs
=
179 .fs_read
= ventoy_fs_read
,
180 .fs_close
= ventoy_fs_close
,
190 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
196 file
->data
= grub_malloc(rawFile
->size
+ 4096);
202 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
203 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
205 g_old_file
= rawFile
;
207 file
->size
= rawFile
->size
+ len
;
208 file
->device
= rawFile
->device
;
210 file
->not_easily_seekable
= 1;
215 static int ventoy_check_decimal_var(const char *name
, long *value
)
217 const char *value_str
= NULL
;
219 value_str
= grub_env_get(name
);
220 if (NULL
== value_str
)
222 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
225 if (!ventoy_is_decimal(value_str
))
227 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
230 *value
= grub_strtol(value_str
, NULL
, 10);
232 return GRUB_ERR_NONE
;
235 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
239 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
242 if (0 == grub_strcmp(args
[0], "on"))
245 grub_env_set("vtdebug_flag", "debug");
250 grub_env_set("vtdebug_flag", "");
253 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
256 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
260 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
262 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
263 grub_printf(" level:\r\n");
264 grub_printf(" 01/11: busybox / (+cat log)\r\n");
265 grub_printf(" 02/12: initrd / (+cat log)\r\n");
266 grub_printf(" 03/13: hook / (+cat log)\r\n");
268 grub_printf(" debug:\r\n");
269 grub_printf(" 0: debug is on\r\n");
270 grub_printf(" 1: debug is off\r\n");
272 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
275 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
277 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
279 g_ventoy_debug_level
= 1;
282 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
285 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
290 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
292 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
295 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
300 value_long
+= grub_strtol(args
[1], NULL
, 10);
302 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
303 grub_env_set(args
[0], buf
);
305 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
308 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
323 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
326 debug("failed to open file <%s> for udf check\n", args
[0]);
330 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
332 grub_env_set(args
[1], buf
);
334 grub_file_close(file
);
340 static grub_err_t
ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
357 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
360 debug("failed to open file <%s> for udf check\n", args
[0]);
364 #ifdef GRUB_MACHINE_EFI
365 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
367 buf
= (char *)grub_malloc(file
->size
);
370 grub_file_read(file
, buf
, file
->size
);
372 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
373 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
374 grub_env_set(name
, value
);
376 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
377 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
378 grub_env_set(name
, value
);
380 grub_file_close(file
);
386 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
391 grub_uint8_t buf
[32];
402 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
405 debug("failed to open file <%s> for udf check\n", args
[0]);
409 for (i
= 16; i
< 32; i
++)
411 grub_file_seek(file
, i
* 2048);
412 grub_file_read(file
, buf
, sizeof(buf
));
420 grub_file_seek(file
, i
* 2048);
421 grub_file_read(file
, buf
, sizeof(buf
));
423 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
426 grub_file_seek(file
, i
* 2048);
427 grub_file_read(file
, buf
, sizeof(buf
));
429 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
430 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
436 grub_file_close(file
);
438 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
443 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
445 long value_long1
= 0;
446 long value_long2
= 0;
448 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
450 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
453 value_long1
= grub_strtol(args
[0], NULL
, 10);
454 value_long2
= grub_strtol(args
[2], NULL
, 10);
456 if (0 == grub_strcmp(args
[1], "eq"))
458 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
460 else if (0 == grub_strcmp(args
[1], "ne"))
462 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
464 else if (0 == grub_strcmp(args
[1], "gt"))
466 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
468 else if (0 == grub_strcmp(args
[1], "lt"))
470 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
472 else if (0 == grub_strcmp(args
[1], "ge"))
474 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
476 else if (0 == grub_strcmp(args
[1], "le"))
478 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
482 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
488 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
495 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
498 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
499 pos
= grub_strstr(buf
, ",");
505 grub_env_set(args
[1], buf
);
507 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
510 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
516 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
522 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
525 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
527 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
528 if (0 == grub_script_execute_sourcecode(buf
))
530 debug("file %s exist, ventoy_compatible YES\n", buf
);
531 grub_env_set("ventoy_compatible", "YES");
532 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
536 debug("file %s NOT exist\n", buf
);
540 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
541 pos
= grub_strstr(buf
, ")");
547 disk
= grub_disk_open(buf
);
550 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
551 grub_disk_close(disk
);
553 g_img_swap_tmp_buf
[703] = 0;
554 for (i
= 319; i
< 703; i
++)
556 if (g_img_swap_tmp_buf
[i
] == 'V' &&
557 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
559 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
560 grub_env_set("ventoy_compatible", "YES");
561 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
567 debug("failed to open disk <%s>\n", buf
);
570 grub_env_set("ventoy_compatible", "NO");
571 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
574 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
580 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
585 if (grub_islower(c1
))
590 if (grub_islower(c2
))
604 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
606 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
608 grub_memcpy(img1
, img2
, sizeof(img_info
));
609 img1
->next
= g_img_swap_tmp
.next
;
610 img1
->prev
= g_img_swap_tmp
.prev
;
612 g_img_swap_tmp
.next
= img2
->next
;
613 g_img_swap_tmp
.prev
= img2
->prev
;
614 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
617 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
621 for (i
= 0; i
< namelen
; i
++)
623 if (filename
[i
] == ' ' || filename
[i
] == '\t')
628 if ((grub_uint8_t
)(filename
[i
]) >= 127)
637 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
641 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
651 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
657 img_iterator_node
*tmp
;
658 img_iterator_node
*new_node
;
659 img_iterator_node
*node
= (img_iterator_node
*)data
;
661 len
= grub_strlen(filename
);
665 if ((len
== 1 && filename
[0] == '.') ||
666 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
671 if (!ventoy_img_name_valid(filename
, len
))
676 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
681 new_node
= grub_zalloc(sizeof(img_iterator_node
));
684 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
686 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
689 debug("Directory %s ignored...\n", new_node
->dir
);
694 new_node
->tail
= node
->tail
;
696 new_node
->parent
= node
;
697 if (!node
->firstchild
)
699 node
->firstchild
= new_node
;
702 if (g_img_iterator_tail
)
704 g_img_iterator_tail
->next
= new_node
;
705 g_img_iterator_tail
= new_node
;
709 g_img_iterator_head
.next
= new_node
;
710 g_img_iterator_tail
= new_node
;
716 debug("Find a file %s\n", filename
);
718 if ((len
> 4) && (0 == grub_strcasecmp(filename
+ len
- 4, ".iso")))
720 if (!ventoy_img_name_valid(filename
, len
))
725 img
= grub_zalloc(sizeof(img_info
));
728 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
729 grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, filename
);
731 if (g_ventoy_img_list
)
733 tail
= *(node
->tail
);
739 g_ventoy_img_list
= img
;
742 img
->size
= info
->size
;
743 img
->id
= g_ventoy_img_count
;
745 if (node
&& NULL
== node
->firstiso
)
747 node
->firstiso
= img
;
758 *((img_info
**)(node
->tail
)) = img
;
759 g_ventoy_img_count
++;
761 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
769 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
771 int len
= GRUB_UINT_MAX
;
772 const char *value
= NULL
;
775 char guidstr
[32] = {0};
776 ventoy_guid guid
= VENTOY_GUID
;
777 const char *fmt1
= NULL
;
778 const char *fmt2
= NULL
;
779 const char *fmt3
= NULL
;
780 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
781 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
782 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
783 const char fmtcode
[]={
784 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
785 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
786 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
787 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
788 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
789 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
792 grub_memset(name
, 0, sizeof(name
));
793 puint
[0] = grub_swap_bytes32(0x56454e54);
794 puint
[3] = grub_swap_bytes32(0x4f4e0000);
795 puint
[2] = grub_swap_bytes32(0x45525349);
796 puint
[1] = grub_swap_bytes32(0x4f595f56);
797 value
= ventoy_get_env(name
);
799 grub_memset(name
, 0, sizeof(name
));
800 puint
[1] = grub_swap_bytes32(0x5f544f50);
801 puint
[0] = grub_swap_bytes32(0x56544c45);
802 fmt1
= ventoy_get_env(name
);
808 grub_memset(name
, 0, sizeof(name
));
809 puint
[1] = grub_swap_bytes32(0x5f4c4654);
810 puint
[0] = grub_swap_bytes32(0x56544c45);
811 fmt2
= ventoy_get_env(name
);
813 grub_memset(name
, 0, sizeof(name
));
814 puint
[1] = grub_swap_bytes32(0x5f434c52);
815 puint
[0] = grub_swap_bytes32(0x56544c45);
816 fmt3
= ventoy_get_env(name
);
818 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
820 #if defined (GRUB_MACHINE_EFI)
821 puint2
[0] = grub_swap_bytes32(0x55454649);
823 puint2
[0] = grub_swap_bytes32(0x42494f53);
826 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
827 #pragma GCC diagnostic push
828 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
829 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
830 fmt1
? fmt1
: fmtdata
,
831 fmt2
? fmt2
: fmtdata
+ 4,
832 value
? value
: "", plat
, guidstr
,
833 fmt3
? fmt3
: fmtdata
+ 6);
834 #pragma GCC diagnostic pop
836 grub_memset(name
, 0, sizeof(name
));
837 puint
[0] = grub_swap_bytes32(0x76746f79);
838 puint
[2] = grub_swap_bytes32(0x656e7365);
839 puint
[1] = grub_swap_bytes32(0x5f6c6963);
840 ventoy_set_env(name
, guidstr
);
845 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
847 img_info
*minimg
= NULL
;
848 img_info
*img
= (img_info
*)(node
->firstiso
);
850 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
852 if (img
->select
== 0 && (NULL
== minimg
|| grub_strcmp(img
->name
, minimg
->name
) < 0))
867 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
869 img_iterator_node
*Minchild
= NULL
;
870 img_iterator_node
*child
= node
->firstchild
;
872 while (child
&& child
->parent
== node
)
874 if (child
->select
== 0 && (NULL
== Minchild
|| grub_strcmp(child
->dir
, Minchild
->dir
) < 0))
883 Minchild
->select
= 1;
889 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
893 img_iterator_node
*child
= NULL
;
895 if (node
->isocnt
== 0 || node
->done
== 1)
900 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
902 offset
= node
->parent
->dirlen
;
905 if (node
!= &g_img_iterator_head
)
907 node
->dir
[node
->dirlen
- 1] = 0;
908 g_tree_script_pos
+= grub_snprintf(g_tree_script_buf
+ g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_tree_script_pos
,
909 "submenu \"%-10s [%s]\" {\n", "DIR", node
->dir
+ offset
);
912 while ((child
= ventoy_get_min_child(node
)) != NULL
)
914 ventoy_dynamic_tree_menu(child
);
917 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
919 g_tree_script_pos
+= grub_snprintf(g_tree_script_buf
+ g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_tree_script_pos
,
920 "menuentry \"%-10s %s\" --id=\"VID_%d\" {\n"
921 " common_menuentry \n"
923 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
), img
->name
, img
->id
);
926 if (node
!= &g_img_iterator_head
)
928 g_tree_script_pos
+= grub_snprintf(g_tree_script_buf
+ g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_tree_script_pos
, "}\n");
935 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
938 grub_device_t dev
= NULL
;
939 img_info
*cur
= NULL
;
940 img_info
*tail
= NULL
;
941 char *device_name
= NULL
;
943 img_iterator_node
*node
= NULL
;
944 img_iterator_node
*tmp
= NULL
;
950 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
953 if (g_ventoy_img_list
|| g_ventoy_img_count
)
955 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
958 device_name
= grub_file_get_device_name(args
[0]);
964 g_enum_dev
= dev
= grub_device_open(device_name
);
970 g_enum_fs
= fs
= grub_fs_probe(dev
);
976 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
978 debug("unsupported fs:<%s>\n", fs
->name
);
982 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
984 g_img_iterator_head
.dirlen
= 1;
985 g_img_iterator_head
.tail
= &tail
;
986 grub_strcpy(g_img_iterator_head
.dir
, "/");
988 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
990 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
993 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
995 ventoy_dynamic_tree_menu(node
);
999 node
= g_img_iterator_head
.next
;
1007 /* sort image list by image name */
1008 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1010 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1012 if (ventoy_cmp_img(cur
, tail
) > 0)
1014 ventoy_swap_img(cur
, tail
);
1019 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1021 g_list_script_pos
+= grub_snprintf(g_list_script_buf
+ g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_list_script_pos
,
1022 "menuentry \"%s\" --id=\"VID_%d\" {\n"
1023 " common_menuentry \n"
1025 cur
->name
, cur
->id
);
1027 g_list_script_buf
[g_list_script_pos
] = 0;
1029 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1030 grub_env_set(args
[1], buf
);
1034 check_free(device_name
, grub_free
);
1035 check_free(dev
, grub_device_close
);
1037 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1041 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1043 img_info
*next
= NULL
;
1044 img_info
*cur
= g_ventoy_img_list
;
1057 g_ventoy_img_list
= NULL
;
1058 g_ventoy_img_count
= 0;
1060 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1063 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1066 img_info
*cur
= g_ventoy_img_list
;
1070 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1072 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1075 img_id
= grub_strtol(args
[0], NULL
, 10);
1076 if (img_id
>= g_ventoy_img_count
)
1078 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
1081 debug("Find image %ld name \n", img_id
);
1083 while (cur
&& img_id
> 0)
1091 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
1094 debug("image name is %s\n", cur
->name
);
1096 grub_env_set(args
[1], cur
->name
);
1098 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1101 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1105 const char *id
= NULL
;
1106 img_info
*cur
= g_ventoy_img_list
;
1112 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
1115 id
= grub_env_get("chosen");
1117 pos
= grub_strstr(id
, "VID_");
1120 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
1124 img_id
= (int)grub_strtoul(id
, NULL
, 10);
1129 if (img_id
== cur
->id
)
1138 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
1141 grub_env_set(args
[0], cur
->path
);
1143 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1146 static int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
)
1153 device_name
= grub_file_get_device_name(filename
);
1165 pos2
= grub_strstr(pos
, ",");
1168 pos2
= grub_strstr(pos
, ")");
1176 disk
= grub_disk_open(pos
);
1179 grub_disk_read(disk
, 0, 0x180, 16, guid
);
1180 grub_disk_close(disk
);
1187 grub_free(device_name
);
1191 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
1193 eltorito_descriptor desc
;
1195 grub_memset(&desc
, 0, sizeof(desc
));
1196 grub_file_seek(file
, 17 * 2048);
1197 grub_file_read(file
, &desc
, sizeof(desc
));
1199 if (desc
.type
!= 0 || desc
.version
!= 1)
1204 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
1205 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
1213 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
1216 grub_uint8_t buf
[512];
1218 grub_file_seek(file
, sector
* 2048);
1219 grub_file_read(file
, buf
, sizeof(buf
));
1221 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
1223 debug("%s efi eltorito in Validation Entry\n", file
->name
);
1227 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
1229 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
1231 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1236 debug("%s does not contain efi eltorito\n", file
->name
);
1240 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
1244 grub_uint8_t chksum
= 0;
1247 disk
= file
->device
->disk
;
1248 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
1250 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
1251 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
1252 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
1254 pos
= grub_strstr(file
->name
, "/");
1260 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
1262 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
);
1264 param
->vtoy_img_size
= file
->size
;
1266 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
1267 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
1269 /* calculate checksum */
1270 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
1272 chksum
+= *((grub_uint8_t
*)param
+ i
);
1274 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
1279 static int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
1282 grub_uint32_t i
= 0;
1283 grub_uint32_t sector
= 0;
1284 grub_uint32_t count
= 0;
1285 grub_off_t size
= 0;
1286 grub_off_t read
= 0;
1288 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
1289 if (fs_type
== ventoy_fs_exfat
)
1291 grub_fat_get_file_chunk(start
, file
, chunklist
);
1295 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
1296 file
->read_hook_data
= chunklist
;
1298 for (size
= file
->size
; size
> 0; size
-= read
)
1300 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
1301 grub_file_read(file
, NULL
, read
);
1304 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
1306 chunklist
->chunk
[i
].disk_start_sector
+= start
;
1307 chunklist
->chunk
[i
].disk_end_sector
+= start
;
1310 if (ventoy_fs_udf
== fs_type
)
1312 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
1314 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
1315 chunklist
->chunk
[i
].img_start_sector
= sector
;
1316 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
1325 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1332 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1335 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
1338 if (g_img_chunk_list
.chunk
)
1340 grub_free(g_img_chunk_list
.chunk
);
1343 /* get image chunk data */
1344 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
1345 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1346 if (NULL
== g_img_chunk_list
.chunk
)
1348 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1351 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1352 g_img_chunk_list
.cur_chunk
= 0;
1354 ventoy_get_block_list(file
, &g_img_chunk_list
, file
->device
->disk
->partition
->start
);
1356 grub_file_close(file
);
1358 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
1360 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1363 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1366 ventoy_img_chunk
*cur
;
1372 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
1374 cur
= g_img_chunk_list
.chunk
+ i
;
1375 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
1376 cur
->img_start_sector
, cur
->img_end_sector
,
1377 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
1381 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1384 #ifdef GRUB_MACHINE_EFI
1385 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1393 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1396 ulong chain_len
= 0;
1397 char *chain_data
= NULL
;
1398 char *relocator_addr
= NULL
;
1399 grub_relocator_chunk_t ch
;
1400 struct grub_relocator
*relocator
= NULL
;
1401 char envbuf
[64] = { 0 };
1412 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
1413 chain_len
= grub_strtoul(args
[1], NULL
, 10);
1415 relocator
= grub_relocator_new ();
1418 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
1422 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
1423 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
1427 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
1428 grub_relocator_unload (relocator
);
1432 relocator_addr
= get_virtual_current_address(ch
);
1434 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
1436 grub_relocator_unload (relocator
);
1438 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
1439 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
1441 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1445 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1449 ventoy_img_chunk_list chunklist
;
1454 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1457 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
1460 /* get image chunk data */
1461 grub_memset(&chunklist
, 0, sizeof(chunklist
));
1462 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1463 if (NULL
== chunklist
.chunk
)
1465 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1468 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
1469 chunklist
.cur_chunk
= 0;
1471 ventoy_get_block_list(file
, &chunklist
, 0);
1473 grub_file_close(file
);
1475 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
1477 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
1479 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
1480 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
1483 grub_printf("\n==================================\n");
1484 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
1486 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
1487 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
1488 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
1489 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
1490 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
1494 grub_free(chunklist
.chunk
);
1496 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1499 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1502 ventoy_grub_param_file_replace
*replace
= NULL
;
1510 replace
= &(g_grub_param
->file_replace
);
1511 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
1513 replace
->old_name_cnt
= 0;
1514 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
1516 replace
->old_name_cnt
++;
1517 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
1520 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
1523 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1526 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1534 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
1535 grub_printf("%s", g_list_script_buf
);
1539 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
1540 grub_printf("%s", g_tree_script_buf
);
1546 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1552 ventoy_plugin_dump_auto_install();
1557 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1568 if (args
[0][0] == '0')
1570 return g_ventoy_memdisk_mode
? 0 : 1;
1572 else if (args
[0][0] == '1')
1574 return g_ventoy_iso_raw
? 0 : 1;
1576 else if (args
[0][0] == '2')
1578 return g_ventoy_iso_uefi_drv
? 0 : 1;
1584 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1586 static int configfile_mode
= 0;
1587 char memfile
[128] = {0};
1594 * args[0]: 0:normal 1:configfile
1595 * args[1]: 0:list_buf 1:tree_buf
1600 debug("Invalid argc %d\n", argc
);
1604 if (args
[0][0] == '0')
1606 if (args
[1][0] == '0')
1608 grub_script_execute_sourcecode(g_list_script_buf
);
1612 grub_script_execute_sourcecode(g_tree_script_buf
);
1617 if (configfile_mode
)
1619 debug("Now already in F3 mode %d\n", configfile_mode
);
1623 if (args
[1][0] == '0')
1625 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
1626 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
1630 g_ventoy_last_entry
= -1;
1631 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
1632 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
1635 configfile_mode
= 1;
1636 grub_script_execute_sourcecode(memfile
);
1637 configfile_mode
= 0;
1643 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1648 const char *isopath
= NULL
;
1650 ventoy_mbr_head mbr
;
1657 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
1660 isopath
= grub_env_get("iso_path");
1663 debug("isopath is null %p\n", isopath
);
1667 debug("isopath is %s\n", isopath
);
1669 for (id
= 0; id
< 30 && (find
== 0); id
++)
1671 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
1672 if (grub_strstr(isopath
, hdname
))
1674 debug("skip %s ...\n", hdname
);
1678 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
1680 disk
= grub_disk_open(hdname
);
1683 debug("%s not exist\n", hdname
);
1687 grub_memset(&mbr
, 0, sizeof(mbr
));
1688 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
1690 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
1692 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
1693 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
1696 grub_env_set(args
[0], hdname
);
1700 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
1704 debug("read %s failed\n", hdname
);
1707 grub_disk_close(disk
);
1713 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
1717 char fullpath
[256] = {0};
1720 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
1723 file
= grub_file_open(fullpath
, type
);
1726 debug("grub_file_open failed <%s>\n", fullpath
);
1733 int ventoy_is_file_exist(const char *fmt
, ...)
1738 char buf
[256] = {0};
1740 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
1744 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
1747 grub_strncpy(pos
+ len
, " ]", 2);
1749 debug("script exec %s\n", buf
);
1751 if (0 == grub_script_execute_sourcecode(buf
))
1759 static int ventoy_env_init(void)
1763 grub_env_set("vtdebug_flag", "");
1764 grub_env_export("vtdebug_flag");
1766 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
1767 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
1769 ventoy_filt_register(0, ventoy_wrapper_open
);
1771 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
1774 g_grub_param
->grub_env_get
= grub_env_get
;
1775 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
1776 grub_env_set("env_param", buf
);
1782 static cmd_para ventoy_cmds
[] =
1784 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
1785 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
1786 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
1787 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
1788 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
1789 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
1790 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
1791 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
1792 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
1793 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
1794 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
1795 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
1796 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
1797 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
1798 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
1799 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
1800 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
1801 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
1802 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
1804 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
1805 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
1806 { "vt_load_iso_to_mem", ventoy_cmd_load_iso_to_mem
, 0, NULL
, "", "", NULL
},
1808 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
1809 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
1810 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
1811 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
1812 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
1813 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
1814 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
1815 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
1816 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
1818 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
1819 { "vt_windows_locate_wim", ventoy_cmd_wimdows_locate_wim
, 0, NULL
, "", "", NULL
},
1820 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
1822 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
1823 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
1824 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
1827 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
1832 GRUB_MOD_INIT(ventoy
)
1835 cmd_para
*cur
= NULL
;
1839 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
1841 cur
= ventoy_cmds
+ i
;
1842 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
1843 cur
->summary
, cur
->description
, cur
->parser
);
1847 GRUB_MOD_FINI(ventoy
)
1851 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
1853 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);