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
;
130 else if (grub_strncmp(fs
, "fat", 3) == 0)
132 return ventoy_fs_fat
;
135 return ventoy_fs_max
;
138 static int ventoy_string_check(const char *str
, grub_char_check_func check
)
157 static grub_ssize_t
ventoy_fs_read(grub_file_t file
, char *buf
, grub_size_t len
)
159 grub_memcpy(buf
, (char *)file
->data
+ file
->offset
, len
);
163 static grub_err_t
ventoy_fs_close(grub_file_t file
)
165 grub_file_close(g_old_file
);
166 grub_free(file
->data
);
174 static grub_file_t
ventoy_wrapper_open(grub_file_t rawFile
, enum grub_file_type type
)
178 static struct grub_fs vtoy_fs
=
183 .fs_read
= ventoy_fs_read
,
184 .fs_close
= ventoy_fs_close
,
194 file
= (grub_file_t
)grub_zalloc(sizeof (*file
));
200 file
->data
= grub_malloc(rawFile
->size
+ 4096);
206 grub_file_read(rawFile
, file
->data
, rawFile
->size
);
207 len
= ventoy_fill_data(4096, (char *)file
->data
+ rawFile
->size
);
209 g_old_file
= rawFile
;
211 file
->size
= rawFile
->size
+ len
;
212 file
->device
= rawFile
->device
;
214 file
->not_easily_seekable
= 1;
219 static int ventoy_check_decimal_var(const char *name
, long *value
)
221 const char *value_str
= NULL
;
223 value_str
= grub_env_get(name
);
224 if (NULL
== value_str
)
226 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s not found", name
);
229 if (!ventoy_is_decimal(value_str
))
231 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Variable %s value '%s' is not an integer", name
, value_str
);
234 *value
= grub_strtol(value_str
, NULL
, 10);
236 return GRUB_ERR_NONE
;
239 static grub_err_t
ventoy_cmd_debug(grub_extcmd_context_t ctxt
, int argc
, char **args
)
243 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {on|off}", cmd_raw_name
);
246 if (0 == grub_strcmp(args
[0], "on"))
249 grub_env_set("vtdebug_flag", "debug");
254 grub_env_set("vtdebug_flag", "");
257 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
260 static grub_err_t
ventoy_cmd_break(grub_extcmd_context_t ctxt
, int argc
, char **args
)
264 if (argc
< 1 || (args
[0][0] != '0' && args
[0][0] != '1'))
266 grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name
);
267 grub_printf(" level:\r\n");
268 grub_printf(" 01/11: busybox / (+cat log)\r\n");
269 grub_printf(" 02/12: initrd / (+cat log)\r\n");
270 grub_printf(" 03/13: hook / (+cat log)\r\n");
272 grub_printf(" debug:\r\n");
273 grub_printf(" 0: debug is on\r\n");
274 grub_printf(" 1: debug is off\r\n");
276 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
279 g_ventoy_break_level
= (grub_uint8_t
)grub_strtoul(args
[0], NULL
, 16);
281 if (argc
> 1 && grub_strtoul(args
[1], NULL
, 10) > 0)
283 g_ventoy_debug_level
= 1;
286 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
289 static grub_err_t
ventoy_cmd_incr(grub_extcmd_context_t ctxt
, int argc
, char **args
)
294 if ((argc
!= 2) || (!ventoy_is_decimal(args
[1])))
296 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Variable} {Int}", cmd_raw_name
);
299 if (GRUB_ERR_NONE
!= ventoy_check_decimal_var(args
[0], &value_long
))
304 value_long
+= grub_strtol(args
[1], NULL
, 10);
306 grub_snprintf(buf
, sizeof(buf
), "%ld", value_long
);
307 grub_env_set(args
[0], buf
);
309 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
312 static grub_err_t
ventoy_cmd_file_size(grub_extcmd_context_t ctxt
, int argc
, char **args
)
327 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
330 debug("failed to open file <%s> for udf check\n", args
[0]);
334 grub_snprintf(buf
, sizeof(buf
), "%llu", (unsigned long long)file
->size
);
336 grub_env_set(args
[1], buf
);
338 grub_file_close(file
);
344 static grub_err_t
ventoy_cmd_load_iso_to_mem(grub_extcmd_context_t ctxt
, int argc
, char **args
)
361 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
364 debug("failed to open file <%s> for udf check\n", args
[0]);
368 #ifdef GRUB_MACHINE_EFI
369 buf
= (char *)grub_efi_allocate_iso_buf(file
->size
);
371 buf
= (char *)grub_malloc(file
->size
);
374 grub_file_read(file
, buf
, file
->size
);
376 grub_snprintf(name
, sizeof(name
), "%s_addr", args
[1]);
377 grub_snprintf(value
, sizeof(value
), "0x%llx", (unsigned long long)(unsigned long)buf
);
378 grub_env_set(name
, value
);
380 grub_snprintf(name
, sizeof(name
), "%s_size", args
[1]);
381 grub_snprintf(value
, sizeof(value
), "%llu", (unsigned long long)file
->size
);
382 grub_env_set(name
, value
);
384 grub_file_close(file
);
390 static grub_err_t
ventoy_cmd_is_udf(grub_extcmd_context_t ctxt
, int argc
, char **args
)
395 grub_uint8_t buf
[32];
406 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
409 debug("failed to open file <%s> for udf check\n", args
[0]);
413 for (i
= 16; i
< 32; i
++)
415 grub_file_seek(file
, i
* 2048);
416 grub_file_read(file
, buf
, sizeof(buf
));
424 grub_file_seek(file
, i
* 2048);
425 grub_file_read(file
, buf
, sizeof(buf
));
427 if (grub_memcmp(buf
+ 1, "BEA01", 5) == 0)
430 grub_file_seek(file
, i
* 2048);
431 grub_file_read(file
, buf
, sizeof(buf
));
433 if (grub_memcmp(buf
+ 1, "NSR02", 5) == 0 ||
434 grub_memcmp(buf
+ 1, "NSR03", 5) == 0)
440 grub_file_close(file
);
442 debug("ISO UDF: %s\n", rc
? "NO" : "YES");
447 static grub_err_t
ventoy_cmd_cmp(grub_extcmd_context_t ctxt
, int argc
, char **args
)
449 long value_long1
= 0;
450 long value_long2
= 0;
452 if ((argc
!= 3) || (!ventoy_is_decimal(args
[0])) || (!ventoy_is_decimal(args
[2])))
454 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name
);
457 value_long1
= grub_strtol(args
[0], NULL
, 10);
458 value_long2
= grub_strtol(args
[2], NULL
, 10);
460 if (0 == grub_strcmp(args
[1], "eq"))
462 grub_errno
= (value_long1
== value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
464 else if (0 == grub_strcmp(args
[1], "ne"))
466 grub_errno
= (value_long1
!= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
468 else if (0 == grub_strcmp(args
[1], "gt"))
470 grub_errno
= (value_long1
> value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
472 else if (0 == grub_strcmp(args
[1], "lt"))
474 grub_errno
= (value_long1
< value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
476 else if (0 == grub_strcmp(args
[1], "ge"))
478 grub_errno
= (value_long1
>= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
480 else if (0 == grub_strcmp(args
[1], "le"))
482 grub_errno
= (value_long1
<= value_long2
) ? GRUB_ERR_NONE
: GRUB_ERR_TEST_FAILURE
;
486 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name
);
492 static grub_err_t
ventoy_cmd_device(grub_extcmd_context_t ctxt
, int argc
, char **args
)
499 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s path var", cmd_raw_name
);
502 grub_strncpy(buf
, (args
[0][0] == '(') ? args
[0] + 1 : args
[0], sizeof(buf
) - 1);
503 pos
= grub_strstr(buf
, ",");
509 grub_env_set(args
[1], buf
);
511 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
514 static grub_err_t
ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt
, int argc
, char **args
)
520 const char *files
[] = { "ventoy.dat", "VENTOY.DAT" };
526 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s (loop)", cmd_raw_name
);
529 for (i
= 0; i
< (int)ARRAY_SIZE(files
); i
++)
531 grub_snprintf(buf
, sizeof(buf
) - 1, "[ -e %s/%s ]", args
[0], files
[i
]);
532 if (0 == grub_script_execute_sourcecode(buf
))
534 debug("file %s exist, ventoy_compatible YES\n", buf
);
535 grub_env_set("ventoy_compatible", "YES");
536 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
540 debug("file %s NOT exist\n", buf
);
544 grub_snprintf(buf
, sizeof(buf
) - 1, "%s", args
[0][0] == '(' ? (args
[0] + 1) : args
[0]);
545 pos
= grub_strstr(buf
, ")");
551 disk
= grub_disk_open(buf
);
554 grub_disk_read(disk
, 16 << 2, 0, 1024, g_img_swap_tmp_buf
);
555 grub_disk_close(disk
);
557 g_img_swap_tmp_buf
[703] = 0;
558 for (i
= 319; i
< 703; i
++)
560 if (g_img_swap_tmp_buf
[i
] == 'V' &&
561 0 == grub_strncmp(g_img_swap_tmp_buf
+ i
, VENTOY_COMPATIBLE_STR
, VENTOY_COMPATIBLE_STR_LEN
))
563 debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i
);
564 grub_env_set("ventoy_compatible", "YES");
565 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
571 debug("failed to open disk <%s>\n", buf
);
574 grub_env_set("ventoy_compatible", "NO");
575 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
578 int ventoy_cmp_img(img_info
*img1
, img_info
*img2
)
584 for (s1
= img1
->name
, s2
= img2
->name
; *s1
&& *s2
; s1
++, s2
++)
589 if (grub_islower(c1
))
594 if (grub_islower(c2
))
608 void ventoy_swap_img(img_info
*img1
, img_info
*img2
)
610 grub_memcpy(&g_img_swap_tmp
, img1
, sizeof(img_info
));
612 grub_memcpy(img1
, img2
, sizeof(img_info
));
613 img1
->next
= g_img_swap_tmp
.next
;
614 img1
->prev
= g_img_swap_tmp
.prev
;
616 g_img_swap_tmp
.next
= img2
->next
;
617 g_img_swap_tmp
.prev
= img2
->prev
;
618 grub_memcpy(img2
, &g_img_swap_tmp
, sizeof(img_info
));
621 static int ventoy_img_name_valid(const char *filename
, grub_size_t namelen
)
625 if (g_filt_dot_underscore_file
&& filename
[0] == '.' && filename
[1] == '_')
630 for (i
= 0; i
< namelen
; i
++)
632 if (filename
[i
] == ' ' || filename
[i
] == '\t')
637 if ((grub_uint8_t
)(filename
[i
]) >= 127)
646 static int ventoy_check_ignore_flag(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
650 if (filename
&& filename
[0] == '.' && 0 == grub_strncmp(filename
, ".ventoyignore", 13))
660 static int ventoy_colect_img_files(const char *filename
, const struct grub_dirhook_info
*info
, void *data
)
666 img_iterator_node
*tmp
;
667 img_iterator_node
*new_node
;
668 img_iterator_node
*node
= (img_iterator_node
*)data
;
670 len
= grub_strlen(filename
);
674 if ((len
== 1 && filename
[0] == '.') ||
675 (len
== 2 && filename
[0] == '.' && filename
[1] == '.'))
680 if (!ventoy_img_name_valid(filename
, len
))
685 if (filename
[0] == '$' && 0 == grub_strncmp(filename
, "$RECYCLE.BIN", 12))
690 new_node
= grub_zalloc(sizeof(img_iterator_node
));
693 new_node
->dirlen
= grub_snprintf(new_node
->dir
, sizeof(new_node
->dir
), "%s%s/", node
->dir
, filename
);
695 g_enum_fs
->fs_dir(g_enum_dev
, new_node
->dir
, ventoy_check_ignore_flag
, &ignore
);
698 debug("Directory %s ignored...\n", new_node
->dir
);
703 new_node
->tail
= node
->tail
;
705 new_node
->parent
= node
;
706 if (!node
->firstchild
)
708 node
->firstchild
= new_node
;
711 if (g_img_iterator_tail
)
713 g_img_iterator_tail
->next
= new_node
;
714 g_img_iterator_tail
= new_node
;
718 g_img_iterator_head
.next
= new_node
;
719 g_img_iterator_tail
= new_node
;
725 debug("Find a file %s\n", filename
);
727 if ((len
> 4) && (0 == grub_strcasecmp(filename
+ len
- 4, ".iso")))
729 if (!ventoy_img_name_valid(filename
, len
))
734 img
= grub_zalloc(sizeof(img_info
));
737 grub_snprintf(img
->name
, sizeof(img
->name
), "%s", filename
);
738 grub_snprintf(img
->path
, sizeof(img
->path
), "%s%s", node
->dir
, filename
);
740 if (g_ventoy_img_list
)
742 tail
= *(node
->tail
);
748 g_ventoy_img_list
= img
;
751 img
->size
= info
->size
;
752 img
->id
= g_ventoy_img_count
;
754 if (node
&& NULL
== node
->firstiso
)
756 node
->firstiso
= img
;
767 *((img_info
**)(node
->tail
)) = img
;
768 g_ventoy_img_count
++;
770 debug("Add %s%s to list %d\n", node
->dir
, filename
, g_ventoy_img_count
);
778 int ventoy_fill_data(grub_uint32_t buflen
, char *buffer
)
780 int len
= GRUB_UINT_MAX
;
781 const char *value
= NULL
;
784 char guidstr
[32] = {0};
785 ventoy_guid guid
= VENTOY_GUID
;
786 const char *fmt1
= NULL
;
787 const char *fmt2
= NULL
;
788 const char *fmt3
= NULL
;
789 grub_uint32_t
*puint
= (grub_uint32_t
*)name
;
790 grub_uint32_t
*puint2
= (grub_uint32_t
*)plat
;
791 const char fmtdata
[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
792 const char fmtcode
[]={
793 0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
794 0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
795 0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
796 0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
797 0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
798 0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
801 grub_memset(name
, 0, sizeof(name
));
802 puint
[0] = grub_swap_bytes32(0x56454e54);
803 puint
[3] = grub_swap_bytes32(0x4f4e0000);
804 puint
[2] = grub_swap_bytes32(0x45525349);
805 puint
[1] = grub_swap_bytes32(0x4f595f56);
806 value
= ventoy_get_env(name
);
808 grub_memset(name
, 0, sizeof(name
));
809 puint
[1] = grub_swap_bytes32(0x5f544f50);
810 puint
[0] = grub_swap_bytes32(0x56544c45);
811 fmt1
= ventoy_get_env(name
);
817 grub_memset(name
, 0, sizeof(name
));
818 puint
[1] = grub_swap_bytes32(0x5f4c4654);
819 puint
[0] = grub_swap_bytes32(0x56544c45);
820 fmt2
= ventoy_get_env(name
);
822 grub_memset(name
, 0, sizeof(name
));
823 puint
[1] = grub_swap_bytes32(0x5f434c52);
824 puint
[0] = grub_swap_bytes32(0x56544c45);
825 fmt3
= ventoy_get_env(name
);
827 grub_memcpy(guidstr
, &guid
, sizeof(guid
));
829 #if defined (GRUB_MACHINE_EFI)
830 puint2
[0] = grub_swap_bytes32(0x55454649);
832 puint2
[0] = grub_swap_bytes32(0x42494f53);
835 /* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
836 #pragma GCC diagnostic push
837 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
838 len
= grub_snprintf(buffer
, buflen
, fmtcode
,
839 fmt1
? fmt1
: fmtdata
,
840 fmt2
? fmt2
: fmtdata
+ 4,
841 value
? value
: "", plat
, guidstr
,
842 fmt3
? fmt3
: fmtdata
+ 6);
843 #pragma GCC diagnostic pop
845 grub_memset(name
, 0, sizeof(name
));
846 puint
[0] = grub_swap_bytes32(0x76746f79);
847 puint
[2] = grub_swap_bytes32(0x656e7365);
848 puint
[1] = grub_swap_bytes32(0x5f6c6963);
849 ventoy_set_env(name
, guidstr
);
854 static img_info
* ventoy_get_min_iso(img_iterator_node
*node
)
856 img_info
*minimg
= NULL
;
857 img_info
*img
= (img_info
*)(node
->firstiso
);
859 while (img
&& (img_iterator_node
*)(img
->parent
) == node
)
861 if (img
->select
== 0 && (NULL
== minimg
|| grub_strcmp(img
->name
, minimg
->name
) < 0))
876 static img_iterator_node
* ventoy_get_min_child(img_iterator_node
*node
)
878 img_iterator_node
*Minchild
= NULL
;
879 img_iterator_node
*child
= node
->firstchild
;
881 while (child
&& child
->parent
== node
)
883 if (child
->select
== 0 && (NULL
== Minchild
|| grub_strcmp(child
->dir
, Minchild
->dir
) < 0))
892 Minchild
->select
= 1;
898 static int ventoy_dynamic_tree_menu(img_iterator_node
*node
)
902 img_iterator_node
*child
= NULL
;
904 if (node
->isocnt
== 0 || node
->done
== 1)
909 if (node
->parent
&& node
->parent
->dirlen
< node
->dirlen
)
911 offset
= node
->parent
->dirlen
;
914 if (node
!= &g_img_iterator_head
)
916 node
->dir
[node
->dirlen
- 1] = 0;
917 g_tree_script_pos
+= grub_snprintf(g_tree_script_buf
+ g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_tree_script_pos
,
918 "submenu \"%-10s [%s]\" {\n", "DIR", node
->dir
+ offset
);
921 while ((child
= ventoy_get_min_child(node
)) != NULL
)
923 ventoy_dynamic_tree_menu(child
);
926 while ((img
= ventoy_get_min_iso(node
)) != NULL
)
928 g_tree_script_pos
+= grub_snprintf(g_tree_script_buf
+ g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_tree_script_pos
,
929 "menuentry \"%-10s %s\" --id=\"VID_%d\" {\n"
930 " common_menuentry \n"
932 grub_get_human_size(img
->size
, GRUB_HUMAN_SIZE_SHORT
), img
->name
, img
->id
);
935 if (node
!= &g_img_iterator_head
)
937 g_tree_script_pos
+= grub_snprintf(g_tree_script_buf
+ g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_tree_script_pos
, "}\n");
944 static grub_err_t
ventoy_cmd_list_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
947 grub_device_t dev
= NULL
;
948 img_info
*cur
= NULL
;
949 img_info
*tail
= NULL
;
950 const char *strdata
= NULL
;
951 char *device_name
= NULL
;
953 img_iterator_node
*node
= NULL
;
954 img_iterator_node
*tmp
= NULL
;
960 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {device} {cntvar}", cmd_raw_name
);
963 if (g_ventoy_img_list
|| g_ventoy_img_count
)
965 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Must clear image before list");
968 strdata
= ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
969 if (strdata
&& strdata
[0] == '1' && strdata
[1] == 0)
971 g_filt_dot_underscore_file
= 1;
974 device_name
= grub_file_get_device_name(args
[0]);
980 g_enum_dev
= dev
= grub_device_open(device_name
);
986 g_enum_fs
= fs
= grub_fs_probe(dev
);
992 if (ventoy_get_fs_type(fs
->name
) >= ventoy_fs_max
)
994 debug("unsupported fs:<%s>\n", fs
->name
);
998 grub_memset(&g_img_iterator_head
, 0, sizeof(g_img_iterator_head
));
1000 g_img_iterator_head
.dirlen
= 1;
1001 g_img_iterator_head
.tail
= &tail
;
1002 grub_strcpy(g_img_iterator_head
.dir
, "/");
1004 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1006 fs
->fs_dir(dev
, node
->dir
, ventoy_colect_img_files
, node
);
1009 for (node
= &g_img_iterator_head
; node
; node
= node
->next
)
1011 ventoy_dynamic_tree_menu(node
);
1015 node
= g_img_iterator_head
.next
;
1023 /* sort image list by image name */
1024 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1026 for (tail
= cur
->next
; tail
; tail
= tail
->next
)
1028 if (ventoy_cmp_img(cur
, tail
) > 0)
1030 ventoy_swap_img(cur
, tail
);
1035 for (cur
= g_ventoy_img_list
; cur
; cur
= cur
->next
)
1037 g_list_script_pos
+= grub_snprintf(g_list_script_buf
+ g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
- g_list_script_pos
,
1038 "menuentry \"%s\" --id=\"VID_%d\" {\n"
1039 " common_menuentry \n"
1041 cur
->name
, cur
->id
);
1043 g_list_script_buf
[g_list_script_pos
] = 0;
1045 grub_snprintf(buf
, sizeof(buf
), "%d", g_ventoy_img_count
);
1046 grub_env_set(args
[1], buf
);
1050 check_free(device_name
, grub_free
);
1051 check_free(dev
, grub_device_close
);
1053 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1057 static grub_err_t
ventoy_cmd_clear_img(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1059 img_info
*next
= NULL
;
1060 img_info
*cur
= g_ventoy_img_list
;
1073 g_ventoy_img_list
= NULL
;
1074 g_ventoy_img_count
= 0;
1076 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1079 static grub_err_t
ventoy_cmd_img_name(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1082 img_info
*cur
= g_ventoy_img_list
;
1086 if (argc
!= 2 || (!ventoy_is_decimal(args
[0])))
1088 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {imageID} {var}", cmd_raw_name
);
1091 img_id
= grub_strtol(args
[0], NULL
, 10);
1092 if (img_id
>= g_ventoy_img_count
)
1094 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images %ld %ld", img_id
, g_ventoy_img_count
);
1097 debug("Find image %ld name \n", img_id
);
1099 while (cur
&& img_id
> 0)
1107 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such many images");
1110 debug("image name is %s\n", cur
->name
);
1112 grub_env_set(args
[1], cur
->name
);
1114 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1117 static grub_err_t
ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1121 const char *id
= NULL
;
1122 img_info
*cur
= g_ventoy_img_list
;
1128 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s {var}", cmd_raw_name
);
1131 id
= grub_env_get("chosen");
1133 pos
= grub_strstr(id
, "VID_");
1136 img_id
= (int)grub_strtoul(pos
+ 4, NULL
, 10);
1140 img_id
= (int)grub_strtoul(id
, NULL
, 10);
1145 if (img_id
== cur
->id
)
1154 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "No such image");
1157 grub_env_set(args
[0], cur
->path
);
1159 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1162 static int ventoy_get_disk_guid(const char *filename
, grub_uint8_t
*guid
)
1169 device_name
= grub_file_get_device_name(filename
);
1181 pos2
= grub_strstr(pos
, ",");
1184 pos2
= grub_strstr(pos
, ")");
1192 disk
= grub_disk_open(pos
);
1195 grub_disk_read(disk
, 0, 0x180, 16, guid
);
1196 grub_disk_close(disk
);
1203 grub_free(device_name
);
1207 grub_uint32_t
ventoy_get_iso_boot_catlog(grub_file_t file
)
1209 eltorito_descriptor desc
;
1211 grub_memset(&desc
, 0, sizeof(desc
));
1212 grub_file_seek(file
, 17 * 2048);
1213 grub_file_read(file
, &desc
, sizeof(desc
));
1215 if (desc
.type
!= 0 || desc
.version
!= 1)
1220 if (grub_strncmp((char *)desc
.id
, "CD001", 5) != 0 ||
1221 grub_strncmp((char *)desc
.system_id
, "EL TORITO SPECIFICATION", 23) != 0)
1229 int ventoy_has_efi_eltorito(grub_file_t file
, grub_uint32_t sector
)
1232 grub_uint8_t buf
[512];
1234 grub_file_seek(file
, sector
* 2048);
1235 grub_file_read(file
, buf
, sizeof(buf
));
1237 if (buf
[0] == 0x01 && buf
[1] == 0xEF)
1239 debug("%s efi eltorito in Validation Entry\n", file
->name
);
1243 for (i
= 64; i
< (int)sizeof(buf
); i
+= 32)
1245 if ((buf
[i
] == 0x90 || buf
[i
] == 0x91) && buf
[i
+ 1] == 0xEF)
1247 debug("%s efi eltorito offset %d 0x%02x\n", file
->name
, i
, buf
[i
]);
1252 debug("%s does not contain efi eltorito\n", file
->name
);
1256 void ventoy_fill_os_param(grub_file_t file
, ventoy_os_param
*param
)
1260 grub_uint8_t chksum
= 0;
1263 disk
= file
->device
->disk
;
1264 grub_memcpy(¶m
->guid
, &g_ventoy_guid
, sizeof(ventoy_guid
));
1266 param
->vtoy_disk_size
= disk
->total_sectors
* (1 << disk
->log_sector_size
);
1267 param
->vtoy_disk_part_id
= disk
->partition
->number
+ 1;
1268 param
->vtoy_disk_part_type
= ventoy_get_fs_type(file
->fs
->name
);
1270 pos
= grub_strstr(file
->name
, "/");
1276 grub_snprintf(param
->vtoy_img_path
, sizeof(param
->vtoy_img_path
), "%s", pos
);
1278 ventoy_get_disk_guid(file
->name
, param
->vtoy_disk_guid
);
1280 param
->vtoy_img_size
= file
->size
;
1282 param
->vtoy_reserved
[0] = g_ventoy_break_level
;
1283 param
->vtoy_reserved
[1] = g_ventoy_debug_level
;
1285 /* calculate checksum */
1286 for (i
= 0; i
< sizeof(ventoy_os_param
); i
++)
1288 chksum
+= *((grub_uint8_t
*)param
+ i
);
1290 param
->chksum
= (grub_uint8_t
)(0x100 - chksum
);
1295 int ventoy_check_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
1297 grub_uint32_t i
= 0;
1298 grub_uint64_t total
= 0;
1299 ventoy_img_chunk
*chunk
= NULL
;
1301 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
1303 chunk
= chunklist
->chunk
+ i
;
1305 if (chunk
->disk_start_sector
<= start
)
1307 debug("%u disk start invalid %lu\n", i
, (ulong
)start
);
1311 total
+= chunk
->disk_end_sector
+ 1 - chunk
->disk_start_sector
;
1314 if (total
!= (file
->size
/ 512))
1316 debug("Invalid total: %llu %llu\n", (ulonglong
)total
, (ulonglong
)(file
->size
/ 512));
1323 int ventoy_get_block_list(grub_file_t file
, ventoy_img_chunk_list
*chunklist
, grub_disk_addr_t start
)
1326 grub_uint32_t i
= 0;
1327 grub_uint32_t sector
= 0;
1328 grub_uint32_t count
= 0;
1329 grub_off_t size
= 0;
1330 grub_off_t read
= 0;
1332 fs_type
= ventoy_get_fs_type(file
->fs
->name
);
1333 if (fs_type
== ventoy_fs_exfat
)
1335 grub_fat_get_file_chunk(start
, file
, chunklist
);
1337 else if (fs_type
== ventoy_fs_ext
)
1339 grub_ext_get_file_chunk(start
, file
, chunklist
);
1343 file
->read_hook
= (grub_disk_read_hook_t
)grub_disk_blocklist_read
;
1344 file
->read_hook_data
= chunklist
;
1346 for (size
= file
->size
; size
> 0; size
-= read
)
1348 read
= (size
> VTOY_SIZE_1GB
) ? VTOY_SIZE_1GB
: size
;
1349 grub_file_read(file
, NULL
, read
);
1352 for (i
= 0; start
> 0 && i
< chunklist
->cur_chunk
; i
++)
1354 chunklist
->chunk
[i
].disk_start_sector
+= start
;
1355 chunklist
->chunk
[i
].disk_end_sector
+= start
;
1358 if (ventoy_fs_udf
== fs_type
)
1360 for (i
= 0; i
< chunklist
->cur_chunk
; i
++)
1362 count
= (chunklist
->chunk
[i
].disk_end_sector
+ 1 - chunklist
->chunk
[i
].disk_start_sector
) >> 2;
1363 chunklist
->chunk
[i
].img_start_sector
= sector
;
1364 chunklist
->chunk
[i
].img_end_sector
= sector
+ count
- 1;
1373 static grub_err_t
ventoy_cmd_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1377 grub_disk_addr_t start
;
1382 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1385 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
1388 if (g_img_chunk_list
.chunk
)
1390 grub_free(g_img_chunk_list
.chunk
);
1393 /* get image chunk data */
1394 grub_memset(&g_img_chunk_list
, 0, sizeof(g_img_chunk_list
));
1395 g_img_chunk_list
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1396 if (NULL
== g_img_chunk_list
.chunk
)
1398 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1401 g_img_chunk_list
.max_chunk
= DEFAULT_CHUNK_NUM
;
1402 g_img_chunk_list
.cur_chunk
= 0;
1404 start
= file
->device
->disk
->partition
->start
;
1406 ventoy_get_block_list(file
, &g_img_chunk_list
, start
);
1408 rc
= ventoy_check_block_list(file
, &g_img_chunk_list
, start
);
1409 grub_file_close(file
);
1413 return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET
, "Unsupported chunk list.\n");
1416 grub_memset(&g_grub_param
->file_replace
, 0, sizeof(g_grub_param
->file_replace
));
1417 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1420 static grub_err_t
ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1423 ventoy_img_chunk
*cur
;
1429 for (i
= 0; i
< g_img_chunk_list
.cur_chunk
; i
++)
1431 cur
= g_img_chunk_list
.chunk
+ i
;
1432 grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
1433 cur
->img_start_sector
, cur
->img_end_sector
,
1434 (unsigned long long)cur
->disk_start_sector
, (unsigned long long)cur
->disk_end_sector
1438 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1441 #ifdef GRUB_MACHINE_EFI
1442 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1450 static grub_err_t
ventoy_cmd_relocator_chaindata(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1453 ulong chain_len
= 0;
1454 char *chain_data
= NULL
;
1455 char *relocator_addr
= NULL
;
1456 grub_relocator_chunk_t ch
;
1457 struct grub_relocator
*relocator
= NULL
;
1458 char envbuf
[64] = { 0 };
1469 chain_data
= (char *)grub_strtoul(args
[0], NULL
, 16);
1470 chain_len
= grub_strtoul(args
[1], NULL
, 10);
1472 relocator
= grub_relocator_new ();
1475 debug("grub_relocator_new failed %p %lu\n", chain_data
, chain_len
);
1479 rc
= grub_relocator_alloc_chunk_addr (relocator
, &ch
,
1480 0x100000, // GRUB_LINUX_BZIMAGE_ADDR,
1484 debug("grub_relocator_alloc_chunk_addr failed %d %p %lu\n", rc
, chain_data
, chain_len
);
1485 grub_relocator_unload (relocator
);
1489 relocator_addr
= get_virtual_current_address(ch
);
1491 grub_memcpy(relocator_addr
, chain_data
, chain_len
);
1493 grub_relocator_unload (relocator
);
1495 grub_snprintf(envbuf
, sizeof(envbuf
), "0x%lx", (unsigned long)relocator_addr
);
1496 grub_env_set("vtoy_chain_relocator_addr", envbuf
);
1498 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1502 static grub_err_t
ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1506 ventoy_img_chunk_list chunklist
;
1511 file
= ventoy_grub_file_open(VENTOY_FILE_TYPE
, "%s", args
[0]);
1514 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Can't open file %s\n", args
[0]);
1517 /* get image chunk data */
1518 grub_memset(&chunklist
, 0, sizeof(chunklist
));
1519 chunklist
.chunk
= grub_malloc(sizeof(ventoy_img_chunk
) * DEFAULT_CHUNK_NUM
);
1520 if (NULL
== chunklist
.chunk
)
1522 return grub_error(GRUB_ERR_OUT_OF_MEMORY
, "Can't allocate image chunk memoty\n");
1525 chunklist
.max_chunk
= DEFAULT_CHUNK_NUM
;
1526 chunklist
.cur_chunk
= 0;
1528 ventoy_get_block_list(file
, &chunklist
, 0);
1530 if (0 != ventoy_check_block_list(file
, &chunklist
, 0))
1532 grub_printf("########## UNSUPPORTED ###############\n");
1535 grub_printf("filesystem: <%s> entry number:<%u>\n", file
->fs
->name
, chunklist
.cur_chunk
);
1537 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
1539 grub_printf("%llu+%llu,", (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
1540 (ulonglong
)(chunklist
.chunk
[i
].disk_end_sector
+ 1 - chunklist
.chunk
[i
].disk_start_sector
));
1543 grub_printf("\n==================================\n");
1545 for (i
= 0; i
< chunklist
.cur_chunk
; i
++)
1547 grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i
,
1548 (ulonglong
)chunklist
.chunk
[i
].img_start_sector
,
1549 (ulonglong
)chunklist
.chunk
[i
].img_end_sector
,
1550 (ulonglong
)chunklist
.chunk
[i
].disk_start_sector
,
1551 (ulonglong
)chunklist
.chunk
[i
].disk_end_sector
1555 grub_free(chunklist
.chunk
);
1556 grub_file_close(file
);
1558 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1561 static grub_err_t
ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1564 ventoy_grub_param_file_replace
*replace
= NULL
;
1572 replace
= &(g_grub_param
->file_replace
);
1573 replace
->magic
= GRUB_FILE_REPLACE_MAGIC
;
1575 replace
->old_name_cnt
= 0;
1576 for (i
= 0; i
< 4 && i
+ 1 < argc
; i
++)
1578 replace
->old_name_cnt
++;
1579 grub_snprintf(replace
->old_file_name
[i
], sizeof(replace
->old_file_name
[i
]), "%s", args
[i
+ 1]);
1582 replace
->new_file_virtual_id
= (grub_uint32_t
)grub_strtoul(args
[0], NULL
, 10);
1585 VENTOY_CMD_RETURN(GRUB_ERR_NONE
);
1588 static grub_err_t
ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1596 grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos
, VTOY_MAX_SCRIPT_BUF
);
1597 grub_printf("%s", g_list_script_buf
);
1601 grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos
, VTOY_MAX_SCRIPT_BUF
);
1602 grub_printf("%s", g_tree_script_buf
);
1608 static grub_err_t
ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1614 ventoy_plugin_dump_auto_install();
1619 static grub_err_t
ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1625 ventoy_plugin_dump_persistence();
1630 static grub_err_t
ventoy_cmd_check_mode(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1641 if (args
[0][0] == '0')
1643 return g_ventoy_memdisk_mode
? 0 : 1;
1645 else if (args
[0][0] == '1')
1647 return g_ventoy_iso_raw
? 0 : 1;
1649 else if (args
[0][0] == '2')
1651 return g_ventoy_iso_uefi_drv
? 0 : 1;
1657 static grub_err_t
ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1659 static int configfile_mode
= 0;
1660 char memfile
[128] = {0};
1667 * args[0]: 0:normal 1:configfile
1668 * args[1]: 0:list_buf 1:tree_buf
1673 debug("Invalid argc %d\n", argc
);
1677 if (args
[0][0] == '0')
1679 if (args
[1][0] == '0')
1681 grub_script_execute_sourcecode(g_list_script_buf
);
1685 grub_script_execute_sourcecode(g_tree_script_buf
);
1690 if (configfile_mode
)
1692 debug("Now already in F3 mode %d\n", configfile_mode
);
1696 if (args
[1][0] == '0')
1698 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
1699 (ulonglong
)(ulong
)g_list_script_buf
, g_list_script_pos
);
1703 g_ventoy_last_entry
= -1;
1704 grub_snprintf(memfile
, sizeof(memfile
), "configfile mem:0x%llx:size:%d",
1705 (ulonglong
)(ulong
)g_tree_script_buf
, g_tree_script_pos
);
1708 configfile_mode
= 1;
1709 grub_script_execute_sourcecode(memfile
);
1710 configfile_mode
= 0;
1716 static grub_err_t
ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt
, int argc
, char **args
)
1721 const char *isopath
= NULL
;
1723 ventoy_mbr_head mbr
;
1730 return grub_error(GRUB_ERR_BAD_ARGUMENT
, "Usage: %s variable\n", cmd_raw_name
);
1733 isopath
= grub_env_get("iso_path");
1736 debug("isopath is null %p\n", isopath
);
1740 debug("isopath is %s\n", isopath
);
1742 for (id
= 0; id
< 30 && (find
== 0); id
++)
1744 grub_snprintf(hdname
, sizeof(hdname
), "hd%d,", id
);
1745 if (grub_strstr(isopath
, hdname
))
1747 debug("skip %s ...\n", hdname
);
1751 grub_snprintf(hdname
, sizeof(hdname
), "hd%d", id
);
1753 disk
= grub_disk_open(hdname
);
1756 debug("%s not exist\n", hdname
);
1760 grub_memset(&mbr
, 0, sizeof(mbr
));
1761 if (0 == grub_disk_read(disk
, 0, 0, 512, &mbr
))
1763 if (mbr
.Byte55
== 0x55 && mbr
.ByteAA
== 0xAA)
1765 if (mbr
.PartTbl
[0].Active
== 0x80 || mbr
.PartTbl
[1].Active
== 0x80 ||
1766 mbr
.PartTbl
[2].Active
== 0x80 || mbr
.PartTbl
[3].Active
== 0x80)
1769 grub_env_set(args
[0], hdname
);
1773 debug("%s is %s\n", hdname
, find
? "bootable" : "NOT bootable");
1777 debug("read %s failed\n", hdname
);
1780 grub_disk_close(disk
);
1786 grub_file_t
ventoy_grub_file_open(enum grub_file_type type
, const char *fmt
, ...)
1790 char fullpath
[256] = {0};
1793 grub_vsnprintf(fullpath
, 255, fmt
, ap
);
1796 file
= grub_file_open(fullpath
, type
);
1799 debug("grub_file_open failed <%s>\n", fullpath
);
1806 int ventoy_is_file_exist(const char *fmt
, ...)
1811 char buf
[256] = {0};
1813 grub_snprintf(buf
, sizeof(buf
), "%s", "[ -f ");
1817 len
= grub_vsnprintf(pos
, 255, fmt
, ap
);
1820 grub_strncpy(pos
+ len
, " ]", 2);
1822 debug("script exec %s\n", buf
);
1824 if (0 == grub_script_execute_sourcecode(buf
))
1832 static int ventoy_env_init(void)
1836 grub_env_set("vtdebug_flag", "");
1837 grub_env_export("vtdebug_flag");
1839 g_tree_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
1840 g_list_script_buf
= grub_malloc(VTOY_MAX_SCRIPT_BUF
);
1842 ventoy_filt_register(0, ventoy_wrapper_open
);
1844 g_grub_param
= (ventoy_grub_param
*)grub_zalloc(sizeof(ventoy_grub_param
));
1847 g_grub_param
->grub_env_get
= grub_env_get
;
1848 grub_snprintf(buf
, sizeof(buf
), "%p", g_grub_param
);
1849 grub_env_set("env_param", buf
);
1855 static cmd_para ventoy_cmds
[] =
1857 { "vt_incr", ventoy_cmd_incr
, 0, NULL
, "{Var} {INT}", "Increase integer variable", NULL
},
1858 { "vt_debug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
1859 { "vtdebug", ventoy_cmd_debug
, 0, NULL
, "{on|off}", "turn debug on/off", NULL
},
1860 { "vtbreak", ventoy_cmd_break
, 0, NULL
, "{level}", "set debug break", NULL
},
1861 { "vt_cmp", ventoy_cmd_cmp
, 0, NULL
, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL
},
1862 { "vt_device", ventoy_cmd_device
, 0, NULL
, "path var", "", NULL
},
1863 { "vt_check_compatible", ventoy_cmd_check_compatible
, 0, NULL
, "", "", NULL
},
1864 { "vt_list_img", ventoy_cmd_list_img
, 0, NULL
, "{device} {cntvar}", "find all iso file in device", NULL
},
1865 { "vt_clear_img", ventoy_cmd_clear_img
, 0, NULL
, "", "clear image list", NULL
},
1866 { "vt_img_name", ventoy_cmd_img_name
, 0, NULL
, "{imageID} {var}", "get image name", NULL
},
1867 { "vt_chosen_img_path", ventoy_cmd_chosen_img_path
, 0, NULL
, "{var}", "get chosen img path", NULL
},
1868 { "vt_img_sector", ventoy_cmd_img_sector
, 0, NULL
, "{imageName}", "", NULL
},
1869 { "vt_dump_img_sector", ventoy_cmd_dump_img_sector
, 0, NULL
, "", "", NULL
},
1870 { "vt_load_cpio", ventoy_cmd_load_cpio
, 0, NULL
, "", "", NULL
},
1871 { "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd
, 0, NULL
, "", "", NULL
},
1872 { "vt_dump_menu", ventoy_cmd_dump_menu
, 0, NULL
, "", "", NULL
},
1873 { "vt_dynamic_menu", ventoy_cmd_dynamic_menu
, 0, NULL
, "", "", NULL
},
1874 { "vt_check_mode", ventoy_cmd_check_mode
, 0, NULL
, "", "", NULL
},
1875 { "vt_dump_auto_install", ventoy_cmd_dump_auto_install
, 0, NULL
, "", "", NULL
},
1876 { "vt_dump_persistence", ventoy_cmd_dump_persistence
, 0, NULL
, "", "", NULL
},
1878 { "vt_is_udf", ventoy_cmd_is_udf
, 0, NULL
, "", "", NULL
},
1879 { "vt_file_size", ventoy_cmd_file_size
, 0, NULL
, "", "", NULL
},
1880 { "vt_load_iso_to_mem", ventoy_cmd_load_iso_to_mem
, 0, NULL
, "", "", NULL
},
1882 { "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
1883 { "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect
, 0, NULL
, "{cfgfile}", "", NULL
},
1884 { "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file
, 0, NULL
, "", "", NULL
},
1885 { "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list
, 0, NULL
, "", "", NULL
},
1886 { "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list
, 0, NULL
, "", "", NULL
},
1887 { "vt_linux_initrd_count", ventoy_cmd_initrd_count
, 0, NULL
, "", "", NULL
},
1888 { "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count
, 0, NULL
, "", "", NULL
},
1889 { "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd
, 0, NULL
, "", "", NULL
},
1890 { "vt_linux_chain_data", ventoy_cmd_linux_chain_data
, 0, NULL
, "", "", NULL
},
1892 { "vt_windows_reset", ventoy_cmd_wimdows_reset
, 0, NULL
, "", "", NULL
},
1893 { "vt_windows_locate_wim", ventoy_cmd_wimdows_locate_wim
, 0, NULL
, "", "", NULL
},
1894 { "vt_windows_chain_data", ventoy_cmd_windows_chain_data
, 0, NULL
, "", "", NULL
},
1896 { "vt_add_replace_file", ventoy_cmd_add_replace_file
, 0, NULL
, "", "", NULL
},
1897 { "vt_relocator_chaindata", ventoy_cmd_relocator_chaindata
, 0, NULL
, "", "", NULL
},
1898 { "vt_test_block_list", ventoy_cmd_test_block_list
, 0, NULL
, "", "", NULL
},
1901 { "vt_load_plugin", ventoy_cmd_load_plugin
, 0, NULL
, "", "", NULL
},
1906 GRUB_MOD_INIT(ventoy
)
1909 cmd_para
*cur
= NULL
;
1913 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
1915 cur
= ventoy_cmds
+ i
;
1916 cur
->cmd
= grub_register_extcmd(cur
->name
, cur
->func
, cur
->flags
,
1917 cur
->summary
, cur
->description
, cur
->parser
);
1921 GRUB_MOD_FINI(ventoy
)
1925 for (i
= 0; i
< ARRAY_SIZE(ventoy_cmds
); i
++)
1927 grub_unregister_extcmd(ventoy_cmds
[i
].cmd
);