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;
52 int g_filt_dot_underscore_file
= 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 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
626 for (i
= 0; i
< namelen
; i
++)
628 if (filename
[i
] == ' ' || filename
[i
] == '\t')
633 if ((grub_uint8_t
)(filename
[i
]) >= 127)
642 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
646 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
656 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
662 img_iterator_node
*tmp
;
663 img_iterator_node
*new_node
;
664 img_iterator_node
*node
= (img_iterator_node
*)data
;
666 len
= grub_strlen(filename
);
670 if ((len
== 1 && filename
[0] == '.') ||
671 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
676 if (!ventoy_img_name_valid(filename
, len
))
681 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
686 new_node
= grub_zalloc(sizeof(img_iterator_node
));
689 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
691 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
694 debug("Directory %s ignored...\n", new_node
->dir
);
699 new_node
->tail
= node
->tail
;
701 new_node
->parent
= node
;
702 if (!node
->firstchild
)
704 node
->firstchild
= new_node
;
707 if (g_img_iterator_tail
)
709 g_img_iterator_tail
->next
= new_node
;
710 g_img_iterator_tail
= new_node
;
714 g_img_iterator_head
.next
= new_node
;
715 g_img_iterator_tail
= new_node
;
721 debug("Find a file %s\n", filename
);
723 if ((len
> 4) && (0 == grub_strcasecmp(filename
+ len
- 4, ".iso")))
725 if (!ventoy_img_name_valid(filename
, len
))
730 img
= grub_zalloc(sizeof(img_info
));
733 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
734 grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, filename
);
736 if (g_ventoy_img_list
)
738 tail
= *(node
->tail
);
744 g_ventoy_img_list
= img
;
747 img
->size
= info
->size
;
748 img
->id
= g_ventoy_img_count
;
750 if (node
&& NULL
== node
->firstiso
)
752 node
->firstiso
= img
;
763 *((img_info
**)(node
->tail
)) = img
;
764 g_ventoy_img_count
++;
766 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
774 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
776 int len
= GRUB_UINT_MAX
;
777 const char *value
= NULL
;
780 char guidstr
[32] = {0};
781 ventoy_guid guid
= VENTOY_GUID
;
782 const char *fmt1
= NULL
;
783 const char *fmt2
= NULL
;
784 const char *fmt3
= NULL
;
785 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
786 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
787 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
788 const char fmtcode
[]={
789 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
790 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
791 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
792 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
793 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
794 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
797 grub_memset(name
, 0, sizeof(name
));
798 puint
[0] = grub_swap_bytes32(0x56454e54);
799 puint
[3] = grub_swap_bytes32(0x4f4e0000);
800 puint
[2] = grub_swap_bytes32(0x45525349);
801 puint
[1] = grub_swap_bytes32(0x4f595f56);
802 value
= ventoy_get_env(name
);
804 grub_memset(name
, 0, sizeof(name
));
805 puint
[1] = grub_swap_bytes32(0x5f544f50);
806 puint
[0] = grub_swap_bytes32(0x56544c45);
807 fmt1
= ventoy_get_env(name
);
813 grub_memset(name
, 0, sizeof(name
));
814 puint
[1] = grub_swap_bytes32(0x5f4c4654);
815 puint
[0] = grub_swap_bytes32(0x56544c45);
816 fmt2
= ventoy_get_env(name
);
818 grub_memset(name
, 0, sizeof(name
));
819 puint
[1] = grub_swap_bytes32(0x5f434c52);
820 puint
[0] = grub_swap_bytes32(0x56544c45);
821 fmt3
= ventoy_get_env(name
);
823 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
825 #if defined (GRUB_MACHINE_EFI)
826 puint2
[0] = grub_swap_bytes32(0x55454649);
828 puint2
[0] = grub_swap_bytes32(0x42494f53);
831 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
832 #pragma GCC diagnostic push
833 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
834 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
835 fmt1
? fmt1
: fmtdata
,
836 fmt2
? fmt2
: fmtdata
+ 4,
837 value
? value
: "", plat
, guidstr
,
838 fmt3
? fmt3
: fmtdata
+ 6);
839 #pragma GCC diagnostic pop
841 grub_memset(name
, 0, sizeof(name
));
842 puint
[0] = grub_swap_bytes32(0x76746f79);
843 puint
[2] = grub_swap_bytes32(0x656e7365);
844 puint
[1] = grub_swap_bytes32(0x5f6c6963);
845 ventoy_set_env(name
, guidstr
);
850 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
852 img_info
*minimg
= NULL
;
853 img_info
*img
= (img_info
*)(node
->firstiso
);
855 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
857 if (img
->select
== 0 && (NULL
== minimg
|| grub_strcmp(img
->name
, minimg
->name
) < 0))
872 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
874 img_iterator_node
*Minchild
= NULL
;
875 img_iterator_node
*child
= node
->firstchild
;
877 while (child
&& child
->parent
== node
)
879 if (child
->select
== 0 && (NULL
== Minchild
|| grub_strcmp(child
->dir
, Minchild
->dir
) < 0))
888 Minchild
->select
= 1;
894 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
898 img_iterator_node
*child
= NULL
;
900 if (node
->isocnt
== 0 || node
->done
== 1)
905 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
907 offset
= node
->parent
->dirlen
;
910 if (node
!= &g_img_iterator_head
)
912 node
->dir
[node
->dirlen
- 1] = 0;
913 g_tree_script_pos
+= grub_snprintf(g_tree_script_buf
+ g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_tree_script_pos
,
914 "submenu \"%-10s [%s]\" {\n", "DIR", node
->dir
+ offset
);
917 while ((child
= ventoy_get_min_child(node
)) != NULL
)
919 ventoy_dynamic_tree_menu(child
);
922 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
924 g_tree_script_pos
+= grub_snprintf(g_tree_script_buf
+ g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_tree_script_pos
,
925 "menuentry \"%-10s %s\" --id=\"VID_%d\" {\n"
926 " common_menuentry \n"
928 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
), img
->name
, img
->id
);
931 if (node
!= &g_img_iterator_head
)
933 g_tree_script_pos
+= grub_snprintf(g_tree_script_buf
+ g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_tree_script_pos
, "}\n");
940 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
943 grub_device_t dev
= NULL
;
944 img_info
*cur
= NULL
;
945 img_info
*tail
= NULL
;
946 const char *strdata
= NULL
;
947 char *device_name
= NULL
;
949 img_iterator_node
*node
= NULL
;
950 img_iterator_node
*tmp
= NULL
;
956 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
959 if (g_ventoy_img_list
|| g_ventoy_img_count
)
961 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
964 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
965 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
967 g_filt_dot_underscore_file
= 1;
970 device_name
= grub_file_get_device_name(args
[0]);
976 g_enum_dev
= dev
= grub_device_open(device_name
);
982 g_enum_fs
= fs
= grub_fs_probe(dev
);
988 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
990 debug("unsupported fs:<%s>\n", fs
->name
);
994 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
996 g_img_iterator_head
.dirlen
= 1;
997 g_img_iterator_head
.tail
= &tail
;
998 grub_strcpy(g_img_iterator_head
.dir
, "/");
1000 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1002 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1005 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1007 ventoy_dynamic_tree_menu(node
);
1011 node
= g_img_iterator_head
.next
;
1019 /* sort image list by image name */
1020 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1022 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1024 if (ventoy_cmp_img(cur
, tail
) > 0)
1026 ventoy_swap_img(cur
, tail
);
1031 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1033 g_list_script_pos
+= grub_snprintf(g_list_script_buf
+ g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_list_script_pos
,
1034 "menuentry \"%s\" --id=\"VID_%d\" {\n"
1035 " common_menuentry \n"
1037 cur
->name
, cur
->id
);
1039 g_list_script_buf
[g_list_script_pos
] = 0;
1041 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1042 grub_env_set(args
[1], buf
);
1046 check_free(device_name
, grub_free
);
1047 check_free(dev
, grub_device_close
);
1049 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1053 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1055 img_info
*next
= NULL
;
1056 img_info
*cur
= g_ventoy_img_list
;
1069 g_ventoy_img_list
= NULL
;
1070 g_ventoy_img_count
= 0;
1072 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1075 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1078 img_info
*cur
= g_ventoy_img_list
;
1082 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1084 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1087 img_id
= grub_strtol(args
[0], NULL
, 10);
1088 if (img_id
>= g_ventoy_img_count
)
1090 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
1093 debug("Find image %ld name \n", img_id
);
1095 while (cur
&& img_id
> 0)
1103 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
1106 debug("image name is %s\n", cur
->name
);
1108 grub_env_set(args
[1], cur
->name
);
1110 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1113 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1117 const char *id
= NULL
;
1118 img_info
*cur
= g_ventoy_img_list
;
1124 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
1127 id
= grub_env_get("chosen");
1129 pos
= grub_strstr(id
, "VID_");
1132 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
1136 img_id
= (int)grub_strtoul(id
, NULL
, 10);
1141 if (img_id
== cur
->id
)
1150 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
1153 grub_env_set(args
[0], cur
->path
);
1155 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1158 static int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
)
1165 device_name
= grub_file_get_device_name(filename
);
1177 pos2
= grub_strstr(pos
, ",");
1180 pos2
= grub_strstr(pos
, ")");
1188 disk
= grub_disk_open(pos
);
1191 grub_disk_read(disk
, 0, 0x180, 16, guid
);
1192 grub_disk_close(disk
);
1199 grub_free(device_name
);
1203 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
1205 eltorito_descriptor desc
;
1207 grub_memset(&desc
, 0, sizeof(desc
));
1208 grub_file_seek(file
, 17 * 2048);
1209 grub_file_read(file
, &desc
, sizeof(desc
));
1211 if (desc
.type
!= 0 || desc
.version
!= 1)
1216 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
1217 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
1225 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
1228 grub_uint8_t buf
[512];
1230 grub_file_seek(file
, sector
* 2048);
1231 grub_file_read(file
, buf
, sizeof(buf
));
1233 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
1235 debug("%s efi eltorito in Validation Entry\n", file
->name
);
1239 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
1241 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
1243 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1248 debug("%s does not contain efi eltorito\n", file
->name
);
1252 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
1256 grub_uint8_t chksum
= 0;
1259 disk
= file
->device
->disk
;
1260 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
1262 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
1263 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
1264 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
1266 pos
= grub_strstr(file
->name
, "/");
1272 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
1274 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
);
1276 param
->vtoy_img_size
= file
->size
;
1278 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
1279 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
1281 /* calculate checksum */
1282 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
1284 chksum
+= *((grub_uint8_t
*)param
+ i
);
1286 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
1291 static int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
1294 grub_uint32_t i
= 0;
1295 grub_uint32_t sector
= 0;
1296 grub_uint32_t count
= 0;
1297 grub_off_t size
= 0;
1298 grub_off_t read
= 0;
1300 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
1301 if (fs_type
== ventoy_fs_exfat
)
1303 grub_fat_get_file_chunk(start
, file
, chunklist
);
1307 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
1308 file
->read_hook_data
= chunklist
;
1310 for (size
= file
->size
; size
> 0; size
-= read
)
1312 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
1313 grub_file_read(file
, NULL
, read
);
1316 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
1318 chunklist
->chunk
[i
].disk_start_sector
+= start
;
1319 chunklist
->chunk
[i
].disk_end_sector
+= start
;
1322 if (ventoy_fs_udf
== fs_type
)
1324 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
1326 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
1327 chunklist
->chunk
[i
].img_start_sector
= sector
;
1328 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
1337 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1344 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1347 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
1350 if (g_img_chunk_list
.chunk
)
1352 grub_free(g_img_chunk_list
.chunk
);
1355 /* get image chunk data */
1356 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
1357 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1358 if (NULL
== g_img_chunk_list
.chunk
)
1360 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1363 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1364 g_img_chunk_list
.cur_chunk
= 0;
1366 ventoy_get_block_list(file
, &g_img_chunk_list
, file
->device
->disk
->partition
->start
);
1368 grub_file_close(file
);
1370 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
1372 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1375 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1378 ventoy_img_chunk
*cur
;
1384 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
1386 cur
= g_img_chunk_list
.chunk
+ i
;
1387 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
1388 cur
->img_start_sector
, cur
->img_end_sector
,
1389 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
1393 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1396 #ifdef GRUB_MACHINE_EFI
1397 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1405 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1408 ulong chain_len
= 0;
1409 char *chain_data
= NULL
;
1410 char *relocator_addr
= NULL
;
1411 grub_relocator_chunk_t ch
;
1412 struct grub_relocator
*relocator
= NULL
;
1413 char envbuf
[64] = { 0 };
1424 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
1425 chain_len
= grub_strtoul(args
[1], NULL
, 10);
1427 relocator
= grub_relocator_new ();
1430 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
1434 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
1435 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
1439 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
1440 grub_relocator_unload (relocator
);
1444 relocator_addr
= get_virtual_current_address(ch
);
1446 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
1448 grub_relocator_unload (relocator
);
1450 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
1451 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
1453 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1457 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1461 ventoy_img_chunk_list chunklist
;
1466 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1469 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
1472 /* get image chunk data */
1473 grub_memset(&chunklist
, 0, sizeof(chunklist
));
1474 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1475 if (NULL
== chunklist
.chunk
)
1477 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1480 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
1481 chunklist
.cur_chunk
= 0;
1483 ventoy_get_block_list(file
, &chunklist
, 0);
1485 grub_file_close(file
);
1487 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
1489 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
1491 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
1492 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
1495 grub_printf("\n==================================\n");
1496 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
1498 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
1499 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
1500 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
1501 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
1502 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
1506 grub_free(chunklist
.chunk
);
1508 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1511 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1514 ventoy_grub_param_file_replace
*replace
= NULL
;
1522 replace
= &(g_grub_param
->file_replace
);
1523 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
1525 replace
->old_name_cnt
= 0;
1526 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
1528 replace
->old_name_cnt
++;
1529 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
1532 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
1535 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1538 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1546 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
1547 grub_printf("%s", g_list_script_buf
);
1551 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
1552 grub_printf("%s", g_tree_script_buf
);
1558 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1564 ventoy_plugin_dump_auto_install();
1569 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1580 if (args
[0][0] == '0')
1582 return g_ventoy_memdisk_mode
? 0 : 1;
1584 else if (args
[0][0] == '1')
1586 return g_ventoy_iso_raw
? 0 : 1;
1588 else if (args
[0][0] == '2')
1590 return g_ventoy_iso_uefi_drv
? 0 : 1;
1596 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1598 static int configfile_mode
= 0;
1599 char memfile
[128] = {0};
1606 * args[0]: 0:normal 1:configfile
1607 * args[1]: 0:list_buf 1:tree_buf
1612 debug("Invalid argc %d\n", argc
);
1616 if (args
[0][0] == '0')
1618 if (args
[1][0] == '0')
1620 grub_script_execute_sourcecode(g_list_script_buf
);
1624 grub_script_execute_sourcecode(g_tree_script_buf
);
1629 if (configfile_mode
)
1631 debug("Now already in F3 mode %d\n", configfile_mode
);
1635 if (args
[1][0] == '0')
1637 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
1638 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
1642 g_ventoy_last_entry
= -1;
1643 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
1644 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
1647 configfile_mode
= 1;
1648 grub_script_execute_sourcecode(memfile
);
1649 configfile_mode
= 0;
1655 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1660 const char *isopath
= NULL
;
1662 ventoy_mbr_head mbr
;
1669 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
1672 isopath
= grub_env_get("iso_path");
1675 debug("isopath is null %p\n", isopath
);
1679 debug("isopath is %s\n", isopath
);
1681 for (id
= 0; id
< 30 && (find
== 0); id
++)
1683 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
1684 if (grub_strstr(isopath
, hdname
))
1686 debug("skip %s ...\n", hdname
);
1690 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
1692 disk
= grub_disk_open(hdname
);
1695 debug("%s not exist\n", hdname
);
1699 grub_memset(&mbr
, 0, sizeof(mbr
));
1700 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
1702 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
1704 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
1705 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
1708 grub_env_set(args
[0], hdname
);
1712 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
1716 debug("read %s failed\n", hdname
);
1719 grub_disk_close(disk
);
1725 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
1729 char fullpath
[256] = {0};
1732 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
1735 file
= grub_file_open(fullpath
, type
);
1738 debug("grub_file_open failed <%s>\n", fullpath
);
1745 int ventoy_is_file_exist(const char *fmt
, ...)
1750 char buf
[256] = {0};
1752 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
1756 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
1759 grub_strncpy(pos
+ len
, " ]", 2);
1761 debug("script exec %s\n", buf
);
1763 if (0 == grub_script_execute_sourcecode(buf
))
1771 static int ventoy_env_init(void)
1775 grub_env_set("vtdebug_flag", "");
1776 grub_env_export("vtdebug_flag");
1778 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
1779 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
1781 ventoy_filt_register(0, ventoy_wrapper_open
);
1783 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
1786 g_grub_param
->grub_env_get
= grub_env_get
;
1787 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
1788 grub_env_set("env_param", buf
);
1794 static cmd_para ventoy_cmds
[] =
1796 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
1797 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
1798 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
1799 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
1800 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
1801 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
1802 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
1803 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
1804 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
1805 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
1806 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
1807 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
1808 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
1809 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
1810 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
1811 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
1812 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
1813 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
1814 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
1816 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
1817 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
1818 { "vt_load_iso_to_mem", ventoy_cmd_load_iso_to_mem
, 0, NULL
, "", "", NULL
},
1820 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
1821 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
1822 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
1823 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
1824 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
1825 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
1826 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
1827 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
1828 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
1830 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
1831 { "vt_windows_locate_wim", ventoy_cmd_wimdows_locate_wim
, 0, NULL
, "", "", NULL
},
1832 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
1834 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
1835 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
1836 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
1839 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
1844 GRUB_MOD_INIT(ventoy
)
1847 cmd_para
*cur
= NULL
;
1851 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
1853 cur
= ventoy_cmds
+ i
;
1854 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
1855 cur
->summary
, cur
->description
, cur
->parser
);
1859 GRUB_MOD_FINI(ventoy
)
1863 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
1865 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);