Commit 849dfb46 authored by longpanda's avatar longpanda
Browse files

1. Change the UTF-16 languages.ini to UTF-8 languages.json

2. The update button is available even if data corrupted in VTOYEFI partition.
3. Set the default focus to No when you click Install button in Ventoy2Disk.exe.
4. Fix a BUG when booting Windows VHD(x) with the latest ventoy_vhdboot.img.
5. Support boot Windows VHD(x) files in local disk.
parent 7715bd70
......@@ -1603,6 +1603,7 @@ module = {
module = {
name = ventoy;
common = ventoy/ventoy.c;
common = ventoy/ventoy_cmd.c;
common = ventoy/ventoy_linux.c;
common = ventoy/ventoy_unix.c;
common = ventoy/ventoy_windows.c;
......
......@@ -31,113 +31,18 @@
#include <grub/normal.h>
#include <grub/extcmd.h>
#include <grub/datetime.h>
#include <grub/i18n.h>
#include <grub/net.h>
#include <grub/misc.h>
#include <grub/kernel.h>
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#endif
#include <grub/time.h>
#include <grub/video.h>
#include <grub/acpi.h>
#include <grub/charset.h>
#include <grub/crypto.h>
#include <grub/lib/crc.h>
#include <grub/ventoy.h>
#include "ventoy_def.h"
#include "miniz.h"
GRUB_MOD_LICENSE ("GPLv3+");
int g_ventoy_debug = 0;
static int g_efi_os = 0xFF;
initrd_info *g_initrd_img_list = NULL;
initrd_info *g_initrd_img_tail = NULL;
int g_initrd_img_count = 0;
int g_valid_initrd_count = 0;
int g_default_menu_mode = 0;
int g_filt_dot_underscore_file = 0;
int g_sort_case_sensitive = 0;
int g_tree_view_menu_style = 0;
static grub_file_t g_old_file;
static int g_ventoy_last_entry_back;
static grub_uint32_t g_ventoy_plat_data;
char g_iso_path[256];
char g_img_swap_tmp_buf[1024];
img_info g_img_swap_tmp;
img_info *g_ventoy_img_list = NULL;
int g_ventoy_img_count = 0;
grub_device_t g_enum_dev = NULL;
grub_fs_t g_enum_fs = NULL;
int g_img_max_search_level = -1;
img_iterator_node g_img_iterator_head;
img_iterator_node *g_img_iterator_tail = NULL;
grub_uint8_t g_ventoy_break_level = 0;
grub_uint8_t g_ventoy_debug_level = 0;
grub_uint8_t g_ventoy_chain_type = 0;
grub_uint8_t *g_ventoy_cpio_buf = NULL;
grub_uint32_t g_ventoy_cpio_size = 0;
cpio_newc_header *g_ventoy_initrd_head = NULL;
grub_uint8_t *g_ventoy_runtime_buf = NULL;
int g_plugin_image_list = 0;
ventoy_grub_param *g_grub_param = NULL;
ventoy_guid g_ventoy_guid = VENTOY_GUID;
ventoy_img_chunk_list g_img_chunk_list;
int g_wimboot_enable = 0;
ventoy_img_chunk_list g_wimiso_chunk_list;
char *g_wimiso_path = NULL;
int g_vhdboot_enable = 0;
grub_uint64_t g_conf_replace_offset = 0;
grub_uint64_t g_svd_replace_offset = 0;
conf_replace *g_conf_replace_node = NULL;
grub_uint8_t *g_conf_replace_new_buf = NULL;
int g_conf_replace_new_len = 0;
int g_conf_replace_new_len_align = 0;
ventoy_gpt_info *g_ventoy_part_info = NULL;
grub_uint64_t g_ventoy_disk_size = 0;
static char *g_tree_script_buf = NULL;
static int g_tree_script_pos = 0;
static char *g_list_script_buf = NULL;
static int g_list_script_pos = 0;
static char *g_part_list_buf = NULL;
static int g_part_list_pos = 0;
static int g_video_mode_max = 0;
static int g_video_mode_num = 0;
static ventoy_video_mode *g_video_mode_list = NULL;
static int g_enumerate_time_checked = 0;
static grub_uint64_t g_enumerate_start_time_ms;
static grub_uint64_t g_enumerate_finish_time_ms;
static int g_vtoy_file_flt[VTOY_FILE_FLT_BUTT] = {0};
static const char *g_menu_class[] =
{
"vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
};
static const char *g_menu_prefix[] =
{
"iso", "wim", "efi", "img", "vhd", "vtoy"
};
grub_uint32_t g_ventoy_plat_data;
void ventoy_debug(const char *fmt, ...)
{
......@@ -179,7 +84,6 @@ int ventoy_strncmp (const char *pattern, const char *str, grub_size_t n)
return (int)(grub_uint8_t)*pattern - (int)(grub_uint8_t)*str;
}
void ventoy_debug_dump_guid(const char *prefix, grub_uint8_t *guid)
{
int i;
......@@ -207,4366 +111,46 @@ int ventoy_is_efi_os(void)
return g_efi_os;
}
static int ventoy_get_fs_type(const char *fs)
{
if (NULL == fs)
{
return ventoy_fs_max;
}
else if (grub_strncmp(fs, "exfat", 5) == 0)
{
return ventoy_fs_exfat;
}
else if (grub_strncmp(fs, "ntfs", 4) == 0)
{
return ventoy_fs_ntfs;
}
else if (grub_strncmp(fs, "ext", 3) == 0)
{
return ventoy_fs_ext;
}
else if (grub_strncmp(fs, "xfs", 3) == 0)
{
return ventoy_fs_xfs;
}
else if (grub_strncmp(fs, "udf", 3) == 0)
{
return ventoy_fs_udf;
}
else if (grub_strncmp(fs, "fat", 3) == 0)
{
return ventoy_fs_fat;
}
return ventoy_fs_max;
}
static int ventoy_string_check(const char *str, grub_char_check_func check)
{
if (!str)
{
return 0;
}
for ( ; *str; str++)
{
if (!check(*str))
{
return 0;
}
}
return 1;
}
static grub_ssize_t ventoy_fs_read(grub_file_t file, char *buf, grub_size_t len)
{
grub_memcpy(buf, (char *)file->data + file->offset, len);
return len;
}
static int ventoy_control_get_flag(const char *key)
{
const char *val = ventoy_get_env(key);
if (val && val[0] == '1' && val[1] == 0)
{
return 1;
}
return 0;
}
static grub_err_t ventoy_fs_close(grub_file_t file)
{
grub_file_close(g_old_file);
grub_free(file->data);
file->device = 0;
file->name = 0;
return 0;
}
static int ventoy_video_hook(const struct grub_video_mode_info *info, void *hook_arg)
{
int i;
(void)hook_arg;
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
{
return 0;
}
for (i = 0; i < g_video_mode_num; i++)
{
if (g_video_mode_list[i].width == info->width &&
g_video_mode_list[i].height == info->height &&
g_video_mode_list[i].bpp == info->bpp)
{
return 0;
}
}
g_video_mode_list[g_video_mode_num].width = info->width;
g_video_mode_list[g_video_mode_num].height = info->height;
g_video_mode_list[g_video_mode_num].bpp = info->bpp;
g_video_mode_num++;
if (g_video_mode_num == g_video_mode_max)
{
g_video_mode_max *= 2;
g_video_mode_list = grub_realloc(g_video_mode_list, g_video_mode_max * sizeof(ventoy_video_mode));
}
return 0;
}
static int ventoy_video_mode_cmp(ventoy_video_mode *v1, ventoy_video_mode *v2)
{
if (v1->bpp == v2->bpp)
{
if (v1->width == v2->width)
{
if (v1->height == v2->height)
{
return 0;
}
else
{
return (v1->height < v2->height) ? -1 : 1;
}
}
else
{
return (v1->width < v2->width) ? -1 : 1;
}
}
else
{
return (v1->bpp < v2->bpp) ? -1 : 1;
}
}
static int ventoy_enum_video_mode(void)
{
int i, j;
grub_video_adapter_t adapter;
grub_video_driver_id_t id;
ventoy_video_mode mode;
g_video_mode_num = 0;
g_video_mode_max = 1024;
g_video_mode_list = grub_malloc(sizeof(ventoy_video_mode) * g_video_mode_max);
if (!g_video_mode_list)
{
return 0;
}
#ifdef GRUB_MACHINE_PCBIOS
grub_dl_load ("vbe");
#endif
id = grub_video_get_driver_id ();
FOR_VIDEO_ADAPTERS (adapter)
{
if (!adapter->iterate ||
(adapter->id != id && (id != GRUB_VIDEO_DRIVER_NONE ||
adapter->init() != GRUB_ERR_NONE)))
{
continue;
}
adapter->iterate(ventoy_video_hook, NULL);
if (adapter->id != id)
{
adapter->fini();
}
}
/* sort video mode */
for (i = 0; i < g_video_mode_num; i++)
for (j = i + 1; j < g_video_mode_num; j++)
{
if (ventoy_video_mode_cmp(g_video_mode_list + i, g_video_mode_list + j) < 0)
{
grub_memcpy(&mode, g_video_mode_list + i, sizeof(ventoy_video_mode));
grub_memcpy(g_video_mode_list + i, g_video_mode_list + j, sizeof(ventoy_video_mode));
grub_memcpy(g_video_mode_list + j, &mode, sizeof(ventoy_video_mode));
}
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_file_t ventoy_wrapper_open(grub_file_t rawFile, enum grub_file_type type)
{
int len;
grub_file_t file;
static struct grub_fs vtoy_fs =
{
.name = "vtoy",
.fs_dir = 0,
.fs_open = 0,
.fs_read = ventoy_fs_read,
.fs_close = ventoy_fs_close,
.fs_label = 0,
.next = 0
};
if (type != 52)
{
return rawFile;
}
file = (grub_file_t)grub_zalloc(sizeof (*file));
if (!file)
{
return 0;
}
file->data = grub_malloc(rawFile->size + 4096);
if (!file->data)
{
return 0;
}
grub_file_read(rawFile, file->data, rawFile->size);
len = ventoy_fill_data(4096, (char *)file->data + rawFile->size);
g_old_file = rawFile;
file->size = rawFile->size + len;
file->device = rawFile->device;
file->fs = &vtoy_fs;
file->not_easily_seekable = 1;
return file;
}
static int ventoy_check_decimal_var(const char *name, long *value)
static int ventoy_arch_mode_init(void)
{
const char *value_str = NULL;
value_str = grub_env_get(name);
if (NULL == value_str)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s not found", name);
}
if (!ventoy_is_decimal(value_str))
#ifdef GRUB_MACHINE_EFI
if (grub_strcmp(GRUB_TARGET_CPU, "i386") == 0)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s value '%s' is not an integer", name, value_str);
g_ventoy_plat_data = VTOY_PLAT_I386_UEFI;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "ia32");
}
*value = grub_strtol(value_str, NULL, 10);
return GRUB_ERR_NONE;
}
static grub_err_t ventoy_cmd_debug(grub_extcmd_context_t ctxt, int argc, char **args)
{
if (argc != 1)
else if (grub_strcmp(GRUB_TARGET_CPU, "arm64") == 0)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {on|off}", cmd_raw_name);
g_ventoy_plat_data = VTOY_PLAT_ARM64_UEFI;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "aa64");
}
if (0 == grub_strcmp(args[0], "on"))
else if (grub_strcmp(GRUB_TARGET_CPU, "mips64el") == 0)
{
g_ventoy_debug = 1;
grub_env_set("vtdebug_flag", "debug");
g_ventoy_plat_data = VTOY_PLAT_MIPS_UEFI;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "mips");
}
else
{
g_ventoy_debug = 0;
grub_env_set("vtdebug_flag", "");
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_break(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
if (argc < 1 || (args[0][0] != '0' && args[0][0] != '1'))
{
grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name);
grub_printf(" level:\r\n");
grub_printf(" 01/11: busybox / (+cat log)\r\n");
grub_printf(" 02/12: initrd / (+cat log)\r\n");
grub_printf(" 03/13: hook / (+cat log)\r\n");
grub_printf("\r\n");
grub_printf(" debug:\r\n");
grub_printf(" 0: debug is off\r\n");
grub_printf(" 1: debug is on\r\n");
grub_printf("\r\n");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
g_ventoy_break_level = (grub_uint8_t)grub_strtoul(args[0], NULL, 16);
if (argc > 1 && grub_strtoul(args[1], NULL, 10) > 0)
{
g_ventoy_debug_level = 1;
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
if (argc != 2)
{
return 1;
}
return (grub_strstr(args[0], args[1])) ? 0 : 1;
}
static grub_err_t ventoy_cmd_strbegin(grub_extcmd_context_t ctxt, int argc, char **args)
{
char *c0, *c1;
(void)ctxt;
if (argc != 2)
{
return 1;
}
c0 = args[0];
c1 = args[1];
while (*c0 && *c1)
{
if (*c0 != *c1)
{
return 1;
}
c0++;
c1++;
}
if (*c1)
{
return 1;
g_ventoy_plat_data = VTOY_PLAT_X86_64_UEFI;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "uefi");
}
#else
g_ventoy_plat_data = VTOY_PLAT_X86_LEGACY;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "legacy");
#endif
return 0;
}
static grub_err_t ventoy_cmd_incr(grub_extcmd_context_t ctxt, int argc, char **args)
{
long value_long = 0;
char buf[32];
if ((argc != 2) || (!ventoy_is_decimal(args[1])))
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Variable} {Int}", cmd_raw_name);
}
if (GRUB_ERR_NONE != ventoy_check_decimal_var(args[0], &value_long))
{
return grub_errno;
}
value_long += grub_strtol(args[1], NULL, 10);
grub_snprintf(buf, sizeof(buf), "%ld", value_long);
grub_env_set(args[0], buf);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_mod(grub_extcmd_context_t ctxt, int argc, char **args)
{
ulonglong value1 = 0;
ulonglong value2 = 0;
char buf[32];
if (argc != 3)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name);
}
value1 = grub_strtoull(args[0], NULL, 10);
value2 = grub_strtoull(args[1], NULL, 10);
grub_snprintf(buf, sizeof(buf), "%llu", (value1 & (value2 - 1)));
grub_env_set(args[2], buf);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_file_size(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char buf[32];
grub_file_t file;
(void)ctxt;
(void)argc;
(void)args;
if (argc != 2)
{
return rc;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s> for udf check\n", args[0]);
return 1;
}
grub_snprintf(buf, sizeof(buf), "%llu", (unsigned long long)file->size);
grub_env_set(args[1], buf);
grub_file_close(file);
rc = 0;
return rc;
}
static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc, char **args)
GRUB_MOD_INIT(ventoy)
{
grub_file_t file;
(void)ctxt;
(void)argc;
(void)args;
g_wimboot_enable = 0;
grub_check_free(g_wimiso_path);
grub_check_free(g_wimiso_chunk_list.chunk);
file = grub_file_open(args[0], VENTOY_FILE_TYPE);
if (!file)
{
return 0;
}
grub_memset(&g_wimiso_chunk_list, 0, sizeof(g_wimiso_chunk_list));
g_wimiso_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
if (NULL == g_wimiso_chunk_list.chunk)
{
return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
}
g_wimiso_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
g_wimiso_chunk_list.cur_chunk = 0;
ventoy_get_block_list(file, &g_wimiso_chunk_list, file->device->disk->partition->start);
g_wimboot_enable = 1;
g_wimiso_path = grub_strdup(args[0]);
grub_file_close(file);
return 0;
ventoy_env_init();
ventoy_arch_mode_init();
ventoy_register_all_cmd();
}
static int ventoy_load_efiboot_template(char **buf, int *datalen, int *direntoff)
GRUB_MOD_FINI(ventoy)
{
int len;
grub_file_t file;
char exec[128];
char *data = NULL;
grub_uint32_t offset;
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
if (file == NULL)
{
debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
return 1;
}
len = (int)file->size;
data = (char *)grub_malloc(file->size);
if (!data)
{
return 1;
}
grub_file_read(file, data, file->size);
grub_file_close(file);
grub_snprintf(exec, sizeof(exec), "loopback efiboot mem:0x%llx:size:%d", (ulonglong)(ulong)data, len);
grub_script_execute_sourcecode(exec);
file = grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD);
offset = (grub_uint32_t)grub_iso9660_get_last_file_dirent_pos(file);
grub_file_close(file);
grub_script_execute_sourcecode("loopback -d efiboot");
*buf = data;
*datalen = len;
*direntoff = offset + 2;
return 0;
}
static grub_err_t ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len = 0;
int totlen = 0;
int offset = 0;
grub_file_t file;
char name[32];
char value[32];
char *buf = NULL;
char *data = NULL;
ventoy_iso9660_override *dirent;
(void)ctxt;
if (argc != 2)
{
return 1;
}
totlen = sizeof(ventoy_chain_head);
if (ventoy_load_efiboot_template(&buf, &len, &offset))
{
debug("failed to load efiboot template %d\n", len);
return 1;
}
totlen += len;
debug("efiboot template len:%d offset:%d\n", len, offset);
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s>\n", args[0]);
return 1;
}
totlen += ventoy_align_2k(file->size);
dirent = (ventoy_iso9660_override *)(buf + offset);
dirent->first_sector = len / 2048;
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
dirent->size = (grub_uint32_t)file->size;
dirent->size_be = grub_swap_bytes32(dirent->size);
debug("rawiso len:%d efilen:%d total:%d\n", len, (int)file->size, totlen);
#ifdef GRUB_MACHINE_EFI
data = (char *)grub_efi_allocate_iso_buf(totlen);
#else
data = (char *)grub_malloc(totlen);
#endif
ventoy_fill_os_param(file, (ventoy_os_param *)data);
grub_memcpy(data + sizeof(ventoy_chain_head), buf, len);
grub_check_free(buf);
grub_file_read(file, data + sizeof(ventoy_chain_head) + len, file->size);
grub_file_close(file);
grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)data);
grub_env_set(name, value);
grub_snprintf(name, sizeof(name), "%s_size", args[1]);
grub_snprintf(value, sizeof(value), "%d", (int)(totlen));
grub_env_set(name, value);
return 0;
}
static grub_err_t ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char name[32];
char value[32];
char *buf = NULL;
grub_file_t file;
(void)ctxt;
(void)argc;
(void)args;
if (argc != 2)
{
return rc;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s>\n", args[0]);
return 1;
}
#ifdef GRUB_MACHINE_EFI
buf = (char *)grub_efi_allocate_iso_buf(file->size);
#else
buf = (char *)grub_malloc(file->size);
#endif
grub_file_read(file, buf, file->size);
grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
grub_env_set(name, value);
grub_snprintf(name, sizeof(name), "%s_size", args[1]);
grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
grub_env_set(name, value);
grub_file_close(file);
rc = 0;
return rc;
}
static grub_err_t ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
int headlen;
char name[32];
char value[32];
char *buf = NULL;
grub_file_t file;
(void)ctxt;
(void)argc;
(void)args;
if (argc != 2)
{
return rc;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s> for udf check\n", args[0]);
return 1;
}
headlen = sizeof(ventoy_chain_head);
#ifdef GRUB_MACHINE_EFI
buf = (char *)grub_efi_allocate_iso_buf(headlen + file->size);
#else
buf = (char *)grub_malloc(headlen + file->size);
#endif
ventoy_fill_os_param(file, (ventoy_os_param *)buf);
grub_file_read(file, buf + headlen, file->size);
grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
grub_env_set(name, value);
grub_snprintf(name, sizeof(name), "%s_size", args[1]);
grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
grub_env_set(name, value);
grub_file_close(file);
rc = 0;
return rc;
}
static grub_err_t ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
if (argc != 1)
{
return 1;
}
if (args[0][0] == '1')
{
grub_iso9660_set_nojoliet(1);
}
else
{
grub_iso9660_set_nojoliet(0);
}
return 0;
}
static grub_err_t ventoy_cmd_is_udf(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int rc = 1;
grub_file_t file;
grub_uint8_t buf[32];
(void)ctxt;
(void)argc;
(void)args;
if (argc != 1)
{
return rc;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s> for udf check\n", args[0]);
return 1;
}
for (i = 16; i < 32; i++)
{
grub_file_seek(file, i * 2048);
grub_file_read(file, buf, sizeof(buf));
if (buf[0] == 255)
{
break;
}
}
i++;
grub_file_seek(file, i * 2048);
grub_file_read(file, buf, sizeof(buf));
if (grub_memcmp(buf + 1, "BEA01", 5) == 0)
{
i++;
grub_file_seek(file, i * 2048);
grub_file_read(file, buf, sizeof(buf));
if (grub_memcmp(buf + 1, "NSR02", 5) == 0 ||
grub_memcmp(buf + 1, "NSR03", 5) == 0)
{
rc = 0;
}
}
grub_file_close(file);
debug("ISO UDF: %s\n", rc ? "NO" : "YES");
return rc;
}
static grub_err_t ventoy_cmd_cmp(grub_extcmd_context_t ctxt, int argc, char **args)
{
long value_long1 = 0;
long value_long2 = 0;
if ((argc != 3) || (!ventoy_is_decimal(args[0])) || (!ventoy_is_decimal(args[2])))
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name);
}
value_long1 = grub_strtol(args[0], NULL, 10);
value_long2 = grub_strtol(args[2], NULL, 10);
if (0 == grub_strcmp(args[1], "eq"))
{
grub_errno = (value_long1 == value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "ne"))
{
grub_errno = (value_long1 != value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "gt"))
{
grub_errno = (value_long1 > value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "lt"))
{
grub_errno = (value_long1 < value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "ge"))
{
grub_errno = (value_long1 >= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "le"))
{
grub_errno = (value_long1 <= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name);
}
return grub_errno;
}
static grub_err_t ventoy_cmd_device(grub_extcmd_context_t ctxt, int argc, char **args)
{
char *pos = NULL;
char buf[128] = {0};
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s path var", cmd_raw_name);
}
grub_strncpy(buf, (args[0][0] == '(') ? args[0] + 1 : args[0], sizeof(buf) - 1);
pos = grub_strstr(buf, ",");
if (pos)
{
*pos = 0;
}
grub_env_set(args[1], buf);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
char buf[256];
grub_disk_t disk;
char *pos = NULL;
const char *files[] = { "ventoy.dat", "VENTOY.DAT" };
(void)ctxt;
if (argc != 1)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s (loop)", cmd_raw_name);
}
for (i = 0; i < (int)ARRAY_SIZE(files); i++)
{
grub_snprintf(buf, sizeof(buf) - 1, "[ -e \"%s/%s\" ]", args[0], files[i]);
if (0 == grub_script_execute_sourcecode(buf))
{
debug("file %s exist, ventoy_compatible YES\n", buf);
grub_env_set("ventoy_compatible", "YES");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
else
{
debug("file %s NOT exist\n", buf);
}
}
grub_snprintf(buf, sizeof(buf) - 1, "%s", args[0][0] == '(' ? (args[0] + 1) : args[0]);
pos = grub_strstr(buf, ")");
if (pos)
{
*pos = 0;
}
disk = grub_disk_open(buf);
if (disk)
{
grub_disk_read(disk, 16 << 2, 0, 1024, g_img_swap_tmp_buf);
grub_disk_close(disk);
g_img_swap_tmp_buf[703] = 0;
for (i = 318; i < 703; i++)
{
if (g_img_swap_tmp_buf[i] == 'V' &&
0 == grub_strncmp(g_img_swap_tmp_buf + i, VENTOY_COMPATIBLE_STR, VENTOY_COMPATIBLE_STR_LEN))
{
debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i);
grub_env_set("ventoy_compatible", "YES");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
}
}
else
{
debug("failed to open disk <%s>\n", buf);
}
grub_env_set("ventoy_compatible", "NO");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
int ventoy_cmp_img(img_info *img1, img_info *img2)
{
char *s1, *s2;
int c1 = 0;
int c2 = 0;
if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
{
return (img1->plugin_list_index - img2->plugin_list_index);
}
for (s1 = img1->name, s2 = img2->name; *s1 && *s2; s1++, s2++)
{
c1 = *s1;
c2 = *s2;
if (0 == g_sort_case_sensitive)
{
if (grub_islower(c1))
{
c1 = c1 - 'a' + 'A';
}
if (grub_islower(c2))
{
c2 = c2 - 'a' + 'A';
}
}
if (c1 != c2)
{
break;
}
}
return (c1 - c2);
}
static int ventoy_cmp_subdir(img_iterator_node *node1, img_iterator_node *node2)
{
char *s1, *s2;
int c1 = 0;
int c2 = 0;
if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
{
return (node1->plugin_list_index - node2->plugin_list_index);
}
for (s1 = node1->dir, s2 = node2->dir; *s1 && *s2; s1++, s2++)
{
c1 = *s1;
c2 = *s2;
if (0 == g_sort_case_sensitive)
{
if (grub_islower(c1))
{
c1 = c1 - 'a' + 'A';
}
if (grub_islower(c2))
{
c2 = c2 - 'a' + 'A';
}
}
if (c1 != c2)
{
break;
}
}
return (c1 - c2);
}
void ventoy_swap_img(img_info *img1, img_info *img2)
{
grub_memcpy(&g_img_swap_tmp, img1, sizeof(img_info));
grub_memcpy(img1, img2, sizeof(img_info));
img1->next = g_img_swap_tmp.next;
img1->prev = g_img_swap_tmp.prev;
g_img_swap_tmp.next = img2->next;
g_img_swap_tmp.prev = img2->prev;
grub_memcpy(img2, &g_img_swap_tmp, sizeof(img_info));
}
static int ventoy_img_name_valid(const char *filename, grub_size_t namelen)
{
(void)namelen;
if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
{
return 0;
}
return 1;
}
static int ventoy_check_ignore_flag(const char *filename, const struct grub_dirhook_info *info, void *data)
{
if (0 == info->dir)
{
if (filename && filename[0] == '.' && 0 == grub_strncmp(filename, ".ventoyignore", 13))
{
*((int *)data) = 1;
return 0;
}
}
return 0;
}
static int ventoy_collect_img_files(const char *filename, const struct grub_dirhook_info *info, void *data)
{
//int i = 0;
int type = 0;
int ignore = 0;
int index = 0;
grub_size_t len;
img_info *img;
img_info *tail;
img_iterator_node *tmp;
img_iterator_node *new_node;
img_iterator_node *node = (img_iterator_node *)data;
if (g_enumerate_time_checked == 0)
{
g_enumerate_finish_time_ms = grub_get_time_ms();
if ((g_enumerate_finish_time_ms - g_enumerate_start_time_ms) >= 3000)
{
grub_cls();
grub_printf("\n\n Ventoy scanning files, please wait...\n");
grub_refresh();
g_enumerate_time_checked = 1;
}
}
len = grub_strlen(filename);
if (info->dir)
{
if (node->level + 1 > g_img_max_search_level)
{
return 0;
}
if ((len == 1 && filename[0] == '.') ||
(len == 2 && filename[0] == '.' && filename[1] == '.'))
{
return 0;
}
if (!ventoy_img_name_valid(filename, len))
{
return 0;
}
if (filename[0] == '$' && 0 == grub_strncmp(filename, "$RECYCLE.BIN", 12))
{
return 0;
}
if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
{
grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s/", node->dir, filename);
index = ventoy_plugin_get_image_list_index(vtoy_class_directory, g_img_swap_tmp_buf);
if (index == 0)
{
debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
return 0;
}
}
new_node = grub_zalloc(sizeof(img_iterator_node));
if (new_node)
{
new_node->level = node->level + 1;
new_node->plugin_list_index = index;
new_node->dirlen = grub_snprintf(new_node->dir, sizeof(new_node->dir), "%s%s/", node->dir, filename);
g_enum_fs->fs_dir(g_enum_dev, new_node->dir, ventoy_check_ignore_flag, &ignore);
if (ignore)
{
debug("Directory %s ignored...\n", new_node->dir);
grub_free(new_node);
return 0;
}
new_node->tail = node->tail;
new_node->parent = node;
if (!node->firstchild)
{
node->firstchild = new_node;
}
if (g_img_iterator_tail)
{
g_img_iterator_tail->next = new_node;
g_img_iterator_tail = new_node;
}
else
{
g_img_iterator_head.next = new_node;
g_img_iterator_tail = new_node;
}
}
}
else
{
debug("Find a file %s\n", filename);
if (len < 4)
{
return 0;
}
if (FILE_FLT(ISO) && 0 == grub_strcasecmp(filename + len - 4, ".iso"))
{
type = img_type_iso;
}
else if (FILE_FLT(WIM) && g_wimboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".wim")))
{
type = img_type_wim;
}
else if (FILE_FLT(VHD) && g_vhdboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".vhd") ||
(len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vhdx"))))
{
type = img_type_vhd;
}
#ifdef GRUB_MACHINE_EFI
else if (FILE_FLT(EFI) && 0 == grub_strcasecmp(filename + len - 4, ".efi"))
{
type = img_type_efi;
}
#endif
else if (FILE_FLT(IMG) && 0 == grub_strcasecmp(filename + len - 4, ".img"))
{
if (len == 18 && grub_strncmp(filename, "ventoy_", 7) == 0)
{
if (grub_strncmp(filename + 7, "wimboot", 7) == 0 ||
grub_strncmp(filename + 7, "vhdboot", 7) == 0)
{
return 0;
}
}
type = img_type_img;
}
else if (FILE_FLT(VTOY) && len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vtoy"))
{
type = img_type_vtoy;
}
else if (len >= 9 && 0 == grub_strcasecmp(filename + len - 5, ".vcfg"))
{
if (filename[len - 9] == '.' || (len >= 10 && filename[len - 10] == '.'))
{
grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf);
}
return 0;
}
else
{
return 0;
}
if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
{
return 0;
}
if (g_plugin_image_list)
{
grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
index = ventoy_plugin_get_image_list_index(vtoy_class_image_file, g_img_swap_tmp_buf);
if (VENTOY_IMG_WHITE_LIST == g_plugin_image_list && index == 0)
{
debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
return 0;
}
else if (VENTOY_IMG_BLACK_LIST == g_plugin_image_list && index > 0)
{
debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf, index);
return 0;
}
}
img = grub_zalloc(sizeof(img_info));
if (img)
{
img->type = type;
img->plugin_list_index = index;
grub_snprintf(img->name, sizeof(img->name), "%s", filename);
img->pathlen = grub_snprintf(img->path, sizeof(img->path), "%s%s", node->dir, img->name);
img->size = info->size;
if (0 == img->size)
{
img->size = ventoy_grub_get_file_size("%s/%s%s", g_iso_path, node->dir, filename);
}
if (img->size < VTOY_FILT_MIN_FILE_SIZE)
{
debug("img <%s> size too small %llu\n", img->name, (ulonglong)img->size);
grub_free(img);
return 0;
}
if (g_ventoy_img_list)
{
tail = *(node->tail);
img->prev = tail;
tail->next = img;
}
else
{
g_ventoy_img_list = img;
}
img->id = g_ventoy_img_count;
img->parent = node;
if (node && NULL == node->firstiso)
{
node->firstiso = img;
}
node->isocnt++;
tmp = node->parent;
while (tmp)
{
tmp->isocnt++;
tmp = tmp->parent;
}
*((img_info **)(node->tail)) = img;
g_ventoy_img_count++;
img->alias = ventoy_plugin_get_menu_alias(vtoy_alias_image_file, img->path);
img->class = ventoy_plugin_get_menu_class(vtoy_class_image_file, img->name, img->path);
if (!img->class)
{
img->class = g_menu_class[type];
}
img->menu_prefix = g_menu_prefix[type];
if (img_type_iso == type)
{
if (ventoy_plugin_check_memdisk(img->path))
{
img->menu_prefix = "miso";
}
}
debug("Add %s%s to list %d\n", node->dir, filename, g_ventoy_img_count);
}
}
return 0;
}
static int ventoy_arch_mode_init(void)
{
#ifdef GRUB_MACHINE_EFI
if (grub_strcmp(GRUB_TARGET_CPU, "i386") == 0)
{
g_ventoy_plat_data = VTOY_PLAT_I386_UEFI;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "ia32");
}
else if (grub_strcmp(GRUB_TARGET_CPU, "arm64") == 0)
{
g_ventoy_plat_data = VTOY_PLAT_ARM64_UEFI;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "aa64");
}
else if (grub_strcmp(GRUB_TARGET_CPU, "mips64el") == 0)
{
g_ventoy_plat_data = VTOY_PLAT_MIPS_UEFI;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "mips");
}
else
{
g_ventoy_plat_data = VTOY_PLAT_X86_64_UEFI;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "uefi");
}
#else
g_ventoy_plat_data = VTOY_PLAT_X86_LEGACY;
grub_snprintf(g_arch_mode_suffix, sizeof(g_arch_mode_suffix), "%s", "legacy");
#endif
return 0;
}
int ventoy_fill_data(grub_uint32_t buflen, char *buffer)
{
int len = GRUB_UINT_MAX;
const char *value = NULL;
char name[32] = {0};
char plat[32] = {0};
char guidstr[32] = {0};
ventoy_guid guid = VENTOY_GUID;
const char *fmt1 = NULL;
const char *fmt2 = NULL;
const char *fmt3 = NULL;
grub_uint32_t *puint = (grub_uint32_t *)name;
grub_uint32_t *puint2 = (grub_uint32_t *)plat;
const char fmtdata[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
const char fmtcode[]={
0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
};
grub_memset(name, 0, sizeof(name));
puint[0] = grub_swap_bytes32(0x56454e54);
puint[3] = grub_swap_bytes32(0x4f4e0000);
puint[2] = grub_swap_bytes32(0x45525349);
puint[1] = grub_swap_bytes32(0x4f595f56);
value = ventoy_get_env(name);
grub_memset(name, 0, sizeof(name));
puint[1] = grub_swap_bytes32(0x5f544f50);
puint[0] = grub_swap_bytes32(0x56544c45);
fmt1 = ventoy_get_env(name);
if (!fmt1)
{
fmt1 = fmtdata;
}
grub_memset(name, 0, sizeof(name));
puint[1] = grub_swap_bytes32(0x5f4c4654);
puint[0] = grub_swap_bytes32(0x56544c45);
fmt2 = ventoy_get_env(name);
grub_memset(name, 0, sizeof(name));
puint[1] = grub_swap_bytes32(0x5f434c52);
puint[0] = grub_swap_bytes32(0x56544c45);
fmt3 = ventoy_get_env(name);
grub_memcpy(guidstr, &guid, sizeof(guid));
puint2[0] = grub_swap_bytes32(g_ventoy_plat_data);
/* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
len = grub_snprintf(buffer, buflen, fmtcode,
fmt1 ? fmt1 : fmtdata,
fmt2 ? fmt2 : fmtdata + 4,
value ? value : "", plat, guidstr,
fmt3 ? fmt3 : fmtdata + 6);
#pragma GCC diagnostic pop
grub_memset(name, 0, sizeof(name));
puint[0] = grub_swap_bytes32(0x76746f79);
puint[2] = grub_swap_bytes32(0x656e7365);
puint[1] = grub_swap_bytes32(0x5f6c6963);
ventoy_set_env(name, guidstr);
return len;
}
int ventoy_check_password(const vtoy_password *pwd, int retry)
{
int offset;
char input[256];
grub_uint8_t md5[16];
while (retry--)
{
grub_memset(input, 0, sizeof(input));
grub_printf("Enter password: ");
grub_refresh();
if (pwd->type == VTOY_PASSWORD_TXT)
{
grub_password_get(input, 128);
if (grub_strcmp(pwd->text, input) == 0)
{
return 0;
}
}
else if (pwd->type == VTOY_PASSWORD_MD5)
{
grub_password_get(input, 128);
grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
if (grub_memcmp(pwd->md5, md5, 16) == 0)
{
return 0;
}
}
else if (pwd->type == VTOY_PASSWORD_SALT_MD5)
{
offset = (int)grub_snprintf(input, 128, "%s", pwd->salt);
grub_password_get(input + offset, 128);
grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
if (grub_memcmp(pwd->md5, md5, 16) == 0)
{
return 0;
}
}
grub_printf("Invalid password!\n\n");
grub_refresh();
}
return 1;
}
static img_info * ventoy_get_min_iso(img_iterator_node *node)
{
img_info *minimg = NULL;
img_info *img = (img_info *)(node->firstiso);
while (img && (img_iterator_node *)(img->parent) == node)
{
if (img->select == 0 && (NULL == minimg || ventoy_cmp_img(img, minimg) < 0))
{
minimg = img;
}
img = img->next;
}
if (minimg)
{
minimg->select = 1;
}
return minimg;
}
static img_iterator_node * ventoy_get_min_child(img_iterator_node *node)
{
img_iterator_node *Minchild = NULL;
img_iterator_node *child = node->firstchild;
while (child && child->parent == node)
{
if (child->select == 0 && (NULL == Minchild || ventoy_cmp_subdir(child, Minchild) < 0))
{
Minchild = child;
}
child = child->next;
}
if (Minchild)
{
Minchild->select = 1;
}
return Minchild;
}
static int ventoy_dynamic_tree_menu(img_iterator_node *node)
{
int offset = 1;
img_info *img = NULL;
const char *dir_class = NULL;
const char *dir_alias = NULL;
img_iterator_node *child = NULL;
if (node->isocnt == 0 || node->done == 1)
{
return 0;
}
if (node->parent && node->parent->dirlen < node->dirlen)
{
offset = node->parent->dirlen;
}
if (node == &g_img_iterator_head)
{
if (g_default_menu_mode == 0)
{
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo 'return ...' \n"
"}\n", "<--");
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo '%s ...' \n"
"}\n", "return");
}
}
}
else
{
node->dir[node->dirlen - 1] = 0;
dir_class = ventoy_plugin_get_menu_class(vtoy_class_directory, node->dir, node->dir);
if (!dir_class)
{
dir_class = "vtoydir";
}
dir_alias = ventoy_plugin_get_menu_alias(vtoy_alias_directory, node->dir);
if (dir_alias)
{
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
"DIR", dir_alias, dir_class, node->dir + offset);
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
dir_alias, dir_class, node->dir + offset);
}
}
else
{
dir_alias = node->dir + offset;
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
"DIR", dir_alias, dir_class, node->dir + offset);
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
dir_alias, dir_class, node->dir + offset);
}
}
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo 'return ...' \n"
"}\n", "<--");
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo '%s ...' \n"
"}\n", "return");
}
}
while ((child = ventoy_get_min_child(node)) != NULL)
{
ventoy_dynamic_tree_menu(child);
}
while ((img = ventoy_get_min_iso(node)) != NULL)
{
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
" %s_%s \n"
"}\n",
grub_get_human_size(img->size, GRUB_HUMAN_SIZE_SHORT),
img->unsupport ? "[***********] " : "",
img->alias ? img->alias : img->name, img->class, img->id,
img->menu_prefix,
img->unsupport ? "unsupport_menuentry" : "common_menuentry");
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
" %s_%s \n"
"}\n",
img->unsupport ? "[***********] " : "",
img->alias ? img->alias : img->name, img->class, img->id,
img->menu_prefix,
img->unsupport ? "unsupport_menuentry" : "common_menuentry");
}
}
if (node != &g_img_iterator_head)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "%s", "}\n");
}
node->done = 1;
return 0;
}
int ventoy_check_device_result(int ret)
{
char buf[32];
grub_snprintf(buf, sizeof(buf), "%d", (ret & 0x7FFF));
grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf);
grub_env_export("VTOY_CHKDEV_RESULT_STRING");
if (ret)
{
grub_printf(VTOY_WARNING"\n");
grub_printf(VTOY_WARNING"\n");
grub_printf(VTOY_WARNING"\n\n\n");
grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret);
grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
grub_printf("\n\nWill exit after 10 seconds ...... ");
grub_refresh();
grub_sleep(10);
}
return ret;
}
int ventoy_check_device(grub_device_t dev)
{
int workaround = 0;
grub_file_t file;
grub_uint64_t offset;
char devname[64];
grub_fs_t fs;
grub_device_t dev2;
char *label = NULL;
struct grub_partition *partition;
if (dev->disk == NULL || dev->disk->partition == NULL)
{
return ventoy_check_device_result(1 | 0x1000);
}
if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev->disk->name) ||
0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev->disk->name) ||
0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
{
#ifndef GRUB_MACHINE_EFI
if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev->disk->name) ||
0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev->disk->name) ||
0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
{
return ventoy_check_device_result(2 | 0x1000);
}
else
{
workaround = 1;
}
#endif
}
/* We must have partition 2 */
if (workaround)
{
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
}
else
{
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(%s,2)/ventoy/ventoy.cpio", dev->disk->name);
}
if (!file)
{
return ventoy_check_device_result(3 | 0x1000);
}
if (NULL == grub_strstr(file->fs->name, "fat"))
{
grub_file_close(file);
return ventoy_check_device_result(4 | 0x1000);
}
partition = dev->disk->partition;
if (partition->number != 0 || partition->start != 2048)
{
return ventoy_check_device_result(5);
}
if (workaround)
{
if (grub_strncmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
{
ventoy_gpt_part_tbl *PartTbl = g_ventoy_part_info->PartTbl;
if (PartTbl[1].StartLBA != PartTbl[0].LastLBA + 1 ||
(PartTbl[1].LastLBA + 1 - PartTbl[1].StartLBA) != 65536)
{
grub_file_close(file);
return ventoy_check_device_result(6);
}
}
else
{
ventoy_part_table *PartTbl = g_ventoy_part_info->MBR.PartTbl;
if (PartTbl[1].StartSectorId != PartTbl[0].StartSectorId + PartTbl[0].SectorCount ||
PartTbl[1].SectorCount != 65536)
{
grub_file_close(file);
return ventoy_check_device_result(6);
}
}
}
else
{
offset = partition->start + partition->len;
partition = file->device->disk->partition;
if ((partition->number != 1) || (partition->len != 65536) || (offset != partition->start))
{
grub_file_close(file);
return ventoy_check_device_result(7);
}
}
grub_file_close(file);
if (workaround == 0)
{
grub_snprintf(devname, sizeof(devname), "%s,2", dev->disk->name);
dev2 = grub_device_open(devname);
if (!dev2)
{
return ventoy_check_device_result(8);
}
fs = grub_fs_probe(dev2);
if (!fs)
{
grub_device_close(dev2);
return ventoy_check_device_result(9);
}
fs->fs_label(dev2, &label);
if ((!label) || grub_strncmp("VTOYEFI", label, 7))
{
grub_device_close(dev2);
return ventoy_check_device_result(10);
}
grub_device_close(dev2);
}
return ventoy_check_device_result(0);
}
static int ventoy_set_default_menu(void)
{
int img_len = 0;
char *pos = NULL;
char *end = NULL;
char *def = NULL;
const char *strdata = NULL;
img_info *cur = NULL;
img_info *default_node = NULL;
const char *default_image = NULL;
default_image = ventoy_get_env("VTOY_DEFAULT_IMAGE");
if (default_image && default_image[0] == '/')
{
img_len = grub_strlen(default_image);
for (cur = g_ventoy_img_list; cur; cur = cur->next)
{
if (img_len == cur->pathlen && grub_strcmp(default_image, cur->path) == 0)
{
default_node = cur;
break;
}
}
if (!default_node)
{
return 1;
}
if (0 == g_default_menu_mode)
{
vtoy_ssprintf(g_list_script_buf, g_list_script_pos, "set default='VID_%d'\n", default_node->id);
}
else
{
def = grub_strdup(default_image);
if (!def)
{
return 1;
}
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "set default=%c", '\'');
strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
if (strdata && strdata[0] == '/')
{
pos = def + grub_strlen(strdata);
if (*pos == '/')
{
pos++;
}
}
else
{
pos = def + 1;
}
while ((end = grub_strchr(pos, '/')) != NULL)
{
*end = 0;
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "DIR_%s>", pos);
pos = end + 1;
}
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "VID_%d'\n", default_node->id);
grub_free(def);
}
}
return 0;
}
static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len;
grub_fs_t fs;
grub_device_t dev = NULL;
img_info *cur = NULL;
img_info *tail = NULL;
const char *strdata = NULL;
char *device_name = NULL;
char buf[32];
img_iterator_node *node = NULL;
img_iterator_node *tmp = NULL;
(void)ctxt;
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {device} {cntvar}", cmd_raw_name);
}
if (g_ventoy_img_list || g_ventoy_img_count)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Must clear image before list");
}
g_enumerate_time_checked = 0;
g_enumerate_start_time_ms = grub_get_time_ms();
strdata = ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
if (strdata && strdata[0] == '1' && strdata[1] == 0)
{
g_filt_dot_underscore_file = 1;
}
strdata = ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
if (strdata && strdata[0] == '1' && strdata[1] == 0)
{
g_sort_case_sensitive = 1;
}
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
goto fail;
}
g_enum_dev = dev = grub_device_open(device_name);
if (!dev)
{
goto fail;
}
g_enum_fs = fs = grub_fs_probe(dev);
if (!fs)
{
goto fail;
}
if (ventoy_get_fs_type(fs->name) >= ventoy_fs_max)
{
debug("unsupported fs:<%s>\n", fs->name);
ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
goto fail;
}
ventoy_set_env("vtoy_iso_fs", fs->name);
strdata = ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
if (strdata && strdata[0] == '1')
{
g_default_menu_mode = 1;
}
grub_memset(&g_img_iterator_head, 0, sizeof(g_img_iterator_head));
grub_snprintf(g_iso_path, sizeof(g_iso_path), "%s", args[0]);
strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
if (strdata && strdata[0] == '/')
{
len = grub_snprintf(g_img_iterator_head.dir, sizeof(g_img_iterator_head.dir) - 1, "%s", strdata);
if (g_img_iterator_head.dir[len - 1] != '/')
{
g_img_iterator_head.dir[len++] = '/';
}
g_img_iterator_head.dirlen = len;
}
else
{
g_img_iterator_head.dirlen = 1;
grub_strcpy(g_img_iterator_head.dir, "/");
}
g_img_iterator_head.tail = &tail;
if (g_img_max_search_level < 0)
{
g_img_max_search_level = GRUB_INT_MAX;
strdata = ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
if (strdata && ventoy_is_decimal(strdata))
{
g_img_max_search_level = (int)grub_strtoul(strdata, NULL, 10);
}
}
g_vtoy_file_flt[VTOY_FILE_FLT_ISO] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
g_vtoy_file_flt[VTOY_FILE_FLT_WIM] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
g_vtoy_file_flt[VTOY_FILE_FLT_EFI] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
g_vtoy_file_flt[VTOY_FILE_FLT_IMG] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
g_vtoy_file_flt[VTOY_FILE_FLT_VHD] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
g_vtoy_file_flt[VTOY_FILE_FLT_VTOY] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
for (node = &g_img_iterator_head; node; node = node->next)
{
fs->fs_dir(dev, node->dir, ventoy_collect_img_files, node);
}
strdata = ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
if (strdata && strdata[0] == '1' && strdata[1] == 0)
{
g_tree_view_menu_style = 1;
}
ventoy_set_default_menu();
for (node = &g_img_iterator_head; node; node = node->next)
{
ventoy_dynamic_tree_menu(node);
}
/* free node */
node = g_img_iterator_head.next;
while (node)
{
tmp = node->next;
grub_free(node);
node = tmp;
}
/* sort image list by image name */
for (cur = g_ventoy_img_list; cur; cur = cur->next)
{
for (tail = cur->next; tail; tail = tail->next)
{
if (ventoy_cmp_img(cur, tail) > 0)
{
ventoy_swap_img(cur, tail);
}
}
}
if (g_default_menu_mode == 1)
{
vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
"menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo 'return ...' \n"
"}\n", "<--");
}
for (cur = g_ventoy_img_list; cur; cur = cur->next)
{
vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
"menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
" %s_%s \n"
"}\n",
cur->unsupport ? "[***********] " : "",
cur->alias ? cur->alias : cur->name, cur->class, cur->id,
cur->menu_prefix,
cur->unsupport ? "unsupport_menuentry" : "common_menuentry");
}
g_tree_script_buf[g_tree_script_pos] = 0;
g_list_script_buf[g_list_script_pos] = 0;
grub_snprintf(buf, sizeof(buf), "%d", g_ventoy_img_count);
grub_env_set(args[1], buf);
fail:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_clear_img(grub_extcmd_context_t ctxt, int argc, char **args)
{
img_info *next = NULL;
img_info *cur = g_ventoy_img_list;
(void)ctxt;
(void)argc;
(void)args;
while (cur)
{
next = cur->next;
grub_free(cur);
cur = next;
}
g_ventoy_img_list = NULL;
g_ventoy_img_count = 0;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_img_name(grub_extcmd_context_t ctxt, int argc, char **args)
{
long img_id = 0;
img_info *cur = g_ventoy_img_list;
(void)ctxt;
if (argc != 2 || (!ventoy_is_decimal(args[0])))
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {imageID} {var}", cmd_raw_name);
}
img_id = grub_strtol(args[0], NULL, 10);
if (img_id >= g_ventoy_img_count)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images %ld %ld", img_id, g_ventoy_img_count);
}
debug("Find image %ld name \n", img_id);
while (cur && img_id > 0)
{
img_id--;
cur = cur->next;
}
if (!cur)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images");
}
debug("image name is %s\n", cur->name);
grub_env_set(args[1], cur->name);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len = 0;
char id[32] = {0};
img_info *cur = g_ventoy_img_list;
(void)ctxt;
if (argc != 1)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
}
len = (int)grub_strlen(args[0]);
while (cur)
{
if (len == cur->pathlen && 0 == grub_strcmp(args[0], cur->path))
{
break;
}
cur = cur->next;
}
if (!cur)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
}
grub_snprintf(id, sizeof(id), "VID_%d", cur->id);
grub_env_set("chosen", id);
grub_env_export("chosen");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
{
int img_id = 0;
char value[32];
char *pos = NULL;
const char *id = NULL;
img_info *cur = g_ventoy_img_list;
(void)ctxt;
if (argc < 1 || argc > 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
}
id = grub_env_get("chosen");
pos = grub_strstr(id, "VID_");
if (pos)
{
img_id = (int)grub_strtoul(pos + 4, NULL, 10);
}
else
{
img_id = (int)grub_strtoul(id, NULL, 10);
}
while (cur)
{
if (img_id == cur->id)
{
break;
}
cur = cur->next;
}
if (!cur)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
}
grub_env_set(args[0], cur->path);
if (argc > 1)
{
grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size));
grub_env_set(args[1], value);
}
g_svd_replace_offset = 0;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t *signature)
{
grub_disk_t disk;
char *device_name;
char *pos;
char *pos2;
device_name = grub_file_get_device_name(filename);
if (!device_name)
{
return 1;
}
pos = device_name;
if (pos[0] == '(')
{
pos++;
}
pos2 = grub_strstr(pos, ",");
if (!pos2)
{
pos2 = grub_strstr(pos, ")");
}
if (pos2)
{
*pos2 = 0;
}
disk = grub_disk_open(pos);
if (disk)
{
grub_disk_read(disk, 0, 0x180, 16, guid);
grub_disk_read(disk, 0, 0x1b8, 4, signature);
grub_disk_close(disk);
}
else
{
return 1;
}
grub_free(device_name);
return 0;
}
grub_uint32_t ventoy_get_iso_boot_catlog(grub_file_t file)
{
eltorito_descriptor desc;
grub_memset(&desc, 0, sizeof(desc));
grub_file_seek(file, 17 * 2048);
grub_file_read(file, &desc, sizeof(desc));
if (desc.type != 0 || desc.version != 1)
{
return 0;
}
if (grub_strncmp((char *)desc.id, "CD001", 5) != 0 ||
grub_strncmp((char *)desc.system_id, "EL TORITO SPECIFICATION", 23) != 0)
{
return 0;
}
return desc.sector;
}
int ventoy_has_efi_eltorito(grub_file_t file, grub_uint32_t sector)
{
int i;
int x86count = 0;
grub_uint8_t buf[512];
grub_uint8_t parttype[] = { 0x04, 0x06, 0x0B, 0x0C };
grub_file_seek(file, sector * 2048);
grub_file_read(file, buf, sizeof(buf));
if (buf[0] == 0x01 && buf[1] == 0xEF)
{
debug("%s efi eltorito in Validation Entry\n", file->name);
return 1;
}
if (buf[0] == 0x01 && buf[1] == 0x00)
{
x86count++;
}
for (i = 64; i < (int)sizeof(buf); i += 32)
{
if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF)
{
debug("%s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
return 1;
}
if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0x00 && x86count == 1)
{
debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
return 1;
}
}
if (x86count && buf[32] == 0x88 && buf[33] == 0x04)
{
for (i = 0; i < (int)(ARRAY_SIZE(parttype)); i++)
{
if (buf[36] == parttype[i])
{
debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file->name, buf[36]);
return 1;
}
}
}
debug("%s does not contain efi eltorito\n", file->name);
return 0;
}
void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
{
char *pos;
const char *fs = NULL;
const char *cdprompt = NULL;
grub_uint32_t i;
grub_uint8_t chksum = 0;
grub_disk_t disk;
disk = file->device->disk;
grub_memcpy(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid));
param->vtoy_disk_size = disk->total_sectors * (1 << disk->log_sector_size);
param->vtoy_disk_part_id = disk->partition->number + 1;
param->vtoy_disk_part_type = ventoy_get_fs_type(file->fs->name);
pos = grub_strstr(file->name, "/");
if (!pos)
{
pos = file->name;
}
grub_snprintf(param->vtoy_img_path, sizeof(param->vtoy_img_path), "%s", pos);
ventoy_get_disk_guid(file->name, param->vtoy_disk_guid, param->vtoy_disk_signature);
param->vtoy_img_size = file->size;
param->vtoy_reserved[0] = g_ventoy_break_level;
param->vtoy_reserved[1] = g_ventoy_debug_level;
param->vtoy_reserved[2] = g_ventoy_chain_type;
/* Windows CD/DVD prompt 0:suppress 1:reserved */
param->vtoy_reserved[4] = 0;
if (g_ventoy_chain_type == 1) /* Windows */
{
cdprompt = ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
if (cdprompt && cdprompt[0] == '1' && cdprompt[1] == 0)
{
param->vtoy_reserved[4] = 1;
}
}
fs = ventoy_get_env("ventoy_fs_probe");
if (fs && grub_strcmp(fs, "udf") == 0)
{
param->vtoy_reserved[3] = 1;
}
/* calculate checksum */
for (i = 0; i < sizeof(ventoy_os_param); i++)
{
chksum += *((grub_uint8_t *)param + i);
}
param->chksum = (grub_uint8_t)(0x100 - chksum);
return;
}
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
{
grub_uint32_t i = 0;
grub_uint64_t total = 0;
grub_uint64_t fileblk = 0;
ventoy_img_chunk *chunk = NULL;
for (i = 0; i < chunklist->cur_chunk; i++)
{
chunk = chunklist->chunk + i;
if (chunk->disk_start_sector <= start)
{
debug("%u disk start invalid %lu\n", i, (ulong)start);
return 1;
}
total += chunk->disk_end_sector + 1 - chunk->disk_start_sector;
}
fileblk = (file->size + 511) / 512;
if (total != fileblk)
{
debug("Invalid total: %llu %llu\n", (ulonglong)total, (ulonglong)fileblk);
if ((file->size % 512) && (total + 1 == fileblk))
{
debug("maybe img file to be processed.\n");
return 0;
}
return 1;
}
return 0;
}
int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
{
int fs_type;
int len;
grub_uint32_t i = 0;
grub_uint32_t sector = 0;
grub_uint32_t count = 0;
grub_off_t size = 0;
grub_off_t read = 0;
fs_type = ventoy_get_fs_type(file->fs->name);
if (fs_type == ventoy_fs_exfat)
{
grub_fat_get_file_chunk(start, file, chunklist);
}
else if (fs_type == ventoy_fs_ext)
{
grub_ext_get_file_chunk(start, file, chunklist);
}
else
{
file->read_hook = (grub_disk_read_hook_t)grub_disk_blocklist_read;
file->read_hook_data = chunklist;
for (size = file->size; size > 0; size -= read)
{
read = (size > VTOY_SIZE_1GB) ? VTOY_SIZE_1GB : size;
grub_file_read(file, NULL, read);
}
for (i = 0; start > 0 && i < chunklist->cur_chunk; i++)
{
chunklist->chunk[i].disk_start_sector += start;
chunklist->chunk[i].disk_end_sector += start;
}
if (ventoy_fs_udf == fs_type)
{
for (i = 0; i < chunklist->cur_chunk; i++)
{
count = (chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector) >> 2;
chunklist->chunk[i].img_start_sector = sector;
chunklist->chunk[i].img_end_sector = sector + count - 1;
sector += count;
}
}
}
len = (int)grub_strlen(file->name);
if ((len > 4 && grub_strncasecmp(file->name + len - 4, ".img", 4) == 0) ||
(len > 4 && grub_strncasecmp(file->name + len - 4, ".vhd", 4) == 0) ||
(len > 5 && grub_strncasecmp(file->name + len - 5, ".vhdx", 5) == 0) ||
(len > 5 && grub_strncasecmp(file->name + len - 5, ".vtoy", 5) == 0))
{
for (i = 0; i < chunklist->cur_chunk; i++)
{
count = chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector;
if (count < 4)
{
count = 1;
}
else
{
count >>= 2;
}
chunklist->chunk[i].img_start_sector = sector;
chunklist->chunk[i].img_end_sector = sector + count - 1;
sector += count;
}
}
return 0;
}
static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc;
grub_file_t file;
grub_disk_addr_t start;
(void)ctxt;
(void)argc;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
}
g_conf_replace_node = NULL;
g_conf_replace_offset = 0;
if (g_img_chunk_list.chunk)
{
grub_free(g_img_chunk_list.chunk);
}
if (ventoy_get_fs_type(file->fs->name) >= ventoy_fs_max)
{
grub_file_close(file);
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Unsupported filesystem %s\n", file->fs->name);
}
/* get image chunk data */
grub_memset(&g_img_chunk_list, 0, sizeof(g_img_chunk_list));
g_img_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
if (NULL == g_img_chunk_list.chunk)
{
return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
}
g_img_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
g_img_chunk_list.cur_chunk = 0;
start = file->device->disk->partition->start;
ventoy_get_block_list(file, &g_img_chunk_list, start);
rc = ventoy_check_block_list(file, &g_img_chunk_list, start);
grub_file_close(file);
if (rc)
{
return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported chunk list.\n");
}
grub_memset(&g_grub_param->file_replace, 0, sizeof(g_grub_param->file_replace));
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_select_conf_replace(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint64_t offset = 0;
grub_uint32_t align = 0;
grub_file_t file = NULL;
conf_replace *node = NULL;
(void)ctxt;
(void)argc;
(void)args;
debug("select conf replace argc:%d\n", argc);
if (argc < 2)
{
return 0;
}
node = ventoy_plugin_find_conf_replace(args[1]);
if (!node)
{
debug("Conf replace not found for %s\n", args[1]);
goto end;
}
debug("Find conf replace for %s\n", args[1]);
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", node->orgconf);
if (!file)
{
debug("<(loop)%s> NOT exist\n", node->orgconf);
goto end;
}
offset = grub_iso9660_get_last_file_dirent_pos(file);
grub_file_close(file);
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], node->newconf);
if (!file)
{
debug("New config file <%s%s> NOT exist\n", args[0], node->newconf);
goto end;
}
align = ((int)file->size + 2047) / 2048 * 2048;
if (align > vtoy_max_replace_file_size)
{
debug("New config file <%s%s> too big\n", args[0], node->newconf);
goto end;
}
grub_file_read(file, g_conf_replace_new_buf, file->size);
g_conf_replace_new_len = (int)file->size;
g_conf_replace_new_len_align = align;
g_conf_replace_node = node;
g_conf_replace_offset = offset + 2;
debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len);
end:
if (file)
{
grub_file_close(file);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i = 0;
int pos = 0;
char *buf = NULL;
char configfile[128];
install_template *node = NULL;
(void)ctxt;
(void)argc;
(void)args;
debug("select auto installation argc:%d\n", argc);
if (argc < 1)
{
return 0;
}
node = ventoy_plugin_find_install_template(args[0]);
if (!node)
{
debug("Auto install template not found for %s\n", args[0]);
return 0;
}
if (node->autosel >= 0 && node->autosel <= node->templatenum)
{
node->cursel = node->autosel - 1;
debug("Auto install template auto select %d\n", node->autosel);
return 0;
}
buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
if (!buf)
{
return 0;
}
vtoy_ssprintf(buf, pos, "menuentry \"Boot without auto installation template\" {\n"
" echo %s\n}\n", "123");
for (i = 0; i < node->templatenum; i++)
{
vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" {\n"
" echo 123\n}\n",
node->templatepath[i].path);
}
g_ventoy_menu_esc = 1;
g_ventoy_suppress_esc = 1;
grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
grub_script_execute_sourcecode(configfile);
g_ventoy_menu_esc = 0;
g_ventoy_suppress_esc = 0;
grub_free(buf);
node->cursel = g_ventoy_last_entry - 1;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i = 0;
int pos = 0;
char *buf = NULL;
char configfile[128];
persistence_config *node;
(void)ctxt;
(void)argc;
(void)args;
debug("select persistence argc:%d\n", argc);
if (argc < 1)
{
return 0;
}
node = ventoy_plugin_find_persistent(args[0]);
if (!node)
{
debug("Persistence image not found for %s\n", args[0]);
return 0;
}
if (node->autosel >= 0 && node->autosel <= node->backendnum)
{
node->cursel = node->autosel - 1;
debug("Persistence image auto select %d\n", node->autosel);
return 0;
}
buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
if (!buf)
{
return 0;
}
vtoy_ssprintf(buf, pos, "menuentry \"Boot without persistence\" {\n"
" echo %s\n}\n", "123");
for (i = 0; i < node->backendnum; i++)
{
vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" {\n"
" echo 123\n}\n",
node->backendpath[i].path);
}
g_ventoy_menu_esc = 1;
g_ventoy_suppress_esc = 1;
grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
grub_script_execute_sourcecode(configfile);
g_ventoy_menu_esc = 0;
g_ventoy_suppress_esc = 0;
grub_free(buf);
node->cursel = g_ventoy_last_entry - 1;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint32_t i;
ventoy_img_chunk *cur;
(void)ctxt;
(void)argc;
(void)args;
for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
{
cur = g_img_chunk_list.chunk + i;
grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
cur->img_start_sector, cur->img_end_sector,
(unsigned long long)cur->disk_start_sector, (unsigned long long)cur->disk_end_sector
);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint32_t i;
grub_file_t file;
ventoy_img_chunk_list chunklist;
(void)ctxt;
(void)argc;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
}
/* get image chunk data */
grub_memset(&chunklist, 0, sizeof(chunklist));
chunklist.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
if (NULL == chunklist.chunk)
{
return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
}
chunklist.max_chunk = DEFAULT_CHUNK_NUM;
chunklist.cur_chunk = 0;
ventoy_get_block_list(file, &chunklist, 0);
if (0 != ventoy_check_block_list(file, &chunklist, 0))
{
grub_printf("########## UNSUPPORTED ###############\n");
}
grub_printf("filesystem: <%s> entry number:<%u>\n", file->fs->name, chunklist.cur_chunk);
for (i = 0; i < chunklist.cur_chunk; i++)
{
grub_printf("%llu+%llu,", (ulonglong)chunklist.chunk[i].disk_start_sector,
(ulonglong)(chunklist.chunk[i].disk_end_sector + 1 - chunklist.chunk[i].disk_start_sector));
}
grub_printf("\n==================================\n");
for (i = 0; i < chunklist.cur_chunk; i++)
{
grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i,
(ulonglong)chunklist.chunk[i].img_start_sector,
(ulonglong)chunklist.chunk[i].img_end_sector,
(ulonglong)chunklist.chunk[i].disk_start_sector,
(ulonglong)chunklist.chunk[i].disk_end_sector
);
}
grub_free(chunklist.chunk);
grub_file_close(file);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
ventoy_grub_param_file_replace *replace = NULL;
(void)ctxt;
(void)argc;
(void)args;
if (argc >= 2)
{
replace = &(g_grub_param->file_replace);
replace->magic = GRUB_FILE_REPLACE_MAGIC;
replace->old_name_cnt = 0;
for (i = 0; i < 4 && i + 1 < argc; i++)
{
replace->old_name_cnt++;
grub_snprintf(replace->old_file_name[i], sizeof(replace->old_file_name[i]), "%s", args[i + 1]);
}
replace->new_file_virtual_id = (grub_uint32_t)grub_strtoul(args[0], NULL, 10);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
if (argc == 0)
{
grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos, VTOY_MAX_SCRIPT_BUF);
grub_printf("%s", g_list_script_buf);
}
else
{
grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos, VTOY_MAX_SCRIPT_BUF);
grub_printf("%s", g_tree_script_buf);
}
return 0;
}
static grub_err_t ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt, int argc, char **args)
{
img_info *cur = g_ventoy_img_list;
(void)ctxt;
(void)argc;
(void)args;
while (cur)
{
grub_printf("path:<%s> id=%d list_index=%d\n", cur->path, cur->id, cur->plugin_list_index);
grub_printf("name:<%s>\n\n", cur->name);
cur = cur->next;
}
return 0;
}
static grub_err_t ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_plugin_dump_injection();
return 0;
}
static grub_err_t ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_plugin_dump_auto_install();
return 0;
}
static grub_err_t ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_plugin_dump_persistence();
return 0;
}
static grub_err_t ventoy_cmd_check_mode(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
if (argc != 1)
{
return 1;
}
if (args[0][0] == '0')
{
return g_ventoy_memdisk_mode ? 0 : 1;
}
else if (args[0][0] == '1')
{
return g_ventoy_iso_raw ? 0 : 1;
}
else if (args[0][0] == '2')
{
return g_ventoy_iso_uefi_drv ? 0 : 1;
}
else if (args[0][0] == '3')
{
return g_ventoy_grub2_mode ? 0 : 1;
}
return 1;
}
static grub_err_t ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt, int argc, char **args)
{
static int configfile_mode = 0;
char memfile[128] = {0};
(void)ctxt;
(void)argc;
(void)args;
/*
* args[0]: 0:normal 1:configfile
* args[1]: 0:list_buf 1:tree_buf
*/
if (argc != 2)
{
debug("Invalid argc %d\n", argc);
return 0;
}
if (args[0][0] == '0')
{
if (args[1][0] == '0')
{
grub_script_execute_sourcecode(g_list_script_buf);
}
else
{
grub_script_execute_sourcecode(g_tree_script_buf);
}
}
else
{
if (configfile_mode)
{
debug("Now already in F3 mode %d\n", configfile_mode);
return 0;
}
if (args[1][0] == '0')
{
grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
(ulonglong)(ulong)g_list_script_buf, g_list_script_pos);
}
else
{
g_ventoy_last_entry = -1;
grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
(ulonglong)(ulong)g_tree_script_buf, g_tree_script_pos);
}
configfile_mode = 1;
grub_script_execute_sourcecode(memfile);
configfile_mode = 0;
}
return 0;
}
static grub_err_t ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_file_t file;
(void)ctxt;
if (argc != 1)
{
return 1;
}
g_ventoy_case_insensitive = 1;
file = grub_file_open(args[0], VENTOY_FILE_TYPE);
g_ventoy_case_insensitive = 0;
grub_errno = 0;
if (file)
{
grub_file_close(file);
return 0;
}
return 1;
}
static grub_err_t ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt, int argc, char **args)
{
int id = 0;
int find = 0;
grub_disk_t disk;
const char *isopath = NULL;
char hdname[32];
ventoy_mbr_head mbr;
(void)ctxt;
(void)argc;
if (argc != 1)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s variable\n", cmd_raw_name);
}
isopath = grub_env_get("vtoy_iso_part");
if (!isopath)
{
debug("isopath is null %p\n", isopath);
return 0;
}
debug("isopath is %s\n", isopath);
for (id = 0; id < 30 && (find == 0); id++)
{
grub_snprintf(hdname, sizeof(hdname), "hd%d,", id);
if (grub_strstr(isopath, hdname))
{
debug("skip %s ...\n", hdname);
continue;
}
grub_snprintf(hdname, sizeof(hdname), "hd%d", id);
disk = grub_disk_open(hdname);
if (!disk)
{
debug("%s not exist\n", hdname);
break;
}
grub_memset(&mbr, 0, sizeof(mbr));
if (0 == grub_disk_read(disk, 0, 0, 512, &mbr))
{
if (mbr.Byte55 == 0x55 && mbr.ByteAA == 0xAA)
{
if (mbr.PartTbl[0].Active == 0x80 || mbr.PartTbl[1].Active == 0x80 ||
mbr.PartTbl[2].Active == 0x80 || mbr.PartTbl[3].Active == 0x80)
{
grub_env_set(args[0], hdname);
find = 1;
}
}
debug("%s is %s\n", hdname, find ? "bootable" : "NOT bootable");
}
else
{
debug("read %s failed\n", hdname);
}
grub_disk_close(disk);
}
return 0;
}
static grub_err_t ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len = 1024;
grub_file_t file;
char *buf = NULL;
(void)ctxt;
(void)argc;
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file var \n", cmd_raw_name);
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 0;
}
buf = grub_malloc(len);
if (!buf)
{
goto end;
}
buf[len - 1] = 0;
grub_file_read(file, buf, len - 1);
ventoy_get_line(buf);
ventoy_set_env(args[1], buf);
end:
grub_check_free(buf);
grub_file_close(file);
return 0;
}
static int ventoy_img_partition_callback (struct grub_disk *disk, const grub_partition_t partition, void *data)
{
(void)disk;
(void)data;
g_part_list_pos += grub_snprintf(g_part_list_buf + g_part_list_pos, VTOY_MAX_SCRIPT_BUF - g_part_list_pos,
"0 %llu linear /dev/ventoy %llu\n",
(ulonglong)partition->len, (ulonglong)partition->start);
return 0;
}
static grub_err_t ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt, int argc, char **args)
{
char *device_name = NULL;
grub_device_t dev = NULL;
char buf[64];
(void)ctxt;
g_part_list_pos = 0;
grub_env_unset("vtoy_img_part_file");
if (argc != 1)
{
return 1;
}
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
debug("ventoy_cmd_img_part_info failed, %s\n", args[0]);
goto end;
}
dev = grub_device_open(device_name);
if (!dev)
{
debug("grub_device_open failed, %s\n", device_name);
goto end;
}
grub_partition_iterate(dev->disk, ventoy_img_partition_callback, NULL);
grub_snprintf(buf, sizeof(buf), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong)(ulong)g_part_list_buf, g_part_list_pos);
grub_env_set("vtoy_img_part_file", buf);
end:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
return 0;
}
static grub_err_t ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
grub_file_t file;
char *buf = NULL;
(void)ctxt;
(void)argc;
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file str \n", cmd_raw_name);
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 1;
}
buf = grub_malloc(file->size + 1);
if (!buf)
{
goto end;
}
buf[file->size] = 0;
grub_file_read(file, buf, file->size);
if (grub_strstr(buf, args[1]))
{
rc = 0;
}
end:
grub_check_free(buf);
grub_file_close(file);
return rc;
}
static grub_err_t ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len;
grub_file_t file;
char buf[64];
grub_uint64_t size;
ventoy_iso9660_vd pvd;
(void)ctxt;
(void)argc;
if (argc != 4)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s sysid volid space \n", cmd_raw_name);
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 0;
}
grub_file_seek(file, 16 * 2048);
len = (int)grub_file_read(file, &pvd, sizeof(pvd));
if (len != sizeof(pvd))
{
debug("failed to read pvd %d\n", len);
goto end;
}
grub_memset(buf, 0, sizeof(buf));
grub_memcpy(buf, pvd.sys, sizeof(pvd.sys));
ventoy_set_env(args[1], buf);
grub_memset(buf, 0, sizeof(buf));
grub_memcpy(buf, pvd.vol, sizeof(pvd.vol));
ventoy_set_env(args[2], buf);
size = pvd.space;
size *= 2048;
grub_snprintf(buf, sizeof(buf), "%llu", (ulonglong)size);
ventoy_set_env(args[3], buf);
end:
grub_file_close(file);
return 0;
}
static grub_err_t ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len;
grub_file_t file;
char buf[64];
(void)ctxt;
(void)argc;
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s var \n", cmd_raw_name);
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 0;
}
grub_memset(buf, 0, sizeof(buf));
grub_file_seek(file, 16 * 2048 + 813);
len = (int)grub_file_read(file, buf, 17);
if (len != 17)
{
debug("failed to read create date %d\n", len);
goto end;
}
ventoy_set_env(args[1], buf);
end:
grub_file_close(file);
return 0;
}
static grub_err_t ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_env_hook_root(1);
return 0;
}
static grub_err_t ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_env_hook_root(0);
return 0;
}
#ifdef GRUB_MACHINE_EFI
static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
{
int ret = 1;
grub_uint8_t *var;
grub_size_t size;
grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
(void)ctxt;
(void)argc;
(void)args;
var = grub_efi_get_variable("SecureBoot", &global, &size);
if (var && *var == 1)
{
return 0;
}
return ret;
}
#else
static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
return 1;
}
#endif
static grub_err_t ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int ret = 1;
grub_file_t file;
grub_uint64_t FileSectors = 0;
ventoy_gpt_info *gpt = NULL;
ventoy_part_table *pt = NULL;
grub_uint8_t zeroguid[16] = {0};
(void)ctxt;
(void)argc;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 1;
}
if (file->size % 512)
{
debug("unaligned file size: %llu\n", (ulonglong)file->size);
goto out;
}
gpt = grub_zalloc(sizeof(ventoy_gpt_info));
if (!gpt)
{
goto out;
}
FileSectors = file->size / 512;
grub_file_read(file, gpt, sizeof(ventoy_gpt_info));
if (grub_strncmp(gpt->Head.Signature, "EFI PART", 8) == 0)
{
debug("This is EFI partition table\n");
for (i = 0; i < 128; i++)
{
if (grub_memcmp(gpt->PartTbl[i].PartGuid, zeroguid, 16))
{
if (FileSectors < gpt->PartTbl[i].LastLBA)
{
debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
(ulonglong)gpt->PartTbl[i].LastLBA, (ulonglong)FileSectors);
goto out;
}
}
}
}
else
{
debug("This is MBR partition table\n");
for (i = 0; i < 4; i++)
{
pt = gpt->MBR.PartTbl + i;
if (FileSectors < pt->StartSectorId + pt->SectorCount)
{
debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
(ulonglong)(pt->StartSectorId + pt->SectorCount),
(ulonglong)FileSectors);
goto out;
}
}
}
ret = 0;
out:
grub_file_close(file);
grub_check_free(gpt);
grub_errno = GRUB_ERR_NONE;
return ret;
}
static grub_err_t ventoy_cmd_clear_key(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int ret;
(void)ctxt;
(void)argc;
(void)args;
for (i = 0; i < 500; i++)
{
ret = grub_getkey_noblock();
if (ret == GRUB_TERM_NO_KEY)
{
break;
}
}
if (i >= 500)
{
grub_cls();
grub_printf("\n\n Still have key input after clear.\n");
grub_refresh();
grub_sleep(5);
}
return 0;
}
static grub_err_t ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int buflen;
int datalen;
int loclen;
int img_chunk_num;
int image_sector_size;
char cmd[64];
ventoy_chain_head *chain;
ventoy_img_chunk *chunk;
ventoy_os_param *osparam;
ventoy_image_location *location;
ventoy_image_disk_region *region;
struct grub_acpi_table_header *acpi;
(void)ctxt;
if (argc != 2)
{
return 1;
}
debug("ventoy_cmd_acpi_param %s %s\n", args[0], args[1]);
chain = (ventoy_chain_head *)(ulong)grub_strtoul(args[0], NULL, 16);
if (!chain)
{
return 1;
}
image_sector_size = (int)grub_strtol(args[1], NULL, 10);
if (grub_memcmp(&g_ventoy_guid, &(chain->os_param.guid), 16))
{
debug("Invalid ventoy guid 0x%x\n", chain->os_param.guid.data1);
return 1;
}
img_chunk_num = chain->img_chunk_num;
loclen = sizeof(ventoy_image_location) + (img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
datalen = sizeof(ventoy_os_param) + loclen;
buflen = sizeof(struct grub_acpi_table_header) + datalen;
acpi = grub_zalloc(buflen);
if (!acpi)
{
return 1;
}
/* Step1: Fill acpi table header */
grub_memcpy(acpi->signature, "VTOY", 4);
acpi->length = buflen;
acpi->revision = 1;
grub_memcpy(acpi->oemid, "VENTOY", 6);
grub_memcpy(acpi->oemtable, "OSPARAMS", 8);
acpi->oemrev = 1;
acpi->creator_id[0] = 1;
acpi->creator_rev = 1;
/* Step2: Fill data */
osparam = (ventoy_os_param *)(acpi + 1);
grub_memcpy(osparam, &chain->os_param, sizeof(ventoy_os_param));
osparam->vtoy_img_location_addr = 0;
osparam->vtoy_img_location_len = loclen;
osparam->chksum = 0;
osparam->chksum = 0x100 - grub_byte_checksum(osparam, sizeof(ventoy_os_param));
location = (ventoy_image_location *)(osparam + 1);
grub_memcpy(&location->guid, &osparam->guid, sizeof(ventoy_guid));
location->image_sector_size = image_sector_size;
location->disk_sector_size = chain->disk_sector_size;
location->region_count = img_chunk_num;
region = location->regions;
chunk = (ventoy_img_chunk *)((char *)chain + chain->img_chunk_offset);
if (512 == image_sector_size)
{
for (i = 0; i < img_chunk_num; i++)
{
region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
region->image_start_sector = chunk->img_start_sector * 4;
region->disk_start_sector = chunk->disk_start_sector;
region++;
chunk++;
}
}
else
{
for (i = 0; i < img_chunk_num; i++)
{
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
region->image_start_sector = chunk->img_start_sector;
region->disk_start_sector = chunk->disk_start_sector;
region++;
chunk++;
}
}
/* Step3: Fill acpi checksum */
acpi->checksum = 0;
acpi->checksum = 0x100 - grub_byte_checksum(acpi, acpi->length);
/* load acpi table */
grub_snprintf(cmd, sizeof(cmd), "acpi mem:0x%lx:size:%d", (ulong)acpi, acpi->length);
grub_script_execute_sourcecode(cmd);
grub_free(acpi);
VENTOY_CMD_RETURN(0);
}
static grub_err_t ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
g_ventoy_last_entry_back = g_ventoy_last_entry;
g_ventoy_last_entry = -1;
return 0;
}
static grub_err_t ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
g_ventoy_last_entry = g_ventoy_last_entry_back;
return 0;
}
grub_uint64_t ventoy_get_part1_size(ventoy_gpt_info *gpt)
{
grub_uint64_t sectors;
if (grub_strncmp(gpt->Head.Signature, "EFI PART", 8) == 0)
{
sectors = gpt->PartTbl[0].LastLBA + 1 - gpt->PartTbl[0].StartLBA;
}
else
{
sectors = gpt->MBR.PartTbl[0].SectorCount;
}
return sectors * 512;
}
static int ventoy_lib_module_callback(const char *filename, const struct grub_dirhook_info *info, void *data)
{
const char *pos = filename + 1;
if (info->dir)
{
while (*pos)
{
if (*pos == '.')
{
if ((*(pos - 1) >= '0' && *(pos - 1) <= '9') && (*(pos + 1) >= '0' && *(pos + 1) <= '9'))
{
grub_strncpy((char *)data, filename, 128);
return 1;
}
}
pos++;
}
}
return 0;
}
static grub_err_t ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char *device_name = NULL;
grub_device_t dev = NULL;
grub_fs_t fs = NULL;
char buf[128] = {0};
(void)ctxt;
if (argc != 3)
{
debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc);
return 1;
}
debug("ventoy_cmd_lib_module_ver %s %s %s\n", args[0], args[1], args[2]);
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
debug("grub_file_get_device_name failed, %s\n", args[0]);
goto end;
}
dev = grub_device_open(device_name);
if (!dev)
{
debug("grub_device_open failed, %s\n", device_name);
goto end;
}
fs = grub_fs_probe(dev);
if (!fs)
{
debug("grub_fs_probe failed, %s\n", device_name);
goto end;
}
fs->fs_dir(dev, args[1], ventoy_lib_module_callback, buf);
if (buf[0])
{
ventoy_set_env(args[2], buf);
}
rc = 0;
end:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
return rc;
}
static grub_err_t ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt, int argc, char **args)
{
char name[64];
int ret;
grub_disk_t disk;
grub_device_t dev;
(void)argc;
(void)ctxt;
g_ventoy_part_info = grub_zalloc(sizeof(ventoy_gpt_info));
if (!g_ventoy_part_info)
{
return 1;
}
disk = grub_disk_open(args[0]);
if (!disk)
{
debug("Failed to open disk %s\n", args[0]);
return 1;
}
g_ventoy_disk_size = disk->total_sectors * (1U << disk->log_sector_size);
grub_disk_read(disk, 0, 0, sizeof(ventoy_gpt_info), g_ventoy_part_info);
grub_disk_close(disk);
grub_snprintf(name, sizeof(name), "%s,1", args[0]);
dev = grub_device_open(name);
if (dev)
{
/* make sure that we are running in a correct Ventoy device */
ret = ventoy_check_device(dev);
grub_device_close(dev);
if (ret)
{
grub_exit();
}
}
return 0;
}
static grub_err_t ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
{
int ret = 1;
const char *vcfg = NULL;
(void)argc;
(void)ctxt;
vcfg = ventoy_plugin_get_custom_boot(args[0]);
if (vcfg)
{
debug("custom boot <%s>:<%s>\n", args[0], vcfg);
grub_env_set(args[1], vcfg);
ret = 0;
}
else
{
debug("custom boot <%s>:<NOT FOUND>\n", args[0]);
}
grub_errno = 0;
return ret;
}
static grub_err_t ventoy_cmd_part_exist(grub_extcmd_context_t ctxt, int argc, char **args)
{
int id;
grub_uint8_t zeroguid[16] = {0};
(void)argc;
(void)ctxt;
id = (int)grub_strtoul(args[0], NULL, 10);
grub_errno = 0;
if (grub_memcmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
{
if (id >= 1 && id <= 128)
{
if (grub_memcmp(g_ventoy_part_info->PartTbl[id - 1].PartGuid, zeroguid, 16))
{
return 0;
}
}
}
else
{
if (id >= 1 && id <= 4)
{
if (g_ventoy_part_info->MBR.PartTbl[id - 1].FsFlag)
{
return 0;
}
}
}
return 1;
}
static grub_err_t ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char *device_name = NULL;
grub_device_t dev = NULL;
grub_fs_t fs = NULL;
char *label = NULL;
(void)ctxt;
debug("get fs label for %s\n", args[0]);
if (argc != 2)
{
debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc);
return 1;
}
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
debug("grub_file_get_device_name failed, %s\n", args[0]);
goto end;
}
dev = grub_device_open(device_name);
if (!dev)
{
debug("grub_device_open failed, %s\n", device_name);
goto end;
}
fs = grub_fs_probe(dev);
if (NULL == fs || NULL == fs->fs_label)
{
debug("grub_fs_probe failed, %s %p %p\n", device_name, fs, fs->fs_label);
goto end;
}
fs->fs_label(dev, &label);
if (label)
{
debug("label=<%s>\n", label);
ventoy_set_env(args[1], label);
grub_free(label);
}
rc = 0;
end:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
return rc;
}
static int ventoy_fs_enum_1st_file(const char *filename, const struct grub_dirhook_info *info, void *data)
{
if (!info->dir)
{
grub_snprintf((char *)data, 256, "%s", filename);
return 1;
}
return 0;
}
static grub_err_t ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char *device_name = NULL;
grub_device_t dev = NULL;
grub_fs_t fs = NULL;
char name[256] ={0};
(void)ctxt;
if (argc != 3)
{
debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc);
return 1;
}
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
debug("grub_file_get_device_name failed, %s\n", args[0]);
goto end;
}
dev = grub_device_open(device_name);
if (!dev)
{
debug("grub_device_open failed, %s\n", device_name);
goto end;
}
fs = grub_fs_probe(dev);
if (!fs)
{
debug("grub_fs_probe failed, %s\n", device_name);
goto end;
}
fs->fs_dir(dev, args[1], ventoy_fs_enum_1st_file, name);
if (name[0])
{
ventoy_set_env(args[2], name);
}
rc = 0;
end:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
return rc;
}
static grub_err_t ventoy_cmd_basename(grub_extcmd_context_t ctxt, int argc, char **args)
{
char c;
char *pos = NULL;
char *end = NULL;
(void)ctxt;
if (argc != 2)
{
debug("ventoy_cmd_basename, invalid param num %d\n", argc);
return 1;
}
for (pos = args[0]; *pos; pos++)
{
if (*pos == '.')
{
end = pos;
}
}
if (end)
{
c = *end;
*end = 0;
}
grub_env_set(args[1], args[0]);
if (end)
{
*end = c;
}
return 0;
}
static grub_err_t ventoy_cmd_basefile(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int len;
const char *buf;
(void)ctxt;
if (argc != 2)
{
debug("ventoy_cmd_basefile, invalid param num %d\n", argc);
return 1;
}
buf = args[0];
len = (int)grub_strlen(buf);
for (i = len; i > 0; i--)
{
if (buf[i - 1] == '/')
{
grub_env_set(args[1], buf + i);
return 0;
}
}
grub_env_set(args[1], buf);
return 0;
}
static grub_err_t ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_video_mode_info info;
char buf[32];
(void)ctxt;
(void)argc;
(void)args;
if (!g_video_mode_list)
{
ventoy_enum_video_mode();
}
if (grub_video_get_info(&info) == GRUB_ERR_NONE)
{
grub_snprintf(buf, sizeof(buf), "Resolution (%ux%u)", info.width, info.height);
}
else
{
grub_snprintf(buf, sizeof(buf), "Resolution (0x0)");
}
grub_env_set("VTOY_CUR_VIDEO_MODE", buf);
grub_snprintf(buf, sizeof(buf), "%d", g_video_mode_num);
grub_env_set("VTOY_VIDEO_MODE_NUM", buf);
VENTOY_CMD_RETURN(0);
}
static grub_err_t vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_video_mode_info info;
char buf[32];
(void)ctxt;
(void)argc;
(void)args;
if (grub_video_get_info(&info) == GRUB_ERR_NONE)
{
grub_snprintf(buf, sizeof(buf), "%ux%ux%u", info.width, info.height, info.bpp);
}
else
{
grub_snprintf(buf, sizeof(buf), "0x0x0");
}
grub_env_set(args[0], buf);
VENTOY_CMD_RETURN(0);
}
static grub_err_t ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
{
int id;
char buf[32];
(void)ctxt;
(void)argc;
if (!g_video_mode_list)
{
return 0;
}
id = (int)grub_strtoul(args[0], NULL, 10);
if (id < g_video_mode_num)
{
grub_snprintf(buf, sizeof(buf), "%ux%ux%u",
g_video_mode_list[id].width, g_video_mode_list[id].height, g_video_mode_list[id].bpp);
}
grub_env_set(args[1], buf);
VENTOY_CMD_RETURN(0);
}
grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...)
{
grub_uint64_t size = 0;
grub_file_t file;
va_list ap;
char fullpath[256] = {0};
va_start (ap, fmt);
grub_vsnprintf(fullpath, 255, fmt, ap);
va_end (ap);
file = grub_file_open(fullpath, VENTOY_FILE_TYPE);
if (!file)
{
debug("grub_file_open failed <%s>\n", fullpath);
grub_errno = 0;
return 0;
}
size = file->size;
grub_file_close(file);
return size;
}
grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...)
{
va_list ap;
grub_file_t file;
char fullpath[256] = {0};
va_start (ap, fmt);
grub_vsnprintf(fullpath, 255, fmt, ap);
va_end (ap);
file = grub_file_open(fullpath, type);
if (!file)
{
debug("grub_file_open failed <%s> %d\n", fullpath, grub_errno);
grub_errno = 0;
}
return file;
}
int ventoy_is_file_exist(const char *fmt, ...)
{
va_list ap;
int len;
char *pos = NULL;
char buf[256] = {0};
grub_snprintf(buf, sizeof(buf), "%s", "[ -f \"");
pos = buf + 6;
va_start (ap, fmt);
len = grub_vsnprintf(pos, 255, fmt, ap);
va_end (ap);
grub_strncpy(pos + len, "\" ]", 3);
debug("script exec %s\n", buf);
if (0 == grub_script_execute_sourcecode(buf))
{
return 1;
}
return 0;
}
int ventoy_is_dir_exist(const char *fmt, ...)
{
va_list ap;
int len;
char *pos = NULL;
char buf[256] = {0};
grub_snprintf(buf, sizeof(buf), "%s", "[ -d \"");
pos = buf + 6;
va_start (ap, fmt);
len = grub_vsnprintf(pos, 255, fmt, ap);
va_end (ap);
grub_strncpy(pos + len, "\" ]", 3);
debug("script exec %s\n", buf);
if (0 == grub_script_execute_sourcecode(buf))
{
return 1;
}
return 0;
}
int ventoy_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len)
{
mz_stream s;
grub_uint8_t *outbuf;
grub_uint8_t gzHdr[10] =
{
0x1F, 0x8B, /* magic */
8, /* z method */
0, /* flags */
0,0,0,0, /* mtime */
4, /* xfl */
3, /* OS */
};
grub_memset(&s, 0, sizeof(mz_stream));
mz_deflateInit2(&s, 1, MZ_DEFLATED, -MZ_DEFAULT_WINDOW_BITS, 6, MZ_DEFAULT_STRATEGY);
outbuf = (grub_uint8_t *)mem_out;
mem_out_len -= sizeof(gzHdr) + 8;
grub_memcpy(outbuf, gzHdr, sizeof(gzHdr));
outbuf += sizeof(gzHdr);
s.avail_in = mem_in_len;
s.next_in = mem_in;
s.avail_out = mem_out_len;
s.next_out = outbuf;
mz_deflate(&s, MZ_FINISH);
mz_deflateEnd(&s);
outbuf += s.total_out;
*(grub_uint32_t *)outbuf = grub_getcrc32c(0, outbuf, s.total_out);
*(grub_uint32_t *)(outbuf + 4) = (grub_uint32_t)(s.total_out);
return s.total_out + sizeof(gzHdr) + 8;
}
static int ventoy_env_init(void)
{
char buf[64];
grub_env_set("vtdebug_flag", "");
g_part_list_buf = grub_malloc(VTOY_PART_BUF_LEN);
g_tree_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
g_list_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
g_conf_replace_new_buf = grub_malloc(vtoy_max_replace_file_size);
ventoy_filt_register(0, ventoy_wrapper_open);
g_grub_param = (ventoy_grub_param *)grub_zalloc(sizeof(ventoy_grub_param));
if (g_grub_param)
{
g_grub_param->grub_env_get = grub_env_get;
g_grub_param->grub_env_set = (grub_env_set_pf)grub_env_set;
g_grub_param->grub_env_printf = (grub_env_printf_pf)grub_printf;
grub_snprintf(buf, sizeof(buf), "%p", g_grub_param);
grub_env_set("env_param", buf);
grub_env_set("ventoy_env_param", buf);
grub_env_export("env_param");
grub_env_export("ventoy_env_param");
}
return 0;
}
static cmd_para ventoy_cmds[] =
{
{ "vt_incr", ventoy_cmd_incr, 0, NULL, "{Var} {INT}", "Increase integer variable", NULL },
{ "vt_mod", ventoy_cmd_mod, 0, NULL, "{Int} {Int} {Var}", "mod integer variable", NULL },
{ "vt_strstr", ventoy_cmd_strstr, 0, NULL, "", "", NULL },
{ "vt_str_begin", ventoy_cmd_strbegin, 0, NULL, "", "", NULL },
{ "vt_debug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
{ "vtdebug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
{ "vtbreak", ventoy_cmd_break, 0, NULL, "{level}", "set debug break", NULL },
{ "vt_cmp", ventoy_cmd_cmp, 0, NULL, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL },
{ "vt_device", ventoy_cmd_device, 0, NULL, "path var", "", NULL },
{ "vt_check_compatible", ventoy_cmd_check_compatible, 0, NULL, "", "", NULL },
{ "vt_list_img", ventoy_cmd_list_img, 0, NULL, "{device} {cntvar}", "find all iso file in device", NULL },
{ "vt_clear_img", ventoy_cmd_clear_img, 0, NULL, "", "clear image list", NULL },
{ "vt_img_name", ventoy_cmd_img_name, 0, NULL, "{imageID} {var}", "get image name", NULL },
{ "vt_chosen_img_path", ventoy_cmd_chosen_img_path, 0, NULL, "{var}", "get chosen img path", NULL },
{ "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path, 0, NULL, "{var}", "select chosen img path", NULL },
{ "vt_img_sector", ventoy_cmd_img_sector, 0, NULL, "{imageName}", "", NULL },
{ "vt_dump_img_sector", ventoy_cmd_dump_img_sector, 0, NULL, "", "", NULL },
{ "vt_load_wimboot", ventoy_cmd_load_wimboot, 0, NULL, "", "", NULL },
{ "vt_load_vhdboot", ventoy_cmd_load_vhdboot, 0, NULL, "", "", NULL },
{ "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot, 0, NULL, "", "", NULL },
{ "vt_raw_chain_data", ventoy_cmd_raw_chain_data, 0, NULL, "", "", NULL },
{ "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type, 0, NULL, "", "", NULL },
{ "vt_check_custom_boot", ventoy_cmd_check_custom_boot, 0, NULL, "", "", NULL },
{ "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot, 0, NULL, "", "", NULL },
{ "vt_skip_svd", ventoy_cmd_skip_svd, 0, NULL, "", "", NULL },
{ "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64, 0, NULL, "", "", NULL },
{ "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
{ "vt_trailer_cpio", ventoy_cmd_trailer_cpio, 0, NULL, "", "", NULL },
{ "vt_push_last_entry", ventoy_cmd_push_last_entry, 0, NULL, "", "", NULL },
{ "vt_pop_last_entry", ventoy_cmd_pop_last_entry, 0, NULL, "", "", NULL },
{ "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver, 0, NULL, "", "", NULL },
{ "vt_load_part_table", ventoy_cmd_load_part_table, 0, NULL, "", "", NULL },
{ "vt_check_part_exist", ventoy_cmd_part_exist, 0, NULL, "", "", NULL },
{ "vt_get_fs_label", ventoy_cmd_get_fs_label, 0, NULL, "", "", NULL },
{ "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file, 0, NULL, "", "", NULL },
{ "vt_file_basename", ventoy_cmd_basename, 0, NULL, "", "", NULL },
{ "vt_file_basefile", ventoy_cmd_basefile, 0, NULL, "", "", NULL },
{ "vt_enum_video_mode", ventoy_cmd_enum_video_mode, 0, NULL, "", "", NULL },
{ "vt_get_video_mode", ventoy_cmd_get_video_mode, 0, NULL, "", "", NULL },
{ "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode, 0, NULL, "", "", NULL },
{ "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd, 0, NULL, "", "", NULL },
{ "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
{ "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
{ "vt_check_mode", ventoy_cmd_check_mode, 0, NULL, "", "", NULL },
{ "vt_dump_img_list", ventoy_cmd_dump_img_list, 0, NULL, "", "", NULL },
{ "vt_dump_injection", ventoy_cmd_dump_injection, 0, NULL, "", "", NULL },
{ "vt_dump_auto_install", ventoy_cmd_dump_auto_install, 0, NULL, "", "", NULL },
{ "vt_dump_persistence", ventoy_cmd_dump_persistence, 0, NULL, "", "", NULL },
{ "vt_select_auto_install", ventoy_cmd_sel_auto_install, 0, NULL, "", "", NULL },
{ "vt_select_persistence", ventoy_cmd_sel_persistence, 0, NULL, "", "", NULL },
{ "vt_select_conf_replace", ventoy_select_conf_replace, 0, NULL, "", "", NULL },
{ "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
{ "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
{ "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
{ "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem, 0, NULL, "", "", NULL },
{ "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk, 0, NULL, "", "", NULL },
{ "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso, 0, NULL, "", "", NULL },
{ "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
{ "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
{ "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file, 0, NULL, "", "", NULL },
{ "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list, 0, NULL, "", "", NULL },
{ "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list, 0, NULL, "", "", NULL },
{ "vt_linux_initrd_count", ventoy_cmd_initrd_count, 0, NULL, "", "", NULL },
{ "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count, 0, NULL, "", "", NULL },
{ "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd, 0, NULL, "", "", NULL },
{ "vt_linux_chain_data", ventoy_cmd_linux_chain_data, 0, NULL, "", "", NULL },
{ "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index, 0, NULL, "", "", NULL },
{ "vt_windows_reset", ventoy_cmd_wimdows_reset, 0, NULL, "", "", NULL },
{ "vt_windows_chain_data", ventoy_cmd_windows_chain_data, 0, NULL, "", "", NULL },
{ "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch, 0, NULL, "", "", NULL },
{ "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch, 0, NULL, "", "", NULL },
{ "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count, 0, NULL, "", "", NULL },
{ "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch, 0, NULL, "", "", NULL },
{ "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable, 0, NULL, "", "", NULL },
{ "vt_wim_chain_data", ventoy_cmd_wim_chain_data, 0, NULL, "", "", NULL },
{ "vt_add_replace_file", ventoy_cmd_add_replace_file, 0, NULL, "", "", NULL },
{ "vt_test_block_list", ventoy_cmd_test_block_list, 0, NULL, "", "", NULL },
{ "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase, 0, NULL, "", "", NULL },
{ "vt_load_plugin", ventoy_cmd_load_plugin, 0, NULL, "", "", NULL },
{ "vt_check_plugin_json", ventoy_cmd_plugin_check_json, 0, NULL, "", "", NULL },
{ "vt_check_password", ventoy_cmd_check_password, 0, NULL, "", "", NULL },
{ "vt_1st_line", ventoy_cmd_read_1st_line, 0, NULL, "", "", NULL },
{ "vt_file_strstr", ventoy_cmd_file_strstr, 0, NULL, "", "", NULL },
{ "vt_img_part_info", ventoy_cmd_img_part_info, 0, NULL, "", "", NULL },
{ "vt_parse_iso_volume", ventoy_cmd_parse_volume, 0, NULL, "", "", NULL },
{ "vt_parse_iso_create_date", ventoy_cmd_parse_create_date, 0, NULL, "", "", NULL },
{ "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver, 0, NULL, "", "", NULL },
{ "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver, 0, NULL, "", "", NULL },
{ "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf, 0, NULL, "", "", NULL },
{ "vt_unix_reset", ventoy_cmd_unix_reset, 0, NULL, "", "", NULL },
{ "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf, 0, NULL, "", "", NULL },
{ "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko, 0, NULL, "", "", NULL },
{ "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc, 0, NULL, "", "", NULL },
{ "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko, 0, NULL, "", "", NULL },
{ "vt_unix_chain_data", ventoy_cmd_unix_chain_data, 0, NULL, "", "", NULL },
{ "vt_img_hook_root", ventoy_cmd_img_hook_root, 0, NULL, "", "", NULL },
{ "vt_img_unhook_root", ventoy_cmd_img_unhook_root, 0, NULL, "", "", NULL },
{ "vt_acpi_param", ventoy_cmd_acpi_param, 0, NULL, "", "", NULL },
{ "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var, 0, NULL, "", "", NULL },
{ "vt_clear_key", ventoy_cmd_clear_key, 0, NULL, "", "", NULL },
{ "vt_img_check_range", ventoy_cmd_img_check_range, 0, NULL, "", "", NULL },
};
GRUB_MOD_INIT(ventoy)
{
grub_uint32_t i;
cmd_para *cur = NULL;
ventoy_env_init();
ventoy_arch_mode_init();
for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
{
cur = ventoy_cmds + i;
cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags,
cur->summary, cur->description, cur->parser);
}
}
GRUB_MOD_FINI(ventoy)
{
grub_uint32_t i;
for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
{
grub_unregister_extcmd(ventoy_cmds[i].cmd);
}
ventoy_unregister_all_cmd();
}
/******************************************************************************
* ventoy_cmd.c
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
*/
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/disk.h>
#include <grub/device.h>
#include <grub/term.h>
#include <grub/partition.h>
#include <grub/file.h>
#include <grub/normal.h>
#include <grub/extcmd.h>
#include <grub/datetime.h>
#include <grub/i18n.h>
#include <grub/net.h>
#include <grub/misc.h>
#include <grub/kernel.h>
#ifdef GRUB_MACHINE_EFI
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#endif
#include <grub/time.h>
#include <grub/video.h>
#include <grub/acpi.h>
#include <grub/charset.h>
#include <grub/crypto.h>
#include <grub/lib/crc.h>
#include <grub/ventoy.h>
#include "ventoy_def.h"
#include "miniz.h"
GRUB_MOD_LICENSE ("GPLv3+");
initrd_info *g_initrd_img_list = NULL;
initrd_info *g_initrd_img_tail = NULL;
int g_initrd_img_count = 0;
int g_valid_initrd_count = 0;
int g_default_menu_mode = 0;
int g_filt_dot_underscore_file = 0;
int g_sort_case_sensitive = 0;
int g_tree_view_menu_style = 0;
static grub_file_t g_old_file;
static int g_ventoy_last_entry_back;
char g_iso_path[256];
char g_img_swap_tmp_buf[1024];
img_info g_img_swap_tmp;
img_info *g_ventoy_img_list = NULL;
int g_ventoy_img_count = 0;
grub_device_t g_enum_dev = NULL;
grub_fs_t g_enum_fs = NULL;
int g_img_max_search_level = -1;
img_iterator_node g_img_iterator_head;
img_iterator_node *g_img_iterator_tail = NULL;
grub_uint8_t g_ventoy_break_level = 0;
grub_uint8_t g_ventoy_debug_level = 0;
grub_uint8_t g_ventoy_chain_type = 0;
grub_uint8_t *g_ventoy_cpio_buf = NULL;
grub_uint32_t g_ventoy_cpio_size = 0;
cpio_newc_header *g_ventoy_initrd_head = NULL;
grub_uint8_t *g_ventoy_runtime_buf = NULL;
int g_plugin_image_list = 0;
ventoy_grub_param *g_grub_param = NULL;
ventoy_guid g_ventoy_guid = VENTOY_GUID;
ventoy_img_chunk_list g_img_chunk_list;
int g_wimboot_enable = 0;
ventoy_img_chunk_list g_wimiso_chunk_list;
char *g_wimiso_path = NULL;
int g_vhdboot_enable = 0;
grub_uint64_t g_conf_replace_offset = 0;
grub_uint64_t g_svd_replace_offset = 0;
conf_replace *g_conf_replace_node = NULL;
grub_uint8_t *g_conf_replace_new_buf = NULL;
int g_conf_replace_new_len = 0;
int g_conf_replace_new_len_align = 0;
ventoy_gpt_info *g_ventoy_part_info = NULL;
grub_uint64_t g_ventoy_disk_size = 0;
grub_uint64_t g_ventoy_disk_part_size[2];
static char *g_tree_script_buf = NULL;
static int g_tree_script_pos = 0;
static char *g_list_script_buf = NULL;
static int g_list_script_pos = 0;
static char *g_part_list_buf = NULL;
static int g_part_list_pos = 0;
static int g_video_mode_max = 0;
static int g_video_mode_num = 0;
static ventoy_video_mode *g_video_mode_list = NULL;
static int g_enumerate_time_checked = 0;
static grub_uint64_t g_enumerate_start_time_ms;
static grub_uint64_t g_enumerate_finish_time_ms;
static int g_vtoy_file_flt[VTOY_FILE_FLT_BUTT] = {0};
static const char *g_menu_class[] =
{
"vtoyiso", "vtoywim", "vtoyefi", "vtoyimg", "vtoyvhd", "vtoyvtoy"
};
static const char *g_menu_prefix[] =
{
"iso", "wim", "efi", "img", "vhd", "vtoy"
};
static int ventoy_get_fs_type(const char *fs)
{
if (NULL == fs)
{
return ventoy_fs_max;
}
else if (grub_strncmp(fs, "exfat", 5) == 0)
{
return ventoy_fs_exfat;
}
else if (grub_strncmp(fs, "ntfs", 4) == 0)
{
return ventoy_fs_ntfs;
}
else if (grub_strncmp(fs, "ext", 3) == 0)
{
return ventoy_fs_ext;
}
else if (grub_strncmp(fs, "xfs", 3) == 0)
{
return ventoy_fs_xfs;
}
else if (grub_strncmp(fs, "udf", 3) == 0)
{
return ventoy_fs_udf;
}
else if (grub_strncmp(fs, "fat", 3) == 0)
{
return ventoy_fs_fat;
}
return ventoy_fs_max;
}
static int ventoy_string_check(const char *str, grub_char_check_func check)
{
if (!str)
{
return 0;
}
for ( ; *str; str++)
{
if (!check(*str))
{
return 0;
}
}
return 1;
}
static grub_ssize_t ventoy_fs_read(grub_file_t file, char *buf, grub_size_t len)
{
grub_memcpy(buf, (char *)file->data + file->offset, len);
return len;
}
static int ventoy_control_get_flag(const char *key)
{
const char *val = ventoy_get_env(key);
if (val && val[0] == '1' && val[1] == 0)
{
return 1;
}
return 0;
}
static grub_err_t ventoy_fs_close(grub_file_t file)
{
grub_file_close(g_old_file);
grub_free(file->data);
file->device = 0;
file->name = 0;
return 0;
}
static int ventoy_video_hook(const struct grub_video_mode_info *info, void *hook_arg)
{
int i;
(void)hook_arg;
if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
{
return 0;
}
for (i = 0; i < g_video_mode_num; i++)
{
if (g_video_mode_list[i].width == info->width &&
g_video_mode_list[i].height == info->height &&
g_video_mode_list[i].bpp == info->bpp)
{
return 0;
}
}
g_video_mode_list[g_video_mode_num].width = info->width;
g_video_mode_list[g_video_mode_num].height = info->height;
g_video_mode_list[g_video_mode_num].bpp = info->bpp;
g_video_mode_num++;
if (g_video_mode_num == g_video_mode_max)
{
g_video_mode_max *= 2;
g_video_mode_list = grub_realloc(g_video_mode_list, g_video_mode_max * sizeof(ventoy_video_mode));
}
return 0;
}
static int ventoy_video_mode_cmp(ventoy_video_mode *v1, ventoy_video_mode *v2)
{
if (v1->bpp == v2->bpp)
{
if (v1->width == v2->width)
{
if (v1->height == v2->height)
{
return 0;
}
else
{
return (v1->height < v2->height) ? -1 : 1;
}
}
else
{
return (v1->width < v2->width) ? -1 : 1;
}
}
else
{
return (v1->bpp < v2->bpp) ? -1 : 1;
}
}
static int ventoy_enum_video_mode(void)
{
int i, j;
grub_video_adapter_t adapter;
grub_video_driver_id_t id;
ventoy_video_mode mode;
g_video_mode_num = 0;
g_video_mode_max = 1024;
g_video_mode_list = grub_malloc(sizeof(ventoy_video_mode) * g_video_mode_max);
if (!g_video_mode_list)
{
return 0;
}
#ifdef GRUB_MACHINE_PCBIOS
grub_dl_load ("vbe");
#endif
id = grub_video_get_driver_id ();
FOR_VIDEO_ADAPTERS (adapter)
{
if (!adapter->iterate ||
(adapter->id != id && (id != GRUB_VIDEO_DRIVER_NONE ||
adapter->init() != GRUB_ERR_NONE)))
{
continue;
}
adapter->iterate(ventoy_video_hook, NULL);
if (adapter->id != id)
{
adapter->fini();
}
}
/* sort video mode */
for (i = 0; i < g_video_mode_num; i++)
for (j = i + 1; j < g_video_mode_num; j++)
{
if (ventoy_video_mode_cmp(g_video_mode_list + i, g_video_mode_list + j) < 0)
{
grub_memcpy(&mode, g_video_mode_list + i, sizeof(ventoy_video_mode));
grub_memcpy(g_video_mode_list + i, g_video_mode_list + j, sizeof(ventoy_video_mode));
grub_memcpy(g_video_mode_list + j, &mode, sizeof(ventoy_video_mode));
}
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_file_t ventoy_wrapper_open(grub_file_t rawFile, enum grub_file_type type)
{
int len;
grub_file_t file;
static struct grub_fs vtoy_fs =
{
.name = "vtoy",
.fs_dir = 0,
.fs_open = 0,
.fs_read = ventoy_fs_read,
.fs_close = ventoy_fs_close,
.fs_label = 0,
.next = 0
};
if (type != 52)
{
return rawFile;
}
file = (grub_file_t)grub_zalloc(sizeof (*file));
if (!file)
{
return 0;
}
file->data = grub_malloc(rawFile->size + 4096);
if (!file->data)
{
return 0;
}
grub_file_read(rawFile, file->data, rawFile->size);
len = ventoy_fill_data(4096, (char *)file->data + rawFile->size);
g_old_file = rawFile;
file->size = rawFile->size + len;
file->device = rawFile->device;
file->fs = &vtoy_fs;
file->not_easily_seekable = 1;
return file;
}
static int ventoy_check_decimal_var(const char *name, long *value)
{
const char *value_str = NULL;
value_str = grub_env_get(name);
if (NULL == value_str)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s not found", name);
}
if (!ventoy_is_decimal(value_str))
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Variable %s value '%s' is not an integer", name, value_str);
}
*value = grub_strtol(value_str, NULL, 10);
return GRUB_ERR_NONE;
}
grub_uint64_t ventoy_get_vtoy_partsize(int part)
{
grub_uint64_t sectors;
if (grub_strncmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
{
sectors = g_ventoy_part_info->PartTbl[part].LastLBA + 1 - g_ventoy_part_info->PartTbl[part].StartLBA;
}
else
{
sectors = g_ventoy_part_info->MBR.PartTbl[part].SectorCount;
}
return sectors * 512;
}
static int ventoy_load_efiboot_template(char **buf, int *datalen, int *direntoff)
{
int len;
grub_file_t file;
char exec[128];
char *data = NULL;
grub_uint32_t offset;
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s/ventoy/ventoy_efiboot.img.xz", ventoy_get_env("vtoy_efi_part"));
if (file == NULL)
{
debug("failed to open file <%s>\n", "ventoy_efiboot.img.xz");
return 1;
}
len = (int)file->size;
data = (char *)grub_malloc(file->size);
if (!data)
{
return 1;
}
grub_file_read(file, data, file->size);
grub_file_close(file);
grub_snprintf(exec, sizeof(exec), "loopback efiboot mem:0x%llx:size:%d", (ulonglong)(ulong)data, len);
grub_script_execute_sourcecode(exec);
file = grub_file_open("(efiboot)/EFI/BOOT/BOOTX64.EFI", GRUB_FILE_TYPE_LINUX_INITRD);
offset = (grub_uint32_t)grub_iso9660_get_last_file_dirent_pos(file);
grub_file_close(file);
grub_script_execute_sourcecode("loopback -d efiboot");
*buf = data;
*datalen = len;
*direntoff = offset + 2;
return 0;
}
static int ventoy_set_check_result(int ret)
{
char buf[32];
grub_snprintf(buf, sizeof(buf), "%d", (ret & 0x7FFF));
grub_env_set("VTOY_CHKDEV_RESULT_STRING", buf);
grub_env_export("VTOY_CHKDEV_RESULT_STRING");
if (ret)
{
grub_printf(VTOY_WARNING"\n");
grub_printf(VTOY_WARNING"\n");
grub_printf(VTOY_WARNING"\n\n\n");
grub_printf("This is NOT a standard Ventoy device and is NOT supported (0x%x).\n\n", ret);
grub_printf("You should follow the instructions in https://www.ventoy.net to use Ventoy.\n");
grub_printf("\n\nWill exit after 10 seconds ...... ");
grub_refresh();
grub_sleep(10);
}
return ret;
}
static int ventoy_check_official_device(grub_device_t dev)
{
int workaround = 0;
grub_file_t file;
grub_uint64_t offset;
char devname[64];
grub_fs_t fs;
grub_device_t dev2;
char *label = NULL;
struct grub_partition *partition;
if (dev->disk == NULL || dev->disk->partition == NULL)
{
return ventoy_set_check_result(1 | 0x1000);
}
if (0 == ventoy_check_file_exist("(%s,2)/ventoy/ventoy.cpio", dev->disk->name) ||
0 == ventoy_check_file_exist("(%s,2)/grub/localboot.cfg", dev->disk->name) ||
0 == ventoy_check_file_exist("(%s,2)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
{
#ifndef GRUB_MACHINE_EFI
if (0 == ventoy_check_file_exist("(ventoydisk)/ventoy/ventoy.cpio", dev->disk->name) ||
0 == ventoy_check_file_exist("(ventoydisk)/grub/localboot.cfg", dev->disk->name) ||
0 == ventoy_check_file_exist("(ventoydisk)/tool/mount.exfat-fuse_aarch64", dev->disk->name))
{
return ventoy_set_check_result(2 | 0x1000);
}
else
{
workaround = 1;
}
#endif
}
/* We must have partition 2 */
if (workaround)
{
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", "(ventoydisk)/ventoy/ventoy.cpio");
}
else
{
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(%s,2)/ventoy/ventoy.cpio", dev->disk->name);
}
if (!file)
{
return ventoy_set_check_result(3 | 0x1000);
}
if (NULL == grub_strstr(file->fs->name, "fat"))
{
grub_file_close(file);
return ventoy_set_check_result(4 | 0x1000);
}
partition = dev->disk->partition;
if (partition->number != 0 || partition->start != 2048)
{
return ventoy_set_check_result(5);
}
if (workaround)
{
if (grub_strncmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
{
ventoy_gpt_part_tbl *PartTbl = g_ventoy_part_info->PartTbl;
if (PartTbl[1].StartLBA != PartTbl[0].LastLBA + 1 ||
(PartTbl[1].LastLBA + 1 - PartTbl[1].StartLBA) != 65536)
{
grub_file_close(file);
return ventoy_set_check_result(6);
}
}
else
{
ventoy_part_table *PartTbl = g_ventoy_part_info->MBR.PartTbl;
if (PartTbl[1].StartSectorId != PartTbl[0].StartSectorId + PartTbl[0].SectorCount ||
PartTbl[1].SectorCount != 65536)
{
grub_file_close(file);
return ventoy_set_check_result(6);
}
}
}
else
{
offset = partition->start + partition->len;
partition = file->device->disk->partition;
if ((partition->number != 1) || (partition->len != 65536) || (offset != partition->start))
{
grub_file_close(file);
return ventoy_set_check_result(7);
}
}
grub_file_close(file);
if (workaround == 0)
{
grub_snprintf(devname, sizeof(devname), "%s,2", dev->disk->name);
dev2 = grub_device_open(devname);
if (!dev2)
{
return ventoy_set_check_result(8);
}
fs = grub_fs_probe(dev2);
if (!fs)
{
grub_device_close(dev2);
return ventoy_set_check_result(9);
}
fs->fs_label(dev2, &label);
if ((!label) || grub_strncmp("VTOYEFI", label, 7))
{
grub_device_close(dev2);
return ventoy_set_check_result(10);
}
grub_device_close(dev2);
}
return ventoy_set_check_result(0);
}
static int ventoy_check_ignore_flag(const char *filename, const struct grub_dirhook_info *info, void *data)
{
if (0 == info->dir)
{
if (filename && filename[0] == '.' && 0 == grub_strncmp(filename, ".ventoyignore", 13))
{
*((int *)data) = 1;
return 0;
}
}
return 0;
}
grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...)
{
grub_uint64_t size = 0;
grub_file_t file;
va_list ap;
char fullpath[256] = {0};
va_start (ap, fmt);
grub_vsnprintf(fullpath, 255, fmt, ap);
va_end (ap);
file = grub_file_open(fullpath, VENTOY_FILE_TYPE);
if (!file)
{
debug("grub_file_open failed <%s>\n", fullpath);
grub_errno = 0;
return 0;
}
size = file->size;
grub_file_close(file);
return size;
}
grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...)
{
va_list ap;
grub_file_t file;
char fullpath[256] = {0};
va_start (ap, fmt);
grub_vsnprintf(fullpath, 255, fmt, ap);
va_end (ap);
file = grub_file_open(fullpath, type);
if (!file)
{
debug("grub_file_open failed <%s> %d\n", fullpath, grub_errno);
grub_errno = 0;
}
return file;
}
int ventoy_is_file_exist(const char *fmt, ...)
{
va_list ap;
int len;
char *pos = NULL;
char buf[256] = {0};
grub_snprintf(buf, sizeof(buf), "%s", "[ -f \"");
pos = buf + 6;
va_start (ap, fmt);
len = grub_vsnprintf(pos, 255, fmt, ap);
va_end (ap);
grub_strncpy(pos + len, "\" ]", 3);
debug("script exec %s\n", buf);
if (0 == grub_script_execute_sourcecode(buf))
{
return 1;
}
return 0;
}
int ventoy_is_dir_exist(const char *fmt, ...)
{
va_list ap;
int len;
char *pos = NULL;
char buf[256] = {0};
grub_snprintf(buf, sizeof(buf), "%s", "[ -d \"");
pos = buf + 6;
va_start (ap, fmt);
len = grub_vsnprintf(pos, 255, fmt, ap);
va_end (ap);
grub_strncpy(pos + len, "\" ]", 3);
debug("script exec %s\n", buf);
if (0 == grub_script_execute_sourcecode(buf))
{
return 1;
}
return 0;
}
int ventoy_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len)
{
mz_stream s;
grub_uint8_t *outbuf;
grub_uint8_t gzHdr[10] =
{
0x1F, 0x8B, /* magic */
8, /* z method */
0, /* flags */
0,0,0,0, /* mtime */
4, /* xfl */
3, /* OS */
};
grub_memset(&s, 0, sizeof(mz_stream));
mz_deflateInit2(&s, 1, MZ_DEFLATED, -MZ_DEFAULT_WINDOW_BITS, 6, MZ_DEFAULT_STRATEGY);
outbuf = (grub_uint8_t *)mem_out;
mem_out_len -= sizeof(gzHdr) + 8;
grub_memcpy(outbuf, gzHdr, sizeof(gzHdr));
outbuf += sizeof(gzHdr);
s.avail_in = mem_in_len;
s.next_in = mem_in;
s.avail_out = mem_out_len;
s.next_out = outbuf;
mz_deflate(&s, MZ_FINISH);
mz_deflateEnd(&s);
outbuf += s.total_out;
*(grub_uint32_t *)outbuf = grub_getcrc32c(0, outbuf, s.total_out);
*(grub_uint32_t *)(outbuf + 4) = (grub_uint32_t)(s.total_out);
return s.total_out + sizeof(gzHdr) + 8;
}
#if 0
ventoy grub cmds
#endif
static grub_err_t ventoy_cmd_debug(grub_extcmd_context_t ctxt, int argc, char **args)
{
if (argc != 1)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {on|off}", cmd_raw_name);
}
if (0 == grub_strcmp(args[0], "on"))
{
g_ventoy_debug = 1;
grub_env_set("vtdebug_flag", "debug");
}
else
{
g_ventoy_debug = 0;
grub_env_set("vtdebug_flag", "");
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_break(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
if (argc < 1 || (args[0][0] != '0' && args[0][0] != '1'))
{
grub_printf("Usage: %s {level} [debug]\r\n", cmd_raw_name);
grub_printf(" level:\r\n");
grub_printf(" 01/11: busybox / (+cat log)\r\n");
grub_printf(" 02/12: initrd / (+cat log)\r\n");
grub_printf(" 03/13: hook / (+cat log)\r\n");
grub_printf("\r\n");
grub_printf(" debug:\r\n");
grub_printf(" 0: debug is off\r\n");
grub_printf(" 1: debug is on\r\n");
grub_printf("\r\n");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
g_ventoy_break_level = (grub_uint8_t)grub_strtoul(args[0], NULL, 16);
if (argc > 1 && grub_strtoul(args[1], NULL, 10) > 0)
{
g_ventoy_debug_level = 1;
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
if (argc != 2)
{
return 1;
}
return (grub_strstr(args[0], args[1])) ? 0 : 1;
}
static grub_err_t ventoy_cmd_strbegin(grub_extcmd_context_t ctxt, int argc, char **args)
{
char *c0, *c1;
(void)ctxt;
if (argc != 2)
{
return 1;
}
c0 = args[0];
c1 = args[1];
while (*c0 && *c1)
{
if (*c0 != *c1)
{
return 1;
}
c0++;
c1++;
}
if (*c1)
{
return 1;
}
return 0;
}
static grub_err_t ventoy_cmd_incr(grub_extcmd_context_t ctxt, int argc, char **args)
{
long value_long = 0;
char buf[32];
if ((argc != 2) || (!ventoy_is_decimal(args[1])))
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Variable} {Int}", cmd_raw_name);
}
if (GRUB_ERR_NONE != ventoy_check_decimal_var(args[0], &value_long))
{
return grub_errno;
}
value_long += grub_strtol(args[1], NULL, 10);
grub_snprintf(buf, sizeof(buf), "%ld", value_long);
grub_env_set(args[0], buf);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_mod(grub_extcmd_context_t ctxt, int argc, char **args)
{
ulonglong value1 = 0;
ulonglong value2 = 0;
char buf[32];
if (argc != 3)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int} {Int} {Variable}", cmd_raw_name);
}
value1 = grub_strtoull(args[0], NULL, 10);
value2 = grub_strtoull(args[1], NULL, 10);
grub_snprintf(buf, sizeof(buf), "%llu", (value1 & (value2 - 1)));
grub_env_set(args[2], buf);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_file_size(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char buf[32];
grub_file_t file;
(void)ctxt;
(void)argc;
(void)args;
if (argc != 2)
{
return rc;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s> for udf check\n", args[0]);
return 1;
}
grub_snprintf(buf, sizeof(buf), "%llu", (unsigned long long)file->size);
grub_env_set(args[1], buf);
grub_file_close(file);
rc = 0;
return rc;
}
static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_file_t file;
(void)ctxt;
(void)argc;
(void)args;
g_wimboot_enable = 0;
grub_check_free(g_wimiso_path);
grub_check_free(g_wimiso_chunk_list.chunk);
file = grub_file_open(args[0], VENTOY_FILE_TYPE);
if (!file)
{
return 0;
}
grub_memset(&g_wimiso_chunk_list, 0, sizeof(g_wimiso_chunk_list));
g_wimiso_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
if (NULL == g_wimiso_chunk_list.chunk)
{
return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
}
g_wimiso_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
g_wimiso_chunk_list.cur_chunk = 0;
ventoy_get_block_list(file, &g_wimiso_chunk_list, file->device->disk->partition->start);
g_wimboot_enable = 1;
g_wimiso_path = grub_strdup(args[0]);
grub_file_close(file);
return 0;
}
static grub_err_t ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len = 0;
int totlen = 0;
int offset = 0;
grub_file_t file;
char name[32];
char value[32];
char *buf = NULL;
char *data = NULL;
ventoy_iso9660_override *dirent;
(void)ctxt;
if (argc != 2)
{
return 1;
}
totlen = sizeof(ventoy_chain_head);
if (ventoy_load_efiboot_template(&buf, &len, &offset))
{
debug("failed to load efiboot template %d\n", len);
return 1;
}
totlen += len;
debug("efiboot template len:%d offset:%d\n", len, offset);
file = ventoy_grub_file_open(GRUB_FILE_TYPE_LINUX_INITRD, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s>\n", args[0]);
return 1;
}
totlen += ventoy_align_2k(file->size);
dirent = (ventoy_iso9660_override *)(buf + offset);
dirent->first_sector = len / 2048;
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
dirent->size = (grub_uint32_t)file->size;
dirent->size_be = grub_swap_bytes32(dirent->size);
debug("rawiso len:%d efilen:%d total:%d\n", len, (int)file->size, totlen);
#ifdef GRUB_MACHINE_EFI
data = (char *)grub_efi_allocate_iso_buf(totlen);
#else
data = (char *)grub_malloc(totlen);
#endif
ventoy_fill_os_param(file, (ventoy_os_param *)data);
grub_memcpy(data + sizeof(ventoy_chain_head), buf, len);
grub_check_free(buf);
grub_file_read(file, data + sizeof(ventoy_chain_head) + len, file->size);
grub_file_close(file);
grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
grub_snprintf(value, sizeof(value), "0x%llx", (ulonglong)(ulong)data);
grub_env_set(name, value);
grub_snprintf(name, sizeof(name), "%s_size", args[1]);
grub_snprintf(value, sizeof(value), "%d", (int)(totlen));
grub_env_set(name, value);
return 0;
}
static grub_err_t ventoy_cmd_load_file_to_mem(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char name[32];
char value[32];
char *buf = NULL;
grub_file_t file;
(void)ctxt;
(void)argc;
(void)args;
if (argc != 2)
{
return rc;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s>\n", args[0]);
return 1;
}
#ifdef GRUB_MACHINE_EFI
buf = (char *)grub_efi_allocate_iso_buf(file->size);
#else
buf = (char *)grub_malloc(file->size);
#endif
grub_file_read(file, buf, file->size);
grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
grub_env_set(name, value);
grub_snprintf(name, sizeof(name), "%s_size", args[1]);
grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
grub_env_set(name, value);
grub_file_close(file);
rc = 0;
return rc;
}
static grub_err_t ventoy_cmd_load_img_memdisk(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
int headlen;
char name[32];
char value[32];
char *buf = NULL;
grub_file_t file;
(void)ctxt;
(void)argc;
(void)args;
if (argc != 2)
{
return rc;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s> for udf check\n", args[0]);
return 1;
}
headlen = sizeof(ventoy_chain_head);
#ifdef GRUB_MACHINE_EFI
buf = (char *)grub_efi_allocate_iso_buf(headlen + file->size);
#else
buf = (char *)grub_malloc(headlen + file->size);
#endif
ventoy_fill_os_param(file, (ventoy_os_param *)buf);
grub_file_read(file, buf + headlen, file->size);
grub_snprintf(name, sizeof(name), "%s_addr", args[1]);
grub_snprintf(value, sizeof(value), "0x%llx", (unsigned long long)(unsigned long)buf);
grub_env_set(name, value);
grub_snprintf(name, sizeof(name), "%s_size", args[1]);
grub_snprintf(value, sizeof(value), "%llu", (unsigned long long)file->size);
grub_env_set(name, value);
grub_file_close(file);
rc = 0;
return rc;
}
static grub_err_t ventoy_cmd_iso9660_nojoliet(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
if (argc != 1)
{
return 1;
}
if (args[0][0] == '1')
{
grub_iso9660_set_nojoliet(1);
}
else
{
grub_iso9660_set_nojoliet(0);
}
return 0;
}
static grub_err_t ventoy_cmd_is_udf(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int rc = 1;
grub_file_t file;
grub_uint8_t buf[32];
(void)ctxt;
(void)argc;
(void)args;
if (argc != 1)
{
return rc;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (file == NULL)
{
debug("failed to open file <%s> for udf check\n", args[0]);
return 1;
}
for (i = 16; i < 32; i++)
{
grub_file_seek(file, i * 2048);
grub_file_read(file, buf, sizeof(buf));
if (buf[0] == 255)
{
break;
}
}
i++;
grub_file_seek(file, i * 2048);
grub_file_read(file, buf, sizeof(buf));
if (grub_memcmp(buf + 1, "BEA01", 5) == 0)
{
i++;
grub_file_seek(file, i * 2048);
grub_file_read(file, buf, sizeof(buf));
if (grub_memcmp(buf + 1, "NSR02", 5) == 0 ||
grub_memcmp(buf + 1, "NSR03", 5) == 0)
{
rc = 0;
}
}
grub_file_close(file);
debug("ISO UDF: %s\n", rc ? "NO" : "YES");
return rc;
}
static grub_err_t ventoy_cmd_cmp(grub_extcmd_context_t ctxt, int argc, char **args)
{
long value_long1 = 0;
long value_long2 = 0;
if ((argc != 3) || (!ventoy_is_decimal(args[0])) || (!ventoy_is_decimal(args[2])))
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq|ne|gt|lt|ge|le } {Int2}", cmd_raw_name);
}
value_long1 = grub_strtol(args[0], NULL, 10);
value_long2 = grub_strtol(args[2], NULL, 10);
if (0 == grub_strcmp(args[1], "eq"))
{
grub_errno = (value_long1 == value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "ne"))
{
grub_errno = (value_long1 != value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "gt"))
{
grub_errno = (value_long1 > value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "lt"))
{
grub_errno = (value_long1 < value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "ge"))
{
grub_errno = (value_long1 >= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else if (0 == grub_strcmp(args[1], "le"))
{
grub_errno = (value_long1 <= value_long2) ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE;
}
else
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {Int1} { eq ne gt lt ge le } {Int2}", cmd_raw_name);
}
return grub_errno;
}
static grub_err_t ventoy_cmd_device(grub_extcmd_context_t ctxt, int argc, char **args)
{
char *pos = NULL;
char buf[128] = {0};
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s path var", cmd_raw_name);
}
grub_strncpy(buf, (args[0][0] == '(') ? args[0] + 1 : args[0], sizeof(buf) - 1);
pos = grub_strstr(buf, ",");
if (pos)
{
*pos = 0;
}
grub_env_set(args[1], buf);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_check_compatible(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
char buf[256];
grub_disk_t disk;
char *pos = NULL;
const char *files[] = { "ventoy.dat", "VENTOY.DAT" };
(void)ctxt;
if (argc != 1)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s (loop)", cmd_raw_name);
}
for (i = 0; i < (int)ARRAY_SIZE(files); i++)
{
grub_snprintf(buf, sizeof(buf) - 1, "[ -e \"%s/%s\" ]", args[0], files[i]);
if (0 == grub_script_execute_sourcecode(buf))
{
debug("file %s exist, ventoy_compatible YES\n", buf);
grub_env_set("ventoy_compatible", "YES");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
else
{
debug("file %s NOT exist\n", buf);
}
}
grub_snprintf(buf, sizeof(buf) - 1, "%s", args[0][0] == '(' ? (args[0] + 1) : args[0]);
pos = grub_strstr(buf, ")");
if (pos)
{
*pos = 0;
}
disk = grub_disk_open(buf);
if (disk)
{
grub_disk_read(disk, 16 << 2, 0, 1024, g_img_swap_tmp_buf);
grub_disk_close(disk);
g_img_swap_tmp_buf[703] = 0;
for (i = 318; i < 703; i++)
{
if (g_img_swap_tmp_buf[i] == 'V' &&
0 == grub_strncmp(g_img_swap_tmp_buf + i, VENTOY_COMPATIBLE_STR, VENTOY_COMPATIBLE_STR_LEN))
{
debug("Ventoy compatible string exist at %d, ventoy_compatible YES\n", i);
grub_env_set("ventoy_compatible", "YES");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
}
}
else
{
debug("failed to open disk <%s>\n", buf);
}
grub_env_set("ventoy_compatible", "NO");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
int ventoy_cmp_img(img_info *img1, img_info *img2)
{
char *s1, *s2;
int c1 = 0;
int c2 = 0;
if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
{
return (img1->plugin_list_index - img2->plugin_list_index);
}
for (s1 = img1->name, s2 = img2->name; *s1 && *s2; s1++, s2++)
{
c1 = *s1;
c2 = *s2;
if (0 == g_sort_case_sensitive)
{
if (grub_islower(c1))
{
c1 = c1 - 'a' + 'A';
}
if (grub_islower(c2))
{
c2 = c2 - 'a' + 'A';
}
}
if (c1 != c2)
{
break;
}
}
return (c1 - c2);
}
static int ventoy_cmp_subdir(img_iterator_node *node1, img_iterator_node *node2)
{
char *s1, *s2;
int c1 = 0;
int c2 = 0;
if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
{
return (node1->plugin_list_index - node2->plugin_list_index);
}
for (s1 = node1->dir, s2 = node2->dir; *s1 && *s2; s1++, s2++)
{
c1 = *s1;
c2 = *s2;
if (0 == g_sort_case_sensitive)
{
if (grub_islower(c1))
{
c1 = c1 - 'a' + 'A';
}
if (grub_islower(c2))
{
c2 = c2 - 'a' + 'A';
}
}
if (c1 != c2)
{
break;
}
}
return (c1 - c2);
}
void ventoy_swap_img(img_info *img1, img_info *img2)
{
grub_memcpy(&g_img_swap_tmp, img1, sizeof(img_info));
grub_memcpy(img1, img2, sizeof(img_info));
img1->next = g_img_swap_tmp.next;
img1->prev = g_img_swap_tmp.prev;
g_img_swap_tmp.next = img2->next;
g_img_swap_tmp.prev = img2->prev;
grub_memcpy(img2, &g_img_swap_tmp, sizeof(img_info));
}
static int ventoy_img_name_valid(const char *filename, grub_size_t namelen)
{
(void)namelen;
if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
{
return 0;
}
return 1;
}
static int ventoy_collect_img_files(const char *filename, const struct grub_dirhook_info *info, void *data)
{
//int i = 0;
int type = 0;
int ignore = 0;
int index = 0;
grub_size_t len;
img_info *img;
img_info *tail;
img_iterator_node *tmp;
img_iterator_node *new_node;
img_iterator_node *node = (img_iterator_node *)data;
if (g_enumerate_time_checked == 0)
{
g_enumerate_finish_time_ms = grub_get_time_ms();
if ((g_enumerate_finish_time_ms - g_enumerate_start_time_ms) >= 3000)
{
grub_cls();
grub_printf("\n\n Ventoy scanning files, please wait...\n");
grub_refresh();
g_enumerate_time_checked = 1;
}
}
len = grub_strlen(filename);
if (info->dir)
{
if (node->level + 1 > g_img_max_search_level)
{
return 0;
}
if ((len == 1 && filename[0] == '.') ||
(len == 2 && filename[0] == '.' && filename[1] == '.'))
{
return 0;
}
if (!ventoy_img_name_valid(filename, len))
{
return 0;
}
if (filename[0] == '$' && 0 == grub_strncmp(filename, "$RECYCLE.BIN", 12))
{
return 0;
}
if (g_plugin_image_list == VENTOY_IMG_WHITE_LIST)
{
grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s/", node->dir, filename);
index = ventoy_plugin_get_image_list_index(vtoy_class_directory, g_img_swap_tmp_buf);
if (index == 0)
{
debug("Directory %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
return 0;
}
}
new_node = grub_zalloc(sizeof(img_iterator_node));
if (new_node)
{
new_node->level = node->level + 1;
new_node->plugin_list_index = index;
new_node->dirlen = grub_snprintf(new_node->dir, sizeof(new_node->dir), "%s%s/", node->dir, filename);
g_enum_fs->fs_dir(g_enum_dev, new_node->dir, ventoy_check_ignore_flag, &ignore);
if (ignore)
{
debug("Directory %s ignored...\n", new_node->dir);
grub_free(new_node);
return 0;
}
new_node->tail = node->tail;
new_node->parent = node;
if (!node->firstchild)
{
node->firstchild = new_node;
}
if (g_img_iterator_tail)
{
g_img_iterator_tail->next = new_node;
g_img_iterator_tail = new_node;
}
else
{
g_img_iterator_head.next = new_node;
g_img_iterator_tail = new_node;
}
}
}
else
{
debug("Find a file %s\n", filename);
if (len < 4)
{
return 0;
}
if (FILE_FLT(ISO) && 0 == grub_strcasecmp(filename + len - 4, ".iso"))
{
type = img_type_iso;
}
else if (FILE_FLT(WIM) && g_wimboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".wim")))
{
type = img_type_wim;
}
else if (FILE_FLT(VHD) && g_vhdboot_enable && (0 == grub_strcasecmp(filename + len - 4, ".vhd") ||
(len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vhdx"))))
{
type = img_type_vhd;
}
#ifdef GRUB_MACHINE_EFI
else if (FILE_FLT(EFI) && 0 == grub_strcasecmp(filename + len - 4, ".efi"))
{
type = img_type_efi;
}
#endif
else if (FILE_FLT(IMG) && 0 == grub_strcasecmp(filename + len - 4, ".img"))
{
if (len == 18 && grub_strncmp(filename, "ventoy_", 7) == 0)
{
if (grub_strncmp(filename + 7, "wimboot", 7) == 0 ||
grub_strncmp(filename + 7, "vhdboot", 7) == 0)
{
return 0;
}
}
type = img_type_img;
}
else if (FILE_FLT(VTOY) && len >= 5 && 0 == grub_strcasecmp(filename + len - 5, ".vtoy"))
{
type = img_type_vtoy;
}
else if (len >= 9 && 0 == grub_strcasecmp(filename + len - 5, ".vcfg"))
{
if (filename[len - 9] == '.' || (len >= 10 && filename[len - 10] == '.'))
{
grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
ventoy_plugin_add_custom_boot(g_img_swap_tmp_buf);
}
return 0;
}
else
{
return 0;
}
if (g_filt_dot_underscore_file && filename[0] == '.' && filename[1] == '_')
{
return 0;
}
if (g_plugin_image_list)
{
grub_snprintf(g_img_swap_tmp_buf, sizeof(g_img_swap_tmp_buf), "%s%s", node->dir, filename);
index = ventoy_plugin_get_image_list_index(vtoy_class_image_file, g_img_swap_tmp_buf);
if (VENTOY_IMG_WHITE_LIST == g_plugin_image_list && index == 0)
{
debug("File %s not found in image_list plugin config...\n", g_img_swap_tmp_buf);
return 0;
}
else if (VENTOY_IMG_BLACK_LIST == g_plugin_image_list && index > 0)
{
debug("File %s found in image_blacklist plugin config %d ...\n", g_img_swap_tmp_buf, index);
return 0;
}
}
img = grub_zalloc(sizeof(img_info));
if (img)
{
img->type = type;
img->plugin_list_index = index;
grub_snprintf(img->name, sizeof(img->name), "%s", filename);
img->pathlen = grub_snprintf(img->path, sizeof(img->path), "%s%s", node->dir, img->name);
img->size = info->size;
if (0 == img->size)
{
img->size = ventoy_grub_get_file_size("%s/%s%s", g_iso_path, node->dir, filename);
}
if (img->size < VTOY_FILT_MIN_FILE_SIZE)
{
debug("img <%s> size too small %llu\n", img->name, (ulonglong)img->size);
grub_free(img);
return 0;
}
if (g_ventoy_img_list)
{
tail = *(node->tail);
img->prev = tail;
tail->next = img;
}
else
{
g_ventoy_img_list = img;
}
img->id = g_ventoy_img_count;
img->parent = node;
if (node && NULL == node->firstiso)
{
node->firstiso = img;
}
node->isocnt++;
tmp = node->parent;
while (tmp)
{
tmp->isocnt++;
tmp = tmp->parent;
}
*((img_info **)(node->tail)) = img;
g_ventoy_img_count++;
img->alias = ventoy_plugin_get_menu_alias(vtoy_alias_image_file, img->path);
img->class = ventoy_plugin_get_menu_class(vtoy_class_image_file, img->name, img->path);
if (!img->class)
{
img->class = g_menu_class[type];
}
img->menu_prefix = g_menu_prefix[type];
if (img_type_iso == type)
{
if (ventoy_plugin_check_memdisk(img->path))
{
img->menu_prefix = "miso";
}
}
debug("Add %s%s to list %d\n", node->dir, filename, g_ventoy_img_count);
}
}
return 0;
}
int ventoy_fill_data(grub_uint32_t buflen, char *buffer)
{
int len = GRUB_UINT_MAX;
const char *value = NULL;
char name[32] = {0};
char plat[32] = {0};
char guidstr[32] = {0};
ventoy_guid guid = VENTOY_GUID;
const char *fmt1 = NULL;
const char *fmt2 = NULL;
const char *fmt3 = NULL;
grub_uint32_t *puint = (grub_uint32_t *)name;
grub_uint32_t *puint2 = (grub_uint32_t *)plat;
const char fmtdata[]={ 0x39, 0x35, 0x25, 0x00, 0x35, 0x00, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x00 };
const char fmtcode[]={
0x22, 0x0A, 0x2B, 0x20, 0x68, 0x62, 0x6F, 0x78, 0x20, 0x7B, 0x0A, 0x20, 0x20, 0x74, 0x6F, 0x70,
0x20, 0x3D, 0x20, 0x25, 0x73, 0x0A, 0x20, 0x20, 0x6C, 0x65, 0x66, 0x74, 0x20, 0x3D, 0x20, 0x25,
0x73, 0x0A, 0x20, 0x20, 0x2B, 0x20, 0x6C, 0x61, 0x62, 0x65, 0x6C, 0x20, 0x7B, 0x74, 0x65, 0x78,
0x74, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x20, 0x25, 0x73, 0x25, 0x73, 0x22, 0x20, 0x63, 0x6F,
0x6C, 0x6F, 0x72, 0x20, 0x3D, 0x20, 0x22, 0x25, 0x73, 0x22, 0x20, 0x61, 0x6C, 0x69, 0x67, 0x6E,
0x20, 0x3D, 0x20, 0x22, 0x6C, 0x65, 0x66, 0x74, 0x22, 0x7D, 0x0A, 0x7D, 0x0A, 0x22, 0x00
};
grub_memset(name, 0, sizeof(name));
puint[0] = grub_swap_bytes32(0x56454e54);
puint[3] = grub_swap_bytes32(0x4f4e0000);
puint[2] = grub_swap_bytes32(0x45525349);
puint[1] = grub_swap_bytes32(0x4f595f56);
value = ventoy_get_env(name);
grub_memset(name, 0, sizeof(name));
puint[1] = grub_swap_bytes32(0x5f544f50);
puint[0] = grub_swap_bytes32(0x56544c45);
fmt1 = ventoy_get_env(name);
if (!fmt1)
{
fmt1 = fmtdata;
}
grub_memset(name, 0, sizeof(name));
puint[1] = grub_swap_bytes32(0x5f4c4654);
puint[0] = grub_swap_bytes32(0x56544c45);
fmt2 = ventoy_get_env(name);
grub_memset(name, 0, sizeof(name));
puint[1] = grub_swap_bytes32(0x5f434c52);
puint[0] = grub_swap_bytes32(0x56544c45);
fmt3 = ventoy_get_env(name);
grub_memcpy(guidstr, &guid, sizeof(guid));
puint2[0] = grub_swap_bytes32(g_ventoy_plat_data);
/* Easter egg :) It will be appreciated if you reserve it, but NOT mandatory. */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
len = grub_snprintf(buffer, buflen, fmtcode,
fmt1 ? fmt1 : fmtdata,
fmt2 ? fmt2 : fmtdata + 4,
value ? value : "", plat, guidstr,
fmt3 ? fmt3 : fmtdata + 6);
#pragma GCC diagnostic pop
grub_memset(name, 0, sizeof(name));
puint[0] = grub_swap_bytes32(0x76746f79);
puint[2] = grub_swap_bytes32(0x656e7365);
puint[1] = grub_swap_bytes32(0x5f6c6963);
ventoy_set_env(name, guidstr);
return len;
}
int ventoy_check_password(const vtoy_password *pwd, int retry)
{
int offset;
char input[256];
grub_uint8_t md5[16];
while (retry--)
{
grub_memset(input, 0, sizeof(input));
grub_printf("Enter password: ");
grub_refresh();
if (pwd->type == VTOY_PASSWORD_TXT)
{
grub_password_get(input, 128);
if (grub_strcmp(pwd->text, input) == 0)
{
return 0;
}
}
else if (pwd->type == VTOY_PASSWORD_MD5)
{
grub_password_get(input, 128);
grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
if (grub_memcmp(pwd->md5, md5, 16) == 0)
{
return 0;
}
}
else if (pwd->type == VTOY_PASSWORD_SALT_MD5)
{
offset = (int)grub_snprintf(input, 128, "%s", pwd->salt);
grub_password_get(input + offset, 128);
grub_crypto_hash(GRUB_MD_MD5, md5, input, grub_strlen(input));
if (grub_memcmp(pwd->md5, md5, 16) == 0)
{
return 0;
}
}
grub_printf("Invalid password!\n\n");
grub_refresh();
}
return 1;
}
static img_info * ventoy_get_min_iso(img_iterator_node *node)
{
img_info *minimg = NULL;
img_info *img = (img_info *)(node->firstiso);
while (img && (img_iterator_node *)(img->parent) == node)
{
if (img->select == 0 && (NULL == minimg || ventoy_cmp_img(img, minimg) < 0))
{
minimg = img;
}
img = img->next;
}
if (minimg)
{
minimg->select = 1;
}
return minimg;
}
static img_iterator_node * ventoy_get_min_child(img_iterator_node *node)
{
img_iterator_node *Minchild = NULL;
img_iterator_node *child = node->firstchild;
while (child && child->parent == node)
{
if (child->select == 0 && (NULL == Minchild || ventoy_cmp_subdir(child, Minchild) < 0))
{
Minchild = child;
}
child = child->next;
}
if (Minchild)
{
Minchild->select = 1;
}
return Minchild;
}
static int ventoy_dynamic_tree_menu(img_iterator_node *node)
{
int offset = 1;
img_info *img = NULL;
const char *dir_class = NULL;
const char *dir_alias = NULL;
img_iterator_node *child = NULL;
if (node->isocnt == 0 || node->done == 1)
{
return 0;
}
if (node->parent && node->parent->dirlen < node->dirlen)
{
offset = node->parent->dirlen;
}
if (node == &g_img_iterator_head)
{
if (g_default_menu_mode == 0)
{
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"%-10s [Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo 'return ...' \n"
"}\n", "<--");
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"[Return to ListView]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo '%s ...' \n"
"}\n", "return");
}
}
}
else
{
node->dir[node->dirlen - 1] = 0;
dir_class = ventoy_plugin_get_menu_class(vtoy_class_directory, node->dir, node->dir);
if (!dir_class)
{
dir_class = "vtoydir";
}
dir_alias = ventoy_plugin_get_menu_alias(vtoy_alias_directory, node->dir);
if (dir_alias)
{
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"%-10s %s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
"DIR", dir_alias, dir_class, node->dir + offset);
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"%s\" --class=\"%s\" --id=\"DIR_%s\" {\n",
dir_alias, dir_class, node->dir + offset);
}
}
else
{
dir_alias = node->dir + offset;
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"%-10s [%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
"DIR", dir_alias, dir_class, node->dir + offset);
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"submenu \"[%s]\" --class=\"%s\" --id=\"DIR_%s\" {\n",
dir_alias, dir_class, node->dir + offset);
}
}
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"%-10s [../]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo 'return ...' \n"
"}\n", "<--");
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"[../]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo '%s ...' \n"
"}\n", "return");
}
}
while ((child = ventoy_get_min_child(node)) != NULL)
{
ventoy_dynamic_tree_menu(child);
}
while ((img = ventoy_get_min_iso(node)) != NULL)
{
if (g_tree_view_menu_style == 0)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"%-10s %s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
" %s_%s \n"
"}\n",
grub_get_human_size(img->size, GRUB_HUMAN_SIZE_SHORT),
img->unsupport ? "[***********] " : "",
img->alias ? img->alias : img->name, img->class, img->id,
img->menu_prefix,
img->unsupport ? "unsupport_menuentry" : "common_menuentry");
}
else
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos,
"menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
" %s_%s \n"
"}\n",
img->unsupport ? "[***********] " : "",
img->alias ? img->alias : img->name, img->class, img->id,
img->menu_prefix,
img->unsupport ? "unsupport_menuentry" : "common_menuentry");
}
}
if (node != &g_img_iterator_head)
{
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "%s", "}\n");
}
node->done = 1;
return 0;
}
static int ventoy_set_default_menu(void)
{
int img_len = 0;
char *pos = NULL;
char *end = NULL;
char *def = NULL;
const char *strdata = NULL;
img_info *cur = NULL;
img_info *default_node = NULL;
const char *default_image = NULL;
default_image = ventoy_get_env("VTOY_DEFAULT_IMAGE");
if (default_image && default_image[0] == '/')
{
img_len = grub_strlen(default_image);
for (cur = g_ventoy_img_list; cur; cur = cur->next)
{
if (img_len == cur->pathlen && grub_strcmp(default_image, cur->path) == 0)
{
default_node = cur;
break;
}
}
if (!default_node)
{
return 1;
}
if (0 == g_default_menu_mode)
{
vtoy_ssprintf(g_list_script_buf, g_list_script_pos, "set default='VID_%d'\n", default_node->id);
}
else
{
def = grub_strdup(default_image);
if (!def)
{
return 1;
}
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "set default=%c", '\'');
strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
if (strdata && strdata[0] == '/')
{
pos = def + grub_strlen(strdata);
if (*pos == '/')
{
pos++;
}
}
else
{
pos = def + 1;
}
while ((end = grub_strchr(pos, '/')) != NULL)
{
*end = 0;
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "DIR_%s>", pos);
pos = end + 1;
}
vtoy_ssprintf(g_tree_script_buf, g_tree_script_pos, "VID_%d'\n", default_node->id);
grub_free(def);
}
}
return 0;
}
static grub_err_t ventoy_cmd_clear_img(grub_extcmd_context_t ctxt, int argc, char **args)
{
img_info *next = NULL;
img_info *cur = g_ventoy_img_list;
(void)ctxt;
(void)argc;
(void)args;
while (cur)
{
next = cur->next;
grub_free(cur);
cur = next;
}
g_ventoy_img_list = NULL;
g_ventoy_img_count = 0;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_img_name(grub_extcmd_context_t ctxt, int argc, char **args)
{
long img_id = 0;
img_info *cur = g_ventoy_img_list;
(void)ctxt;
if (argc != 2 || (!ventoy_is_decimal(args[0])))
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {imageID} {var}", cmd_raw_name);
}
img_id = grub_strtol(args[0], NULL, 10);
if (img_id >= g_ventoy_img_count)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images %ld %ld", img_id, g_ventoy_img_count);
}
debug("Find image %ld name \n", img_id);
while (cur && img_id > 0)
{
img_id--;
cur = cur->next;
}
if (!cur)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such many images");
}
debug("image name is %s\n", cur->name);
grub_env_set(args[1], cur->name);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_ext_select_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len = 0;
char id[32] = {0};
img_info *cur = g_ventoy_img_list;
(void)ctxt;
if (argc != 1)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
}
len = (int)grub_strlen(args[0]);
while (cur)
{
if (len == cur->pathlen && 0 == grub_strcmp(args[0], cur->path))
{
break;
}
cur = cur->next;
}
if (!cur)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
}
grub_snprintf(id, sizeof(id), "VID_%d", cur->id);
grub_env_set("chosen", id);
grub_env_export("chosen");
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_chosen_img_path(grub_extcmd_context_t ctxt, int argc, char **args)
{
int img_id = 0;
char value[32];
char *pos = NULL;
const char *id = NULL;
img_info *cur = g_ventoy_img_list;
(void)ctxt;
if (argc < 1 || argc > 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {var}", cmd_raw_name);
}
id = grub_env_get("chosen");
pos = grub_strstr(id, "VID_");
if (pos)
{
img_id = (int)grub_strtoul(pos + 4, NULL, 10);
}
else
{
img_id = (int)grub_strtoul(id, NULL, 10);
}
while (cur)
{
if (img_id == cur->id)
{
break;
}
cur = cur->next;
}
if (!cur)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "No such image");
}
grub_env_set(args[0], cur->path);
if (argc > 1)
{
grub_snprintf(value, sizeof(value), "%llu", (ulonglong)(cur->size));
grub_env_set(args[1], value);
}
g_svd_replace_offset = 0;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_list_img(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len;
grub_fs_t fs;
grub_device_t dev = NULL;
img_info *cur = NULL;
img_info *tail = NULL;
const char *strdata = NULL;
char *device_name = NULL;
char buf[32];
img_iterator_node *node = NULL;
img_iterator_node *tmp = NULL;
(void)ctxt;
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s {device} {cntvar}", cmd_raw_name);
}
if (g_ventoy_img_list || g_ventoy_img_count)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Must clear image before list");
}
VTOY_CMD_CHECK(1);
g_enumerate_time_checked = 0;
g_enumerate_start_time_ms = grub_get_time_ms();
strdata = ventoy_get_env("VTOY_FILT_DOT_UNDERSCORE_FILE");
if (strdata && strdata[0] == '1' && strdata[1] == 0)
{
g_filt_dot_underscore_file = 1;
}
strdata = ventoy_get_env("VTOY_SORT_CASE_SENSITIVE");
if (strdata && strdata[0] == '1' && strdata[1] == 0)
{
g_sort_case_sensitive = 1;
}
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
goto fail;
}
g_enum_dev = dev = grub_device_open(device_name);
if (!dev)
{
goto fail;
}
g_enum_fs = fs = grub_fs_probe(dev);
if (!fs)
{
goto fail;
}
if (ventoy_get_fs_type(fs->name) >= ventoy_fs_max)
{
debug("unsupported fs:<%s>\n", fs->name);
ventoy_set_env("VTOY_NO_ISO_TIP", "unsupported file system");
goto fail;
}
ventoy_set_env("vtoy_iso_fs", fs->name);
strdata = ventoy_get_env("VTOY_DEFAULT_MENU_MODE");
if (strdata && strdata[0] == '1')
{
g_default_menu_mode = 1;
}
grub_memset(&g_img_iterator_head, 0, sizeof(g_img_iterator_head));
grub_snprintf(g_iso_path, sizeof(g_iso_path), "%s", args[0]);
strdata = ventoy_get_env("VTOY_DEFAULT_SEARCH_ROOT");
if (strdata && strdata[0] == '/')
{
len = grub_snprintf(g_img_iterator_head.dir, sizeof(g_img_iterator_head.dir) - 1, "%s", strdata);
if (g_img_iterator_head.dir[len - 1] != '/')
{
g_img_iterator_head.dir[len++] = '/';
}
g_img_iterator_head.dirlen = len;
}
else
{
g_img_iterator_head.dirlen = 1;
grub_strcpy(g_img_iterator_head.dir, "/");
}
g_img_iterator_head.tail = &tail;
if (g_img_max_search_level < 0)
{
g_img_max_search_level = GRUB_INT_MAX;
strdata = ventoy_get_env("VTOY_MAX_SEARCH_LEVEL");
if (strdata && ventoy_is_decimal(strdata))
{
g_img_max_search_level = (int)grub_strtoul(strdata, NULL, 10);
}
}
g_vtoy_file_flt[VTOY_FILE_FLT_ISO] = ventoy_control_get_flag("VTOY_FILE_FLT_ISO");
g_vtoy_file_flt[VTOY_FILE_FLT_WIM] = ventoy_control_get_flag("VTOY_FILE_FLT_WIM");
g_vtoy_file_flt[VTOY_FILE_FLT_EFI] = ventoy_control_get_flag("VTOY_FILE_FLT_EFI");
g_vtoy_file_flt[VTOY_FILE_FLT_IMG] = ventoy_control_get_flag("VTOY_FILE_FLT_IMG");
g_vtoy_file_flt[VTOY_FILE_FLT_VHD] = ventoy_control_get_flag("VTOY_FILE_FLT_VHD");
g_vtoy_file_flt[VTOY_FILE_FLT_VTOY] = ventoy_control_get_flag("VTOY_FILE_FLT_VTOY");
for (node = &g_img_iterator_head; node; node = node->next)
{
fs->fs_dir(dev, node->dir, ventoy_collect_img_files, node);
}
strdata = ventoy_get_env("VTOY_TREE_VIEW_MENU_STYLE");
if (strdata && strdata[0] == '1' && strdata[1] == 0)
{
g_tree_view_menu_style = 1;
}
ventoy_set_default_menu();
for (node = &g_img_iterator_head; node; node = node->next)
{
ventoy_dynamic_tree_menu(node);
}
/* free node */
node = g_img_iterator_head.next;
while (node)
{
tmp = node->next;
grub_free(node);
node = tmp;
}
/* sort image list by image name */
for (cur = g_ventoy_img_list; cur; cur = cur->next)
{
for (tail = cur->next; tail; tail = tail->next)
{
if (ventoy_cmp_img(cur, tail) > 0)
{
ventoy_swap_img(cur, tail);
}
}
}
if (g_default_menu_mode == 1)
{
vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
"menuentry \"%s [Return to TreeView]\" --class=\"vtoyret\" VTOY_RET {\n "
" echo 'return ...' \n"
"}\n", "<--");
}
for (cur = g_ventoy_img_list; cur; cur = cur->next)
{
vtoy_ssprintf(g_list_script_buf, g_list_script_pos,
"menuentry \"%s%s\" --class=\"%s\" --id=\"VID_%d\" {\n"
" %s_%s \n"
"}\n",
cur->unsupport ? "[***********] " : "",
cur->alias ? cur->alias : cur->name, cur->class, cur->id,
cur->menu_prefix,
cur->unsupport ? "unsupport_menuentry" : "common_menuentry");
}
g_tree_script_buf[g_tree_script_pos] = 0;
g_list_script_buf[g_list_script_pos] = 0;
grub_snprintf(buf, sizeof(buf), "%d", g_ventoy_img_count);
grub_env_set(args[1], buf);
fail:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
int ventoy_get_disk_guid(const char *filename, grub_uint8_t *guid, grub_uint8_t *signature)
{
grub_disk_t disk;
char *device_name;
char *pos;
char *pos2;
device_name = grub_file_get_device_name(filename);
if (!device_name)
{
return 1;
}
pos = device_name;
if (pos[0] == '(')
{
pos++;
}
pos2 = grub_strstr(pos, ",");
if (!pos2)
{
pos2 = grub_strstr(pos, ")");
}
if (pos2)
{
*pos2 = 0;
}
disk = grub_disk_open(pos);
if (disk)
{
grub_disk_read(disk, 0, 0x180, 16, guid);
grub_disk_read(disk, 0, 0x1b8, 4, signature);
grub_disk_close(disk);
}
else
{
return 1;
}
grub_free(device_name);
return 0;
}
grub_uint32_t ventoy_get_iso_boot_catlog(grub_file_t file)
{
eltorito_descriptor desc;
grub_memset(&desc, 0, sizeof(desc));
grub_file_seek(file, 17 * 2048);
grub_file_read(file, &desc, sizeof(desc));
if (desc.type != 0 || desc.version != 1)
{
return 0;
}
if (grub_strncmp((char *)desc.id, "CD001", 5) != 0 ||
grub_strncmp((char *)desc.system_id, "EL TORITO SPECIFICATION", 23) != 0)
{
return 0;
}
return desc.sector;
}
int ventoy_has_efi_eltorito(grub_file_t file, grub_uint32_t sector)
{
int i;
int x86count = 0;
grub_uint8_t buf[512];
grub_uint8_t parttype[] = { 0x04, 0x06, 0x0B, 0x0C };
grub_file_seek(file, sector * 2048);
grub_file_read(file, buf, sizeof(buf));
if (buf[0] == 0x01 && buf[1] == 0xEF)
{
debug("%s efi eltorito in Validation Entry\n", file->name);
return 1;
}
if (buf[0] == 0x01 && buf[1] == 0x00)
{
x86count++;
}
for (i = 64; i < (int)sizeof(buf); i += 32)
{
if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0xEF)
{
debug("%s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
return 1;
}
if ((buf[i] == 0x90 || buf[i] == 0x91) && buf[i + 1] == 0x00 && x86count == 1)
{
debug("0x9100 assume %s efi eltorito offset %d 0x%02x\n", file->name, i, buf[i]);
return 1;
}
}
if (x86count && buf[32] == 0x88 && buf[33] == 0x04)
{
for (i = 0; i < (int)(ARRAY_SIZE(parttype)); i++)
{
if (buf[36] == parttype[i])
{
debug("hard disk image assume %s efi eltorito, part type 0x%x\n", file->name, buf[36]);
return 1;
}
}
}
debug("%s does not contain efi eltorito\n", file->name);
return 0;
}
void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
{
char *pos;
const char *fs = NULL;
const char *cdprompt = NULL;
grub_uint32_t i;
grub_uint8_t chksum = 0;
grub_disk_t disk;
disk = file->device->disk;
grub_memcpy(&param->guid, &g_ventoy_guid, sizeof(ventoy_guid));
param->vtoy_disk_size = disk->total_sectors * (1 << disk->log_sector_size);
param->vtoy_disk_part_id = disk->partition->number + 1;
param->vtoy_disk_part_type = ventoy_get_fs_type(file->fs->name);
pos = grub_strstr(file->name, "/");
if (!pos)
{
pos = file->name;
}
grub_snprintf(param->vtoy_img_path, sizeof(param->vtoy_img_path), "%s", pos);
ventoy_get_disk_guid(file->name, param->vtoy_disk_guid, param->vtoy_disk_signature);
param->vtoy_img_size = file->size;
param->vtoy_reserved[0] = g_ventoy_break_level;
param->vtoy_reserved[1] = g_ventoy_debug_level;
param->vtoy_reserved[2] = g_ventoy_chain_type;
/* Windows CD/DVD prompt 0:suppress 1:reserved */
param->vtoy_reserved[4] = 0;
if (g_ventoy_chain_type == 1) /* Windows */
{
cdprompt = ventoy_get_env("VTOY_WINDOWS_CD_PROMPT");
if (cdprompt && cdprompt[0] == '1' && cdprompt[1] == 0)
{
param->vtoy_reserved[4] = 1;
}
}
fs = ventoy_get_env("ventoy_fs_probe");
if (fs && grub_strcmp(fs, "udf") == 0)
{
param->vtoy_reserved[3] = 1;
}
/* calculate checksum */
for (i = 0; i < sizeof(ventoy_os_param); i++)
{
chksum += *((grub_uint8_t *)param + i);
}
param->chksum = (grub_uint8_t)(0x100 - chksum);
return;
}
int ventoy_check_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
{
grub_uint32_t i = 0;
grub_uint64_t total = 0;
grub_uint64_t fileblk = 0;
ventoy_img_chunk *chunk = NULL;
for (i = 0; i < chunklist->cur_chunk; i++)
{
chunk = chunklist->chunk + i;
if (chunk->disk_start_sector <= start)
{
debug("%u disk start invalid %lu\n", i, (ulong)start);
return 1;
}
total += chunk->disk_end_sector + 1 - chunk->disk_start_sector;
}
fileblk = (file->size + 511) / 512;
if (total != fileblk)
{
debug("Invalid total: %llu %llu\n", (ulonglong)total, (ulonglong)fileblk);
if ((file->size % 512) && (total + 1 == fileblk))
{
debug("maybe img file to be processed.\n");
return 0;
}
return 1;
}
return 0;
}
int ventoy_get_block_list(grub_file_t file, ventoy_img_chunk_list *chunklist, grub_disk_addr_t start)
{
int fs_type;
int len;
grub_uint32_t i = 0;
grub_uint32_t sector = 0;
grub_uint32_t count = 0;
grub_off_t size = 0;
grub_off_t read = 0;
fs_type = ventoy_get_fs_type(file->fs->name);
if (fs_type == ventoy_fs_exfat)
{
grub_fat_get_file_chunk(start, file, chunklist);
}
else if (fs_type == ventoy_fs_ext)
{
grub_ext_get_file_chunk(start, file, chunklist);
}
else
{
file->read_hook = (grub_disk_read_hook_t)grub_disk_blocklist_read;
file->read_hook_data = chunklist;
for (size = file->size; size > 0; size -= read)
{
read = (size > VTOY_SIZE_1GB) ? VTOY_SIZE_1GB : size;
grub_file_read(file, NULL, read);
}
for (i = 0; start > 0 && i < chunklist->cur_chunk; i++)
{
chunklist->chunk[i].disk_start_sector += start;
chunklist->chunk[i].disk_end_sector += start;
}
if (ventoy_fs_udf == fs_type)
{
for (i = 0; i < chunklist->cur_chunk; i++)
{
count = (chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector) >> 2;
chunklist->chunk[i].img_start_sector = sector;
chunklist->chunk[i].img_end_sector = sector + count - 1;
sector += count;
}
}
}
len = (int)grub_strlen(file->name);
if ((len > 4 && grub_strncasecmp(file->name + len - 4, ".img", 4) == 0) ||
(len > 4 && grub_strncasecmp(file->name + len - 4, ".vhd", 4) == 0) ||
(len > 5 && grub_strncasecmp(file->name + len - 5, ".vhdx", 5) == 0) ||
(len > 5 && grub_strncasecmp(file->name + len - 5, ".vtoy", 5) == 0))
{
for (i = 0; i < chunklist->cur_chunk; i++)
{
count = chunklist->chunk[i].disk_end_sector + 1 - chunklist->chunk[i].disk_start_sector;
if (count < 4)
{
count = 1;
}
else
{
count >>= 2;
}
chunklist->chunk[i].img_start_sector = sector;
chunklist->chunk[i].img_end_sector = sector + count - 1;
sector += count;
}
}
return 0;
}
static grub_err_t ventoy_cmd_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc;
grub_file_t file;
grub_disk_addr_t start;
(void)ctxt;
(void)argc;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
}
g_conf_replace_node = NULL;
g_conf_replace_offset = 0;
if (g_img_chunk_list.chunk)
{
grub_free(g_img_chunk_list.chunk);
}
if (ventoy_get_fs_type(file->fs->name) >= ventoy_fs_max)
{
grub_file_close(file);
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Unsupported filesystem %s\n", file->fs->name);
}
/* get image chunk data */
grub_memset(&g_img_chunk_list, 0, sizeof(g_img_chunk_list));
g_img_chunk_list.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
if (NULL == g_img_chunk_list.chunk)
{
return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
}
g_img_chunk_list.max_chunk = DEFAULT_CHUNK_NUM;
g_img_chunk_list.cur_chunk = 0;
start = file->device->disk->partition->start;
ventoy_get_block_list(file, &g_img_chunk_list, start);
rc = ventoy_check_block_list(file, &g_img_chunk_list, start);
grub_file_close(file);
if (rc)
{
return grub_error(GRUB_ERR_NOT_IMPLEMENTED_YET, "Unsupported chunk list.\n");
}
grub_memset(&g_grub_param->file_replace, 0, sizeof(g_grub_param->file_replace));
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_select_conf_replace(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint64_t offset = 0;
grub_uint32_t align = 0;
grub_file_t file = NULL;
conf_replace *node = NULL;
(void)ctxt;
(void)argc;
(void)args;
debug("select conf replace argc:%d\n", argc);
if (argc < 2)
{
return 0;
}
node = ventoy_plugin_find_conf_replace(args[1]);
if (!node)
{
debug("Conf replace not found for %s\n", args[1]);
goto end;
}
debug("Find conf replace for %s\n", args[1]);
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(loop)%s", node->orgconf);
if (!file)
{
debug("<(loop)%s> NOT exist\n", node->orgconf);
goto end;
}
offset = grub_iso9660_get_last_file_dirent_pos(file);
grub_file_close(file);
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", args[0], node->newconf);
if (!file)
{
debug("New config file <%s%s> NOT exist\n", args[0], node->newconf);
goto end;
}
align = ((int)file->size + 2047) / 2048 * 2048;
if (align > vtoy_max_replace_file_size)
{
debug("New config file <%s%s> too big\n", args[0], node->newconf);
goto end;
}
grub_file_read(file, g_conf_replace_new_buf, file->size);
g_conf_replace_new_len = (int)file->size;
g_conf_replace_new_len_align = align;
g_conf_replace_node = node;
g_conf_replace_offset = offset + 2;
debug("conf_replace OK: newlen: %d\n", g_conf_replace_new_len);
end:
if (file)
{
grub_file_close(file);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_sel_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i = 0;
int pos = 0;
char *buf = NULL;
char configfile[128];
install_template *node = NULL;
(void)ctxt;
(void)argc;
(void)args;
debug("select auto installation argc:%d\n", argc);
if (argc < 1)
{
return 0;
}
node = ventoy_plugin_find_install_template(args[0]);
if (!node)
{
debug("Auto install template not found for %s\n", args[0]);
return 0;
}
if (node->autosel >= 0 && node->autosel <= node->templatenum)
{
node->cursel = node->autosel - 1;
debug("Auto install template auto select %d\n", node->autosel);
return 0;
}
buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
if (!buf)
{
return 0;
}
vtoy_ssprintf(buf, pos, "menuentry \"Boot without auto installation template\" {\n"
" echo %s\n}\n", "123");
for (i = 0; i < node->templatenum; i++)
{
vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" {\n"
" echo 123\n}\n",
node->templatepath[i].path);
}
g_ventoy_menu_esc = 1;
g_ventoy_suppress_esc = 1;
grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
grub_script_execute_sourcecode(configfile);
g_ventoy_menu_esc = 0;
g_ventoy_suppress_esc = 0;
grub_free(buf);
node->cursel = g_ventoy_last_entry - 1;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_sel_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i = 0;
int pos = 0;
char *buf = NULL;
char configfile[128];
persistence_config *node;
(void)ctxt;
(void)argc;
(void)args;
debug("select persistence argc:%d\n", argc);
if (argc < 1)
{
return 0;
}
node = ventoy_plugin_find_persistent(args[0]);
if (!node)
{
debug("Persistence image not found for %s\n", args[0]);
return 0;
}
if (node->autosel >= 0 && node->autosel <= node->backendnum)
{
node->cursel = node->autosel - 1;
debug("Persistence image auto select %d\n", node->autosel);
return 0;
}
buf = (char *)grub_malloc(VTOY_MAX_SCRIPT_BUF);
if (!buf)
{
return 0;
}
vtoy_ssprintf(buf, pos, "menuentry \"Boot without persistence\" {\n"
" echo %s\n}\n", "123");
for (i = 0; i < node->backendnum; i++)
{
vtoy_ssprintf(buf, pos, "menuentry \"Boot with %s\" {\n"
" echo 123\n}\n",
node->backendpath[i].path);
}
g_ventoy_menu_esc = 1;
g_ventoy_suppress_esc = 1;
grub_snprintf(configfile, sizeof(configfile), "configfile mem:0x%llx:size:%d", (ulonglong)(ulong)buf, pos);
grub_script_execute_sourcecode(configfile);
g_ventoy_menu_esc = 0;
g_ventoy_suppress_esc = 0;
grub_free(buf);
node->cursel = g_ventoy_last_entry - 1;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_dump_img_sector(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint32_t i;
ventoy_img_chunk *cur;
(void)ctxt;
(void)argc;
(void)args;
for (i = 0; i < g_img_chunk_list.cur_chunk; i++)
{
cur = g_img_chunk_list.chunk + i;
grub_printf("image:[%u - %u] <==> disk:[%llu - %llu]\n",
cur->img_start_sector, cur->img_end_sector,
(unsigned long long)cur->disk_start_sector, (unsigned long long)cur->disk_end_sector
);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_test_block_list(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_uint32_t i;
grub_file_t file;
ventoy_img_chunk_list chunklist;
(void)ctxt;
(void)argc;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Can't open file %s\n", args[0]);
}
/* get image chunk data */
grub_memset(&chunklist, 0, sizeof(chunklist));
chunklist.chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
if (NULL == chunklist.chunk)
{
return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
}
chunklist.max_chunk = DEFAULT_CHUNK_NUM;
chunklist.cur_chunk = 0;
ventoy_get_block_list(file, &chunklist, 0);
if (0 != ventoy_check_block_list(file, &chunklist, 0))
{
grub_printf("########## UNSUPPORTED ###############\n");
}
grub_printf("filesystem: <%s> entry number:<%u>\n", file->fs->name, chunklist.cur_chunk);
for (i = 0; i < chunklist.cur_chunk; i++)
{
grub_printf("%llu+%llu,", (ulonglong)chunklist.chunk[i].disk_start_sector,
(ulonglong)(chunklist.chunk[i].disk_end_sector + 1 - chunklist.chunk[i].disk_start_sector));
}
grub_printf("\n==================================\n");
for (i = 0; i < chunklist.cur_chunk; i++)
{
grub_printf("%2u: [%llu %llu] - [%llu %llu]\n", i,
(ulonglong)chunklist.chunk[i].img_start_sector,
(ulonglong)chunklist.chunk[i].img_end_sector,
(ulonglong)chunklist.chunk[i].disk_start_sector,
(ulonglong)chunklist.chunk[i].disk_end_sector
);
}
grub_free(chunklist.chunk);
grub_file_close(file);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_add_replace_file(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
ventoy_grub_param_file_replace *replace = NULL;
(void)ctxt;
(void)argc;
(void)args;
if (argc >= 2)
{
replace = &(g_grub_param->file_replace);
replace->magic = GRUB_FILE_REPLACE_MAGIC;
replace->old_name_cnt = 0;
for (i = 0; i < 4 && i + 1 < argc; i++)
{
replace->old_name_cnt++;
grub_snprintf(replace->old_file_name[i], sizeof(replace->old_file_name[i]), "%s", args[i + 1]);
}
replace->new_file_virtual_id = (grub_uint32_t)grub_strtoul(args[0], NULL, 10);
}
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_cmd_dump_menu(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
if (argc == 0)
{
grub_printf("List Mode: CurLen:%d MaxLen:%u\n", g_list_script_pos, VTOY_MAX_SCRIPT_BUF);
grub_printf("%s", g_list_script_buf);
}
else
{
grub_printf("Tree Mode: CurLen:%d MaxLen:%u\n", g_tree_script_pos, VTOY_MAX_SCRIPT_BUF);
grub_printf("%s", g_tree_script_buf);
}
return 0;
}
static grub_err_t ventoy_cmd_dump_img_list(grub_extcmd_context_t ctxt, int argc, char **args)
{
img_info *cur = g_ventoy_img_list;
(void)ctxt;
(void)argc;
(void)args;
while (cur)
{
grub_printf("path:<%s> id=%d list_index=%d\n", cur->path, cur->id, cur->plugin_list_index);
grub_printf("name:<%s>\n\n", cur->name);
cur = cur->next;
}
return 0;
}
static grub_err_t ventoy_cmd_dump_injection(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_plugin_dump_injection();
return 0;
}
static grub_err_t ventoy_cmd_dump_auto_install(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_plugin_dump_auto_install();
return 0;
}
static grub_err_t ventoy_cmd_dump_persistence(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_plugin_dump_persistence();
return 0;
}
static grub_err_t ventoy_cmd_check_mode(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
if (argc != 1)
{
return 1;
}
if (args[0][0] == '0')
{
return g_ventoy_memdisk_mode ? 0 : 1;
}
else if (args[0][0] == '1')
{
return g_ventoy_iso_raw ? 0 : 1;
}
else if (args[0][0] == '2')
{
return g_ventoy_iso_uefi_drv ? 0 : 1;
}
else if (args[0][0] == '3')
{
return g_ventoy_grub2_mode ? 0 : 1;
}
return 1;
}
static grub_err_t ventoy_cmd_dynamic_menu(grub_extcmd_context_t ctxt, int argc, char **args)
{
static int configfile_mode = 0;
char memfile[128] = {0};
(void)ctxt;
(void)argc;
(void)args;
/*
* args[0]: 0:normal 1:configfile
* args[1]: 0:list_buf 1:tree_buf
*/
if (argc != 2)
{
debug("Invalid argc %d\n", argc);
return 0;
}
VTOY_CMD_CHECK(1);
if (args[0][0] == '0')
{
if (args[1][0] == '0')
{
grub_script_execute_sourcecode(g_list_script_buf);
}
else
{
grub_script_execute_sourcecode(g_tree_script_buf);
}
}
else
{
if (configfile_mode)
{
debug("Now already in F3 mode %d\n", configfile_mode);
return 0;
}
if (args[1][0] == '0')
{
grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
(ulonglong)(ulong)g_list_script_buf, g_list_script_pos);
}
else
{
g_ventoy_last_entry = -1;
grub_snprintf(memfile, sizeof(memfile), "configfile mem:0x%llx:size:%d",
(ulonglong)(ulong)g_tree_script_buf, g_tree_script_pos);
}
configfile_mode = 1;
grub_script_execute_sourcecode(memfile);
configfile_mode = 0;
}
return 0;
}
static grub_err_t ventoy_cmd_file_exist_nocase(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_file_t file;
(void)ctxt;
if (argc != 1)
{
return 1;
}
g_ventoy_case_insensitive = 1;
file = grub_file_open(args[0], VENTOY_FILE_TYPE);
g_ventoy_case_insensitive = 0;
grub_errno = 0;
if (file)
{
grub_file_close(file);
return 0;
}
return 1;
}
static grub_err_t ventoy_cmd_find_bootable_hdd(grub_extcmd_context_t ctxt, int argc, char **args)
{
int id = 0;
int find = 0;
grub_disk_t disk;
const char *isopath = NULL;
char hdname[32];
ventoy_mbr_head mbr;
(void)ctxt;
(void)argc;
if (argc != 1)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s variable\n", cmd_raw_name);
}
isopath = grub_env_get("vtoy_iso_part");
if (!isopath)
{
debug("isopath is null %p\n", isopath);
return 0;
}
debug("isopath is %s\n", isopath);
for (id = 0; id < 30 && (find == 0); id++)
{
grub_snprintf(hdname, sizeof(hdname), "hd%d,", id);
if (grub_strstr(isopath, hdname))
{
debug("skip %s ...\n", hdname);
continue;
}
grub_snprintf(hdname, sizeof(hdname), "hd%d", id);
disk = grub_disk_open(hdname);
if (!disk)
{
debug("%s not exist\n", hdname);
break;
}
grub_memset(&mbr, 0, sizeof(mbr));
if (0 == grub_disk_read(disk, 0, 0, 512, &mbr))
{
if (mbr.Byte55 == 0x55 && mbr.ByteAA == 0xAA)
{
if (mbr.PartTbl[0].Active == 0x80 || mbr.PartTbl[1].Active == 0x80 ||
mbr.PartTbl[2].Active == 0x80 || mbr.PartTbl[3].Active == 0x80)
{
grub_env_set(args[0], hdname);
find = 1;
}
}
debug("%s is %s\n", hdname, find ? "bootable" : "NOT bootable");
}
else
{
debug("read %s failed\n", hdname);
}
grub_disk_close(disk);
}
return 0;
}
static grub_err_t ventoy_cmd_read_1st_line(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len = 1024;
grub_file_t file;
char *buf = NULL;
(void)ctxt;
(void)argc;
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file var \n", cmd_raw_name);
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 0;
}
buf = grub_malloc(len);
if (!buf)
{
goto end;
}
buf[len - 1] = 0;
grub_file_read(file, buf, len - 1);
ventoy_get_line(buf);
ventoy_set_env(args[1], buf);
end:
grub_check_free(buf);
grub_file_close(file);
return 0;
}
static int ventoy_img_partition_callback (struct grub_disk *disk, const grub_partition_t partition, void *data)
{
(void)disk;
(void)data;
g_part_list_pos += grub_snprintf(g_part_list_buf + g_part_list_pos, VTOY_MAX_SCRIPT_BUF - g_part_list_pos,
"0 %llu linear /dev/ventoy %llu\n",
(ulonglong)partition->len, (ulonglong)partition->start);
return 0;
}
static grub_err_t ventoy_cmd_img_part_info(grub_extcmd_context_t ctxt, int argc, char **args)
{
char *device_name = NULL;
grub_device_t dev = NULL;
char buf[64];
(void)ctxt;
g_part_list_pos = 0;
grub_env_unset("vtoy_img_part_file");
if (argc != 1)
{
return 1;
}
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
debug("ventoy_cmd_img_part_info failed, %s\n", args[0]);
goto end;
}
dev = grub_device_open(device_name);
if (!dev)
{
debug("grub_device_open failed, %s\n", device_name);
goto end;
}
grub_partition_iterate(dev->disk, ventoy_img_partition_callback, NULL);
grub_snprintf(buf, sizeof(buf), "newc:vtoy_dm_table:mem:0x%llx:size:%d", (ulonglong)(ulong)g_part_list_buf, g_part_list_pos);
grub_env_set("vtoy_img_part_file", buf);
end:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
return 0;
}
static grub_err_t ventoy_cmd_file_strstr(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
grub_file_t file;
char *buf = NULL;
(void)ctxt;
(void)argc;
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s file str \n", cmd_raw_name);
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 1;
}
buf = grub_malloc(file->size + 1);
if (!buf)
{
goto end;
}
buf[file->size] = 0;
grub_file_read(file, buf, file->size);
if (grub_strstr(buf, args[1]))
{
rc = 0;
}
end:
grub_check_free(buf);
grub_file_close(file);
return rc;
}
static grub_err_t ventoy_cmd_parse_volume(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len;
grub_file_t file;
char buf[64];
grub_uint64_t size;
ventoy_iso9660_vd pvd;
(void)ctxt;
(void)argc;
if (argc != 4)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s sysid volid space \n", cmd_raw_name);
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 0;
}
grub_file_seek(file, 16 * 2048);
len = (int)grub_file_read(file, &pvd, sizeof(pvd));
if (len != sizeof(pvd))
{
debug("failed to read pvd %d\n", len);
goto end;
}
grub_memset(buf, 0, sizeof(buf));
grub_memcpy(buf, pvd.sys, sizeof(pvd.sys));
ventoy_set_env(args[1], buf);
grub_memset(buf, 0, sizeof(buf));
grub_memcpy(buf, pvd.vol, sizeof(pvd.vol));
ventoy_set_env(args[2], buf);
size = pvd.space;
size *= 2048;
grub_snprintf(buf, sizeof(buf), "%llu", (ulonglong)size);
ventoy_set_env(args[3], buf);
end:
grub_file_close(file);
return 0;
}
static grub_err_t ventoy_cmd_parse_create_date(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len;
grub_file_t file;
char buf[64];
(void)ctxt;
(void)argc;
if (argc != 2)
{
return grub_error(GRUB_ERR_BAD_ARGUMENT, "Usage: %s var \n", cmd_raw_name);
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 0;
}
grub_memset(buf, 0, sizeof(buf));
grub_file_seek(file, 16 * 2048 + 813);
len = (int)grub_file_read(file, buf, 17);
if (len != 17)
{
debug("failed to read create date %d\n", len);
goto end;
}
ventoy_set_env(args[1], buf);
end:
grub_file_close(file);
return 0;
}
static grub_err_t ventoy_cmd_img_hook_root(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_env_hook_root(1);
return 0;
}
static grub_err_t ventoy_cmd_img_unhook_root(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
ventoy_env_hook_root(0);
return 0;
}
#ifdef GRUB_MACHINE_EFI
static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
{
int ret = 1;
grub_uint8_t *var;
grub_size_t size;
grub_efi_guid_t global = GRUB_EFI_GLOBAL_VARIABLE_GUID;
(void)ctxt;
(void)argc;
(void)args;
var = grub_efi_get_variable("SecureBoot", &global, &size);
if (var && *var == 1)
{
return 0;
}
return ret;
}
#else
static grub_err_t ventoy_cmd_check_secureboot_var(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
return 1;
}
#endif
static grub_err_t ventoy_cmd_img_check_range(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int ret = 1;
grub_file_t file;
grub_uint64_t FileSectors = 0;
ventoy_gpt_info *gpt = NULL;
ventoy_part_table *pt = NULL;
grub_uint8_t zeroguid[16] = {0};
(void)ctxt;
(void)argc;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", args[0]);
if (!file)
{
debug("failed to open file %s\n", args[0]);
return 1;
}
if (file->size % 512)
{
debug("unaligned file size: %llu\n", (ulonglong)file->size);
goto out;
}
gpt = grub_zalloc(sizeof(ventoy_gpt_info));
if (!gpt)
{
goto out;
}
FileSectors = file->size / 512;
grub_file_read(file, gpt, sizeof(ventoy_gpt_info));
if (grub_strncmp(gpt->Head.Signature, "EFI PART", 8) == 0)
{
debug("This is EFI partition table\n");
for (i = 0; i < 128; i++)
{
if (grub_memcmp(gpt->PartTbl[i].PartGuid, zeroguid, 16))
{
if (FileSectors < gpt->PartTbl[i].LastLBA)
{
debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
(ulonglong)gpt->PartTbl[i].LastLBA, (ulonglong)FileSectors);
goto out;
}
}
}
}
else
{
debug("This is MBR partition table\n");
for (i = 0; i < 4; i++)
{
pt = gpt->MBR.PartTbl + i;
if (FileSectors < pt->StartSectorId + pt->SectorCount)
{
debug("out of range: part[%d] LastLBA:%llu FileSectors:%llu\n", i,
(ulonglong)(pt->StartSectorId + pt->SectorCount),
(ulonglong)FileSectors);
goto out;
}
}
}
ret = 0;
out:
grub_file_close(file);
grub_check_free(gpt);
grub_errno = GRUB_ERR_NONE;
return ret;
}
static grub_err_t ventoy_cmd_clear_key(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int ret;
(void)ctxt;
(void)argc;
(void)args;
for (i = 0; i < 500; i++)
{
ret = grub_getkey_noblock();
if (ret == GRUB_TERM_NO_KEY)
{
break;
}
}
if (i >= 500)
{
grub_cls();
grub_printf("\n\n Still have key input after clear.\n");
grub_refresh();
grub_sleep(5);
}
return 0;
}
static grub_err_t ventoy_cmd_acpi_param(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int buflen;
int datalen;
int loclen;
int img_chunk_num;
int image_sector_size;
char cmd[64];
ventoy_chain_head *chain;
ventoy_img_chunk *chunk;
ventoy_os_param *osparam;
ventoy_image_location *location;
ventoy_image_disk_region *region;
struct grub_acpi_table_header *acpi;
(void)ctxt;
if (argc != 2)
{
return 1;
}
debug("ventoy_cmd_acpi_param %s %s\n", args[0], args[1]);
chain = (ventoy_chain_head *)(ulong)grub_strtoul(args[0], NULL, 16);
if (!chain)
{
return 1;
}
image_sector_size = (int)grub_strtol(args[1], NULL, 10);
if (grub_memcmp(&g_ventoy_guid, &(chain->os_param.guid), 16))
{
debug("Invalid ventoy guid 0x%x\n", chain->os_param.guid.data1);
return 1;
}
img_chunk_num = chain->img_chunk_num;
loclen = sizeof(ventoy_image_location) + (img_chunk_num - 1) * sizeof(ventoy_image_disk_region);
datalen = sizeof(ventoy_os_param) + loclen;
buflen = sizeof(struct grub_acpi_table_header) + datalen;
acpi = grub_zalloc(buflen);
if (!acpi)
{
return 1;
}
/* Step1: Fill acpi table header */
grub_memcpy(acpi->signature, "VTOY", 4);
acpi->length = buflen;
acpi->revision = 1;
grub_memcpy(acpi->oemid, "VENTOY", 6);
grub_memcpy(acpi->oemtable, "OSPARAMS", 8);
acpi->oemrev = 1;
acpi->creator_id[0] = 1;
acpi->creator_rev = 1;
/* Step2: Fill data */
osparam = (ventoy_os_param *)(acpi + 1);
grub_memcpy(osparam, &chain->os_param, sizeof(ventoy_os_param));
osparam->vtoy_img_location_addr = 0;
osparam->vtoy_img_location_len = loclen;
osparam->chksum = 0;
osparam->chksum = 0x100 - grub_byte_checksum(osparam, sizeof(ventoy_os_param));
location = (ventoy_image_location *)(osparam + 1);
grub_memcpy(&location->guid, &osparam->guid, sizeof(ventoy_guid));
location->image_sector_size = image_sector_size;
location->disk_sector_size = chain->disk_sector_size;
location->region_count = img_chunk_num;
region = location->regions;
chunk = (ventoy_img_chunk *)((char *)chain + chain->img_chunk_offset);
if (512 == image_sector_size)
{
for (i = 0; i < img_chunk_num; i++)
{
region->image_sector_count = chunk->disk_end_sector - chunk->disk_start_sector + 1;
region->image_start_sector = chunk->img_start_sector * 4;
region->disk_start_sector = chunk->disk_start_sector;
region++;
chunk++;
}
}
else
{
for (i = 0; i < img_chunk_num; i++)
{
region->image_sector_count = chunk->img_end_sector - chunk->img_start_sector + 1;
region->image_start_sector = chunk->img_start_sector;
region->disk_start_sector = chunk->disk_start_sector;
region++;
chunk++;
}
}
/* Step3: Fill acpi checksum */
acpi->checksum = 0;
acpi->checksum = 0x100 - grub_byte_checksum(acpi, acpi->length);
/* load acpi table */
grub_snprintf(cmd, sizeof(cmd), "acpi mem:0x%lx:size:%d", (ulong)acpi, acpi->length);
grub_script_execute_sourcecode(cmd);
grub_free(acpi);
VENTOY_CMD_RETURN(0);
}
static grub_err_t ventoy_cmd_push_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
g_ventoy_last_entry_back = g_ventoy_last_entry;
g_ventoy_last_entry = -1;
return 0;
}
static grub_err_t ventoy_cmd_pop_last_entry(grub_extcmd_context_t ctxt, int argc, char **args)
{
(void)ctxt;
(void)argc;
(void)args;
g_ventoy_last_entry = g_ventoy_last_entry_back;
return 0;
}
static int ventoy_lib_module_callback(const char *filename, const struct grub_dirhook_info *info, void *data)
{
const char *pos = filename + 1;
if (info->dir)
{
while (*pos)
{
if (*pos == '.')
{
if ((*(pos - 1) >= '0' && *(pos - 1) <= '9') && (*(pos + 1) >= '0' && *(pos + 1) <= '9'))
{
grub_strncpy((char *)data, filename, 128);
return 1;
}
}
pos++;
}
}
return 0;
}
static grub_err_t ventoy_cmd_lib_module_ver(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char *device_name = NULL;
grub_device_t dev = NULL;
grub_fs_t fs = NULL;
char buf[128] = {0};
(void)ctxt;
if (argc != 3)
{
debug("ventoy_cmd_lib_module_ver, invalid param num %d\n", argc);
return 1;
}
debug("ventoy_cmd_lib_module_ver %s %s %s\n", args[0], args[1], args[2]);
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
debug("grub_file_get_device_name failed, %s\n", args[0]);
goto end;
}
dev = grub_device_open(device_name);
if (!dev)
{
debug("grub_device_open failed, %s\n", device_name);
goto end;
}
fs = grub_fs_probe(dev);
if (!fs)
{
debug("grub_fs_probe failed, %s\n", device_name);
goto end;
}
fs->fs_dir(dev, args[1], ventoy_lib_module_callback, buf);
if (buf[0])
{
ventoy_set_env(args[2], buf);
}
rc = 0;
end:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
return rc;
}
int ventoy_load_part_table(const char *diskname)
{
char name[64];
int ret;
grub_disk_t disk;
grub_device_t dev;
g_ventoy_part_info = grub_zalloc(sizeof(ventoy_gpt_info));
if (!g_ventoy_part_info)
{
return 1;
}
disk = grub_disk_open(diskname);
if (!disk)
{
debug("Failed to open disk %s\n", diskname);
return 1;
}
g_ventoy_disk_size = disk->total_sectors * (1U << disk->log_sector_size);
grub_disk_read(disk, 0, 0, sizeof(ventoy_gpt_info), g_ventoy_part_info);
grub_disk_close(disk);
grub_snprintf(name, sizeof(name), "%s,1", diskname);
dev = grub_device_open(name);
if (dev)
{
/* Check for official Ventoy device */
ret = ventoy_check_official_device(dev);
grub_device_close(dev);
if (ret)
{
return 1;
}
}
g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
return 0;
}
static grub_err_t ventoy_cmd_load_part_table(grub_extcmd_context_t ctxt, int argc, char **args)
{
int ret;
(void)argc;
(void)ctxt;
ret = ventoy_load_part_table(args[0]);
if (ret)
{
grub_exit();
}
g_ventoy_disk_part_size[0] = ventoy_get_vtoy_partsize(0);
g_ventoy_disk_part_size[1] = ventoy_get_vtoy_partsize(1);
return 0;
}
static grub_err_t ventoy_cmd_check_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args)
{
int ret = 1;
const char *vcfg = NULL;
(void)argc;
(void)ctxt;
vcfg = ventoy_plugin_get_custom_boot(args[0]);
if (vcfg)
{
debug("custom boot <%s>:<%s>\n", args[0], vcfg);
grub_env_set(args[1], vcfg);
ret = 0;
}
else
{
debug("custom boot <%s>:<NOT FOUND>\n", args[0]);
}
grub_errno = 0;
return ret;
}
static grub_err_t ventoy_cmd_part_exist(grub_extcmd_context_t ctxt, int argc, char **args)
{
int id;
grub_uint8_t zeroguid[16] = {0};
(void)argc;
(void)ctxt;
id = (int)grub_strtoul(args[0], NULL, 10);
grub_errno = 0;
if (grub_memcmp(g_ventoy_part_info->Head.Signature, "EFI PART", 8) == 0)
{
if (id >= 1 && id <= 128)
{
if (grub_memcmp(g_ventoy_part_info->PartTbl[id - 1].PartGuid, zeroguid, 16))
{
return 0;
}
}
}
else
{
if (id >= 1 && id <= 4)
{
if (g_ventoy_part_info->MBR.PartTbl[id - 1].FsFlag)
{
return 0;
}
}
}
return 1;
}
static grub_err_t ventoy_cmd_get_fs_label(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char *device_name = NULL;
grub_device_t dev = NULL;
grub_fs_t fs = NULL;
char *label = NULL;
(void)ctxt;
debug("get fs label for %s\n", args[0]);
if (argc != 2)
{
debug("ventoy_cmd_get_fs_label, invalid param num %d\n", argc);
return 1;
}
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
debug("grub_file_get_device_name failed, %s\n", args[0]);
goto end;
}
dev = grub_device_open(device_name);
if (!dev)
{
debug("grub_device_open failed, %s\n", device_name);
goto end;
}
fs = grub_fs_probe(dev);
if (NULL == fs || NULL == fs->fs_label)
{
debug("grub_fs_probe failed, %s %p %p\n", device_name, fs, fs->fs_label);
goto end;
}
fs->fs_label(dev, &label);
if (label)
{
debug("label=<%s>\n", label);
ventoy_set_env(args[1], label);
grub_free(label);
}
rc = 0;
end:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
return rc;
}
static int ventoy_fs_enum_1st_file(const char *filename, const struct grub_dirhook_info *info, void *data)
{
if (!info->dir)
{
grub_snprintf((char *)data, 256, "%s", filename);
return 1;
}
return 0;
}
static grub_err_t ventoy_cmd_fs_enum_1st_file(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc = 1;
char *device_name = NULL;
grub_device_t dev = NULL;
grub_fs_t fs = NULL;
char name[256] ={0};
(void)ctxt;
if (argc != 3)
{
debug("ventoy_cmd_fs_enum_1st_file, invalid param num %d\n", argc);
return 1;
}
device_name = grub_file_get_device_name(args[0]);
if (!device_name)
{
debug("grub_file_get_device_name failed, %s\n", args[0]);
goto end;
}
dev = grub_device_open(device_name);
if (!dev)
{
debug("grub_device_open failed, %s\n", device_name);
goto end;
}
fs = grub_fs_probe(dev);
if (!fs)
{
debug("grub_fs_probe failed, %s\n", device_name);
goto end;
}
fs->fs_dir(dev, args[1], ventoy_fs_enum_1st_file, name);
if (name[0])
{
ventoy_set_env(args[2], name);
}
rc = 0;
end:
check_free(device_name, grub_free);
check_free(dev, grub_device_close);
return rc;
}
static grub_err_t ventoy_cmd_basename(grub_extcmd_context_t ctxt, int argc, char **args)
{
char c;
char *pos = NULL;
char *end = NULL;
(void)ctxt;
if (argc != 2)
{
debug("ventoy_cmd_basename, invalid param num %d\n", argc);
return 1;
}
for (pos = args[0]; *pos; pos++)
{
if (*pos == '.')
{
end = pos;
}
}
if (end)
{
c = *end;
*end = 0;
}
grub_env_set(args[1], args[0]);
if (end)
{
*end = c;
}
return 0;
}
static grub_err_t ventoy_cmd_basefile(grub_extcmd_context_t ctxt, int argc, char **args)
{
int i;
int len;
const char *buf;
(void)ctxt;
if (argc != 2)
{
debug("ventoy_cmd_basefile, invalid param num %d\n", argc);
return 1;
}
buf = args[0];
len = (int)grub_strlen(buf);
for (i = len; i > 0; i--)
{
if (buf[i - 1] == '/')
{
grub_env_set(args[1], buf + i);
return 0;
}
}
grub_env_set(args[1], buf);
return 0;
}
static grub_err_t ventoy_cmd_enum_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_video_mode_info info;
char buf[32];
(void)ctxt;
(void)argc;
(void)args;
if (!g_video_mode_list)
{
ventoy_enum_video_mode();
}
if (grub_video_get_info(&info) == GRUB_ERR_NONE)
{
grub_snprintf(buf, sizeof(buf), "Resolution (%ux%u)", info.width, info.height);
}
else
{
grub_snprintf(buf, sizeof(buf), "Resolution (0x0)");
}
grub_env_set("VTOY_CUR_VIDEO_MODE", buf);
grub_snprintf(buf, sizeof(buf), "%d", g_video_mode_num);
grub_env_set("VTOY_VIDEO_MODE_NUM", buf);
VENTOY_CMD_RETURN(0);
}
static grub_err_t vt_cmd_update_cur_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_video_mode_info info;
char buf[32];
(void)ctxt;
(void)argc;
(void)args;
if (grub_video_get_info(&info) == GRUB_ERR_NONE)
{
grub_snprintf(buf, sizeof(buf), "%ux%ux%u", info.width, info.height, info.bpp);
}
else
{
grub_snprintf(buf, sizeof(buf), "0x0x0");
}
grub_env_set(args[0], buf);
VENTOY_CMD_RETURN(0);
}
static grub_err_t ventoy_cmd_get_video_mode(grub_extcmd_context_t ctxt, int argc, char **args)
{
int id;
char buf[32];
(void)ctxt;
(void)argc;
if (!g_video_mode_list)
{
return 0;
}
id = (int)grub_strtoul(args[0], NULL, 10);
if (id < g_video_mode_num)
{
grub_snprintf(buf, sizeof(buf), "%ux%ux%u",
g_video_mode_list[id].width, g_video_mode_list[id].height, g_video_mode_list[id].bpp);
}
grub_env_set(args[1], buf);
VENTOY_CMD_RETURN(0);
}
int ventoy_env_init(void)
{
char buf[64];
grub_env_set("vtdebug_flag", "");
g_part_list_buf = grub_malloc(VTOY_PART_BUF_LEN);
g_tree_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
g_list_script_buf = grub_malloc(VTOY_MAX_SCRIPT_BUF);
g_conf_replace_new_buf = grub_malloc(vtoy_max_replace_file_size);
ventoy_filt_register(0, ventoy_wrapper_open);
g_grub_param = (ventoy_grub_param *)grub_zalloc(sizeof(ventoy_grub_param));
if (g_grub_param)
{
g_grub_param->grub_env_get = grub_env_get;
g_grub_param->grub_env_set = (grub_env_set_pf)grub_env_set;
g_grub_param->grub_env_printf = (grub_env_printf_pf)grub_printf;
grub_snprintf(buf, sizeof(buf), "%p", g_grub_param);
grub_env_set("env_param", buf);
grub_env_set("ventoy_env_param", buf);
grub_env_export("env_param");
grub_env_export("ventoy_env_param");
}
return 0;
}
static cmd_para ventoy_cmds[] =
{
{ "vt_incr", ventoy_cmd_incr, 0, NULL, "{Var} {INT}", "Increase integer variable", NULL },
{ "vt_mod", ventoy_cmd_mod, 0, NULL, "{Int} {Int} {Var}", "mod integer variable", NULL },
{ "vt_strstr", ventoy_cmd_strstr, 0, NULL, "", "", NULL },
{ "vt_str_begin", ventoy_cmd_strbegin, 0, NULL, "", "", NULL },
{ "vt_debug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
{ "vtdebug", ventoy_cmd_debug, 0, NULL, "{on|off}", "turn debug on/off", NULL },
{ "vtbreak", ventoy_cmd_break, 0, NULL, "{level}", "set debug break", NULL },
{ "vt_cmp", ventoy_cmd_cmp, 0, NULL, "{Int1} { eq|ne|gt|lt|ge|le } {Int2}", "Comare two integers", NULL },
{ "vt_device", ventoy_cmd_device, 0, NULL, "path var", "", NULL },
{ "vt_check_compatible", ventoy_cmd_check_compatible, 0, NULL, "", "", NULL },
{ "vt_list_img", ventoy_cmd_list_img, 0, NULL, "{device} {cntvar}", "find all iso file in device", NULL },
{ "vt_clear_img", ventoy_cmd_clear_img, 0, NULL, "", "clear image list", NULL },
{ "vt_img_name", ventoy_cmd_img_name, 0, NULL, "{imageID} {var}", "get image name", NULL },
{ "vt_chosen_img_path", ventoy_cmd_chosen_img_path, 0, NULL, "{var}", "get chosen img path", NULL },
{ "vt_ext_select_img_path", ventoy_cmd_ext_select_img_path, 0, NULL, "{var}", "select chosen img path", NULL },
{ "vt_img_sector", ventoy_cmd_img_sector, 0, NULL, "{imageName}", "", NULL },
{ "vt_dump_img_sector", ventoy_cmd_dump_img_sector, 0, NULL, "", "", NULL },
{ "vt_load_wimboot", ventoy_cmd_load_wimboot, 0, NULL, "", "", NULL },
{ "vt_load_vhdboot", ventoy_cmd_load_vhdboot, 0, NULL, "", "", NULL },
{ "vt_patch_vhdboot", ventoy_cmd_patch_vhdboot, 0, NULL, "", "", NULL },
{ "vt_raw_chain_data", ventoy_cmd_raw_chain_data, 0, NULL, "", "", NULL },
{ "vt_get_vtoy_type", ventoy_cmd_get_vtoy_type, 0, NULL, "", "", NULL },
{ "vt_check_custom_boot", ventoy_cmd_check_custom_boot, 0, NULL, "", "", NULL },
{ "vt_dump_custom_boot", ventoy_cmd_dump_custom_boot, 0, NULL, "", "", NULL },
{ "vt_skip_svd", ventoy_cmd_skip_svd, 0, NULL, "", "", NULL },
{ "vt_cpio_busybox64", ventoy_cmd_cpio_busybox_64, 0, NULL, "", "", NULL },
{ "vt_load_cpio", ventoy_cmd_load_cpio, 0, NULL, "", "", NULL },
{ "vt_trailer_cpio", ventoy_cmd_trailer_cpio, 0, NULL, "", "", NULL },
{ "vt_push_last_entry", ventoy_cmd_push_last_entry, 0, NULL, "", "", NULL },
{ "vt_pop_last_entry", ventoy_cmd_pop_last_entry, 0, NULL, "", "", NULL },
{ "vt_get_lib_module_ver", ventoy_cmd_lib_module_ver, 0, NULL, "", "", NULL },
{ "vt_load_part_table", ventoy_cmd_load_part_table, 0, NULL, "", "", NULL },
{ "vt_check_part_exist", ventoy_cmd_part_exist, 0, NULL, "", "", NULL },
{ "vt_get_fs_label", ventoy_cmd_get_fs_label, 0, NULL, "", "", NULL },
{ "vt_fs_enum_1st_file", ventoy_cmd_fs_enum_1st_file, 0, NULL, "", "", NULL },
{ "vt_file_basename", ventoy_cmd_basename, 0, NULL, "", "", NULL },
{ "vt_file_basefile", ventoy_cmd_basefile, 0, NULL, "", "", NULL },
{ "vt_enum_video_mode", ventoy_cmd_enum_video_mode, 0, NULL, "", "", NULL },
{ "vt_get_video_mode", ventoy_cmd_get_video_mode, 0, NULL, "", "", NULL },
{ "vt_update_cur_video_mode", vt_cmd_update_cur_video_mode, 0, NULL, "", "", NULL },
{ "vt_find_first_bootable_hd", ventoy_cmd_find_bootable_hdd, 0, NULL, "", "", NULL },
{ "vt_dump_menu", ventoy_cmd_dump_menu, 0, NULL, "", "", NULL },
{ "vt_dynamic_menu", ventoy_cmd_dynamic_menu, 0, NULL, "", "", NULL },
{ "vt_check_mode", ventoy_cmd_check_mode, 0, NULL, "", "", NULL },
{ "vt_dump_img_list", ventoy_cmd_dump_img_list, 0, NULL, "", "", NULL },
{ "vt_dump_injection", ventoy_cmd_dump_injection, 0, NULL, "", "", NULL },
{ "vt_dump_auto_install", ventoy_cmd_dump_auto_install, 0, NULL, "", "", NULL },
{ "vt_dump_persistence", ventoy_cmd_dump_persistence, 0, NULL, "", "", NULL },
{ "vt_select_auto_install", ventoy_cmd_sel_auto_install, 0, NULL, "", "", NULL },
{ "vt_select_persistence", ventoy_cmd_sel_persistence, 0, NULL, "", "", NULL },
{ "vt_select_conf_replace", ventoy_select_conf_replace, 0, NULL, "", "", NULL },
{ "vt_iso9660_nojoliet", ventoy_cmd_iso9660_nojoliet, 0, NULL, "", "", NULL },
{ "vt_is_udf", ventoy_cmd_is_udf, 0, NULL, "", "", NULL },
{ "vt_file_size", ventoy_cmd_file_size, 0, NULL, "", "", NULL },
{ "vt_load_file_to_mem", ventoy_cmd_load_file_to_mem, 0, NULL, "", "", NULL },
{ "vt_load_img_memdisk", ventoy_cmd_load_img_memdisk, 0, NULL, "", "", NULL },
{ "vt_concat_efi_iso", ventoy_cmd_concat_efi_iso, 0, NULL, "", "", NULL },
{ "vt_linux_parse_initrd_isolinux", ventoy_cmd_isolinux_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
{ "vt_linux_parse_initrd_grub", ventoy_cmd_grub_initrd_collect, 0, NULL, "{cfgfile}", "", NULL },
{ "vt_linux_specify_initrd_file", ventoy_cmd_specify_initrd_file, 0, NULL, "", "", NULL },
{ "vt_linux_clear_initrd", ventoy_cmd_clear_initrd_list, 0, NULL, "", "", NULL },
{ "vt_linux_dump_initrd", ventoy_cmd_dump_initrd_list, 0, NULL, "", "", NULL },
{ "vt_linux_initrd_count", ventoy_cmd_initrd_count, 0, NULL, "", "", NULL },
{ "vt_linux_valid_initrd_count", ventoy_cmd_valid_initrd_count, 0, NULL, "", "", NULL },
{ "vt_linux_locate_initrd", ventoy_cmd_linux_locate_initrd, 0, NULL, "", "", NULL },
{ "vt_linux_chain_data", ventoy_cmd_linux_chain_data, 0, NULL, "", "", NULL },
{ "vt_linux_get_main_initrd_index", ventoy_cmd_linux_get_main_initrd_index, 0, NULL, "", "", NULL },
{ "vt_windows_reset", ventoy_cmd_wimdows_reset, 0, NULL, "", "", NULL },
{ "vt_windows_chain_data", ventoy_cmd_windows_chain_data, 0, NULL, "", "", NULL },
{ "vt_windows_collect_wim_patch", ventoy_cmd_collect_wim_patch, 0, NULL, "", "", NULL },
{ "vt_windows_locate_wim_patch", ventoy_cmd_locate_wim_patch, 0, NULL, "", "", NULL },
{ "vt_windows_count_wim_patch", ventoy_cmd_wim_patch_count, 0, NULL, "", "", NULL },
{ "vt_dump_wim_patch", ventoy_cmd_dump_wim_patch, 0, NULL, "", "", NULL },
{ "vt_wim_check_bootable", ventoy_cmd_wim_check_bootable, 0, NULL, "", "", NULL },
{ "vt_wim_chain_data", ventoy_cmd_wim_chain_data, 0, NULL, "", "", NULL },
{ "vt_add_replace_file", ventoy_cmd_add_replace_file, 0, NULL, "", "", NULL },
{ "vt_test_block_list", ventoy_cmd_test_block_list, 0, NULL, "", "", NULL },
{ "vt_file_exist_nocase", ventoy_cmd_file_exist_nocase, 0, NULL, "", "", NULL },
{ "vt_load_plugin", ventoy_cmd_load_plugin, 0, NULL, "", "", NULL },
{ "vt_check_plugin_json", ventoy_cmd_plugin_check_json, 0, NULL, "", "", NULL },
{ "vt_check_password", ventoy_cmd_check_password, 0, NULL, "", "", NULL },
{ "vt_1st_line", ventoy_cmd_read_1st_line, 0, NULL, "", "", NULL },
{ "vt_file_strstr", ventoy_cmd_file_strstr, 0, NULL, "", "", NULL },
{ "vt_img_part_info", ventoy_cmd_img_part_info, 0, NULL, "", "", NULL },
{ "vt_parse_iso_volume", ventoy_cmd_parse_volume, 0, NULL, "", "", NULL },
{ "vt_parse_iso_create_date", ventoy_cmd_parse_create_date, 0, NULL, "", "", NULL },
{ "vt_parse_freenas_ver", ventoy_cmd_parse_freenas_ver, 0, NULL, "", "", NULL },
{ "vt_unix_parse_freebsd_ver", ventoy_cmd_unix_freebsd_ver, 0, NULL, "", "", NULL },
{ "vt_unix_parse_freebsd_ver_elf", ventoy_cmd_unix_freebsd_ver_elf, 0, NULL, "", "", NULL },
{ "vt_unix_reset", ventoy_cmd_unix_reset, 0, NULL, "", "", NULL },
{ "vt_unix_replace_conf", ventoy_cmd_unix_replace_conf, 0, NULL, "", "", NULL },
{ "vt_unix_replace_ko", ventoy_cmd_unix_replace_ko, 0, NULL, "", "", NULL },
{ "vt_unix_fill_image_desc", ventoy_cmd_unix_fill_image_desc, 0, NULL, "", "", NULL },
{ "vt_unix_gzip_new_ko", ventoy_cmd_unix_gzip_newko, 0, NULL, "", "", NULL },
{ "vt_unix_chain_data", ventoy_cmd_unix_chain_data, 0, NULL, "", "", NULL },
{ "vt_img_hook_root", ventoy_cmd_img_hook_root, 0, NULL, "", "", NULL },
{ "vt_img_unhook_root", ventoy_cmd_img_unhook_root, 0, NULL, "", "", NULL },
{ "vt_acpi_param", ventoy_cmd_acpi_param, 0, NULL, "", "", NULL },
{ "vt_check_secureboot_var", ventoy_cmd_check_secureboot_var, 0, NULL, "", "", NULL },
{ "vt_clear_key", ventoy_cmd_clear_key, 0, NULL, "", "", NULL },
{ "vt_img_check_range", ventoy_cmd_img_check_range, 0, NULL, "", "", NULL },
};
int ventoy_register_all_cmd(void)
{
grub_uint32_t i;
cmd_para *cur = NULL;
for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
{
cur = ventoy_cmds + i;
cur->cmd = grub_register_extcmd(cur->name, cur->func, cur->flags,
cur->summary, cur->description, cur->parser);
}
return 0;
}
int ventoy_unregister_all_cmd(void)
{
grub_uint32_t i;
for (i = 0; i < ARRAY_SIZE(ventoy_cmds); i++)
{
grub_unregister_extcmd(ventoy_cmds[i].cmd);
}
return 0;
}
......@@ -140,6 +140,7 @@ typedef struct cpio_newc_header
typedef int (*grub_char_check_func)(int c);
#define ventoy_is_decimal(str) ventoy_string_check(str, grub_isdigit)
#define OFFSET_OF(TYPE, MEMBER) ((grub_size_t) &((TYPE *)0)->MEMBER)
#pragma pack(1)
typedef struct ventoy_patch_vhd
......@@ -932,6 +933,8 @@ extern grub_uint8_t *g_conf_replace_new_buf;
extern int g_conf_replace_new_len;
extern int g_conf_replace_new_len_align;
extern grub_uint64_t g_ventoy_disk_size;
extern grub_uint64_t g_ventoy_disk_part_size[2];
extern grub_uint32_t g_ventoy_plat_data;
#define ventoy_unix_fill_virt(new_data, new_len) \
{ \
......@@ -949,12 +952,16 @@ extern grub_uint64_t g_ventoy_disk_size;
chain->virt_img_size_in_bytes += data_secs * 2048; \
}
#define ventoy_syscall0(name) grub_##name()
#define ventoy_syscall1(name, a) grub_##name(a)
char * ventoy_get_line(char *start);
int ventoy_cmp_img(img_info *img1, img_info *img2);
void ventoy_swap_img(img_info *img1, img_info *img2);
char * ventoy_plugin_get_cur_install_template(const char *isopath);
install_template * ventoy_plugin_find_install_template(const char *isopath);
persistence_config * ventoy_plugin_find_persistent(const char *isopath);
grub_uint64_t ventoy_get_vtoy_partsize(int part);
void ventoy_plugin_dump_injection(void);
void ventoy_plugin_dump_auto_install(void);
int ventoy_fill_windows_rtdata(void *buf, char *isopath);
......@@ -994,11 +1001,16 @@ grub_err_t ventoy_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char *
grub_err_t ventoy_cmd_raw_chain_data(grub_extcmd_context_t ctxt, int argc, char **args);
grub_err_t ventoy_cmd_get_vtoy_type(grub_extcmd_context_t ctxt, int argc, char **args);
int ventoy_check_password(const vtoy_password *pwd, int retry);
int ventoy_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len);
grub_uint64_t ventoy_get_part1_size(ventoy_gpt_info *gpt);
int ventoy_plugin_add_custom_boot(const char *vcfgpath);
const char * ventoy_plugin_get_custom_boot(const char *isopath);
grub_err_t ventoy_cmd_dump_custom_boot(grub_extcmd_context_t ctxt, int argc, char **args);
int ventoy_gzip_compress(void *mem_in, int mem_in_len, void *mem_out, int mem_out_len);
int ventoy_load_part_table(const char *diskname);
int ventoy_env_init(void);
int ventoy_register_all_cmd(void);
int ventoy_unregister_all_cmd(void);
#define VTOY_CMD_CHECK(a) if (33554432 != g_ventoy_disk_part_size[a]) ventoy_syscall0(exit)
#endif /* __VENTOY_DEF_H__ */
......@@ -720,7 +720,7 @@ grub_err_t ventoy_cmd_unix_fill_image_desc(grub_extcmd_context_t ctxt, int argc,
desc = (ventoy_image_desc *)(byte + i);
desc->disk_size = g_ventoy_disk_size;
desc->part1_size = ventoy_get_part1_size(g_ventoy_part_info);
desc->part1_size = g_ventoy_disk_part_size[0];
grub_memcpy(desc->disk_uuid, g_ventoy_part_info->MBR.BootCode + 0x180, 16);
grub_memcpy(desc->disk_signature, g_ventoy_part_info->MBR.BootCode + 0x1B8, 4);
......
......@@ -44,14 +44,12 @@
GRUB_MOD_LICENSE ("GPLv3+");
static int g_vhdboot_bcd_offset = 0;
static int g_vhdboot_bcd_len = 0;
static int g_vhdboot_isolen = 0;
static char *g_vhdboot_totbuf = NULL;
static char *g_vhdboot_isobuf = NULL;
static grub_uint64_t g_img_trim_head_secnum = 0;
static int ventoy_vhd_find_bcd(int *bcdoffset, int *bcdlen)
static int ventoy_vhd_find_bcd(int *bcdoffset, int *bcdlen, const char *path)
{
grub_uint32_t offset;
grub_file_t file;
......@@ -61,10 +59,9 @@ static int ventoy_vhd_find_bcd(int *bcdoffset, int *bcdlen)
grub_script_execute_sourcecode(cmdbuf);
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", "(vhdiso)/boot/bcd");
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "(vhdiso)%s", path);
if (!file)
{
grub_printf("Failed to open bcd file in the image file\n");
return 1;
}
......@@ -83,13 +80,15 @@ static int ventoy_vhd_find_bcd(int *bcdoffset, int *bcdlen)
return 0;
}
static int ventoy_vhd_patch_path(char *vhdpath, ventoy_patch_vhd *patch1, ventoy_patch_vhd *patch2)
static int ventoy_vhd_patch_path(char *vhdpath, ventoy_patch_vhd *patch1, ventoy_patch_vhd *patch2,
int bcdoffset, int bcdlen)
{
int i;
int cnt = 0;
char *pos;
grub_size_t pathlen;
const char *plat;
char *newpath = NULL;
grub_uint16_t *unicode_path;
const grub_uint8_t winloadexe[] =
{
......@@ -97,6 +96,11 @@ static int ventoy_vhd_patch_path(char *vhdpath, ventoy_patch_vhd *patch1, ventoy
0x65, 0x00, 0x78, 0x00, 0x65, 0x00
};
while ((*vhdpath) != '/')
{
vhdpath++;
}
pathlen = sizeof(grub_uint16_t) * (grub_strlen(vhdpath) + 1);
debug("unicode path for <%s> len:%d\n", vhdpath, (int)pathlen);
......@@ -110,10 +114,10 @@ static int ventoy_vhd_patch_path(char *vhdpath, ventoy_patch_vhd *patch1, ventoy
if (plat && (plat[0] == 'e')) /* UEFI */
{
pos = g_vhdboot_isobuf + g_vhdboot_bcd_offset;
pos = g_vhdboot_isobuf + bcdoffset;
/* winload.exe ==> winload.efi */
for (i = 0; i + (int)sizeof(winloadexe) < g_vhdboot_bcd_len; i++)
for (i = 0; i + (int)sizeof(winloadexe) < bcdlen; i++)
{
if (*((grub_uint32_t *)(pos + i)) == 0x00690077 &&
grub_memcmp(pos + i, winloadexe, sizeof(winloadexe)) == 0)
......@@ -127,7 +131,8 @@ static int ventoy_vhd_patch_path(char *vhdpath, ventoy_patch_vhd *patch1, ventoy
debug("winload patch %d times\n", cnt);
}
for (pos = vhdpath; *pos; pos++)
newpath = grub_strdup(vhdpath);
for (pos = newpath; *pos; pos++)
{
if (*pos == '/')
{
......@@ -135,40 +140,127 @@ static int ventoy_vhd_patch_path(char *vhdpath, ventoy_patch_vhd *patch1, ventoy
}
}
grub_utf8_to_utf16(unicode_path, pathlen, (grub_uint8_t *)vhdpath, -1, NULL);
grub_utf8_to_utf16(unicode_path, pathlen, (grub_uint8_t *)newpath, -1, NULL);
grub_memcpy(patch1->vhd_file_path, unicode_path, pathlen);
grub_memcpy(patch2->vhd_file_path, unicode_path, pathlen);
grub_free(newpath);
return 0;
}
static int ventoy_vhd_patch_disk(ventoy_patch_vhd *patch1, ventoy_patch_vhd *patch2)
static int ventoy_vhd_read_parttbl(const char *filename, ventoy_gpt_info *gpt, int *index)
{
int ret = 1;
grub_file_t file = NULL;
grub_disk_t disk = NULL;
file = grub_file_open(filename, VENTOY_FILE_TYPE);
if (!file)
{
goto end;
}
disk = grub_disk_open(file->device->disk->name);
if (!disk)
{
goto end;
}
*index = file->device->disk->partition->index;
grub_disk_read(disk, 0, 0, sizeof(ventoy_gpt_info), gpt);
ret = 0;
end:
check_free(file, grub_file_close);
check_free(disk, grub_disk_close);
return ret;
}
static int ventoy_vhd_patch_disk(const char *vhdpath, ventoy_patch_vhd *patch1, ventoy_patch_vhd *patch2)
{
int partIndex = 0;
grub_uint64_t offset = 0;
char efipart[16] = {0};
ventoy_gpt_info *gpt = NULL;
grub_memcpy(efipart, g_ventoy_part_info->Head.Signature, sizeof(g_ventoy_part_info->Head.Signature));
if (vhdpath[0] == '/')
{
gpt = g_ventoy_part_info;
partIndex = 0;
debug("This is Ventoy ISO partIndex %d %s\n", partIndex, vhdpath);
}
else
{
gpt = grub_zalloc(sizeof(ventoy_gpt_info));
ventoy_vhd_read_parttbl(vhdpath, gpt, &partIndex);
debug("This is HDD partIndex %d %s\n", partIndex, vhdpath);
}
debug("part1 type: 0x%x <%s>\n", g_ventoy_part_info->MBR.PartTbl[0].FsFlag, efipart);
grub_memcpy(efipart, gpt->Head.Signature, sizeof(gpt->Head.Signature));
grub_memset(patch1, 0, OFFSET_OF(ventoy_patch_vhd, vhd_file_path));
grub_memset(patch2, 0, OFFSET_OF(ventoy_patch_vhd, vhd_file_path));
if (grub_strncmp(efipart, "EFI PART", 8) == 0)
{
ventoy_debug_dump_guid("GPT disk GUID: ", g_ventoy_part_info->Head.DiskGuid);
ventoy_debug_dump_guid("GPT part GUID: ", g_ventoy_part_info->PartTbl[0].PartGuid);
ventoy_debug_dump_guid("GPT disk GUID: ", gpt->Head.DiskGuid);
ventoy_debug_dump_guid("GPT partIndex GUID: ", gpt->PartTbl[partIndex].PartGuid);
grub_memcpy(patch1->disk_signature_or_guid, g_ventoy_part_info->Head.DiskGuid, 16);
grub_memcpy(patch1->part_offset_or_guid, g_ventoy_part_info->PartTbl[0].PartGuid, 16);
grub_memcpy(patch2->disk_signature_or_guid, g_ventoy_part_info->Head.DiskGuid, 16);
grub_memcpy(patch2->part_offset_or_guid, g_ventoy_part_info->PartTbl[0].PartGuid, 16);
grub_memcpy(patch1->disk_signature_or_guid, gpt->Head.DiskGuid, 16);
grub_memcpy(patch1->part_offset_or_guid, gpt->PartTbl[partIndex].PartGuid, 16);
grub_memcpy(patch2->disk_signature_or_guid, gpt->Head.DiskGuid, 16);
grub_memcpy(patch2->part_offset_or_guid, gpt->PartTbl[partIndex].PartGuid, 16);
patch1->part_type = patch2->part_type = 0;
}
else
{
debug("MBR disk signature: %02x%02x%02x%02x\n",
g_ventoy_part_info->MBR.BootCode[0x1b8 + 0], g_ventoy_part_info->MBR.BootCode[0x1b8 + 1],
g_ventoy_part_info->MBR.BootCode[0x1b8 + 2], g_ventoy_part_info->MBR.BootCode[0x1b8 + 3]);
grub_memcpy(patch1->disk_signature_or_guid, g_ventoy_part_info->MBR.BootCode + 0x1b8, 4);
grub_memcpy(patch2->disk_signature_or_guid, g_ventoy_part_info->MBR.BootCode + 0x1b8, 4);
offset = gpt->MBR.PartTbl[partIndex].StartSectorId;
offset *= 512;
debug("MBR disk signature: %02x%02x%02x%02x Part(%d) offset:%llu\n",
gpt->MBR.BootCode[0x1b8 + 0], gpt->MBR.BootCode[0x1b8 + 1],
gpt->MBR.BootCode[0x1b8 + 2], gpt->MBR.BootCode[0x1b8 + 3],
partIndex + 1, offset);
grub_memcpy(patch1->part_offset_or_guid, &offset, 8);
grub_memcpy(patch2->part_offset_or_guid, &offset, 8);
grub_memcpy(patch1->disk_signature_or_guid, gpt->MBR.BootCode + 0x1b8, 4);
grub_memcpy(patch2->disk_signature_or_guid, gpt->MBR.BootCode + 0x1b8, 4);
patch1->part_type = patch2->part_type = 1;
}
if (gpt != g_ventoy_part_info)
{
grub_free(gpt);
}
return 0;
}
static int ventoy_find_vhdpatch_offset(int bcdoffset, int bcdlen, int *offset)
{
int i;
int cnt = 0;
grub_uint8_t *buf = (grub_uint8_t *)(g_vhdboot_isobuf + bcdoffset);
grub_uint8_t magic[16] = {
0x5C, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00, 0x58, 0x00
};
for (i = 0; i < bcdlen - 16 && cnt < 2; i++)
{
if (*(grub_uint32_t *)(buf + i) == 0x0058005C)
{
if (grub_memcmp(magic, buf + i, 16) == 0)
{
*offset++ = i - (int)OFFSET_OF(ventoy_patch_vhd, vhd_file_path);
cnt++;
}
}
}
return 0;
......@@ -177,6 +269,8 @@ static int ventoy_vhd_patch_disk(ventoy_patch_vhd *patch1, ventoy_patch_vhd *pat
grub_err_t ventoy_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args)
{
int rc;
int bcdoffset, bcdlen;
int patchoffset[2];
ventoy_patch_vhd *patch1;
ventoy_patch_vhd *patch2;
char envbuf[64];
......@@ -194,18 +288,39 @@ grub_err_t ventoy_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char *
return 0;
}
rc = ventoy_vhd_find_bcd(&g_vhdboot_bcd_offset, &g_vhdboot_bcd_len);
rc = ventoy_vhd_find_bcd(&bcdoffset, &bcdlen, "/boot/bcd");
if (rc)
{
debug("failed to get bcd location %d\n", rc);
return 0;
}
else
{
ventoy_find_vhdpatch_offset(bcdoffset, bcdlen, patchoffset);
patch1 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + bcdoffset + patchoffset[0]);
patch2 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + bcdoffset + patchoffset[1]);
debug("Find /boot/bcd (%d %d) now patch it (offset: 0x%x 0x%x) ...\n",
bcdoffset, bcdlen, patchoffset[0], patchoffset[1]);
ventoy_vhd_patch_disk(args[0], patch1, patch2);
ventoy_vhd_patch_path(args[0], patch1, patch2, bcdoffset, bcdlen);
}
patch1 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + g_vhdboot_bcd_offset + 0x495a);
patch2 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + g_vhdboot_bcd_offset + 0x50aa);
ventoy_vhd_patch_disk(patch1, patch2);
ventoy_vhd_patch_path(args[0], patch1, patch2);
rc = ventoy_vhd_find_bcd(&bcdoffset, &bcdlen, "/boot/BCD");
if (rc)
{
debug("No file /boot/BCD \n");
}
else
{
ventoy_find_vhdpatch_offset(bcdoffset, bcdlen, patchoffset);
patch1 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + bcdoffset + patchoffset[0]);
patch2 = (ventoy_patch_vhd *)(g_vhdboot_isobuf + bcdoffset + patchoffset[1]);
debug("Find /boot/BCD (%d %d) now patch it (offset: 0x%x 0x%x) ...\n",
bcdoffset, bcdlen, patchoffset[0], patchoffset[1]);
ventoy_vhd_patch_disk(args[0], patch1, patch2);
ventoy_vhd_patch_path(args[0], patch1, patch2, bcdoffset, bcdlen);
}
/* set buffer and size */
#ifdef GRUB_MACHINE_EFI
......@@ -220,7 +335,7 @@ grub_err_t ventoy_cmd_patch_vhdboot(grub_extcmd_context_t ctxt, int argc, char *
grub_env_set("vtoy_vhd_buf_size", envbuf);
#endif
return 0;
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_load_vhdboot(grub_extcmd_context_t ctxt, int argc, char **args)
......
No preview for this file type
......@@ -131,7 +131,7 @@ function get_os_type {
function vt_check_compatible_pe {
#Check for PE without external tools
if [ -f "$1/HBCD_PE.ini" ]; then
set ventoy_compatible=YES
set ventoy_compatible=YES
fi
}
......@@ -1230,6 +1230,30 @@ function efi_unsupport_menuentry {
common_unsupport_menuentry
}
function vhdboot_common_func {
vt_patch_vhdboot "$1"
ventoy_debug_pause
if [ -n "$vtoy_vhd_buf_addr" ]; then
if [ "$grub_platform" = "pc" ]; then
ventoy_cli_console
linux16 $vtoy_path/memdisk iso raw
initrd16 mem:${vtoy_vhd_buf_addr}:size:${vtoy_vhd_buf_size}
boot
ventoy_gui_console
else
ventoy_cli_console
chainloader ${vtoy_path}/ventoy_${VTOY_EFI_ARCH}.efi memdisk env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_vhd_buf_addr}:size:${vtoy_vhd_buf_size}
boot
ventoy_gui_console
fi
else
echo "Please put the right ventoy_vhdboot.img file to the 1st partition"
ventoy_pause
fi
}
function vhd_common_menuentry {
if [ "$VTOY_VHD_NO_WARNING" != "1" ]; then
......@@ -1252,25 +1276,7 @@ function vhd_common_menuentry {
return
fi
vt_patch_vhdboot "$vt_chosen_path"
ventoy_debug_pause
if [ -n "$vtoy_vhd_buf_addr" ]; then
if [ "$grub_platform" = "pc" ]; then
linux16 $vtoy_path/memdisk iso raw
initrd16 mem:${vtoy_vhd_buf_addr}:size:${vtoy_vhd_buf_size}
boot
else
ventoy_cli_console
chainloader ${vtoy_path}/ventoy_${VTOY_EFI_ARCH}.efi memdisk env_param=${env_param} isoefi=${LoadIsoEfiDriver} ${vtdebug_flag} mem:${vtoy_vhd_buf_addr}:size:${vtoy_vhd_buf_size}
boot
ventoy_gui_console
fi
else
echo "Please put the right ventoy_vhdboot.img file to the 1st partition"
ventoy_pause
fi
vhdboot_common_func "${vt_chosen_path}"
}
function vhd_unsupport_menuentry {
......
......@@ -365,11 +365,15 @@ else
oldver=$(get_disk_ventoy_version $DISK)
if [ $? -ne 0 ]; then
vtwarn "$DISK does not contain Ventoy or data corrupted"
echo ""
vtwarn "Please use -i option if you want to install ventoy to $DISK"
echo ""
exit 1
if is_disk_contains_ventoy $DISK; then
oldver="Unknown"
else
vtwarn "$DISK does not contain Ventoy or data corrupted"
echo ""
vtwarn "Please use -i option if you want to install ventoy to $DISK"
echo ""
exit 1
fi
fi
#reserve secure boot option
......
......@@ -151,7 +151,7 @@ tar -czvf ventoy-${curver}-linux.tar.gz $tmpdir
rm -f ventoy-${curver}-windows.zip
cp $OPT Ventoy2Disk*.exe $tmpdir/
cp $OPT $LANG_DIR/languages.ini $tmpdir/ventoy/
cp $OPT $LANG_DIR/languages.json $tmpdir/ventoy/
rm -rf $tmpdir/tool
rm -f $tmpdir/*.sh
rm -rf $tmpdir/WebUI
......
File encoding: UTF-8
language name must in the format: "Language-XXX (YYY)"
1. Language- fixed 9 characters
2. XXX: name in English
3. a space (ASCII: 0x20)
4. a left brace (ASCII: 0x28)
5. YYY: name in the specified language
6. a right brace (ASCII: 0x29)
string translation:
all the String Define
#@ will be replaced with \r\n
All the languages will be sorted by the name
#!/bin/sh
VTOY_PATH=$1
if [ ! -f $VTOY_PATH/LANGUAGES/languages.json ]; then
exit 1
fi
gcc -DFOR_VTOY_JSON_CHECK $VTOY_PATH/Ventoy2Disk/Ventoy2Disk/VentoyJson.c -I $VTOY_PATH/Ventoy2Disk/Ventoy2Disk/ -o checkjson
./checkjson $VTOY_PATH/LANGUAGES/languages.json
ret=$?
rm -f ./checkjson
[ $ret -eq 0 ]
Binary files a/LANGUAGES/languages.ini and /dev/null differ
[
{
"name":"Arabic (العربية)",
"FontFamily":"Courier New",
"FontSize":20,
"Author":"Omar Namis Mostafa",
"STR_ERROR":"خطأ",
"STR_WARNING":"تحذير",
"STR_INFO":"معلومات",
"STR_INCORRECT_DIR":"يرجى التشغيل من المسار الصحيح!",
"STR_INCORRECT_TREE_DIR":"لا تقم بالتشغيل من هنا، يرجى تحميل حزمة التثبيت، وتشغيلها من هناك.",
"STR_DEVICE":"الجهاز",
"STR_LOCAL_VER":"في الحزمة Ventoy",
"STR_DISK_VER":"في الجهاز Ventoy",
"STR_STATUS":"الحالة - جاهز",
"STR_INSTALL":"تثبيت",
"STR_UPDATE":"تحديث",
"STR_UPDATE_TIP":"عملية التحديث آمنة, لن يتم عمل تغييرات على ملفات الـISO.#@استمرار؟",
"STR_INSTALL_TIP":"سوف يتم تهيئة القرص وسيتم حذف جميع البيانات.#@المواصلة؟",
"STR_INSTALL_TIP2":"سوف يتم تهيئة القرص وسيتم حذف جميع البيانات.#@المواصلة؟ (التحقق مرة أخرى)",
"STR_INSTALL_SUCCESS":"مبروك!#@تم تثبيت Ventoy بنجاح على الجهاز.",
"STR_INSTALL_FAILED":"حدث خطأ أثناء التثبيت. يمكنك إعادة توصيل الـUSB والمحاولة مرة أخرى. تفقّد log.txt للتفاصيل.",
"STR_UPDATE_SUCCESS":"مبروك!#@تم تحديث Ventoy بنجاح على الجهاز.",
"STR_UPDATE_FAILED":"حدث خطأ أثناء التحديث. يمكنك إعادة توصيل الـUSB والمحاولة مرة أخرى. تفقّد log.txt للتفاصيل.",
"STR_WAIT_PROCESS":"هناك عملية نشطة، يرجى الانتظار...",
"STR_MENU_OPTION":"خيارات",
"STR_MENU_SECURE_BOOT":"تمهيد آمن",
"STR_MENU_PART_CFG":"تكوين التقسيم",
"STR_BTN_OK":"موافق",
"STR_BTN_CANCEL":"إلغاء",
"STR_PRESERVE_SPACE":"الحفاظ على بعض المساحة في الجزء السفلي من القرص",
"STR_SPACE_VAL_INVALID":"قيمة غير صالحة للمساحة المحجوزة",
"STR_MENU_CLEAR":"إزالة Ventoy",
"STR_CLEAR_SUCCESS":"تمت إزالة Ventoy من الجهاز بنجاح.",
"STR_CLEAR_FAILED":"حدث خطأ عند إزالة Ventoy من القرص. يمكنك إعادة توصيل الـUSB والمحاولة مرة أخرى. تفقد log.txt للتفاصيل.",
"STR_MENU_PART_STYLE":"أسلوب التقسيم",
"STR_DISK_2TB_MBR_ERROR":"يرجى اختيار GPT للأقراص الأكبر من 2 تيرابايت",
"STR_SHOW_ALL_DEV":"عرض كافة الأجهزة",
"STR_PART_ALIGN_4KB":"محاذاة الأقسام مع 4KB",
"STR_WEB_COMMUNICATION_ERR":"خطأ في الاتصال:",
"STR_WEB_REMOTE_ABNORMAL":"خطأ في الاتصال: بعيد غير طبيعي",
"STR_WEB_REQUEST_TIMEOUT":"خطأ في الاتصال: انتهت مهلة الطلب",
"STR_WEB_SERVICE_UNAVAILABLE":"خطأ في الاتصال: الخدمة غير متوفرة",
"STR_WEB_TOKEN_MISMATCH":"تم تحديث حالة البرنامج الخفي ، يرجى إعادة المحاولة لاحقًا.",
"STR_WEB_SERVICE_BUSY":"الخدمة مشغولة ، يرجى إعادة المحاولة لاحقًا.",
"STRXXX":""
},
{
"name":"Korean (한국어)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Remiz,VenusGirl",
"STR_ERROR":"오류",
"STR_WARNING":"경고",
"STR_INFO":"정보",
"STR_INCORRECT_DIR":"올바른 디렉토리에서 실행하십시오!",
"STR_INCORRECT_TREE_DIR":"여기서 저를 실행하지 말고, 출시된 설치 패키지를 다운로드한 다음 거기서 실행하십시오.",
"STR_DEVICE":"장치",
"STR_LOCAL_VER":"패키지의 Ventoy 버전",
"STR_DISK_VER":"장치 내부의 Ventoy 버전",
"STR_STATUS":"상태 - 준비 완료",
"STR_INSTALL":"설치",
"STR_UPDATE":"업데이트",
"STR_UPDATE_TIP":"업그레이드 작업은 안전하며 ISO 파일은 변경되지 않습니다.#@계속하시겠습니까?",
"STR_INSTALL_TIP":"디스크가 포맷되고 모든 데이터가 손실됩니다.#@계속하시겠습니까?",
"STR_INSTALL_TIP2":"디스크가 포맷되고 모든 데이터가 손실됩니다.#@계속하시겠습니까? (다시 확인)",
"STR_INSTALL_SUCCESS":"축하합니다!#@Ventoy가 장치에 성공적으로 설치되었습니다.",
"STR_INSTALL_FAILED":"설치 중 오류가 발생했습니다. USB를 다시 연결하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_UPDATE_SUCCESS":"축하합니다!#@Ventoy가 장치에 성공적으로 업데이트되었습니다.",
"STR_UPDATE_FAILED":"업데이트 중에 오류가 발생했습니다. USB를 다시 연결하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_WAIT_PROCESS":"현재 작업이 실행 중입니다. 기다려 주십시오...",
"STR_MENU_OPTION":"옵션",
"STR_MENU_SECURE_BOOT":"보안 부트 (Secure Boot) 지원",
"STR_MENU_PART_CFG":"파티션 구성",
"STR_BTN_OK":"확인",
"STR_BTN_CANCEL":"취소",
"STR_PRESERVE_SPACE":"디스크의 끝에 예약된 공간 확보",
"STR_SPACE_VAL_INVALID":"예약된 공간의 값이 잘못되었습니다",
"STR_MENU_CLEAR":"Ventoy 제거",
"STR_CLEAR_SUCCESS":"Ventoy가 장치에서 성공적으로 제거되었습니다.",
"STR_CLEAR_FAILED":"디스크에서 Ventoy를 지울 때 오류가 발생했습니다. USB를 다시 연결하고 다시 시도할 수 있습니다. 자세한 내용은 log.txt를 확인하십시오.",
"STR_MENU_PART_STYLE":"파티션 유형",
"STR_DISK_2TB_MBR_ERROR":"2TB 이상의 디스크는 GPT를 선택하십시오",
"STR_SHOW_ALL_DEV":"모든 장치 표시",
"STR_PART_ALIGN_4KB":"파티션을 4KB로 정렬",
"STR_WEB_COMMUNICATION_ERR":"통신 오류:",
"STR_WEB_REMOTE_ABNORMAL":"통신 오류: 원격 이상",
"STR_WEB_REQUEST_TIMEOUT":"통신 오류: 요청이 시간 초과됨",
"STR_WEB_SERVICE_UNAVAILABLE":"통신 오류: 서비스를 사용할 수 없음",
"STR_WEB_TOKEN_MISMATCH":"데몬 상태가 업데이트되었습니다. 나중에 다시 시도하십시오.",
"STR_WEB_SERVICE_BUSY":"서비스가 사용 중입니다. 나중에 다시 시도하십시오.",
"STRXXX":""
},
{
"name":"Chinese Simplified (简体中文)",
"FontFamily":"宋体",
"FontSize":14,
"Author":"longpanda",
"STR_ERROR":"错误",
"STR_WARNING":"警告",
"STR_INFO":"提醒",
"STR_INCORRECT_DIR":"请在正确的目录下运行!",
"STR_INCORRECT_TREE_DIR":"请不要在代码树下运行此程序(INSTALL目录),请下载安装包,解压后在那里运行。",
"STR_DEVICE":"设备",
"STR_LOCAL_VER":"安装包内 Ventoy 版本",
"STR_DISK_VER":"设备内部 Ventoy 版本",
"STR_STATUS":"状态 - 准备就绪",
"STR_INSTALL":"安装",
"STR_UPDATE":"升级",
"STR_UPDATE_TIP":"升级操作是安全的, ISO文件不会丢失#@是否继续?",
"STR_INSTALL_TIP":"磁盘会被格式化, 所有数据都会丢失!#@是否继续?",
"STR_INSTALL_TIP2":"磁盘会被格式化, 所有数据都会丢失!#@再次确认是否继续?",
"STR_INSTALL_SUCCESS":"恭喜你! Ventoy 已经成功安装到此设备中.",
"STR_INSTALL_FAILED":"安装 Ventoy 过程中发生错误. 你可以重新拔插一下U盘然后重试一次, 详细信息请查阅 log.txt 文件.",
"STR_UPDATE_SUCCESS":"恭喜你! 新版本的 Ventoy 已经成功更新到此设备中.",
"STR_UPDATE_FAILED":"更新 Ventoy 过程中遇到错误. 你可以重新拔插一下U盘然后重试一次, 详细信息请查阅 log.txt 文件.",
"STR_WAIT_PROCESS":"当前有任务正在运行, 请等待...",
"STR_MENU_OPTION":"配置选项",
"STR_MENU_SECURE_BOOT":"安全启动支持",
"STR_MENU_PART_CFG":"分区设置",
"STR_BTN_OK":"确定",
"STR_BTN_CANCEL":"取消",
"STR_PRESERVE_SPACE":"在磁盘最后保留一段空间",
"STR_SPACE_VAL_INVALID":"保留空间的数值非法",
"STR_MENU_CLEAR":"清除 Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy已经成功从此设备中清除.",
"STR_CLEAR_FAILED":"清除 Ventoy 过程中遇到错误. 你可以重新拔插一下U盘然后重试一次, 详细信息请查阅 log.txt 文件.",
"STR_MENU_PART_STYLE":"分区类型",
"STR_DISK_2TB_MBR_ERROR":"磁盘容量超过2TB,请选择GPT分区格式",
"STR_SHOW_ALL_DEV":"显示所有设备",
"STR_PART_ALIGN_4KB":"分区按照 4KB 对齐",
"STR_WEB_COMMUNICATION_ERR":"通信失败:",
"STR_WEB_REMOTE_ABNORMAL":"通信失败:服务端异常",
"STR_WEB_REQUEST_TIMEOUT":"通信失败:请求超时",
"STR_WEB_SERVICE_UNAVAILABLE":"通信失败:服务不可用",
"STR_WEB_TOKEN_MISMATCH":"后台服务状态更新,请稍后重试",
"STR_WEB_SERVICE_BUSY":"后台服务正忙,请稍后重试",
"STRXXX":""
},
{
"name":"English (English)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"longpanda",
"STR_ERROR":"Error",
"STR_WARNING":"Warning",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Please run under the correct directory!",
"STR_INCORRECT_TREE_DIR":"Don't run me here, please download the released install package, and run there.",
"STR_DEVICE":"Device",
"STR_LOCAL_VER":"Ventoy In Package",
"STR_DISK_VER":"Ventoy In Device",
"STR_STATUS":"Status - READY",
"STR_INSTALL":"Install",
"STR_UPDATE":"Update",
"STR_UPDATE_TIP":"Upgrade operation is safe, ISO files will be unchanged.#@Continue?",
"STR_INSTALL_TIP":"The disk will be formatted and all the data will be lost.#@Continue?",
"STR_INSTALL_TIP2":"The disk will be formatted and all the data will be lost.#@Continue? (Double Check)",
"STR_INSTALL_SUCCESS":"Congratulations!#@Ventoy has been successfully installed to the device.",
"STR_INSTALL_FAILED":"An error occurred during the installation. You can replug the USB and try again. Check log.txt for detail.",
"STR_UPDATE_SUCCESS":"Congratulations!#@Ventoy has been successfully updated to the device.",
"STR_UPDATE_FAILED":"An error occurred during the update. You can replug the USB and try again. Check log.txt for detail.",
"STR_WAIT_PROCESS":"A thread is running, please wait...",
"STR_MENU_OPTION":"Option",
"STR_MENU_SECURE_BOOT":"Secure Boot Support",
"STR_MENU_PART_CFG":"Partition Configuration",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Cancel",
"STR_PRESERVE_SPACE":"Preserve some space at the end of the disk",
"STR_SPACE_VAL_INVALID":"Invalid value for reserved space",
"STR_MENU_CLEAR":"Clear Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy has been successfully removed from the device.",
"STR_CLEAR_FAILED":"An error occurred when clear Ventoy from disk. You can replug the USB and try again. Check log.txt for detail.",
"STR_MENU_PART_STYLE":"Partition Style",
"STR_DISK_2TB_MBR_ERROR":"Please select GPT for disk over 2TB",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Persian (فارسی)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"ivadham",
"STR_ERROR":"خطا",
"STR_WARNING":"هشدار",
"STR_INFO":"توضیحات",
"STR_INCORRECT_DIR":".لطفاً در پوشه‌دان صحیح اجرا کنید",
"STR_INCORRECT_TREE_DIR":".این‌جا اجرا نکنید، لطفاً بستهٔ نصب را دانلود و آن‌جا اجرا کنید",
"STR_DEVICE":"حافظهٔ قابل حمل",
"STR_LOCAL_VER":"آمادهٔ نصب Ventoy",
"STR_DISK_VER":"نصب‌شده روی حافظه Ventoy",
"STR_STATUS":"وضعیت - آماده",
"STR_INSTALL":"فرمت و نصب",
"STR_UPDATE":"به‌روزرسانی",
"STR_UPDATE_TIP":"عملیات به‌روزرسانی بی‌خطر است و داده‌های روی حافظهٔ قابل حمل سالم باقی خواهند ماند. ادامه؟",
"STR_INSTALL_TIP":"حافظهٔ قابل حمل فرمت و تمامی داده‌های آن پاک خواهد شد. ادامه؟",
"STR_INSTALL_TIP2":"توجه: این عملیات غیرقابل بازگشت است. ادامه؟",
"STR_INSTALL_SUCCESS":".تبریک! عملیات نصب بر روی حافظهٔ قابل حمل با موفقیت پایان یافت",
"STR_INSTALL_FAILED":".خطا در عملیات نصب! یو‌اس‌بی را از نو متصل و دوباره تلاش کنید",
"STR_UPDATE_SUCCESS":".تبریک! نرم‌افزار با موفقیت بر روی حافظهٔ قابل حمل به‌روزرسانی شد",
"STR_UPDATE_FAILED":".خطا در به‌روزرسانی! یو‌اس‌بی را از نو متصل و دوباره تلاش کنید",
"STR_WAIT_PROCESS":"...پروسه‌ای در حال اجرا است، لطفاً صبر کنید",
"STR_MENU_OPTION":"تنظیمات",
"STR_MENU_SECURE_BOOT":"(Secure Boot) بوت امن",
"STR_MENU_PART_CFG":"پیکربندی پارتیشن",
"STR_BTN_OK":"تأیید",
"STR_BTN_CANCEL":"انصراف",
"STR_PRESERVE_SPACE":"اختصاص مقداری فضا به انتهای حافظهٔ قابل حمل",
"STR_SPACE_VAL_INVALID":".این مقدار فضا برای اختصاص‌یافتن نامعتبر است",
"STR_MENU_CLEAR":"Ventoy را پاک کنید",
"STR_CLEAR_SUCCESS":"Ventoy با موفقیت از دستگاه برداشته شد.",
"STR_CLEAR_FAILED":"هنگام پاک کردن Ventoy از روی دیسک خطایی روی داد. می توانید USB را دوباره از برق جدا کنید و دوباره امتحان کنید. log.txt را برای جزئیات بررسی کنید.",
"STR_MENU_PART_STYLE":"سبک پارتیشن بندی",
"STR_DISK_2TB_MBR_ERROR":"لطفاً GPT را برای دیسک بیش از 2 ترابایت انتخاب کنید",
"STR_SHOW_ALL_DEV":"نمایش همه دستگاه ها",
"STR_PART_ALIGN_4KB":"پارتیشن ها را با 4KB تراز کنید",
"STR_WEB_COMMUNICATION_ERR":"خطای ارتباطی:",
"STR_WEB_REMOTE_ABNORMAL":"خطای ارتباطی: از راه دور غیر طبیعی است",
"STR_WEB_REQUEST_TIMEOUT":"خطای ارتباطی: زمان درخواست به پایان رسیده است",
"STR_WEB_SERVICE_UNAVAILABLE":"خطای ارتباطی: سرویس موجود نیست",
"STR_WEB_TOKEN_MISMATCH":"وضعیت Daemon به روز شد ، لطفاً بعداً دوباره امتحان کنید.",
"STR_WEB_SERVICE_BUSY":"سرویس شلوغ است ، لطفاً بعداً دوباره امتحان کنید.",
"STRXXX":""
},
{
"name":"Polish (Polski)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"B.O.S.S",
"STR_ERROR":"Błąd",
"STR_WARNING":"Ostrzeżenie",
"STR_INFO":"Informacja",
"STR_INCORRECT_DIR":"Proszę uruchom w odpowiednim katalogu!",
"STR_INCORRECT_TREE_DIR":"Nie uruchamiaj mnie tutaj, pobierz pakiet instalacyjny i uruchom go.",
"STR_DEVICE":"Urządzenie",
"STR_LOCAL_VER":"Ventoy w programie",
"STR_DISK_VER":"Ventoy na urządzeniu",
"STR_STATUS":"Status - GOTOWY",
"STR_INSTALL":"Zainstaluj",
"STR_UPDATE":"Zaktualizuj",
"STR_UPDATE_TIP":"Operacja aktualizacji jest bezpieczna, pliki ISO pozostaną niezmienione.#@Kontynuować?",
"STR_INSTALL_TIP":"Dysk zostanie sformatowany, a wszystkie dane zostaną utracone.#@Kontynuować?",
"STR_INSTALL_TIP2":"Dysk zostanie sformatowany, a wszystkie dane zostaną utracone.#@Kontynuować? (Podwójne sprawdzenie)",
"STR_INSTALL_SUCCESS":"Gratulacje!#@Ventoy został pomyślnie zainstalowany na urządzeniu.",
"STR_INSTALL_FAILED":"Wystąpił błąd podczas instalacji. Możesz ponownie podłączyć USB i spróbować jeszcze raz. Szczegóły w log.txt.",
"STR_UPDATE_SUCCESS":"Gratulacje!#@Ventoy zostało pomyślnie zaktualizowane na urządzeniu.",
"STR_UPDATE_FAILED":"Wystąpił błąd podczas aktualizacji. Możesz ponownie podłączyć USB i spróbować jeszcze raz. Szczegóły w log.txt.",
"STR_WAIT_PROCESS":"Wątek jest uruchomiony, proszę czekać...",
"STR_MENU_OPTION":"Opcje",
"STR_MENU_SECURE_BOOT":"Bezpieczny rozruch/Secure Boot",
"STR_MENU_PART_CFG":"Konfiguracja partycji",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Anuluj",
"STR_PRESERVE_SPACE":"Zachowaj trochę miejsca na dole dysku",
"STR_SPACE_VAL_INVALID":"Nieprawidłowa wartość zarezerwowanego miejsca",
"STR_MENU_CLEAR":"Wyczyść Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy został pomyślnie usunięty z urządzenia.",
"STR_CLEAR_FAILED":"Wystąpił błąd podczas usuwania Ventoy z dysku. Możesz podłączyć USB i spróbować jeszcze raz. Szczegóły w log.txt.",
"STR_MENU_PART_STYLE":"Schemat partycji",
"STR_DISK_2TB_MBR_ERROR":"Wybierz GPT dla dysku powyżej 2TB",
"STR_SHOW_ALL_DEV":"Pokaż wszystkie urządzenia",
"STR_PART_ALIGN_4KB":"Wyrównaj partycje z 4KB",
"STR_WEB_COMMUNICATION_ERR":"Błąd komunikacji:",
"STR_WEB_REMOTE_ABNORMAL":"Błąd komunikacji: nieprawidłowy serwer",
"STR_WEB_REQUEST_TIMEOUT":"Błąd komunikacji: przekroczono limit czasu żądania",
"STR_WEB_SERVICE_UNAVAILABLE":"Błąd komunikacji: usługa niedostępna",
"STR_WEB_TOKEN_MISMATCH":"Stan daemona został zaktualizowany, spróbuj ponownie później.",
"STR_WEB_SERVICE_BUSY":"Usługa jest zajęta, spróbuj ponownie później.",
"STRXXX":""
},
{
"name":"Portuguese Brazilian (Português do Brasil)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"EstevaoCostaG3, David BrazSan",
"STR_ERROR":"Erro",
"STR_WARNING":"Atenção",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Por favor, execute no diretório correto!",
"STR_INCORRECT_TREE_DIR":"Não me execute aqui, por favor baixe o pacote de instalação lançado, e me execute lá.",
"STR_DEVICE":"Dispositivo",
"STR_LOCAL_VER":"Ventoy em pacote",
"STR_DISK_VER":"Ventoy em dispositivo",
"STR_STATUS":"Status - PRONTO",
"STR_INSTALL":"Instalar",
"STR_UPDATE":"Atualizar",
"STR_UPDATE_TIP":"A operação de atualização é segura, os arquivos ISO não serão alterados.#@Continuar?",
"STR_INSTALL_TIP":"O disco será formatado e todos os dados serão perdidos.#@Continuar?",
"STR_INSTALL_TIP2":"O disco será formatado e todos os dados serão perdidos.#@Continuar? (Verificação dupla)",
"STR_INSTALL_SUCCESS":"Parabéns!#@Ventoy foi instalado com sucesso no dispositivo.",
"STR_INSTALL_FAILED":"Um erro ocorreu durante a instalação. Você pode reconectar o dispositivo USB e tentar novamente. Verifique o arquivo log.txt para mais detalhes.",
"STR_UPDATE_SUCCESS":"Parabéns!#@Ventoy foi atualizado com sucesso no dispositivo.",
"STR_UPDATE_FAILED":"Um erro ocorreu durante a atualização. Você pode reconectar o dispositivo USB e tentar novamente. Verifique o arquivo log.txt para mais detalhes.",
"STR_WAIT_PROCESS":"Uma thread está em execução, por favor espere...",
"STR_MENU_OPTION":"Opção",
"STR_MENU_SECURE_BOOT":"Boot seguro",
"STR_MENU_PART_CFG":"Configuração de Partição",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Cancelar",
"STR_PRESERVE_SPACE":"Preservar algum espaço no final do disco",
"STR_SPACE_VAL_INVALID":"Valor invalido para o espaço reservado",
"STR_MENU_CLEAR":"Remover o Ventoy",
"STR_CLEAR_SUCCESS":"O Ventoy foi removido deste dispositivo com sucesso.",
"STR_CLEAR_FAILED":"Um erro ocorreu ao remover o Ventoy do disco. Você pode reconectar o dispositivo USB e tentar novamente. Verifique o Arquivo log.txt para mais detalhes.",
"STR_MENU_PART_STYLE":"Estilo de Partição",
"STR_DISK_2TB_MBR_ERROR":"Por favor selecione GPT para discos maiores que 2TB",
"STR_SHOW_ALL_DEV":"Mostrar Todos os Dispositivos",
"STR_PART_ALIGN_4KB":"Alinhar partições com 4KB",
"STR_WEB_COMMUNICATION_ERR":"Erro de comunicação:",
"STR_WEB_REMOTE_ABNORMAL":"Erro de comunicação: remoto anormal",
"STR_WEB_REQUEST_TIMEOUT":"Erro de comunicação: Solicitação cronometrado",
"STR_WEB_SERVICE_UNAVAILABLE":"Erro de comunicação: Serviço indisponível",
"STR_WEB_TOKEN_MISMATCH":"Status daemon atualizado, por favor, tente novamente mais tarde.",
"STR_WEB_SERVICE_BUSY":"O serviço está ocupado, por favor, tente novamente mais tarde.",
"STRXXX":""
},
{
"name":"Turkish (Türkçe)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Erhan Kültür/crasadure",
"STR_ERROR":"Hata",
"STR_WARNING":"Uyarı",
"STR_INFO":"Bilgi",
"STR_INCORRECT_DIR":"Lütfen doğru dizin altında çalıştırın!",
"STR_INCORRECT_TREE_DIR":"Dosyayı burada çalıştırma, lütfen yayınlanan en son kurulum paketini indirin ve oradan çalıştırın.",
"STR_DEVICE":"Aygıt",
"STR_LOCAL_VER":"Ventoy GÜNCEL Sürüm",
"STR_DISK_VER":"Cihazdaki Ventoy Sürümü",
"STR_STATUS":"Durum - HAZIR",
"STR_INSTALL":"Kur",
"STR_UPDATE":"Güncelle",
"STR_UPDATE_TIP":"Ventoyun versiyon bilgisi güncellenecek, ISO dosyalarınız bundan etkilenmiyecek.#@Devam edilsinmi?",
"STR_INSTALL_TIP":"Disk biçimlendirilecek ve tüm veriler kaybolacak.#@Devam edilsinmi?",
"STR_INSTALL_TIP2":"Disk biçimlendirilecek ve tüm veriler kaybolacak.#@Devam edilsinmi? (Son UYARI!)",
"STR_INSTALL_SUCCESS":"Tebrikler!#@ventoy cihaza başarıyla kuruldu.",
"STR_INSTALL_FAILED":"Yükleme sırasında bir hata oluştu. USB'yi yeniden takıp tekrar deneyebilirsiniz. Ayrıntılar için log.txt dosyasına bakın.",
"STR_UPDATE_SUCCESS":"Tebrikler!#@ventoy cihazda başarıyla güncellendi.",
"STR_UPDATE_FAILED":"Güncelleme sırasında bir hata oluştu. USB'yi yeniden takıp tekrar deneyebilirsiniz. Ayrıntılar için log.txt dosyasına bakın.",
"STR_WAIT_PROCESS":"Mevcut işlem çalışıyor, lütfen bekleyiniz ...",
"STR_MENU_OPTION":"Seçenek",
"STR_MENU_SECURE_BOOT":"Güvenli Önyükleme",
"STR_MENU_PART_CFG":"Partisyon Yapılandırması",
"STR_BTN_OK":"Tamam",
"STR_BTN_CANCEL":"İptal et",
"STR_PRESERVE_SPACE":"Diskin sonunda ayrılmış disk partisyonu oluştur",
"STR_SPACE_VAL_INVALID":"Ayrılmış alan için geçersiz değer girdiniz",
"STR_MENU_CLEAR":"Ventoyu USB Diskten Sil",
"STR_CLEAR_SUCCESS":"Ventoy başarılı bir şekilde diskten silindi",
"STR_CLEAR_FAILED":"Ventoy USB diskten temizlenirken bir hata oluştu.Lütfen USB Diski tekrar takın ve tekrar deneyin.Hatanın detayları için Log.txt dosyasını okuyun",
"STR_MENU_PART_STYLE":"Partisyon Yapısı",
"STR_DISK_2TB_MBR_ERROR":"2TB üstündeki diskler için lütfen GPT disk yapısını seçiniz.",
"STR_SHOW_ALL_DEV":"Tüm Cihazları Göster",
"STR_PART_ALIGN_4KB":"Tüm Partisyonları 4KB düzeninde hizala",
"STR_WEB_COMMUNICATION_ERR":"Iletişim Hatası:",
"STR_WEB_REMOTE_ABNORMAL":"Iletişim Hatası:Uzaktan erişim hizmeti anormal durumda",
"STR_WEB_REQUEST_TIMEOUT":"Iletişim hatası: Uzaktan erişim isteği zaman aşımına uğradı",
"STR_WEB_SERVICE_UNAVAILABLE":"Iletişim hatası: Uzaktan web erişim hizmeti erişilemez durumda",
"STR_WEB_TOKEN_MISMATCH":"Daemon durumu güncellendi,lütfen daha sonra tekrar deneyiniz.",
"STR_WEB_SERVICE_BUSY":"Hizmet meşgul, lütfen daha sonra tekrar deneyin.",
"STRXXX":""
},
{
"name":"German (Deutsch)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"luzea & u!^DEV",
"STR_ERROR":"Fehler",
"STR_WARNING":"Warnung",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Bitte im richtigen Verzeichnis ausführen!",
"STR_INCORRECT_TREE_DIR":"Bitte nicht hier ausführen. Laden Sie das Installationspaket herunter und von dort aus ausführen.",
"STR_DEVICE":"Gerät",
"STR_LOCAL_VER":"Ventoy (lokal)",
"STR_DISK_VER":"Ventoy (Gerät)",
"STR_STATUS":"Status - BEREIT",
"STR_INSTALL":"Installieren",
"STR_UPDATE":"Aktualisieren",
"STR_UPDATE_TIP":"Die Durchführung der Aktualisierung ist sicher, ISO-Dateien bleiben unverändert.#@Fortfahren?",
"STR_INSTALL_TIP":"Das Gerät wird formatiert und alle Daten gehen verloren.#@Fortfahren?",
"STR_INSTALL_TIP2":"Das Gerät wird formatiert und alle Daten gehen verloren.#@Fortfahren? (erneute Überprüfung)",
"STR_INSTALL_SUCCESS":"Herzlichen Glückwunsch!#@Ventoy wurde erfolgreich auf dem Gerät installiert.",
"STR_INSTALL_FAILED":"Während der Installation ist ein Fehler aufgetreten. Stecken Sie das Gerät neu ein und versuchen Sie es erneut. Überprüfen Sie die log.txt auf Details.",
"STR_UPDATE_SUCCESS":"Herzlichen Glückwunsch!#@Ventoy wurde erfolgreich auf dem Gerät aktualisiert.",
"STR_UPDATE_FAILED":"Während der Aktualisierung ist ein Fehler aufgetreten. Stecken Sie das Gerät neu ein und versuchen Sie es erneut. Überprüfen Sie die log.txt auf Details.",
"STR_WAIT_PROCESS":"Ein anderer Thread läuft, bitte warten...",
"STR_MENU_OPTION":"Optionen",
"STR_MENU_SECURE_BOOT":"Secure Boot",
"STR_MENU_PART_CFG":"Partitionskonfiguration",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Abbrechen",
"STR_PRESERVE_SPACE":"Etwas Speicher am Ende des Datenträgers reservieren.",
"STR_SPACE_VAL_INVALID":"Ungültiger Wert für reservierten Speicherplatz!",
"STR_MENU_CLEAR":"Ventoy entfernen",
"STR_CLEAR_SUCCESS":"Ventoy wurde erfolgreich vom Gerät entfernt.",
"STR_CLEAR_FAILED":"Beim Versuch, Ventoy zu entfernen, ist ein Fehler aufgetreten. Stecken Sie das Gerät neu ein und versuchen Sie es erneut. Überprüfen Sie die log.txt auf Details.",
"STR_MENU_PART_STYLE":"Partitionsstil",
"STR_DISK_2TB_MBR_ERROR":"Wählen Sie GPT für Geräte > 2TB aus.",
"STR_SHOW_ALL_DEV":"Alle Geräte anzeigen",
"STR_PART_ALIGN_4KB":"Richten Sie Partitionen mit 4KB aus",
"STR_WEB_COMMUNICATION_ERR":"Kommunikationsfehler:",
"STR_WEB_REMOTE_ABNORMAL":"Kommunikationsfehler: unnormales Verhalten",
"STR_WEB_REQUEST_TIMEOUT":"Kommunikationsfehler: Zeitüberschreitung der Anforderung",
"STR_WEB_SERVICE_UNAVAILABLE":"Kommunikationsfehler: Dienst nicht verfügbar",
"STR_WEB_TOKEN_MISMATCH":"Daemon-Status aktualisiert, bitte später erneut versuchen.",
"STR_WEB_SERVICE_BUSY":"Dienst ist ausgelastet, bitte später erneut versuchen.",
"STRXXX":""
},
{
"name":"Occitan (Occitan)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"quentin",
"STR_ERROR":"Error",
"STR_WARNING":"Avertiment",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Aqueste programa deu s’executar dins lo bon repertòri!",
"STR_INCORRECT_TREE_DIR":"Lancetz pas aquò, mercés de telecargar lo programa d’installacion e relançatz-lo.",
"STR_DEVICE":"Periferic",
"STR_LOCAL_VER":"Ventoy en local",
"STR_DISK_VER":"Ventoy sul periferic",
"STR_STATUS":"Estat - prèst",
"STR_INSTALL":"Installacion",
"STR_UPDATE":"Mesa a jorn",
"STR_UPDATE_TIP":"La mesa a jorn es segura, los fichièrs ISO seràn pas modificats.#@Continhar ?",
"STR_INSTALL_TIP":"Lo disc serà formatat e totas sas donadas seràn perdudas.#@Contunhar ?",
"STR_INSTALL_TIP2":"Lo disc serà formatat e totas sas donadas seràn perdudas.#@Contunhar ? (confirmacion)",
"STR_INSTALL_SUCCESS":"Felicitacions !#@Ventoy es estat corrèctament installat sul periferic.",
"STR_INSTALL_FAILED":"Una error s’es producha pendent l’installacion. Podètz tornar brancar lo periferic USB e tornar ensajar. Agachatz lo fichièr log.txt per ne saber mai.",
"STR_UPDATE_SUCCESS":"Felicitacions !#@Ventoy es estat corrèctament mes a jorn sul periferic.",
"STR_UPDATE_FAILED":"Una error s’es producha pendent la mesa a jorn. Podètz tornar brancar lo periferic USB e tornar ensajar. Agachatz lo fichièr log.txt per ne saber mai.",
"STR_WAIT_PROCESS":"Una operacion es en cors, esperatz...",
"STR_MENU_OPTION":"Opcion",
"STR_MENU_SECURE_BOOT":"Secure Boot",
"STR_MENU_PART_CFG":"Configuracion de particion",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Anullar",
"STR_PRESERVE_SPACE":"Preserve some space at the end of the disk",
"STR_SPACE_VAL_INVALID":"Valor invalida per l’espaci reservat",
"STR_MENU_CLEAR":"Escafar Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy es estat corrèctament tirat del periferic.",
"STR_CLEAR_FAILED":"Una error s’es producha pendent l’esfaçament de Ventoy del disc. Podètz tornar brancar l’USB e tornar ensajar. Vejatz log.txt pels detalhs.",
"STR_MENU_PART_STYLE":"Estil de particion",
"STR_DISK_2TB_MBR_ERROR":"Pels disques de mai de 2To seleccionatz GPT",
"STR_SHOW_ALL_DEV":"Mostrar totes los periferics",
"STR_PART_ALIGN_4KB":"Alinhar las particions sus 4Ko",
"STR_WEB_COMMUNICATION_ERR":"Error de comunicacion :",
"STR_WEB_REMOTE_ABNORMAL":"Error de comunicacion : remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Error de comunicacion: requèsta tardièra",
"STR_WEB_SERVICE_UNAVAILABLE":"Error de comunicacion : servici pas disponible",
"STR_WEB_TOKEN_MISMATCH":"Estat del Daemon actualizat, tornatz ensajar mai tard.",
"STR_WEB_SERVICE_BUSY":"Lo servici es ocupat, tornatz ensajar mai tard.",
"STRXXX":""
},
{
"name":"French (Français)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"vboucard",
"STR_ERROR":"Erreur",
"STR_WARNING":"Avertissement",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Ce programme doit s'exécuter dans le bon répertoire !",
"STR_INCORRECT_TREE_DIR":"Ne me lancez pas d'ici, veuillez télécharger le programme d'installation et relancez-le.",
"STR_DEVICE":"Périphérique",
"STR_LOCAL_VER":"Ventoy en local",
"STR_DISK_VER":"Ventoy sur le périphérique",
"STR_STATUS":"Etat - prêt",
"STR_INSTALL":"Installation",
"STR_UPDATE":"Mise à jour",
"STR_UPDATE_TIP":"La mise à jour est sûre, les fichiers ISO ne seront pas modifiés.#@Continuer?",
"STR_INSTALL_TIP":"Le disque va être formaté et toutes ses données seront perdues.#@Continuer?",
"STR_INSTALL_TIP2":"Le disque va être formaté et toutes ses données seront perdues.#@Continuer? (confirmation)",
"STR_INSTALL_SUCCESS":"Félicitations !#@Ventoy a été correctement installé sur le périphérique.",
"STR_INSTALL_FAILED":"Une erreur est survenue durant l'installation. Vous pouvez rebrancher le périphérique USB et réessayer. Vérifiez le fichier log.txt pour plus de détails.",
"STR_UPDATE_SUCCESS":"Félicitations !#@Ventoy a été correctement mis à jour sur le périphérique.",
"STR_UPDATE_FAILED":"Une erreur est survenue durant la mise à jour. Vous pouvez rebrancher le périphérique USB et réessayer. Vérifiez le fichier log.txt pour plus de détails.",
"STR_WAIT_PROCESS":"Une opération est en cours, veuillez patienter...",
"STR_MENU_OPTION":"Option",
"STR_MENU_SECURE_BOOT":"Secure Boot",
"STR_MENU_PART_CFG":"Configuration de partition",
"STR_BTN_OK":"D'accord",
"STR_BTN_CANCEL":"Annuler",
"STR_PRESERVE_SPACE":"Préservez de l'espace au bas du disque",
"STR_SPACE_VAL_INVALID":"Valeur non valide pour l'espace réservé",
"STR_MENU_CLEAR":"Effacer Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy a été enlevé du périphérique avec succès.",
"STR_CLEAR_FAILED":"Une erreur est survenue pendant la suppression de Ventoy. Vous pouvez rebrancher le périphérique USB. Vérifiez le fichier log.txt pour plus de détails.",
"STR_MENU_PART_STYLE":"Type de partition",
"STR_DISK_2TB_MBR_ERROR":"Sélectionnez le type GPT pour les disques de plus de 2TO",
"STR_SHOW_ALL_DEV":"Afficher tous les appareils",
"STR_PART_ALIGN_4KB":"Alignez les partitions avec 4 KO",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Czech (Čeština)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"vavanade",
"STR_ERROR":"Chyba",
"STR_WARNING":"Varování",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Spusťte prosím ve správném adresáři!",
"STR_INCORRECT_TREE_DIR":"Nespouštějte mě zde, stáhněte si prosím vydaný instalační balík a spusťte v něm.",
"STR_DEVICE":"Zařízení",
"STR_LOCAL_VER":"Ventoy v balíčku",
"STR_DISK_VER":"Ventoy v zařízení",
"STR_STATUS":"Status - PŘIPRAVENO",
"STR_INSTALL":"Instalovat",
"STR_UPDATE":"Aktualizovat",
"STR_UPDATE_TIP":"Operace aktualizace je bezpečná, ISO soubory nebudou změněny.#@Pokračovat?",
"STR_INSTALL_TIP":"Disk bude zformátován a všechna data budou ztracena!#@Pokračovat?",
"STR_INSTALL_TIP2":"Disk bude zformátován a všechna data budou ztracena!#@Pokračovat? (druhá kontrola)",
"STR_INSTALL_SUCCESS":"Gratulujeme!#@Ventoy byla na zařízení úspěšně nainstalována.",
"STR_INSTALL_FAILED":"V průběhu instalace se vyskytla chyba. Můžete vyjmout a znovu zastrčit USB zařízení a zkusit to znovu. Pro podrobnosti se podívejte do souboru log.txt.",
"STR_UPDATE_SUCCESS":"Gratulujeme!#@Ventoy byla na zařízení úspěšně aktualizována.",
"STR_UPDATE_FAILED":"V průběhu aktualizace se vyskytla chyba. Můžete vyjmout a znovu zastrčit USB zařízení a zkusit to znovu. Pro podrobnosti se podívejte do souboru log.txt.",
"STR_WAIT_PROCESS":"Vlákno běží, prosíme vyčkejte...",
"STR_MENU_OPTION":"Možnosti",
"STR_MENU_SECURE_BOOT":"Secure Boot",
"STR_MENU_PART_CFG":"Konfigurace oddílu",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"zrušení",
"STR_PRESERVE_SPACE":"Zachovejte místo na spodní straně disku",
"STR_SPACE_VAL_INVALID":"Neplatná hodnota pro vyhrazený prostor",
"STR_MENU_CLEAR":"Vymazat Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy has been successfully removed from the device.",
"STR_CLEAR_FAILED":"An error occurred when clear Ventoy from disk. You can replug the USB and try again. Check log.txt for detail.",
"STR_MENU_PART_STYLE":"Styl oddílu",
"STR_DISK_2TB_MBR_ERROR":"Vyberte GPT pro disk přes 2TB",
"STR_SHOW_ALL_DEV":"Zobrazit všechna zařízení",
"STR_PART_ALIGN_4KB":"Zarovnejte oddíly s 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Spanish (Español)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Carlos Sánchez, MELERIX",
"STR_ERROR":"Error",
"STR_WARNING":"Advertencia",
"STR_INFO":"Información",
"STR_INCORRECT_DIR":"¡Por favor, ejecuta bajo el directorio correcto!",
"STR_INCORRECT_TREE_DIR":"No me ejecute aquí, por favor descarga el paquete de instalacion lanzado, y ejecutalo allí.",
"STR_DEVICE":"Dispositivo",
"STR_LOCAL_VER":"Ventoy En Paquete",
"STR_DISK_VER":"Ventoy En Dispositivo",
"STR_STATUS":"Estado - LISTO",
"STR_INSTALL":"Instalar",
"STR_UPDATE":"Actualizar",
"STR_UPDATE_TIP":"La operación de actualización es segura, Los archivo ISO no se modificarán.#@¿Continuar?",
"STR_INSTALL_TIP":"El dispositivo será formateado y todos los datos se perderán.#@¿Continuar?",
"STR_INSTALL_TIP2":"El dispositivo será formateado y todos los datos se perderán.#@¿Continuar? (Doble Comprobación)",
"STR_INSTALL_SUCCESS":"¡Felicitaciones!#@Ventoy ha sido instalado exitosamente en el dispositivo.",
"STR_INSTALL_FAILED":"Ocurrío un error durante la instalación. Puedes reconectar el USB e intentar de nuevo. Comprueba log.txt para detalles.",
"STR_UPDATE_SUCCESS":"¡Felicitaciones!#@Ventoy ha sido actualizado exitosamente en el dispositivo.",
"STR_UPDATE_FAILED":"Ocurrío un error durante la actualización. Puedes reconectar el USB e intentar de nuevo. Comprueba log.txt para detalles.",
"STR_WAIT_PROCESS":"Un hilo está ejecutandose, por favor espera...",
"STR_MENU_OPTION":"Opción",
"STR_MENU_SECURE_BOOT":"Soporte de Arranque Seguro",
"STR_MENU_PART_CFG":"Confirguración de Partición",
"STR_BTN_OK":"ACEPTAR",
"STR_BTN_CANCEL":"Cancelar",
"STR_PRESERVE_SPACE":"Preservar algo de espacio en la parte inferior del dispositivo",
"STR_SPACE_VAL_INVALID":"Valor inválido para espacio preservado",
"STR_MENU_CLEAR":"Limpiar Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy ha sido removido exotosamente desde el dispositivo.",
"STR_CLEAR_FAILED":"Ocurrío un error al limpiar Ventoy desde el dispositivo. Puedes reconectar el USB e intentar de nuevo. Comprueba log.txt para detalle.",
"STR_MENU_PART_STYLE":"Estilo de Partición",
"STR_DISK_2TB_MBR_ERROR":"Por favor selecciona GPT para dispositivos sobre 2TB",
"STR_SHOW_ALL_DEV":"Mostrar todos los dispositivos",
"STR_PART_ALIGN_4KB":"Alinear particiones con 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Russian (Pусский)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"BL4CKH47H4CK3R",
"STR_ERROR":"Ошибка",
"STR_WARNING":"Предупреждение",
"STR_INFO":"Информация",
"STR_INCORRECT_DIR":"Пожалуйста, запустите в другом каталоге!",
"STR_INCORRECT_TREE_DIR":"Не запускайте меня здесь, пожалуйста, загрузите выпущенный установочный пакет и запустите его в другом месте.",
"STR_DEVICE":"Устройство",
"STR_LOCAL_VER":"Ventoy в пакете",
"STR_DISK_VER":"Ventoy на устройстве",
"STR_STATUS":"Статус - ГОТОВ",
"STR_INSTALL":"Установить",
"STR_UPDATE":"Обновить",
"STR_UPDATE_TIP":"Обновление безопасно, ISO-файлы останутся без изменений.#@Продолжить?",
"STR_INSTALL_TIP":"Диск будет отформатирован и все данные будут потеряны.#@Продолжить?",
"STR_INSTALL_TIP2":"Диск будет отформатирован и все данные будут потеряны.#@Вы ДЕЙСТВИТЕЛЬНО хотите продолжить?",
"STR_INSTALL_SUCCESS":"Поздравляем!#@Ventoy был успешно установлен на устройство.",
"STR_INSTALL_FAILED":"Во время установки Ventoy произошла ошибка. Переподключите устройство и попробуйте снова. Проверьте log.txt на ошибки.",
"STR_UPDATE_SUCCESS":"Поздравляем!#@Ventoy был успешно обновлен на устройстве.",
"STR_UPDATE_FAILED":"Во время обновления Ventoy произошла ошибка. Переподключите устройство и попробуйте снова. Проверьте log.txt на ошибки.",
"STR_WAIT_PROCESS":"Процесс запущен, пожалуйста подождите...",
"STR_MENU_OPTION":"Опции",
"STR_MENU_SECURE_BOOT":"Поддержка Secure Boot",
"STR_MENU_PART_CFG":"Дополнительный раздел",
"STR_BTN_OK":"ОК",
"STR_BTN_CANCEL":"Отмена",
"STR_PRESERVE_SPACE":"Создать дополнительный раздел в конце диска",
"STR_SPACE_VAL_INVALID":"Неверное значение размера раздела",
"STR_MENU_CLEAR":"Удалить Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy был успешно удалён с устройства.",
"STR_CLEAR_FAILED":"Во время удаления Ventoy произошла ошибка. Переподключите устройство и попробуйте снова. Проверьте log.txt на ошибки.",
"STR_MENU_PART_STYLE":"Стиль разметки разделов",
"STR_DISK_2TB_MBR_ERROR":"Пожалуйста, выберите GPT для дисков более 2ТБ",
"STR_SHOW_ALL_DEV":"Показать все устройства",
"STR_PART_ALIGN_4KB":"Выровнять разделы с размером 4КБ",
"STR_WEB_COMMUNICATION_ERR":"Ошибка связи:",
"STR_WEB_REMOTE_ABNORMAL":"Ошибка связи: Удаленное соединение недействительно",
"STR_WEB_REQUEST_TIMEOUT":"Ошибка связи: Истекло время ожидания запроса",
"STR_WEB_SERVICE_UNAVAILABLE":"Ошибка связи: Служба недоступна",
"STR_WEB_TOKEN_MISMATCH":"Статус демона обновлен. Повторите попытку позже.",
"STR_WEB_SERVICE_BUSY":"Служба занята, повторите попытку позже.",
"STRXXX":""
},
{
"name":"Bengali (বাংলা)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"BL4CKH47H4CK3R",
"STR_ERROR":"ত্রুটি",
"STR_WARNING":"সতর্কতা",
"STR_INFO":"তথ্য",
"STR_INCORRECT_DIR":"দয়া করে সঠিক ডিরেক্টরিতে চালান!",
"STR_INCORRECT_TREE_DIR":"আমাকে এখানে চালাবেন না, দয়া করে প্রকাশিত ইনস্টল প্যাকেজটি ডাউনলোড করুন এবং সেখানে চালান।",
"STR_DEVICE":"ডিভাইস",
"STR_LOCAL_VER":"Ventoy প্যাকেজে আছে",
"STR_DISK_VER":"Ventoy ডিভাইসে আছে",
"STR_STATUS":"স্থিতি - প্রস্তুত",
"STR_INSTALL":"ইনস্টল করুন",
"STR_UPDATE":"আপডেট করুন",
"STR_UPDATE_TIP":"আপগ্রেড অপারেশন নিরাপদ, ISO ফাইলগুলি অপরিবর্তিত থাকবে।#@চালিয়ে যাবেন?",
"STR_INSTALL_TIP":"ডিস্কটি ফর্ম্যাট করা হবে এবং সমস্ত ডেটা হারিয়ে যাবে।#@চালিয়ে যাবেন?",
"STR_INSTALL_TIP2":"ডিস্কটি ফর্ম্যাট করা হবে এবং সমস্ত ডেটা হারিয়ে যাবে।#@চালিয়ে যাবেন? (পুনঃনিরীক্ষণ)",
"STR_INSTALL_SUCCESS":"অভিনন্দন! #@Ventoy সফলভাবে ডিভাইসে ইনস্টল করা হয়েছে।",
"STR_INSTALL_FAILED":"ইনস্টলেশন চলাকালীন একটি ত্রুটি ঘটেছে। আপনি USB পুনরায় প্লাগ করতে পারেন এবং আবার চেষ্টা করতে পারেন। বিস্তারিত জানার জন্য log.txt পরীক্ষা করুন।",
"STR_UPDATE_SUCCESS":"অভিনন্দন! #@Ventoy সফলভাবে ডিভাইসে আপডেট করা হয়েছে।",
"STR_UPDATE_FAILED":"আপডেটের সময় একটি ত্রুটি ঘটেছে। আপনি USB পুনরায় প্লাগ করতে পারেন এবং আবার চেষ্টা করতে পারেন। বিস্তারিত জানার জন্য log.txt পরীক্ষা করুন।",
"STR_WAIT_PROCESS":"একটি থ্রেড চলছে, দয়া করে অপেক্ষা করুন ...",
"STR_MENU_OPTION":"অপসন",
"STR_MENU_SECURE_BOOT":"নিরাপদ বুট",
"STR_MENU_PART_CFG":"পার্টিশন কনফিগারেশন",
"STR_BTN_OK":"ঠিক আছে",
"STR_BTN_CANCEL":"বাতিল",
"STR_PRESERVE_SPACE":"ডিস্কের নীচে কিছু স্থান সংরক্ষণ করুন",
"STR_SPACE_VAL_INVALID":"সংরক্ষিত জায়গার জন্য অবৈধ মান",
"STR_MENU_CLEAR":"Ventoy সাফ",
"STR_CLEAR_SUCCESS":"Ventoy সফলভাবে ডিভাইস থেকে সরানো হয়েছে।",
"STR_CLEAR_FAILED":"ডিস্ক থেকে Ventoy সাফ করার সময় একটি ত্রুটি ঘটেছে। আপনি USB পুনরায় প্লাগ করতে পারেন এবং আবার চেষ্টা করতে পারেন। বিস্তারিত জানার জন্য log.txt পরীক্ষা করুন।",
"STR_MENU_PART_STYLE":"পার্টিশন স্টাইল",
"STR_DISK_2TB_MBR_ERROR":"2TB এর বেশি ডিস্কের জন্য দয়া করে GPT নির্বাচন করুন",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Hindi (हिन्दी)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"BL4CKH47H4CK3R",
"STR_ERROR":"त्रुटि",
"STR_WARNING":"चेतावनी",
"STR_INFO":"जानकारी",
"STR_INCORRECT_DIR":"कृपया सही निर्देशिका के तहत चलाएं!",
"STR_INCORRECT_TREE_DIR":"मुझे यहां न चलाएं, कृपया जारी किए गए इंस्टॉल पैकेज को डाउनलोड करें, और वहां चलाएं।",
"STR_DEVICE":"डिवाइस",
"STR_LOCAL_VER":"पैकेज में Ventoy",
"STR_DISK_VER":"डिवाइस में Ventoy",
"STR_STATUS":"स्थिति - तैयार",
"STR_INSTALL":"इंस्टॉल",
"STR_UPDATE":"अपडेट करें",
"STR_UPDATE_TIP":"नवीनीकरण ऑपरेशन सुरक्षित है, ISO फाइल अपरिवर्तित रहेंगी।#@जारी रखें?",
"STR_INSTALL_TIP":"डिस्क को स्वरूपित किया जाएगा और सभी डेटा खो जाएगा।#@जारी रखें?",
"STR_INSTALL_TIP2":"डिस्क को स्वरूपित किया जाएगा और सभी डेटा खो जाएगा।#@जारी रखें? (दोहरी जाँच)",
"STR_INSTALL_SUCCESS":"बधाई! #@Ventoy डिवाइस में सफलतापूर्वक स्थापित किया गया है।",
"STR_INSTALL_FAILED":"स्थापना के दौरान एक त्रुटि हुई। आप USB को पुन: स्थापित कर सकते हैं और पुनः प्रयास कर सकते हैं। विस्तार के लिए log.txt की जाँच करें।",
"STR_UPDATE_SUCCESS":"बधाई! #@Ventoy डिवाइस में सफलतापूर्वक अपडेट हो गई है।",
"STR_UPDATE_FAILED":"अपडेट के दौरान एक त्रुटि हुई। आप USB को पुन: भर सकते हैं और पुनः प्रयास कर सकते हैं। विस्तार के लिए log.txt की जाँच करें।",
"STR_WAIT_PROCESS":"एक धागा चल रहा है, कृपया प्रतीक्षा करें ...",
"STR_MENU_OPTION":"विकल्प",
"STR_MENU_SECURE_BOOT":"सुरक्षित बूट",
"STR_MENU_PART_CFG":"विभाजन विन्यास",
"STR_BTN_OK":"ठीक है",
"STR_BTN_CANCEL":"रद्द करना",
"STR_PRESERVE_SPACE":"डिस्क के निचले भाग में कुछ स्थान सुरक्षित रखें",
"STR_SPACE_VAL_INVALID":"आरक्षित स्थान के लिए अमान्य मान",
"STR_MENU_CLEAR":"Ventoy को हटा दें",
"STR_CLEAR_SUCCESS":"डिवाइस से Ventoy को सफलतापूर्वक हटा दिया गया है।",
"STR_CLEAR_FAILED":"डिस्क से Ventoy को साफ़ करते समय एक त्रुटि हुई। आप USB को पुन: भर सकते हैं और पुनः प्रयास कर सकते हैं। विस्तार के लिए log.txt की जाँच करें।",
"STR_MENU_PART_STYLE":"विभाजन शैली",
"STR_DISK_2TB_MBR_ERROR":"कृपया 2TB से अधिक डिस्क के लिए GPT का चयन करें",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Dutch (Nederlands)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"UmitCanbolat",
"STR_ERROR":"Fout",
"STR_WARNING":"Waarschuwing",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Voer Ventoy uit in de juiste directory!",
"STR_INCORRECT_TREE_DIR":"Ventoy kan hier niet worden uitgevoerd. Download het installatiepakket en probeer Ventoy daarmee te starten.",
"STR_DEVICE":"Apparaat",
"STR_LOCAL_VER":"Ventoy in pakket",
"STR_DISK_VER":"Ventoy op apparaat",
"STR_STATUS":"Status - GEREED",
"STR_INSTALL":"Installeren",
"STR_UPDATE":"Bijwerken",
"STR_UPDATE_TIP":"Upgraden is veilig: ISO-bestanden blijven ongewijzigd.#@Doorgaan?",
"STR_INSTALL_TIP":"De schijf wordt geformatteerd en alle gegevens gaan verloren.#@Doorgaan?",
"STR_INSTALL_TIP2":"De schijf wordt geformatteerd en alle gegevens gaan verloren.#@Doorgaan? (Dubbelcheck)",
"STR_INSTALL_SUCCESS":"Gefeliciteerd!#@Ventoy is met succes op het apparaat geïnstalleerd.",
"STR_INSTALL_FAILED":"Er is een fout opgetreden tijdens de installatie. U kunt het apparaat opnieuw aansluiten en het nogmaals proberen. Controleer log.txt voor details.",
"STR_UPDATE_SUCCESS":"Gefeliciteerd!#@Ventoy is succesvol bijgewerkt op het apparaat.",
"STR_UPDATE_FAILED":"Er is een fout opgetreden tijdens de update. U kunt het apparaat opnieuw aansluiten en het nogmaals proberen. Controleer log.txt voor details.",
"STR_WAIT_PROCESS":"Ventoy is nog bezig, even geduld...",
"STR_MENU_OPTION":"Opties",
"STR_MENU_SECURE_BOOT":"Secure Boot",
"STR_MENU_PART_CFG":"Partitieconfiguratie",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Annuleren",
"STR_PRESERVE_SPACE":"Ruimte aan het einde van de schijf reserveren",
"STR_SPACE_VAL_INVALID":"Ongeldige waarde voor gereserveerde ruimte",
"STR_MENU_CLEAR":"Ventoy verwijderen",
"STR_CLEAR_SUCCESS":"Ventoy is succesvol verwijderd van het apparaat.",
"STR_CLEAR_FAILED":"Er is een fout opgetreden bij het verwijderen van Ventoy. U kunt het apparaat opnieuw aansluiten en het nogmaals proberen. Controleer log.txt voor details.",
"STR_MENU_PART_STYLE":"Partitietabel",
"STR_DISK_2TB_MBR_ERROR":"Selecteer GPT als partitietabel voor schijven groter dan 2TB",
"STR_SHOW_ALL_DEV":"Toon alle apparaten",
"STR_PART_ALIGN_4KB":"Lijn partities uit met 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communicatie fout:",
"STR_WEB_REMOTE_ABNORMAL":"Communicatiefout: abnormaal op afstand",
"STR_WEB_REQUEST_TIMEOUT":"Communicatiefout: time-out van verzoek",
"STR_WEB_SERVICE_UNAVAILABLE":"Communicatiefout: service niet beschikbaar",
"STR_WEB_TOKEN_MISMATCH":"Daemon-status bijgewerkt, probeer het later opnieuw.",
"STR_WEB_SERVICE_BUSY":"Service is bezet, probeer het later opnieuw.",
"STRXXX":""
},
{
"name":"Romanian (Română)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"DorinMol",
"STR_ERROR":"Eroare",
"STR_WARNING":"Avertisment",
"STR_INFO":"Informare",
"STR_INCORRECT_DIR":"Vă rugăm executați în directorul corect!",
"STR_INCORRECT_TREE_DIR":"Nu rulați aici, vă rugăm să descărcați pachetul de instalare și executati acolo.",
"STR_DEVICE":"Dispozitiv",
"STR_LOCAL_VER":"Ventoy În Pachet",
"STR_DISK_VER":"Ventoy În Dispozitiv",
"STR_STATUS":"Stare - PREGĂTIT",
"STR_INSTALL":"Instalare",
"STR_UPDATE":"Actualizare",
"STR_UPDATE_TIP":"Operația de actualizare este sigură, fișierele ISO nu vor fi alterate / modificate.#@Continuați?",
"STR_INSTALL_TIP":"Unitatea disc va fi formatată și toate datele vor fi pierdute.#@Continuați?",
"STR_INSTALL_TIP2":"Unitatea disc va fi formatată și toate datele vor fi pierdute.#@Continuați? (Verificare Dublă)",
"STR_INSTALL_SUCCESS":"Felicitări!#@Ventoy a fost instalat cu succes pe dispozitiv.",
"STR_INSTALL_FAILED":"A apărut o eroare în timpul instalării. Reintroduceți dispozitivul USB și încercați din nou. Verificați log.txt pentru detalii.",
"STR_UPDATE_SUCCESS":"Felicitări!#@Ventoy a fost actualizat cu succes pe dispozitiv.",
"STR_UPDATE_FAILED":"A apărut o eroare în timpul actualizării. Reintroduceți dispozitivul USB și încercați din nou. Verificați log.txt pentru detalii.",
"STR_WAIT_PROCESS":"Rulează un fir de execuție, vă rugăm așteptați...",
"STR_MENU_OPTION":"Opțiune",
"STR_MENU_SECURE_BOOT":"Încărcare Sigură",
"STR_MENU_PART_CFG":"Configurare partiție",
"STR_BTN_OK":"O.K",
"STR_BTN_CANCEL":"Anulare",
"STR_PRESERVE_SPACE":"Păstrați puțin spațiu în partea de jos a discului",
"STR_SPACE_VAL_INVALID":"Valoare nevalidă pentru spațiul rezervat",
"STR_MENU_CLEAR":"Clear Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy has been successfully removed from the device.",
"STR_CLEAR_FAILED":"An error occurred when clear Ventoy from disk. You can replug the USB and try again. Check log.txt for detail.",
"STR_MENU_PART_STYLE":"Partition Style",
"STR_DISK_2TB_MBR_ERROR":"Please select GPT for disk over 2TB",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Japanese (日本語)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"taichi eto,Bentnand",
"STR_ERROR":"エラー",
"STR_WARNING":"警告",
"STR_INFO":"情報",
"STR_INCORRECT_DIR":"正しいディレクトリーで実行してください",
"STR_INCORRECT_TREE_DIR":"ここで実行するには、パッケージをインストールしてください。.",
"STR_DEVICE":"デバイス",
"STR_LOCAL_VER":"Ventoy In Package",
"STR_DISK_VER":"Ventoy In Device",
"STR_STATUS":"Status - 準備完了",
"STR_INSTALL":"インストール",
"STR_UPDATE":"更新",
"STR_UPDATE_TIP":"アップグレード可能です、ISOファイルは改変されません。.#@続行?",
"STR_INSTALL_TIP":"選択されたディスクは完全に初期化され、保存されたデータは二度と復元できません。#@続行?",
"STR_INSTALL_TIP2":"選択されたディスクは完全に初期化され、保存されたデータは二度と復元できません。#@続行? (再確認)",
"STR_INSTALL_SUCCESS":"Congratulations!#@Ventoy は正常にインストールされました",
"STR_INSTALL_FAILED":"インストール中にエラーが発生しました。デバイスを再接続してもう一度やり直してください。 詳細ログ log.txt ",
"STR_UPDATE_SUCCESS":"Congratulations!#@Ventoy は正常にアップデートされました.",
"STR_UPDATE_FAILED":"更新中にエラーが発生しました。デバイスを再接続してもう一度やり直してください。. 詳細ログ log.txt",
"STR_WAIT_PROCESS":"処理中...",
"STR_MENU_OPTION":"設定",
"STR_MENU_SECURE_BOOT":"Secure Boot",
"STR_MENU_PART_CFG":"パーティション構成",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"キャンセル",
"STR_PRESERVE_SPACE":"ディスクの下部にある程度のスペースを確保する",
"STR_SPACE_VAL_INVALID":"予約スペースの無効な値",
"STR_MENU_CLEAR":"Ventoyを削除",
"STR_CLEAR_SUCCESS":"Ventoyがディスクから削除されました。",
"STR_CLEAR_FAILED":"Ventoyをディスクから削除できませんでした。USBを再挿入してみてください。 詳細ログ log.txt",
"STR_MENU_PART_STYLE":"パーティションスタイル",
"STR_DISK_2TB_MBR_ERROR":"2TB以上のディスクにはGPTを使用してください。",
"STR_SHOW_ALL_DEV":"すべてのデバイスを表示",
"STR_PART_ALIGN_4KB":"パーティションを4KBに揃える",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"デーモンのステータスが更新されました。しばらくしてから再試行してください。",
"STR_WEB_SERVICE_BUSY":"サービスがビジーです。後で再試行してください。",
"STRXXX":""
},
{
"name":"Italian (Italiano)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"AverageUser2",
"STR_ERROR":"Errore",
"STR_WARNING":"Attenzione",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Si prega di eseguire nella cartella corretta",
"STR_INCORRECT_TREE_DIR":"Non eseguire qui, scarica il pacchetto di installazione ed avvialo",
"STR_DEVICE":"Dispositivo",
"STR_LOCAL_VER":"Versione Ventoy locale",
"STR_DISK_VER":"Ventoy nel dispositivo",
"STR_STATUS":"Stato - PRONTO",
"STR_INSTALL":"Installa",
"STR_UPDATE":"Aggiorna",
"STR_UPDATE_TIP":"L'aggiornamento è sicuro, i file presenti nel dispositivo rimarranno invariati.#@Continue?",
"STR_INSTALL_TIP":"Il disco verrà formattato e tutti i dati saranno persi.#@Continue?",
"STR_INSTALL_TIP2":"Il disco verrà formattato e tutti i dati saranno persi.#@Continue?' (Seconda Verifica)",
"STR_INSTALL_SUCCESS":"Congratulazioni!#@Ventoy è stato installato con successo nel dispositivo",
"STR_INSTALL_FAILED":"Si è verificato un errore durante l'installazione. Reinserisci il dispostivo e riprova. Controlla il file log.txt per i dettagli.",
"STR_UPDATE_SUCCESS":"Congratulazioni!#@Ventoy è stato aggiornato con successo nel dispositivo",
"STR_UPDATE_FAILED":"Si è verificato un errore durante l'aggiornamento. Reinserisci il dispostivo e riprova. Controlla il file log.txt per i dettagli.",
"STR_WAIT_PROCESS":"Un processo è in esecuzione, attendere prego...",
"STR_MENU_OPTION":"Opzioni",
"STR_MENU_SECURE_BOOT":"Avvio protetto (secure boot)",
"STR_MENU_PART_CFG":"Configurazione della partizione",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Annulla",
"STR_PRESERVE_SPACE":"Conserva spazio nella parte finale del disco",
"STR_SPACE_VAL_INVALID":"Quantità di spazio da riservare non valida",
"STR_MENU_CLEAR":"Rimuovi Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy è stato rimosso con successo dal dispositivo.",
"STR_CLEAR_FAILED":"Si è verificato un errore durante la rimozione di Ventoy dal dispositivo. Reinserisci il dispositivo e riprova. Controlla il file log.txt per maggiori dettagli",
"STR_MENU_PART_STYLE":"Stile Tabella delle partizioni",
"STR_DISK_2TB_MBR_ERROR":"Seleziona GPT per dischi con dimensioni maggiori di 2TB",
"STR_SHOW_ALL_DEV":"Mostra tutti i dispositivi",
"STR_PART_ALIGN_4KB":"Allinea le partizioni con 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Croatian (Hrvatski)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Valnjes",
"STR_ERROR":"Pogreška",
"STR_WARNING":"Upozorenje",
"STR_INFO":"Informacija",
"STR_INCORRECT_DIR":"Molim vas pokrenite unutar pravog direktorija!",
"STR_INCORRECT_TREE_DIR":"Ne pokrećite me ovdje, molim vas downloadajte poslijednju verziju, te ponovno pokrenite!",
"STR_DEVICE":"Uređaj",
"STR_LOCAL_VER":"Ventoy (lokalni)",
"STR_DISK_VER":"Ventoy (na uređaju)",
"STR_STATUS":"Status - SPREMAN",
"STR_INSTALL":"Instaliraj",
"STR_UPDATE":"Ažuriraj",
"STR_UPDATE_TIP":"Nadogradnja je sigurna, ISO datoteke neće biti promjenjene.#@Nastaviti?",
"STR_INSTALL_TIP":"USB disk će biti formatiran i svi podatci će biti izgubljeni!#@Nastaviti?",
"STR_INSTALL_TIP2":"USB disk će biti formatiran i svi podatci će biti izgubljeni!#@Nastaviti? (Dodatna provjera)",
"STR_INSTALL_SUCCESS":"Čestitam!#@Ventoy je uspješno instaliran na vaš uređaj.",
"STR_INSTALL_FAILED":"Dogodila se pogreška tokom instalacije. Pokušajte ponovno spojiti USB i pokušati ponovno. Provjerite log.txt za više detalja o nastaloj pogrešci.",
"STR_UPDATE_SUCCESS":"Čestitam!#@Ventoy je uspješno ažuriran na vašem uređaju.",
"STR_UPDATE_FAILED":"Dogodila se pogreška tokom ažuriranja. Pokušajte ponovno spojiti USB i pokušati ponovno. Provjerite log.txt za više detalja o nastaloj pogrešci.",
"STR_WAIT_PROCESS":"Instanca je vec pokrenuta, molimo vas pričekajte...",
"STR_MENU_OPTION":"Opcije",
"STR_MENU_SECURE_BOOT":"Secure Boot",
"STR_MENU_PART_CFG":"Konfiguracija particije",
"STR_BTN_OK":"u redu",
"STR_BTN_CANCEL":"Otkazati",
"STR_PRESERVE_SPACE":"Sačuvajte malo prostora na dnu diska",
"STR_SPACE_VAL_INVALID":"Nevažeća vrijednost rezerviranog prostora",
"STR_MENU_CLEAR":"Obriši Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy je uspesno obrisan sa uređaja",
"STR_CLEAR_FAILED":"Dogodila se greška tokom brisanja Ventoy sa diska. Možeš ponovo ubacit USB i pokušati opet. Pogledaj log.txt za još detalja.",
"STR_MENU_PART_STYLE":"Stil particija",
"STR_DISK_2TB_MBR_ERROR":"Molim te, koristi GPT za diskove preko 2TB",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Hungarian (Magyar)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Bitfarago",
"STR_ERROR":"Hiba",
"STR_WARNING":"Figyelem",
"STR_INFO":"Infó",
"STR_INCORRECT_DIR":"Kérjük, futtasd a megfelelő könyvtárból!",
"STR_INCORRECT_TREE_DIR":"Ne futtasd innen. Töltsd le a kiadott telepítőcsomagot és onnan futtasd.",
"STR_DEVICE":"Eszköz",
"STR_LOCAL_VER":"Ventoy a csomagban",
"STR_DISK_VER":"Ventoy az eszközön",
"STR_STATUS":"Állapot - KÉSZ",
"STR_INSTALL":"Telepítés",
"STR_UPDATE":"Frissítés",
"STR_UPDATE_TIP":"A frissítés biztonságos, az ISO fájlok nem változnak.#@Folytatod?",
"STR_INSTALL_TIP":"A meghajtó formázva lesz és minden rajta lévő adat elveszik.#@Folytatod?",
"STR_INSTALL_TIP2":"A meghajtó formázva lesz és minden rajta lévő adat elveszik.#@Folytatod? (Második jóváhagyás)",
"STR_INSTALL_SUCCESS":"Gratulálunk!#@A Ventoy sikeresen telepítve lett az eszközön.",
"STR_INSTALL_FAILED":"Hiba történt a telepítés során. Csatlakoztasd újra az USB eszközt, és próbáld újra.#@A részleteket lásd a log.txt fájlban.",
"STR_UPDATE_SUCCESS":"Gratulálunk!#@A Ventoy sikeresen frissítve lett az eszközön.",
"STR_UPDATE_FAILED":"Hiba történt a frissítés során. Csatlakoztasd újra az USB eszközt, és próbáld újra.#@A részleteket lásd a log.txt fájlban.",
"STR_WAIT_PROCESS":"A feldolgozás még folyamatban van, kérlek várj...",
"STR_MENU_OPTION":"Opció",
"STR_MENU_SECURE_BOOT":"Biztonsági mód (Secure Boot)",
"STR_MENU_PART_CFG":"Partíciókonfiguráció",
"STR_BTN_OK":"rendben",
"STR_BTN_CANCEL":"Megszünteti",
"STR_PRESERVE_SPACE":"Tartson szabad helyet a lemez alján",
"STR_SPACE_VAL_INVALID":"A fenntartott hely érvénytelen értéke",
"STR_MENU_CLEAR":"Clear Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy has been successfully removed from the device.",
"STR_CLEAR_FAILED":"An error occurred when clear Ventoy from disk. You can replug the USB and try again. Check log.txt for detail.",
"STR_MENU_PART_STYLE":"Partition Style",
"STR_DISK_2TB_MBR_ERROR":"Please select GPT for disk over 2TB",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Chinese Traditional (繁體中文)",
"FontFamily":"新細明體",
"FontSize":14,
"Author":"penut85420",
"STR_ERROR":"錯誤",
"STR_WARNING":"警告",
"STR_INFO":"提醒",
"STR_INCORRECT_DIR":"請在正確的資料夾下開啟!",
"STR_INCORRECT_TREE_DIR":"請下載並使用發行版本的安裝包",
"STR_DEVICE":"裝置",
"STR_LOCAL_VER":"當前 Ventoy 版本",
"STR_DISK_VER":"裝置內部的 Ventoy 版本",
"STR_STATUS":"狀態 - 準備就緒",
"STR_INSTALL":"安裝",
"STR_UPDATE":"升級",
"STR_UPDATE_TIP":"升級操作是安全的,磁碟內的 ISO 文件不會被清除#@是否繼續?",
"STR_INSTALL_TIP":"磁碟將會被格式化,所有內容將會被清除!#@是否繼續?",
"STR_INSTALL_TIP2":"磁碟將會被格式化,所有內容將會被清除!#@再次確認是否繼續?",
"STR_INSTALL_SUCCESS":"恭喜,Ventoy 已經成功安裝到此裝置中!",
"STR_INSTALL_FAILED":"安裝 Ventoy 的過程中發生錯誤,請重新插入磁碟並重試一次,詳細訊息請調閱 log.txt 文件。",
"STR_UPDATE_SUCCESS":"恭喜,新版本的 Ventoy 已經成功更新到此裝置中!",
"STR_UPDATE_FAILED":"更新 Ventoy 的過程中發生錯誤,請重新插入磁碟並重試一次,詳細訊息請調閱 log.txt 文件。",
"STR_WAIT_PROCESS":"目前有執行緒正在運作中,請稍候",
"STR_MENU_OPTION":"選項",
"STR_MENU_SECURE_BOOT":"支援 Secure Boot",
"STR_MENU_PART_CFG":"分區配置",
"STR_BTN_OK":"確定",
"STR_BTN_CANCEL":"取消",
"STR_PRESERVE_SPACE":"在磁盤最後保留一部分空間",
"STR_SPACE_VAL_INVALID":"保留空間的大小不合法",
"STR_MENU_CLEAR":"清除Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy已成功從設備中清除",
"STR_CLEAR_FAILED":"清除 Ventoy 的過程中發生錯誤,請重新插入磁碟並重試一次,詳細訊息請調閱 log.txt 文件。",
"STR_MENU_PART_STYLE":"分區格式",
"STR_DISK_2TB_MBR_ERROR":"對於超過2TB的磁片請選擇GPT分區格式",
"STR_SHOW_ALL_DEV":"顯示所有設備",
"STR_PART_ALIGN_4KB":"分區按照4KB對齊",
"STR_WEB_COMMUNICATION_ERR":"通信錯誤:",
"STR_WEB_REMOTE_ABNORMAL":"通信錯誤: 服務端異常",
"STR_WEB_REQUEST_TIMEOUT":"通信錯誤: 請求超時",
"STR_WEB_SERVICE_UNAVAILABLE":"通信錯誤: 服務不可用",
"STR_WEB_TOKEN_MISMATCH":"服務狀態已更新",
"STR_WEB_SERVICE_BUSY":"服務正忙,請稍後重試",
"STRXXX":""
},
{
"name":"Serbian Latin (Srpski)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Bojan Maksimović, panickingkernel, Zoran Jankov",
"STR_ERROR":"Greška",
"STR_WARNING":"Upozorenje",
"STR_INFO":"Informacija",
"STR_INCORRECT_DIR":"Molim Vas, pokrenite ме u pravom direktorijumu!",
"STR_INCORRECT_TREE_DIR":"Nemojте me pokretati ovde, molim Vas preuzmite objavljeni instalacioni paket i pokrenite me tamo.",
"STR_DEVICE":"Uređaj",
"STR_LOCAL_VER":"Ventoy u paketu",
"STR_DISK_VER":"Ventoy u uređaju",
"STR_STATUS":"Status - SPREMAN",
"STR_INSTALL":"Instaliraj",
"STR_UPDATE":"Nadogradi",
"STR_UPDATE_TIP":"Nadogradnja je sigurna, ISO fajlovi neće biti promenjeni.#@Nastavi?",
"STR_INSTALL_TIP":"Disk će biti formatiran i svi podaci će biti izgubljeni.#@Nastavi?",
"STR_INSTALL_TIP2":"Disk će biti formatiran i svi podaci će biti izgubljeni.#@Nastavi? (Dvostruka provera)",
"STR_INSTALL_SUCCESS":"Čestitam!#@Ventoy je uspešno instaliran na ovom uređaju.",
"STR_INSTALL_FAILED":"Dogodila se greška tokom instalacije. Možete izvaditi i ponovo ubaciti USB, pa pokušati opet. Pogledajte log.txt za još detalja.",
"STR_UPDATE_SUCCESS":"Čestitam!#@Ventoy je uspešno nadograđen na ovom uređaju.",
"STR_UPDATE_FAILED":"Dogodila se greška prilikom nadogradnje. Možeте izvaditi i ponovo ubaciti USB, pa pokušati opet. Pogledajte log.txt za još detalja.",
"STR_WAIT_PROCESS":"Odvija se operacija, molim Vas sačekajte...",
"STR_MENU_OPTION":"Opcije",
"STR_MENU_SECURE_BOOT":"Sigurno uključivanje je podržano",
"STR_MENU_PART_CFG":"Konfiguracija particija",
"STR_BTN_OK":"U redu",
"STR_BTN_CANCEL":"Otkaži",
"STR_PRESERVE_SPACE":"Sačuvaj nešto prostora na kraju diska",
"STR_SPACE_VAL_INVALID":"Neispravna vrednost za prezervirani prostor",
"STR_MENU_CLEAR":"Obriši Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy je uspešno obrisan sa uređaja",
"STR_CLEAR_FAILED":"Dogodila se greška tokom brisanja Ventoy sa diska. Možete ponovo ubaciti USB i pokušati opet. Pogledajte log.txt za još detalja.",
"STR_MENU_PART_STYLE":"Stil particija",
"STR_DISK_2TB_MBR_ERROR":"Molim Vas, izaberite GPT za diskove preko 2TB",
"STR_SHOW_ALL_DEV":"Pokaži sve uređaje",
"STR_PART_ALIGN_4KB":"Poravnajte sve particije sa 4KB",
"STR_WEB_COMMUNICATION_ERR":"Greška u komunikaciji:",
"STR_WEB_REMOTE_ABNORMAL":"Greška u komunikaciji: nenormalno daljinsko upravljanje",
"STR_WEB_REQUEST_TIMEOUT":"Greška u komunikaciji: Zahtev je istekao",
"STR_WEB_SERVICE_UNAVAILABLE":"Greška u komunikaciji: Servis nije dostupan",
"STR_WEB_TOKEN_MISMATCH":"Status demona ažuriran, pokušajte ponovo kasnije.",
"STR_WEB_SERVICE_BUSY":"Servis je zauzet, pokušajte ponovo kasnije.",
"STRXXX":""
},
{
"name":"Serbian Cyrillic (Српски)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Bojan Maksimović, panickingkernel, Zoran Jankov",
"STR_ERROR":"Грешка",
"STR_WARNING":"Упозорење",
"STR_INFO":"Информација",
"STR_INCORRECT_DIR":"Молим Вас, покрените ме у правом директоријуму!",
"STR_INCORRECT_TREE_DIR":"Немојте ме покретати овде, молим Вас преузмите објављени инсталациони пакет и покрените ме тамо.",
"STR_DEVICE":"Уређај",
"STR_LOCAL_VER":"Ventoy у пакету",
"STR_DISK_VER":"Ventoy у уређају",
"STR_STATUS":"Статус - СПРЕМАН",
"STR_INSTALL":"Инсталирај",
"STR_UPDATE":"Надогради",
"STR_UPDATE_TIP":"Надоградња је сигурна, ISO фајлови неће бити промењени.#@Настави?",
"STR_INSTALL_TIP":"Диск ће бити форматиран и сви подаци ће бити изгубљени.#@Настави?",
"STR_INSTALL_TIP2":"Диск ће бити форматиран и сви подаци ће бити изгубљени.#@Настави? (Двострука провера)",
"STR_INSTALL_SUCCESS":"Честитам!#@Ventoy је успешно инсталиран на овом уређају.",
"STR_INSTALL_FAILED":"Догодила се грешка током инсталације. Можете извадити и поново убацити USB, па покушати опет. Погледајте log.txt за још детаља.",
"STR_UPDATE_SUCCESS":"Честитам!#@Ventoy је био успешно надограђен на овом уређају.",
"STR_UPDATE_FAILED":"Догодила се грешка током надоградње. Можете извадити и поново убацити USB, па покушати опет. Погледајте log.txt за још детаља.",
"STR_WAIT_PROCESS":"Одвија се операција, молим Вас сачекајте...",
"STR_MENU_OPTION":"Опције",
"STR_MENU_SECURE_BOOT":"Сигурно уклјучиванје је подржано",
"STR_MENU_PART_CFG":"Конфигурација партиција",
"STR_BTN_OK":"У реду",
"STR_BTN_CANCEL":"Откажи",
"STR_PRESERVE_SPACE":"Саћувај нешто простора на крају диска",
"STR_SPACE_VAL_INVALID":"Неисправна вредност за презервирани простор",
"STR_MENU_CLEAR":"Обриши Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy је успешно обрисан са уређаја",
"STR_CLEAR_FAILED":"Можете поново убацити USB и покушати опет. Погледајте log.txt за још детаља.",
"STR_MENU_PART_STYLE":"Стил партиција",
"STR_DISK_2TB_MBR_ERROR":"Молим Вас, изаберите GPT за дискове преко 2ТB",
"STR_SHOW_ALL_DEV":"Прикажи све уређаје",
"STR_PART_ALIGN_4KB":"Поравнајте партиције са 4KB",
"STR_WEB_COMMUNICATION_ERR":"Комуникациона грешка:",
"STR_WEB_REMOTE_ABNORMAL":"Комуникациона грешка: ненормално даљинско управљање",
"STR_WEB_REQUEST_TIMEOUT":"Комуникациона грешка: Захтев је истекао",
"STR_WEB_SERVICE_UNAVAILABLE":"Комуникациона грешка: Сервис је недоступан",
"STR_WEB_TOKEN_MISMATCH":"Статус демона ажуриран, покушајте поново касније.",
"STR_WEB_SERVICE_BUSY":"Севис је заузет, покушајте поново касније.",
"STRXXX":""
},
{
"name":"Thai (ไทย)",
"FontFamily":"Courier New",
"FontSize":17,
"Author":"longpanda",
"STR_ERROR":"ผิดพลาด",
"STR_WARNING":"คำเตือน",
"STR_INFO":"ข้อมูล",
"STR_INCORRECT_DIR":"กรุณาเรียกใช้ในอุปกรณ์ที่ถูกต้อง!",
"STR_INCORRECT_TREE_DIR":"อย่าติดตั้งในนี้, โปรดดาวน์โหลดและใช้แพ็คเกจการติดตั้งของรุ่นที่วางจำหน่าย",
"STR_DEVICE":"อุปกรณ์",
"STR_LOCAL_VER":"เวอร์ชั่น Ventoy ",
"STR_DISK_VER":"ลง Ventoy ในอุปกรณ์",
"STR_STATUS":"สถานะ - พร้อม",
"STR_INSTALL":"ติดตั้ง",
"STR_UPDATE":"ปรับปรุง",
"STR_UPDATE_TIP":"การดำเนินการอัปเกรดปลอดภัย, ไฟล์ ISO จะไม่มีการเปลี่ยนแปลง.#@ต่อเนื่อง?",
"STR_INSTALL_TIP":"ดิสก์จะถูกฟอร์แมตและข้อมูลทั้งหมดจะสูญหาย.#@ต่อเนื่อง?",
"STR_INSTALL_TIP2":"ดิสก์จะถูกฟอร์แมตและข้อมูลทั้งหมดจะสูญหาย#@ต่อเนื่อง? (ตรวจสอบอีกครั้ง)",
"STR_INSTALL_SUCCESS":"ขอแสดงความยินดี!#@Ventoy ติดตั้งไปยังอุปกรณ์สำเร็จแล้ว",
"STR_INSTALL_FAILED":"เกิดข้อผิดพลาดระหว่างการติดตั้ง. คุณสามารถถอด USB และลองอีกครั้ง. ตรวจสอบรายละเอียดได้ที่ log.txt.",
"STR_UPDATE_SUCCESS":"ขอแสดงความยินดี!#@Ventoy อัปเดตไปยังอุปกรณ์สำเร็จแล้ว.",
"STR_UPDATE_FAILED":"เกิดข้อผิดพลาดระหว่างการอัพเดต. คุณสามารถถอด USB และลองอีกครั้ง. ตรวจสอบรายละเอียดได้ที่ log.txt.",
"STR_WAIT_PROCESS":"CPU กำลังทำงานอยู่,ได้โปรดรอ...",
"STR_MENU_OPTION":"ตัวเลือก",
"STR_MENU_SECURE_BOOT":"สนับสนุนการบูตที่ปลอดภัย",
"STR_MENU_PART_CFG":"กำหนดค่าพาร์ติชัน",
"STR_BTN_OK":"ตกลง",
"STR_BTN_CANCEL":"ยกเลิก",
"STR_PRESERVE_SPACE":"เก็บพื้นที่บางส่วนของอุปกรณ์ไว้",
"STR_SPACE_VAL_INVALID":"มีปัญหาสำหรับพื้นที่ที่สงวนไว้(กรุณา ฟอร์แมต และติดตั้งใหม่)",
"STR_MENU_CLEAR":"Clear Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy has been successfully removed from the device.",
"STR_CLEAR_FAILED":"An error occurred when clear Ventoy from disk. You can replug the USB and try again. Check log.txt for detail.",
"STR_MENU_PART_STYLE":"Partition Style",
"STR_DISK_2TB_MBR_ERROR":"Please select GPT for disk over 2TB",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Norwegian (Norsk)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Stein-Ove Bøthun",
"STR_ERROR":"Feil",
"STR_WARNING":"Advarsel",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Vennligst kjør fra den riktige mappen!",
"STR_INCORRECT_TREE_DIR":"Ikke kjør meg her, vennligst last ned den utgitte installasjonspakken og kjør den der.",
"STR_DEVICE":"Enhet",
"STR_LOCAL_VER":"Ventoy i Pakken",
"STR_DISK_VER":"Ventoy på Enheten",
"STR_STATUS":"Status - KLAR",
"STR_INSTALL":"Installer",
"STR_UPDATE":"Oppdater",
"STR_UPDATE_TIP":"Oppgraderingen er trygg, ISO-filene vil være uendret.#@Fortsette?",
"STR_INSTALL_TIP":"Disken blir formatert og alle dataene vil gå tapt.#@Fortsette?",
"STR_INSTALL_TIP2":"Disken blir formatert og alle dataene vil gå tapt.#@Fortsette? (Dobbelsjekk)",
"STR_INSTALL_SUCCESS":"Gratulerer!#@Ventoy er blitt installert på enheten.",
"STR_INSTALL_FAILED":"Det oppstod en feil under installasjonen. Du kan koble til USB-en på nytt og prøve igjen. Check log.txt for flere detaljer.",
"STR_UPDATE_SUCCESS":"Gratulerer!#@Ventoy har blitt oppdatert på enheten.",
"STR_UPDATE_FAILED":"Det oppstod en feil under oppdateringen. Du kan koble til USB-en på nytt og prøve igjen. Se log.txt for flere detaljer.",
"STR_WAIT_PROCESS":"En prosess kjører, vennligst vent...",
"STR_MENU_OPTION":"Alternativ",
"STR_MENU_SECURE_BOOT":"Støtte for sikker oppstart",
"STR_MENU_PART_CFG":"Partisjonskonfigirasjon",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Avbryt",
"STR_PRESERVE_SPACE":"Bevar litt plass på bunnen av disken",
"STR_SPACE_VAL_INVALID":"Ugyldig verdi for reservert plass",
"STR_MENU_CLEAR":"Fjern Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy er blitt fjernet fra enheten.",
"STR_CLEAR_FAILED":"Det oppstod en feil da Ventoy bler fjernet fra disken. Du kan koble til USB-en på nytt og prøve igjen. Sjekk log.txt for flere detaljer.",
"STR_MENU_PART_STYLE":"Partisjonsstil",
"STR_DISK_2TB_MBR_ERROR":"Velg GPT for disker over 2 TB",
"STR_SHOW_ALL_DEV":"Vis alle enheter",
"STR_PART_ALIGN_4KB":"Juster partisjoner med 4KB",
"STR_WEB_COMMUNICATION_ERR":"Kommunikasjonsfeil:",
"STR_WEB_REMOTE_ABNORMAL":"Kommunokasjonsfeil: unormalt fjerntliggende",
"STR_WEB_REQUEST_TIMEOUT":"Kommunikasjonsfeil: Forespørselen ble tidsavbrutt",
"STR_WEB_SERVICE_UNAVAILABLE":"Kommunikasjonsfeil: Tjeneste utilgjengelig",
"STR_WEB_TOKEN_MISMATCH":"Daemon status er oppdatert, vennligst prøv igjen senere.",
"STR_WEB_SERVICE_BUSY":"Tjenesten er opptatt, vennligst prøv igjen senere.",
"STRXXX":""
},
{
"name":"Vietnamese (Tiếng Việt)",
"FontFamily":"Tahoma",
"FontSize":14,
"Author":"Nguyen Quoc Hoang - cuumay.com",
"STR_ERROR":"Lỗi",
"STR_WARNING":"Cảnh báo",
"STR_INFO":"Thông tin",
"STR_INCORRECT_DIR":"Vui lòng chạy Ventoy2Disk tại đúng thư mục của nó !",
"STR_INCORRECT_TREE_DIR":"Không được chạy Ventoy2Disk ở đây, vui lòng tải gói cài đặt đã phát hành và chạy ở đó.",
"STR_DEVICE":"Thiết bị",
"STR_LOCAL_VER":"Phiên bản Ventoy",
"STR_DISK_VER":"Phiên bản Ventoy ở thiết bị",
"STR_STATUS":"Trạng thái - SẴN SÀNG",
"STR_INSTALL":"Cài đặt",
"STR_UPDATE":"Cập nhật",
"STR_UPDATE_TIP":"Việc cập nhật Ventoy là an toàn, các tập tin ISO của bạn sẽ được giữ nguyên trạng.#@ Bạn thật sự muốn tiếp tục ?.",
"STR_INSTALL_TIP":"Thiết bị sẽ được định dạng và do đó TẤT CẢ DỮ LIỆU trên thiết bị sẽ bị mất.#@ Bạn thật sự muốn tiếp tục ?.",
"STR_INSTALL_TIP2":"Thiết bị sẽ được định dạng và do đó TẤT CẢ DỮ LIỆU trên thiết bị sẽ bị mất.#@ Bạn thật sự muốn tiếp tục ?. (Xác nhận lần hai)",
"STR_INSTALL_SUCCESS":"Chúc mừng bạn !.#@ Thiết bị đã được cài Ventoy thành công.",
"STR_INSTALL_FAILED":"Đã xảy ra lỗi trong quá trình cài đặt Ventoy. Bạn có thể rút thiết bị ra và thử lại. Xem chi tiết ở tệp log.txt.",
"STR_UPDATE_SUCCESS":"Chúc mừng bạn !.#@ Thiết bị đã được cập nhật Ventoy thành công.",
"STR_UPDATE_FAILED":"Đã xảy ra lỗi trong quá trình cập nhật Ventoy. Bạn có thể rút thiết bị ra và thử lại. Xem chi tiết ở tệp log.txt.",
"STR_WAIT_PROCESS":"Một luồng xử lý đang chạy, vui lòng chờ...",
"STR_MENU_OPTION":"Tùy chọn",
"STR_MENU_SECURE_BOOT":"Bật hỗ trợ Secure Boot",
"STR_MENU_PART_CFG":"Cấu hình phân vùng",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Hủy",
"STR_PRESERVE_SPACE":"Giữ lại phần dung lượng ở cuối thiết bị",
"STR_SPACE_VAL_INVALID":"Giá trị dung lượng giữ lại không hợp lệ.",
"STR_MENU_CLEAR":"Gỡ bỏ Ventoy",
"STR_CLEAR_SUCCESS":"Chúc mừng bạn !.#@ Thiết bị đã được gỡ bỏ Ventoy thành công.",
"STR_CLEAR_FAILED":"Đã xảy ra lỗi trong quá trình gỡ bỏ Ventoy. Bạn có thể rút thiết bị ra và thử lại. Xem chi tiết ở tệp log.txt.",
"STR_MENU_PART_STYLE":"Kiểu phân vùng",
"STR_DISK_2TB_MBR_ERROR":"Thiết bị có dung lượng lớn hơn 2TB. Vui lòng chọn Kiểu phân vùng là GPT.",
"STR_SHOW_ALL_DEV":"Hiện tất cả Thiết bị",
"STR_PART_ALIGN_4KB":"Căn chỉnh phân vùng với 4KB",
"STR_WEB_COMMUNICATION_ERR":"Lỗi giao tiếp:",
"STR_WEB_REMOTE_ABNORMAL":"Lỗi giao tiếp: Remote bất thường",
"STR_WEB_REQUEST_TIMEOUT":"Lỗi giao tiếp: Yêu cầu đã hết thời gian chờ",
"STR_WEB_SERVICE_UNAVAILABLE":"Lỗi giao tiếp: Dịch vụ không sẵn có",
"STR_WEB_TOKEN_MISMATCH":"Đã cập nhật trạng thái Daemon, vui lòng thử lại sau.",
"STR_WEB_SERVICE_BUSY":"Dịch vụ bận, vui lòng thử lại sau.",
"STRXXX":""
},
{
"name":"Lithuanian (Lietuvių)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"r0manas",
"STR_ERROR ":"Klaida",
"STR_WARNING ":"Įspėjimas",
"STR_INFO ":"Informacija",
"STR_INCORRECT_DIR ":"Prašome paleisti teisingame kataloge!",
"STR_INCORRECT_TREE_DIR ":"Nepaleiskite manęs čia, atsisiųskite išleistą diegimo paketą ir paleiskite ten.",
"STR_DEVICE ":"Įrenginys",
"STR_LOCAL_VER ":"„Ventoy“ versija pakuotėje",
"STR_DISK_VER ":"„Ventoy“ versija įrenginyje",
"STR_STATUS ":"Būsena - PASIRENGĘS",
"STR_INSTALL ":"Įdiegti",
"STR_UPDATE ":"Atnaujinti",
"STR_UPDATE_TIP ":"Atnaujinti - saugu, ISO failai liks nepažeisti.#@Tęsti?",
"STR_INSTALL_TIP ":"Įrenginys bus suformatuotas ir visi duomenys bus prarasti.#@Tęsti?",
"STR_INSTALL_TIP2 ":"Įrenginys bus suformatuotas ir visi duomenys bus prarasti.#@Tęsti? (TIKRAI TĘSTI?)",
"STR_INSTALL_SUCCESS ":"Sveikinu!#@Ventoy sėkmingai įdiegtas įrenginyje.",
"STR_INSTALL_FAILED ":"Diegimo metu įvyko klaida. Galite iš naujo prijungti USB ir bandyti dar kartą. Patikrinkite log.txt, jei norite sužinoti daugiau.",
"STR_UPDATE_SUCCESS ":"Sveikinu!#@Ventoy sėkmingai atnaujintas įrenginyje.",
"STR_UPDATE_FAILED ":"Atnaujinant įvyko klaida. Galite iš naujo prijungti USB ir bandyti dar kartą. Patikrinkite log.txt, jei norite sužinoti daugiau.",
"STR_WAIT_PROCESS ":"Pradėtas procesas, palaukite ...",
"STR_MENU_OPTION ":"Nustatymai",
"STR_MENU_SECURE_BOOT ":"Secure Boot palaikymas",
"STR_MENU_PART_CFG ":"Skirsnio konfigūracija",
"STR_BTN_OK ":"Gerai",
"STR_BTN_CANCEL ":"Atšaukti",
"STR_PRESERVE_SPACE ":"Rezervuoti vietos įrenginyje",
"STR_SPACE_VAL_INVALID ":"Neteisinga rezervuotos vietos vertė",
"STR_MENU_CLEAR ":"Pašalinti „Ventoy“",
"STR_CLEAR_SUCCESS ":"„Ventoy“ sėkmingai pašalintas iš įrenginio.",
"STR_CLEAR_FAILED ":"Įvyko klaida pašalinant „Ventoy“ iš įrenginio. USB ir bandyti dar kartą. Patikrinkite log.txt, jei norite sužinoti daugiau.",
"STR_MENU_PART_STYLE ":"Skirsnio formatas",
"STR_DISK_2TB_MBR_ERROR ":"Prašome pasirinkti GPT, jei įrenginys didesnis nei 2 TB.",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Macedonian (Македонски)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Влатко Стојанов",
"STR_ERROR":"Грешка",
"STR_WARNING":"Предупредување",
"STR_INFO":"Инфо",
"STR_INCORRECT_DIR":"Ве молам покренете ме коректниот фолдер!",
"STR_INCORRECT_TREE_DIR":"Не покренувајте ме овде, ве молам превземете ја последната верзија и покренете ме таму.",
"STR_DEVICE":"Уред",
"STR_LOCAL_VER":"Ventoy Во Пакетот",
"STR_DISK_VER":"Ventoy Во Уредот",
"STR_STATUS":"Статус - Спремен",
"STR_INSTALL":"Инсталирај",
"STR_UPDATE":"Ажурирај",
"STR_UPDATE_TIP":"Операцијата ажурирање е безбедна, ISO датотеките нема да бидат променети.#@Продолжи?",
"STR_INSTALL_TIP":"УСБ дискот ќе биде форматиран и сите податоци ќе бидат уништени.#@Продолжи?",
"STR_INSTALL_TIP2":"УСБ дискот ќе биде форматиран и сите податоци ќе бидат уништени.#@Продолжи? (Двојна проверка)",
"STR_INSTALL_SUCCESS":"Честитки!#@Ventoy е успешно инсталиран на уредот.",
"STR_INSTALL_FAILED":"Се појави грешка при инсталацијата. Отстранете го УСБ драјвот и пробајте повторно. Проверете го log.txt за детали.",
"STR_UPDATE_SUCCESS":"Честитки!#@Ventoy е успешно ажуриран на уредот.",
"STR_UPDATE_FAILED":"Се појави грешка при ажурирањето. Отстранете го УСБ драјвот и пробајте повторно. Проверете го log.txt за детали.",
"STR_WAIT_PROCESS":"Процесот е вклучен, ве молиме почекајте...",
"STR_MENU_OPTION":"Опции",
"STR_MENU_SECURE_BOOT":"Secure Boot Поддршка",
"STR_MENU_PART_CFG":"Конфигурирање на партиции",
"STR_BTN_OK":"ОК",
"STR_BTN_CANCEL":"Излез",
"STR_PRESERVE_SPACE":"Резервирај место на крајот на дискот",
"STR_SPACE_VAL_INVALID":"Невалидна вредност за резервираното место",
"STR_MENU_CLEAR":"Отстрани го Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy е успешно отстранет од уредот.",
"STR_CLEAR_FAILED":"Се појави грешка при отстранувањето на Ventoy од уредот. Отстранете го УСБ драјвот и пробајте повторно. Проверете го log.txt за детали.",
"STR_MENU_PART_STYLE":"Тип на партиција",
"STR_DISK_2TB_MBR_ERROR":"Ве молиме изберете GPT за дискови поголеми од 2TB",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Hebrew (עברית)",
"FontFamily":"tahoma",
"FontSize":16,
"Author":"chaim-chv",
"STR_ERROR":"תקלה",
"STR_WARNING":"אזהרה",
"STR_INFO":"מידע",
"STR_INCORRECT_DIR":"הרץ בבקשה בתיקייה הנכונה!",
"STR_INCORRECT_TREE_DIR":"אל תריץ אותי כאן. בבקשה הורד את חבילת ההתקנה ששוחררה, ותריץ אותי שם.",
"STR_DEVICE":"התקן",
"STR_LOCAL_VER":"גרסת Ventoy מקומית",
"STR_DISK_VER":"גרסת Ventoy בהתקן",
"STR_STATUS":"סטטוס - מוכן",
"STR_INSTALL":"התקנה",
"STR_UPDATE":"עדכון",
"STR_UPDATE_TIP":"אופציית העדכון היא בטוחה לשימוש. קבצי ה-ISO לא ייפגעו.#@להמשיך?",
"STR_INSTALL_TIP":"הדיסק יפורמט וכל המידע שבו ייעלם.#@להמשיך?",
"STR_INSTALL_TIP2":"הדיסק יפורמט וכל המידע שבו ייעלפ ויימחק לחלוטין.#@להמשיך? (בדיקה לווידוא)",
"STR_INSTALL_SUCCESS":"הצלחה!#@Ventoy הותקנה בהצלחה על הדיסק הנבחר",
"STR_INSTALL_FAILED":"אירעה תקלה בניסיון ההתקנה. אפשר לנסות לחבר את הדיסק מחדש ולבצע ניסיון התקנה נוסף. עיין בקובץ ה-log.txt לפרטים נוספים.",
"STR_UPDATE_SUCCESS":"הצלחה!#@Ventoy הותקנה בהצלחה על הדיסק הנבחר",
"STR_UPDATE_FAILED":"אירעה תקלה בניסיון העדכון. אפשר לנסות לחבר את הדיסק מחדש ולבצע ניסיון נוסף לעדכון. עיין בקובץ ה-log.txt לפרטים נוספים.",
"STR_WAIT_PROCESS":"עובד... נא המתן",
"STR_MENU_OPTION":"אפשרויות",
"STR_MENU_SECURE_BOOT":"תמיכה ב-Secure Boot",
"STR_MENU_PART_CFG":"הגדרת מחיצות",
"STR_BTN_OK":"אישור",
"STR_BTN_CANCEL":"ביטול",
"STR_PRESERVE_SPACE":"הגדר מקום לשמירה בדיסק",
"STR_SPACE_VAL_INVALID":"ערך לא חוקי עבור שטח לשמירה",
"STR_MENU_CLEAR":"נקה את Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy נמחקה בהצלחה מהדיסק הנבחר.",
"STR_CLEAR_FAILED":"אירעה תקלה בניסיון למחוק את Ventoy מהדיסק הנבחר. אפשר לנסות לחבר את הדיסק מחדש ולבצע שוב מחיקה. עיין בקובץ ה-log.txt לפרטים נוספים.",
"STR_MENU_PART_STYLE":"סוג מחיצה",
"STR_DISK_2TB_MBR_ERROR":"בחר ב-GPT עבור דיסק שגדול מ-2TB",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Portuguese (Português de Portugal)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Eskiso",
"STR_ERROR":"Erro",
"STR_WARNING":"Aviso",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Por favor, execute na pasta correta!",
"STR_INCORRECT_TREE_DIR":"Não me execute aqui, por favor transfira o pacote de instalação, e execute lá.",
"STR_DEVICE":"Dispositivo",
"STR_LOCAL_VER":"Ventoy em pacote",
"STR_DISK_VER":"Ventoy no dispositivo",
"STR_STATUS":"Estado - PRONTO",
"STR_INSTALL":"Instalar",
"STR_UPDATE":"Atualizar",
"STR_UPDATE_TIP":"A operação de atualização é segura, os ficheiros ISO não serão alterados.#@Continuar?",
"STR_INSTALL_TIP":"O disco será formatado e todos os dados serão perdidos.#@Continuar?",
"STR_INSTALL_TIP2":"O disco será formatado e todos os dados serão perdidos.#@Continuar? (Confirmação)",
"STR_INSTALL_SUCCESS":"Parabéns!#@Ventoy foi instalado com sucesso no dispositivo.",
"STR_INSTALL_FAILED":"Um erro ocorreu durante a instalação. Pode reconectar o dispositivo USB e tentar novamente. Verifique o ficheiro log.txt para mais detalhes.",
"STR_UPDATE_SUCCESS":"Parabéns!#@Ventoy foi atualizado com sucesso no dispositivo.",
"STR_UPDATE_FAILED":"Um erro ocorreu durante a atualização. Pode reconectar o dispositivo USB e tentar novamente. Verifique o ficheiro log.txt para mais detalhes.",
"STR_WAIT_PROCESS":"Uma thread está em execução, por favor espere...",
"STR_MENU_OPTION":"Opção",
"STR_MENU_SECURE_BOOT":"Boot seguro",
"STR_MENU_PART_CFG":"Configuração da Partição",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Cancelar",
"STR_PRESERVE_SPACE":"Preservar algum espaço no final do disco",
"STR_SPACE_VAL_INVALID":"Valor invalido para o espaço reservado",
"STR_MENU_CLEAR":"Remover o Ventoy",
"STR_CLEAR_SUCCESS":"O Ventoy foi removido deste dispositivo com sucesso.",
"STR_CLEAR_FAILED":"Um erro ocorreu ao remover o Ventoy do disco. Pode reconectar o dispositivo USB e tentar novamente. Verifique o ficheiro log.txt para mais detalhes.",
"STR_MENU_PART_STYLE":"Estilo de Partição",
"STR_DISK_2TB_MBR_ERROR":"Por favor selecione GPT para discos maiores que 2TB",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Indonesian (Bahasa Indonesia)",
"FontFamily":"Comic Sans MS",
"FontSize":16,
"Author":"Ida Bagus Anom Sanjaya",
"STR_ERROR":"Kesalahan",
"STR_WARNING":"Peringatan",
"STR_INFO":"Informasi",
"STR_INCORRECT_DIR":"Silakan jalankan pada direktori yang benar!",
"STR_INCORRECT_TREE_DIR":"Jangan jalankan di sini, silakan unduh paket pemasangan yang diliris, dan jalankan di sana.",
"STR_DEVICE":"Perangkat",
"STR_LOCAL_VER":"Ventoy pada Paket",
"STR_DISK_VER":"Ventoy pada Perangkat",
"STR_STATUS":"Status - SIAP",
"STR_INSTALL":"Pasang",
"STR_UPDATE":"Perbarui",
"STR_UPDATE_TIP":"Operasi pembaruan ini aman, Tidak akan ada perubahan berkas ISO.#@Lanjutkan?",
"STR_INSTALL_TIP":"Disk akan di-format dan semua data akan hilang.#@Lanjutkan?",
"STR_INSTALL_TIP2":"Disk akan di-format dan semua data akan hilang.#@Lanjutkan? (YAKIN)",
"STR_INSTALL_SUCCESS":"Selamat!#@Ventoy telah berhasil terpasang di perangkat ini.",
"STR_INSTALL_FAILED":"Terjadi kesalahan ketika pemasangan berlangsung. Anda perlu mencabut-pasang ulang USB dan coba lagi. Cek log.txt untuk detil.",
"STR_UPDATE_SUCCESS":"Selamat!#@Ventoy telah berhasil diperbarui di perangkat ini.",
"STR_UPDATE_FAILED":"Terjadi kesalahan ketika pembaruan berlangsung. Anda perlu mencabut-pasang ulang USB dan coba lagi. Cek log.txt untuk detil.",
"STR_WAIT_PROCESS":"Tugas sedang berjalan, silakan tunggu...",
"STR_MENU_OPTION":"Pilihan",
"STR_MENU_SECURE_BOOT":"Dukungan Secure Boot",
"STR_MENU_PART_CFG":"Konfigurasi Partisi",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Batal",
"STR_PRESERVE_SPACE":"Mempertahankan sejumlah ruang penyimpanan pada disk di bawah ini",
"STR_SPACE_VAL_INVALID":"Nilai menpertahankan ruang tidak valid",
"STR_MENU_CLEAR":"Bersihkan Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy telah berhasil dihapus pada perangkat ini.",
"STR_CLEAR_FAILED":"Terjadi kesalahan ketika penghapusan berlangsung. Anda perlu mencabut-pasang ulang USB dan coba lagi. Cek log.txt untuk detil.",
"STR_MENU_PART_STYLE":"Gaya Partisi",
"STR_DISK_2TB_MBR_ERROR":"Silakan pilih GPT untuk disk yang lebih dari 2TB",
"STR_SHOW_ALL_DEV":"Show All Devices",
"STR_PART_ALIGN_4KB":"Align partitions with 4KB",
"STR_WEB_COMMUNICATION_ERR":"Communication error:",
"STR_WEB_REMOTE_ABNORMAL":"Communication error: remote abnormal",
"STR_WEB_REQUEST_TIMEOUT":"Communication error: Request timed out",
"STR_WEB_SERVICE_UNAVAILABLE":"Communication error: Service Unavailable",
"STR_WEB_TOKEN_MISMATCH":"Daemon status updated, please retry later.",
"STR_WEB_SERVICE_BUSY":"Service is busy, please retry later.",
"STRXXX":""
},
{
"name":"Ukrainian (Українська)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Teraskull",
"STR_ERROR":"Помилка",
"STR_WARNING":"Попередження",
"STR_INFO":"Інформація",
"STR_INCORRECT_DIR":"Будь ласка, запустіть у правильному каталозі!",
"STR_INCORRECT_TREE_DIR":"Не запускайте мене тут, завантажте реліз інсталяційного пакету і запустіть там.",
"STR_DEVICE":"Пристрій",
"STR_LOCAL_VER":"Ventoy в пакеті",
"STR_DISK_VER":"Ventoy на пристрої",
"STR_STATUS":"Стан - ГОТОВИЙ",
"STR_INSTALL":"Встановити",
"STR_UPDATE":"Оновити",
"STR_UPDATE_TIP":"Процес оновлення безпечний, файли ISO залишаться незмінними.#@Продовжити?",
"STR_INSTALL_TIP":"Диск буде відформатовано, і всі дані будуть втрачені.#@Продовжити?",
"STR_INSTALL_TIP2":"Диск буде відформатовано, і всі дані будуть втрачені.#@Продовжити? (Подвійна перевірка)",
"STR_INSTALL_SUCCESS":"Вітаємо!#@Ventoy успішно встановлено на пристрій.",
"STR_INSTALL_FAILED":"Під час встановлення сталася помилка. Ви можете ще раз підключити USB і повторити спробу. Перевірте log.txt для деталей.",
"STR_UPDATE_SUCCESS":"Вітаємо!#@Ventoy на пристрої успішно оновлено.",
"STR_UPDATE_FAILED":"Під час оновлення сталася помилка. Ви можете ще раз підключити USB і повторити спробу. Перевірте log.txt для деталей.",
"STR_WAIT_PROCESS":"Потік запущено, зачекайте...",
"STR_MENU_OPTION":"Опції",
"STR_MENU_SECURE_BOOT":"Підтримка Secure Boot",
"STR_MENU_PART_CFG":"Конфігурація розділів",
"STR_BTN_OK":"ОК",
"STR_BTN_CANCEL":"Скасувати",
"STR_PRESERVE_SPACE":"Зарезервувати простір в кінці диска",
"STR_SPACE_VAL_INVALID":"Недійсне значення для зарезервованого простору",
"STR_MENU_CLEAR":"Видалити Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy успішно видалено з пристрою.",
"STR_CLEAR_FAILED":"Під час видалення Ventoy сталася помилка. Ви можете ще раз підключити USB і повторити спробу. Перевірте log.txt для деталей.",
"STR_MENU_PART_STYLE":"Стиль розмітки розділів",
"STR_DISK_2TB_MBR_ERROR":"Будь ласка, виберіть GPT для дисків понад 2TB",
"STR_SHOW_ALL_DEV":"Показати всі пристрої",
"STR_PART_ALIGN_4KB":"Вирівняти розділи з розміром 4КБ",
"STR_WEB_COMMUNICATION_ERR":"Помилка зв'язку: ",
"STR_WEB_REMOTE_ABNORMAL":"Помилка зв'язку: віддалене з'єднання недійсне",
"STR_WEB_REQUEST_TIMEOUT":"Помилка зв'язку: Час очікування запиту минув",
"STR_WEB_SERVICE_UNAVAILABLE":"Помилка зв'язку: Служба недоступна",
"STR_WEB_TOKEN_MISMATCH":"Статус демона оновлено. Повторіть спробу пізніше.",
"STR_WEB_SERVICE_BUSY":"Служба зайнята, повторіть спробу пізніше.",
"STRXXX":""
},
{
"name":"Greek (Ελληνικά)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"grmasa, Vasilis Kosmidis",
"STR_ERROR":"Σφάλμα",
"STR_WARNING":"Προειδοποίηση",
"STR_INFO":"Πληροφορίες",
"STR_INCORRECT_DIR":"Παρακαλώ εκτελέστε στον σωστό κατάλογο!",
"STR_INCORRECT_TREE_DIR":"Μην με εκτελείτε εδώ, κατεβάστε το πακέτο εγκατάστασης και εκτελέστε εκεί.",
"STR_DEVICE":"Συσκευή",
"STR_LOCAL_VER":"Ventoy στο πρόγραμμα",
"STR_DISK_VER":"Ventoy στη συσκευή",
"STR_STATUS":"Κατάσταση - ΕΤΟΙΜΟ",
"STR_INSTALL":"Εγκατάσταση",
"STR_UPDATE":"Αναβάθμιση",
"STR_UPDATE_TIP":"Η λειτουργία αναβάθμισης είναι ασφαλής, τα αρχεία ISO δεν θα αλλάξουν.#@Συνέχεια;",
"STR_INSTALL_TIP":"Ο δίσκος θα μορφοποιηθεί και όλα τα δεδομένα θα χαθούν.#@Συνέχεια;",
"STR_INSTALL_TIP2":"Ο δίσκος θα μορφοποιηθεί και όλα τα δεδομένα θα χαθούν.#@Συνέχεια; (Επανελέγξτε)",
"STR_INSTALL_SUCCESS":"Συγχαρητήρια!#Το @Ventoy έχει εγκατασταθεί με επιτυχία στη συσκευή.",
"STR_INSTALL_FAILED":"Παρουσιάστηκε σφάλμα κατά την εγκατάσταση. Μπορείτε να επανασυνδέσετε το USB και να δοκιμάσετε ξανά. Ελέγξτε το αρχείο log.txt για λεπτομέρειες.",
"STR_UPDATE_SUCCESS":"Συγχαρητήρια!#Το @Ventoy ενημερώθηκε με επιτυχία στη συσκευή.",
"STR_UPDATE_FAILED":"Παρουσιάστηκε σφάλμα κατά την ενημέρωση. Μπορείτε να επανασυνδέσετε το USB και να δοκιμάσετε ξανά. Ελέγξτε το αρχείο log.txt για λεπτομέρειες.",
"STR_WAIT_PROCESS":"Ένα νήμα εκτελείται, παρακαλώ περιμένετε...",
"STR_MENU_OPTION":"Επιλογές",
"STR_MENU_SECURE_BOOT":"Υποστήριξη ασφαλούς εκκίνησης (Secure Boot)",
"STR_MENU_PART_CFG":"Διαμόρφωση κατατμήσεων",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Ακύρωση",
"STR_PRESERVE_SPACE":"Διατηρήστε λίγο χώρο στο κάτω μέρος του δίσκου",
"STR_SPACE_VAL_INVALID":"Μη έγκυρη τιμή για τον δεσμευμένο χώρο",
"STR_MENU_CLEAR":"Απεγκατάσταση του Ventoy",
"STR_CLEAR_SUCCESS":"Το Ventoy καταργήθηκε με επιτυχία από τη συσκευή.",
"STR_CLEAR_FAILED":"Παρουσιάστηκε σφάλμα κατά την εκκαθάριση του Ventoy από το δίσκο. Μπορείτε να επανασυνδέσετε το USB και να δοκιμάσετε ξανά. Ελέγξτε το αρχείο log.txt για λεπτομέρειες.",
"STR_MENU_PART_STYLE":"Στυλ κατατμήσεων",
"STR_DISK_2TB_MBR_ERROR":"Παρακαλώ επιλέξτε GPT για δίσκο άνω των 2 TB",
"STR_SHOW_ALL_DEV":"Προβολή όλων των συσκευών",
"STR_PART_ALIGN_4KB":"Ευθυγράμμιση κατατμήσεων με 4KB",
"STR_WEB_COMMUNICATION_ERR":"Σφάλμα επικοινωνίας:",
"STR_WEB_REMOTE_ABNORMAL":"Σφάλμα επικοινωνίας: απομακρυσμένη ανωμαλία",
"STR_WEB_REQUEST_TIMEOUT":"Σφάλμα επικοινωνίας: χρονική λήξη αιτήματος",
"STR_WEB_SERVICE_UNAVAILABLE":"Σφάλμα επικοινωνίας: υπηρεσία μη διαθέσιμη",
"STR_WEB_TOKEN_MISMATCH":"Η κατάσταση του δαίμονα επικαιροποιήθηκε. Παρακαλώ δοκιμάστε αργότερα.",
"STR_WEB_SERVICE_BUSY":"Η υπηρεσία είναι απασχολημένη. Παρακαλώ δοκιμάστε αργότερα.",
"STRXXX":""
},
{
"name":"Swedish (Svenska)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Sopor",
"STR_ERROR":"Fel",
"STR_WARNING":"Varning",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Kör programmet från korrekt katalog!",
"STR_INCORRECT_TREE_DIR":"Kör inte programmet här. Ladda ner installationspaketet och kör programmet där.",
"STR_DEVICE":"Enhet",
"STR_LOCAL_VER":"Ventoy i paketet",
"STR_DISK_VER":"Ventoy på enheten",
"STR_STATUS":"Status - REDO",
"STR_INSTALL":"Installera",
"STR_UPDATE":"Uppdatera",
"STR_UPDATE_TIP":"Uppdateringen är säker, ISO-filerna kommer att vara oförändrade.#@Fortsätta?",
"STR_INSTALL_TIP":"Enheten kommer att formateras och all data kommer att gå förlorad.#@Fortsätta?",
"STR_INSTALL_TIP2":"Enheten kommer att formateras och all data kommer att gå förlorad.#@Fortsätta? (Sista varningen!)",
"STR_INSTALL_SUCCESS":"Gratulerar!#@Ventoy har installerats på enheten.",
"STR_INSTALL_FAILED":"Ett fel inträffade under installationen. Prova att återansluta USB-enheten och försök igen. Läs i log.txt för mer information.",
"STR_UPDATE_SUCCESS":"Gratulerar!#@Ventoy har uppdaterats på enheten.",
"STR_UPDATE_FAILED":"Ett fel inträffade under uppdateringen. Prova att återansluta USB-enheten och försök igen. Läs i log.txt för mer information.",
"STR_WAIT_PROCESS":"En tråd körs redan, vänta...",
"STR_MENU_OPTION":"Alternativ",
"STR_MENU_SECURE_BOOT":"Stöd för säker start",
"STR_MENU_PART_CFG":"Partitionskonfiguration",
"STR_BTN_OK":"OK",
"STR_BTN_CANCEL":"Avbryt",
"STR_PRESERVE_SPACE":"Spara lite utrymme i slutet av enheten",
"STR_SPACE_VAL_INVALID":"Ogiltigt värde för reserverat utrymme",
"STR_MENU_CLEAR":"Ta bort Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy har tagits bort från enheten.",
"STR_CLEAR_FAILED":"Ett fel inträffade när Ventoy skulle tas bort från enheten. Prova att återansluta USB-enheten och försök igen. Läs i log.txt för mer information.",
"STR_MENU_PART_STYLE":"Partitionsstil",
"STR_DISK_2TB_MBR_ERROR":"Välj GPT för enhet över 2 TB",
"STR_SHOW_ALL_DEV":"Visa alla enheter",
"STR_PART_ALIGN_4KB":"Justera partitioner med 4KB",
"STR_WEB_COMMUNICATION_ERR":"Kommunikationsfel:",
"STR_WEB_REMOTE_ABNORMAL":"Kommunikationsfel: onormal fjärr",
"STR_WEB_REQUEST_TIMEOUT":"Kommunikationsfel: Begäran tog för lång tid",
"STR_WEB_SERVICE_UNAVAILABLE":"Kommunikationsfel: Tjänsten är inte tillgänglig",
"STR_WEB_TOKEN_MISMATCH":"Daemon-status uppdaterad. Försök igen senare.",
"STR_WEB_SERVICE_BUSY":"Tjänster är upptagen. Försök igen senare.",
"STRXXX":""
},
{
"name":"Slovenian (Slovenski)",
"FontFamily":"Courier New",
"FontSize":16,
"Author":"Urajmal",
"STR_ERROR":"Napaka",
"STR_WARNING":"Opozorilo",
"STR_INFO":"Info",
"STR_INCORRECT_DIR":"Prosim izberite pravilno pot!",
"STR_INCORRECT_TREE_DIR":"Ne zaganjajte tukaj. Prosim prenesite posodobljeno verzijo in jo zaženite.",
"STR_DEVICE":"Naprava",
"STR_LOCAL_VER":"Ventoy verzija",
"STR_DISK_VER":"Ventoy na napravi",
"STR_STATUS":"Status - PRIPRAVLJEN",
"STR_INSTALL":"Namesti",
"STR_UPDATE":"Nadgradi",
"STR_UPDATE_TIP":"Varna nadgradnja. ISO datoteke ne bodo spremenjene.#@Nadaljujem?",
"STR_INSTALL_TIP":"Ta disk bo formatiran in vsi podatki bodo izbrisani.#@Nadaljujem?",
"STR_INSTALL_TIP2":"Ta disk bo formatiran in vsi podatki bodo izbrisani.#@Nadaljujem? (Druga potrditev)",
"STR_INSTALL_SUCCESS":"Čestitamo!#@ventoy je bil uspešno nameščen na napravo.",
"STR_INSTALL_FAILED":"Med namestitvijo je prišlo do napake. Iztaknite in ponovno priklopite USB. Preverite log.txt za podrobnosti.",
"STR_UPDATE_SUCCESS":"Čestitamo!#@ventoy na napravi je bil uspešno posodobljen.",
"STR_UPDATE_FAILED":"Prišlo je do napake med nadgradnjo. Iztaknite in ponovno priklopite USB. Preverite log.txt za podrobnosti.",
"STR_WAIT_PROCESS":"Proces teče, prosimo počakajte, ...",
"STR_MENU_OPTION":"Nastavitve",
"STR_MENU_SECURE_BOOT":"Podpora Secure Boot",
"STR_MENU_PART_CFG":"Konfiguracija particij",
"STR_BTN_OK":"V redu",
"STR_BTN_CANCEL":"Prekliči",
"STR_PRESERVE_SPACE":"Ohrani nekaj prostora na koncu particije",
"STR_SPACE_VAL_INVALID":"Nepravilna vrednost za rezerviran prostor",
"STR_MENU_CLEAR":"Odstrani Ventoy",
"STR_CLEAR_SUCCESS":"Ventoy je bil uspešno odstranjen.",
"STR_CLEAR_FAILED":"Prišlo je do napake pri odstranjevanju Ventoy-a iz diska. Iztaknite in ponovno priklopite USB. Preverite log.txt za podrobnosti.",
"STR_MENU_PART_STYLE":"Vrsta particije",
"STR_DISK_2TB_MBR_ERROR":"Prosim izberite GPT za particije nad 2TB",
"STR_SHOW_ALL_DEV":"Pokaži vse naprave",
"STR_PART_ALIGN_4KB":"Poravnaj particije na 4KB",
"STR_WEB_COMMUNICATION_ERR":"Napaka v komunikaciji:",
"STR_WEB_REMOTE_ABNORMAL":"Napaka v komunikaciji: oddaljena težava",
"STR_WEB_REQUEST_TIMEOUT":"Napaka v komunikaciji: čas je potekel",
"STR_WEB_SERVICE_UNAVAILABLE":"Napaka v komunikaciji: storitev ni na voljo",
"STR_WEB_TOKEN_MISMATCH":"Zahteva storitve je potekla, prosim poskusite kasneje.",
"STR_WEB_SERVICE_BUSY":"Storitev je zasedena, prosim poskusite kasneje.",
"STRXXX":""
}
]
\ No newline at end of file
#!/bin/bash
echo "generating languages.js ..."
VTOY_PATH=$PWD/../
iconv -f utf-16 -t utf-8 ../LANGUAGES/languages.ini | egrep -v '=STR|^;' | egrep 'Language-|STR_' > languages.js
echo "checking languages.json ..."
sh $VTOY_PATH/LANGUAGES/check.sh $VTOY_PATH || exit 1
dos2unix languages.js
sed 's/\(STR_.*\)=/"\1":/g' -i languages.js
sed "s/: *'/:\"/g" -i languages.js
sed "s/'\s*$/\",/g" -i languages.js
sed 's/\[Language-\(.*\)\].*/"STR_XXX":""},{"name":"\1",/g' -i languages.js
echo "generating languages.json ..."
sed "1s/.*\},/var vtoy_language_data = \[/" -i languages.js
echo "var vtoy_language_data = " > languages.js
cat $VTOY_PATH/LANGUAGES/languages.json >> languages.js
echo ";" >> languages.js
sed 's/\("STR_WEB_COMMUNICATION_ERR"[^,]*\)/\1,/g' -i languages.js
sed 's/,,/,/g' -i languages.js
CNT=$(grep -v -c ',$' languages.js)
if [ $CNT -gt 0 ]; then
echo "====== FAILED ========="
grep -v -n ',$' languages.js
exit 1
fi
echo '"STR_XXX":""}' >> languages.js
echo '];' >> languages.js
dos2unix languages.js
rm -f WebUI/static/js/languages.js
mv languages.js WebUI/static/js/
echo "====== SUCCESS =========="
\ No newline at end of file
echo "====== SUCCESS =========="
......@@ -101,13 +101,19 @@ typedef enum OPT_SUBMENU
#define VTOY_MENU_LANGUAGE_BEGIN 0xB000
#define VENTOY_LANGUAGE_INI TEXT(".\\ventoy\\languages.ini")
#define VENTOY_LANGUAGE_INI TEXT(".\\ventoy\\languages.ini")
#define VENTOY_LANGUAGE_JSON TEXT(".\\ventoy\\languages.json")
#define VENTOY_LANGUAGE_INI_A ".\\ventoy\\languages.ini"
#define VENTOY_LANGUAGE_JSON_A ".\\ventoy\\languages.json"
#define VENTOY_CFG_INI TEXT(".\\Ventoy2Disk.ini")
#define VENTOY_CFG_INI_A ".\\Ventoy2Disk.ini"
#define VENTOY_MAX_LANGUAGE 200
#define GET_INI_STRING(Section, Key, Buf) GetPrivateProfileString(Section, Key, TEXT("#"), Buf, sizeof(Buf), VENTOY_LANGUAGE_INI)
typedef struct VENTOY_LANGUAGE
{
WCHAR Name[128];
......
......@@ -283,6 +283,12 @@ static int FilterPhysicalDrive(PHY_DRIVE_INFO *pDriveList, DWORD DriveCount)
CurDrive->PartStyle = (MBR.PartTbl[0].FsFlag == 0xEE) ? 1 : 0;
GetVentoyVerInPhyDrive(CurDrive, Part2StartSector, CurDrive->VentoyVersion, sizeof(CurDrive->VentoyVersion), &(CurDrive->SecureBootSupport));
Log("PhyDrive %d is Ventoy Disk ver:%s SecureBoot:%u", CurDrive->PhyDrive, CurDrive->VentoyVersion, CurDrive->SecureBootSupport);
if (CurDrive->VentoyVersion[0] == 0)
{
CurDrive->VentoyVersion[0] = '?';
Log("Unknown Ventoy Version");
}
}
}
......
......@@ -148,7 +148,7 @@ typedef struct PHY_DRIVE_INFO
STORAGE_BUS_TYPE BusType;
CHAR DriveLetters[64];
CHAR VentoyVersion[32];
BOOL SecureBootSupport;
......
......@@ -110,6 +110,7 @@
<ClCompile Include="process.c" />
<ClCompile Include="Utility.c" />
<ClCompile Include="Ventoy2Disk.c" />
<ClCompile Include="VentoyJson.c" />
<ClCompile Include="WinDialog.c" />
<ClCompile Include="xz-embedded-20130513\linux\lib\decompress_unxz.c" />
</ItemGroup>
......@@ -133,6 +134,7 @@
<ClInclude Include="process.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Ventoy2Disk.h" />
<ClInclude Include="VentoyJson.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Ventoy2Disk.rc" />
......
......@@ -78,6 +78,9 @@
<ClCompile Include="crc32.c">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="VentoyJson.c">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Ventoy2Disk.h">
......@@ -137,6 +140,9 @@
<ClInclude Include="process.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="VentoyJson.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Ventoy2Disk.rc">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment