1.0.66 release

This commit is contained in:
longpanda
2022-02-13 17:00:39 +08:00
parent c57717aea2
commit ba5978d298
287 changed files with 3349 additions and 226 deletions

View File

@@ -106,19 +106,109 @@ int ventoy_check_file_exist(const char * fmt, ...)
}
}
typedef struct grub_vlnk
{
int srclen;
char src[512];
char dst[512];
struct grub_vlnk *next;
}grub_vlnk;
static grub_vlnk *g_vlnk_list;
int grub_file_is_vlnk_suffix(const char *name, int len)
{
grub_uint32_t suffix;
if (len > 9)
{
suffix = *(grub_uint32_t *)(name + len - 4);
if (grub_strncmp(name + len - 9, ".vlnk.", 6) == 0)
{
/* .iso .wim .img .vhd .efi .dat */
if (suffix == 0x6F73692E || suffix == 0x6D69772E ||
suffix == 0x676D692E || suffix == 0x6468762E ||
suffix == 0x6966652E || suffix == 0x7461642E)
{
return 1;
}
}
else if (len > 10 && grub_strncmp(name + len - 10, ".vlnk.", 6) == 0)
{
/* vhdx vtoy */
if (suffix == 0x78646876 || suffix == 0x796F7476)
{
return 1;
}
}
}
return 0;
}
int grub_file_add_vlnk(const char *src, const char *dst)
{
grub_vlnk *node = NULL;
if (src && dst)
{
node = grub_zalloc(sizeof(grub_vlnk));
if (node)
{
node->srclen = (int)grub_strlen(src);
grub_strncpy(node->src, src, sizeof(node->src) - 1);
grub_strncpy(node->dst, dst, sizeof(node->dst) - 1);
node->next = g_vlnk_list;
g_vlnk_list = node;
return 0;
}
}
return 1;
}
const char *grub_file_get_vlnk(const char *name, int *vlnk)
{
int len;
grub_vlnk *node = g_vlnk_list;
len = grub_strlen(name);
if (!grub_file_is_vlnk_suffix(name, len))
{
return name;
}
while (node)
{
if (node->srclen == len && grub_strcmp(name, node->src) == 0)
{
*vlnk = 1;
return node->dst;
}
node = node->next;
}
return name;
}
grub_file_t
grub_file_open (const char *name, enum grub_file_type type)
{
int vlnk = 0;
grub_device_t device = 0;
grub_file_t file = 0, last_file = 0;
char *device_name;
const char *file_name;
grub_file_filter_id_t filter;
/* <DESC> : mem:xxx:size:xxx format in chainloader */
if (grub_strncmp(name, GRUB_MEMFILE_MEM, grub_strlen(GRUB_MEMFILE_MEM)) == 0) {
/* <DESC> : mem:xxx:size:xxx format in chainloader grub_strlen(GRUB_MEMFILE_MEM) */
if (grub_strncmp(name, GRUB_MEMFILE_MEM, 4) == 0) {
return grub_memfile_open(name);
}
}
if (g_vlnk_list && (type & GRUB_FILE_TYPE_NO_VLNK) == 0)
name = grub_file_get_vlnk(name, &vlnk);
device_name = grub_file_get_device_name (name);
if (grub_errno)
@@ -141,6 +231,7 @@ grub_file_open (const char *name, enum grub_file_type type)
goto fail;
file->device = device;
file->vlnk = vlnk;
/* In case of relative pathnames and non-Unix systems (like Windows)
* name of host files may not start with `/'. Blocklists for host files

View File

@@ -42,6 +42,44 @@ probe_dummy_iter (const char *filename __attribute__ ((unused)),
return 1;
}
grub_fs_t grub_fs_list_probe(grub_device_t device, const char **list)
{
int i;
grub_fs_t p;
if (!device->disk)
return 0;
for (p = grub_fs_list; p; p = p->next)
{
for (i = 0; list[i]; i++)
{
if (grub_strcmp(p->name, list[i]) == 0)
break;
}
if (list[i] == NULL)
continue;
grub_dprintf("fs", "Detecting %s...\n", p->name);
(p->fs_dir) (device, "/", probe_dummy_iter, NULL);
if (grub_errno == GRUB_ERR_NONE)
return p;
grub_error_push ();
grub_dprintf ("fs", "%s detection failed.\n", p->name);
grub_error_pop ();
if (grub_errno != GRUB_ERR_BAD_FS && grub_errno != GRUB_ERR_OUT_OF_RANGE) {
return 0;
}
grub_errno = GRUB_ERR_NONE;
}
return 0;
}
grub_fs_t
grub_fs_probe (grub_device_t device)
{

View File

@@ -102,6 +102,7 @@ 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;
grub_uint32_t g_wimiso_size = 0;
int g_vhdboot_enable = 0;
@@ -155,6 +156,8 @@ static char g_vtoy_prompt_msg[64];
static char g_json_case_mis_path[32];
static ventoy_vlnk_part *g_vlnk_part_list = NULL;
static int ventoy_get_fs_type(const char *fs)
{
if (NULL == fs)
@@ -699,32 +702,6 @@ grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...
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;
@@ -1007,6 +984,7 @@ static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc,
(void)args;
g_wimboot_enable = 0;
g_wimiso_size = 0;
grub_check_free(g_wimiso_path);
grub_check_free(g_wimiso_chunk_list.chunk);
@@ -1030,7 +1008,7 @@ static grub_err_t ventoy_cmd_load_wimboot(grub_extcmd_context_t ctxt, int argc,
g_wimboot_enable = 1;
g_wimiso_path = grub_strdup(args[0]);
g_wimiso_size = (grub_uint32_t)(file->size);
grub_file_close(file);
return 0;
@@ -1074,6 +1052,11 @@ static grub_err_t ventoy_cmd_concat_efi_iso(grub_extcmd_context_t ctxt, int argc
return 1;
}
if (grub_strncmp(args[0], g_iso_path, grub_strlen(g_iso_path)))
{
file->vlnk = 1;
}
totlen += ventoy_align_2k(file->size);
dirent = (ventoy_iso9660_override *)(buf + offset);
@@ -1611,12 +1594,231 @@ static int ventoy_img_name_valid(const char *filename, grub_size_t namelen)
return 1;
}
static int ventoy_vlnk_iterate_partition(struct grub_disk *disk, const grub_partition_t partition, void *data)
{
ventoy_vlnk_part *node = NULL;
grub_uint32_t *pSig = (grub_uint32_t *)data;
node = grub_zalloc(sizeof(ventoy_vlnk_part));
if (node)
{
node->disksig = *pSig;
node->partoffset = (partition->start << GRUB_DISK_SECTOR_BITS);
grub_snprintf(node->disk, sizeof(node->disk) - 1, "%s", disk->name);
grub_snprintf(node->device, sizeof(node->device) - 1, "%s,%d", disk->name, partition->number + 1);
node->next = g_vlnk_part_list;
g_vlnk_part_list = node;
}
return 0;
}
static int ventoy_vlnk_iterate_disk(const char *name, void *data)
{
grub_disk_t disk;
grub_uint32_t sig;
(void)data;
disk = grub_disk_open(name);
if (disk)
{
grub_disk_read(disk, 0, 0x1b8, 4, &sig);
/* skip ventoy device self */
if (sig != *(grub_uint32_t *)data)
{
grub_partition_iterate(disk, ventoy_vlnk_iterate_partition, &sig);
}
grub_disk_close(disk);
}
return 0;
}
static int ventoy_vlnk_probe_fs(ventoy_vlnk_part *cur)
{
const char *fs[ventoy_fs_max + 1] =
{
"exfat", "ntfs", "ext2", "xfs", "udf", "fat", NULL
};
if (!cur->dev)
{
cur->dev = grub_device_open(cur->device);
}
if (cur->dev)
{
cur->fs = grub_fs_list_probe(cur->dev, fs);
}
return 0;
}
static int ventoy_check_vlnk_data(ventoy_vlnk *vlnk, int print, char *dst, int size)
{
int diskfind = 0;
int partfind = 0;
int filefind = 0;
char *disk, *device;
grub_uint32_t readcrc, calccrc;
ventoy_vlnk_part *cur;
grub_fs_t fs = NULL;
if (grub_memcmp(&(vlnk->guid), &g_ventoy_guid, sizeof(ventoy_guid)))
{
if (print)
{
grub_printf("VLNK invalid guid\n");
grub_refresh();
}
return 1;
}
readcrc = vlnk->crc32;
vlnk->crc32 = 0;
calccrc = grub_getcrc32c(0, vlnk, sizeof(ventoy_vlnk));
if (readcrc != calccrc)
{
if (print)
{
grub_printf("VLNK invalid crc 0x%08x 0x%08x\n", calccrc, readcrc);
grub_refresh();
}
return 1;
}
if (!g_vlnk_part_list)
{
grub_disk_dev_iterate(ventoy_vlnk_iterate_disk, g_ventoy_part_info->MBR.BootCode + 0x1b8);
}
for (cur = g_vlnk_part_list; cur && filefind == 0; cur = cur->next)
{
if (cur->disksig == vlnk->disk_signature)
{
diskfind = 1;
disk = cur->disk;
if (cur->partoffset == vlnk->part_offset)
{
partfind = 1;
device = cur->device;
if (cur->probe == 0)
{
cur->probe = 1;
ventoy_vlnk_probe_fs(cur);
}
if (!fs)
{
fs = cur->fs;
}
if (cur->fs)
{
struct grub_file file;
grub_memset(&file, 0, sizeof(file));
file.device = cur->dev;
if (cur->fs->fs_open(&file, vlnk->filepath) == GRUB_ERR_NONE)
{
filefind = 1;
cur->fs->fs_close(&file);
grub_snprintf(dst, size - 1, "(%s)%s", cur->device, vlnk->filepath);
}
}
}
}
}
if (print)
{
grub_printf("\n==== VLNK Information ====\n"
"Disk Signature: %08x\n"
"Partition Offset: %llu\n"
"File Path: <%s>\n\n",
vlnk->disk_signature, (ulonglong)vlnk->part_offset, vlnk->filepath);
if (diskfind)
{
grub_printf("Disk Find: [ YES ] [ %s ]\n", disk);
}
else
{
grub_printf("Disk Find: [ NO ]\n");
}
if (partfind)
{
grub_printf("Part Find: [ YES ] [ %s ] [ %s ]\n", device, fs ? fs->name : "N/A");
}
else
{
grub_printf("Part Find: [ NO ]\n");
}
grub_printf("File Find: [ %s ]\n", filefind ? "YES" : "NO");
if (filefind)
{
grub_printf("VLNK File: <%s>\n", dst);
}
grub_printf("\n");
grub_refresh();
}
return (1 - filefind);
}
int ventoy_add_vlnk_file(char *dir, const char *name)
{
int rc = 1;
char src[512];
char dst[512];
grub_file_t file = NULL;
ventoy_vlnk vlnk;
if (!dir)
{
grub_snprintf(src, sizeof(src), "%s%s", g_iso_path, name);
}
else if (dir[0] == '/')
{
grub_snprintf(src, sizeof(src), "%s%s%s", g_iso_path, dir, name);
}
else
{
grub_snprintf(src, sizeof(src), "%s/%s%s", g_iso_path, dir, name);
}
file = grub_file_open(src, VENTOY_FILE_TYPE);
if (!file)
{
return 1;
}
grub_memset(&vlnk, 0, sizeof(vlnk));
grub_file_read(file, &vlnk, sizeof(vlnk));
grub_file_close(file);
if (ventoy_check_vlnk_data(&vlnk, 0, dst, sizeof(dst)) == 0)
{
rc = grub_file_add_vlnk(src, dst);
}
return rc;
}
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;
int vlnk = 0;
grub_size_t len;
img_info *img;
img_info *tail;
@@ -1785,6 +1987,18 @@ static int ventoy_collect_img_files(const char *filename, const struct grub_dirh
return 0;
}
}
if (info->size == VTOY_FILT_MIN_FILE_SIZE || info->size == 0)
{
if (grub_file_is_vlnk_suffix(filename, len))
{
vlnk = 1;
if (ventoy_add_vlnk_file(node->dir, filename) != 0)
{
return 0;
}
}
}
img = grub_zalloc(sizeof(img_info));
if (img)
@@ -1796,9 +2010,16 @@ static int ventoy_collect_img_files(const char *filename, const struct grub_dirh
img->pathlen = grub_snprintf(img->path, sizeof(img->path), "%s%s", node->dir, img->name);
img->size = info->size;
if (0 == img->size)
if (vlnk || 0 == img->size)
{
img->size = ventoy_grub_get_file_size("%s/%s%s", g_iso_path, node->dir, filename);
if (node->dir[0] == '/')
{
img->size = ventoy_grub_get_file_size("%s%s%s", g_iso_path, node->dir, filename);
}
else
{
img->size = ventoy_grub_get_file_size("%s/%s%s", g_iso_path, node->dir, filename);
}
}
if (img->size < VTOY_FILT_MIN_FILE_SIZE)
@@ -2803,6 +3024,10 @@ void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param)
param->vtoy_reserved[5] = 1;
}
/* ventoy_disk_signature used for vlnk */
param->vtoy_reserved[6] = file->vlnk;
grub_memcpy(param->vtoy_reserved + 7, g_ventoy_part_info->MBR.BootCode + 0x1b8, 4);
/* calculate checksum */
for (i = 0; i < sizeof(ventoy_os_param); i++)
{
@@ -5084,6 +5309,114 @@ out:
return ret;
}
static grub_err_t grub_cmd_vlnk_dump_part(grub_extcmd_context_t ctxt, int argc, char **args)
{
int n = 0;
ventoy_vlnk_part *node;
(void)ctxt;
(void)argc;
(void)args;
for (node = g_vlnk_part_list; node; node = node->next)
{
grub_printf("[%d] %s disksig:%08x offset:%llu fs:%s\n",
++n, node->device, node->disksig,
(ulonglong)node->partoffset, (node->fs ? node->fs->name : "N/A"));
}
return 0;
}
static grub_err_t grub_cmd_is_vlnk_name(grub_extcmd_context_t ctxt, int argc, char **args)
{
int len = 0;
(void)ctxt;
if (argc == 1)
{
len = (int)grub_strlen(args[0]);
if (grub_file_is_vlnk_suffix(args[0], len))
{
return 0;
}
}
return 1;
}
static grub_err_t grub_cmd_get_vlnk_dst(grub_extcmd_context_t ctxt, int argc, char **args)
{
int vlnk = 0;
const char *name = NULL;
(void)ctxt;
if (argc == 2)
{
grub_env_unset(args[1]);
name = grub_file_get_vlnk(args[0], &vlnk);
if (vlnk)
{
debug("VLNK SRC: <%s>\n", args[0]);
debug("VLNK DST: <%s>\n", name);
grub_env_set(args[1], name);
return 0;
}
}
return 1;
}
static grub_err_t grub_cmd_check_vlnk(grub_extcmd_context_t ctxt, int argc, char **args)
{
int ret = 1;
int len = 0;
grub_file_t file = NULL;
ventoy_vlnk vlnk;
char dst[512];
(void)ctxt;
if (argc != 1)
{
goto out;
}
len = (int)grub_strlen(args[0]);
if (!grub_file_is_vlnk_suffix(args[0], len))
{
grub_printf("Invalid vlnk suffix\n");
goto out;
}
file = grub_file_open(args[0], VENTOY_FILE_TYPE | GRUB_FILE_TYPE_NO_VLNK);
if (!file)
{
grub_printf("Failed to open %s\n", args[0]);
goto out;
}
if (file->size != 32768)
{
grub_printf("Invalid vlnk file (size=%llu).\n", (ulonglong)file->size);
goto out;
}
grub_memset(&vlnk, 0, sizeof(vlnk));
grub_file_read(file, &vlnk, sizeof(vlnk));
ret = ventoy_check_vlnk_data(&vlnk, 1, dst, sizeof(dst));
out:
grub_refresh();
check_free(file, grub_file_close);
grub_errno = GRUB_ERR_NONE;
return ret;
}
int ventoy_env_init(void)
{
char buf[64];
@@ -5271,6 +5604,10 @@ static cmd_para ventoy_cmds[] =
{ "vt_append_extra_sector", ventoy_cmd_append_ext_sector, 0, NULL, "", "", NULL },
{ "gptpriority", grub_cmd_gptpriority, 0, NULL, "", "", NULL },
{ "vt_syslinux_need_nojoliet", grub_cmd_syslinux_nojoliet, 0, NULL, "", "", NULL },
{ "vt_vlnk_check", grub_cmd_check_vlnk, 0, NULL, "", "", NULL },
{ "vt_vlnk_dump_part", grub_cmd_vlnk_dump_part, 0, NULL, "", "", NULL },
{ "vt_is_vlnk_name", grub_cmd_is_vlnk_name, 0, NULL, "", "", NULL },
{ "vt_get_vlnk_dst", grub_cmd_get_vlnk_dst, 0, NULL, "", "", NULL },
};
int ventoy_register_all_cmd(void)

View File

@@ -304,6 +304,7 @@ extern ventoy_guid g_ventoy_guid;
extern ventoy_img_chunk_list g_img_chunk_list;
extern ventoy_img_chunk_list g_wimiso_chunk_list;
extern char *g_wimiso_path;
extern grub_uint32_t g_wimiso_size;
extern char g_arch_mode_suffix[64];
extern const char *g_menu_prefix[img_type_max];
@@ -604,7 +605,6 @@ grub_err_t ventoy_cmd_trailer_cpio(grub_extcmd_context_t ctxt, int argc, char **
int ventoy_cpio_newc_fill_head(void *buf, int filesize, const void *filedata, const char *name);
grub_file_t ventoy_grub_file_open(enum grub_file_type type, const char *fmt, ...);
grub_uint64_t ventoy_grub_get_file_size(const char *fmt, ...);
int ventoy_is_file_exist(const char *fmt, ...);
int ventoy_is_dir_exist(const char *fmt, ...);
int ventoy_fill_data(grub_uint32_t buflen, char *buffer);
grub_err_t ventoy_cmd_load_plugin(grub_extcmd_context_t ctxt, int argc, char **args);
@@ -826,6 +826,7 @@ typedef struct ventoy_video_mode
typedef struct file_fullpath
{
char path[256];
int vlnk_add;
}file_fullpath;
typedef struct theme_list
@@ -1153,5 +1154,20 @@ struct g_ventoy_map{
};
#pragma pack()
typedef struct ventoy_vlnk_part
{
grub_uint32_t disksig;
grub_uint64_t partoffset;
char disk[64];
char device[64];
grub_device_t dev;
grub_fs_t fs;
int probe;
struct ventoy_vlnk_part *next;
}ventoy_vlnk_part;
extern char g_iso_path[256];
int ventoy_add_vlnk_file(char *dir, const char *name);
#endif /* __VENTOY_DEF_H__ */

View File

@@ -171,11 +171,11 @@ static int ventoy_plugin_theme_check(VTOY_JSON *json, const char *isodisk)
grub_printf("file: %s\n", value);
if (value[0] == '/')
{
exist = ventoy_is_file_exist("%s%s", isodisk, value);
exist = ventoy_check_file_exist("%s%s", isodisk, value);
}
else
{
exist = ventoy_is_file_exist("%s/ventoy/%s", isodisk, value);
exist = ventoy_check_file_exist("%s/ventoy/%s", isodisk, value);
}
if (exist == 0)
@@ -195,11 +195,11 @@ static int ventoy_plugin_theme_check(VTOY_JSON *json, const char *isodisk)
grub_printf("file: %s\n", value);
if (value[0] == '/')
{
exist = ventoy_is_file_exist("%s%s", isodisk, value);
exist = ventoy_check_file_exist("%s%s", isodisk, value);
}
else
{
exist = ventoy_is_file_exist("%s/ventoy/%s", isodisk, value);
exist = ventoy_check_file_exist("%s/ventoy/%s", isodisk, value);
}
if (exist == 0)
@@ -463,7 +463,7 @@ static int ventoy_plugin_check_path(const char *path, const char *file)
return 1;
}
if (!ventoy_is_file_exist("%s%s", path, file))
if (!ventoy_check_file_exist("%s%s", path, file))
{
grub_printf("%s%s does NOT exist\n", path, file);
return 1;
@@ -561,7 +561,7 @@ static int ventoy_plugin_parse_fullpath
{
debug("%s is string type data\n", node->pcName);
if ((node->unData.pcStrVal[0] != '/') || (!ventoy_is_file_exist("%s%s", isodisk, node->unData.pcStrVal)))
if ((node->unData.pcStrVal[0] != '/') || (!ventoy_check_file_exist("%s%s", isodisk, node->unData.pcStrVal)))
{
debug("%s%s file not found\n", isodisk, node->unData.pcStrVal);
return 1;
@@ -596,7 +596,7 @@ static int ventoy_plugin_parse_fullpath
for (count = 0, child = node->pstChild; child; child = child->pstNext)
{
if (ventoy_is_file_exist("%s%s", isodisk, child->unData.pcStrVal))
if (ventoy_check_file_exist("%s%s", isodisk, child->unData.pcStrVal))
{
grub_snprintf(path->path, sizeof(path->path), "%s", child->unData.pcStrVal);
path++;
@@ -1401,7 +1401,7 @@ static int ventoy_plugin_menualias_check(VTOY_JSON *json, const char *isodisk)
{
grub_printf("image: <%s> [ * ]\n", path);
}
else if (ventoy_is_file_exist("%s%s", isodisk, path))
else if (ventoy_check_file_exist("%s%s", isodisk, path))
{
grub_printf("image: <%s> [ OK ]\n", path);
}
@@ -1542,7 +1542,7 @@ static int ventoy_plugin_menutip_check(VTOY_JSON *json, const char *isodisk)
{
grub_printf("image: <%s> [ * ]\n", path);
}
else if (ventoy_is_file_exist("%s%s", isodisk, path))
else if (ventoy_check_file_exist("%s%s", isodisk, path))
{
grub_printf("image: <%s> [ OK ]\n", path);
}
@@ -2684,6 +2684,8 @@ persistence_config * ventoy_plugin_find_persistent(const char *isopath)
int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, ventoy_img_chunk_list *chunk_list)
{
int rc = 1;
int len = 0;
char *path = NULL;
grub_uint64_t start = 0;
grub_file_t file = NULL;
persistence_config *node = NULL;
@@ -2704,10 +2706,22 @@ int ventoy_plugin_get_persistent_chunklist(const char *isopath, int index, vento
return 1;
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", g_iso_disk_name, node->backendpath[index].path);
path = node->backendpath[index].path;
if (node->backendpath[index].vlnk_add == 0)
{
len = grub_strlen(path);
if (len > 9 && grub_strncmp(path + len - 9, ".vlnk.dat", 9) == 0)
{
ventoy_add_vlnk_file(NULL, path);
node->backendpath[index].vlnk_add = 1;
}
}
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s%s", g_iso_disk_name, path);
if (!file)
{
debug("Failed to open file %s%s\n", g_iso_disk_name, node->backendpath[index].path);
debug("Failed to open file %s%s\n", g_iso_disk_name, path);
goto end;
}

View File

@@ -667,6 +667,11 @@ grub_err_t ventoy_cmd_raw_chain_data(grub_extcmd_context_t ctxt, int argc, char
return 1;
}
if (grub_strncmp(args[0], g_iso_path, grub_strlen(g_iso_path)))
{
file->vlnk = 1;
}
img_chunk_size = g_img_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
size = sizeof(ventoy_chain_head) + img_chunk_size;

View File

@@ -1994,21 +1994,12 @@ static grub_uint32_t ventoy_get_wim_iso_offset(const char *filepath)
return imgoffset;
}
static int ventoy_get_wim_chunklist(const char *filename, ventoy_img_chunk_list *wimchunk, grub_uint64_t *wimsize)
static int ventoy_get_wim_chunklist(grub_file_t wimfile, ventoy_img_chunk_list *wimchunk)
{
grub_file_t wimfile;
wimfile = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", filename);
if (!wimfile)
{
return 1;
}
grub_memset(wimchunk, 0, sizeof(ventoy_img_chunk_list));
wimchunk->chunk = grub_malloc(sizeof(ventoy_img_chunk) * DEFAULT_CHUNK_NUM);
if (NULL == wimchunk->chunk)
{
grub_file_close(wimfile);
return grub_error(GRUB_ERR_OUT_OF_MEMORY, "Can't allocate image chunk memoty\n");
}
@@ -2017,9 +2008,6 @@ static int ventoy_get_wim_chunklist(const char *filename, ventoy_img_chunk_list
ventoy_get_block_list(wimfile, wimchunk, wimfile->device->disk->partition->start);
*wimsize = wimfile->size;
grub_file_close(wimfile);
return 0;
}
@@ -2058,7 +2046,7 @@ grub_err_t ventoy_cmd_wim_check_bootable(grub_extcmd_context_t ctxt, int argc, c
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
static grub_err_t ventoy_vlnk_wim_chain_data(grub_file_t wimfile)
{
grub_uint32_t i = 0;
grub_uint32_t imgoffset = 0;
@@ -2079,10 +2067,7 @@ grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char
ventoy_img_chunk_list wimchunk;
char envbuf[128];
(void)ctxt;
(void)argc;
debug("wim chain data begin <%s> ...\n", args[0]);
debug("vlnk wim chain data begin <%s> ...\n", wimfile->name);
if (NULL == g_wimiso_chunk_list.chunk || NULL == g_wimiso_path)
{
@@ -2097,11 +2082,177 @@ grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char
return 1;
}
if (0 != ventoy_get_wim_chunklist(args[0], &wimchunk, &wimsize))
if (0 != ventoy_get_wim_chunklist(wimfile, &wimchunk))
{
grub_printf("Failed to get wim chunklist\n");
return 1;
}
wimsize = wimfile->size;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", g_wimiso_path);
if (!file)
{
return 1;
}
boot_catlog = ventoy_get_iso_boot_catlog(file);
img_chunk1_size = g_wimiso_chunk_list.cur_chunk * sizeof(ventoy_img_chunk);
img_chunk2_size = wimchunk.cur_chunk * sizeof(ventoy_img_chunk);
override_size = sizeof(ventoy_override_chunk) + g_wimiso_size;
size = sizeof(ventoy_chain_head) + img_chunk1_size + img_chunk2_size + override_size;
pLastChain = grub_env_get("vtoy_chain_mem_addr");
if (pLastChain)
{
chain = (ventoy_chain_head *)grub_strtoul(pLastChain, NULL, 16);
if (chain)
{
debug("free last chain memory %p\n", chain);
grub_free(chain);
}
}
chain = grub_malloc(size);
if (!chain)
{
grub_printf("Failed to alloc chain memory size %u\n", size);
grub_file_close(file);
return 1;
}
grub_snprintf(envbuf, sizeof(envbuf), "0x%lx", (unsigned long)chain);
grub_env_set("vtoy_chain_mem_addr", envbuf);
grub_snprintf(envbuf, sizeof(envbuf), "%u", size);
grub_env_set("vtoy_chain_mem_size", envbuf);
grub_memset(chain, 0, sizeof(ventoy_chain_head));
/* part 1: os parameter */
g_ventoy_chain_type = ventoy_chain_wim;
ventoy_fill_os_param(wimfile, &(chain->os_param));
/* part 2: chain head */
disk = wimfile->device->disk;
chain->disk_drive = disk->id;
chain->disk_sector_size = (1 << disk->log_sector_size);
chain->real_img_size_in_bytes = ventoy_align_2k(file->size) + ventoy_align_2k(wimsize);
chain->virt_img_size_in_bytes = chain->real_img_size_in_bytes;
chain->boot_catalog = boot_catlog;
if (!ventoy_is_efi_os())
{
grub_file_seek(file, boot_catlog * 2048);
grub_file_read(file, chain->boot_catalog_sector, sizeof(chain->boot_catalog_sector));
}
/* part 3: image chunk */
chain->img_chunk_offset = sizeof(ventoy_chain_head);
chain->img_chunk_num = g_wimiso_chunk_list.cur_chunk + wimchunk.cur_chunk;
grub_memcpy((char *)chain + chain->img_chunk_offset, g_wimiso_chunk_list.chunk, img_chunk1_size);
chunknode = (ventoy_img_chunk *)((char *)chain + chain->img_chunk_offset);
for (i = 0; i < g_wimiso_chunk_list.cur_chunk; i++)
{
chunknode->disk_end_sector = chunknode->disk_end_sector - chunknode->disk_start_sector;
chunknode->disk_start_sector = 0;
chunknode++;
}
/* fs cluster size >= 2048, so don't need to proc align */
/* align by 2048 */
chunknode = wimchunk.chunk + wimchunk.cur_chunk - 1;
i = (chunknode->disk_end_sector + 1 - chunknode->disk_start_sector) % 4;
if (i)
{
chunknode->disk_end_sector += 4 - i;
}
isosector = (grub_uint32_t)((file->size + 2047) / 2048);
for (i = 0; i < wimchunk.cur_chunk; i++)
{
chunknode = wimchunk.chunk + i;
chunknode->img_start_sector = isosector;
chunknode->img_end_sector = chunknode->img_start_sector +
((chunknode->disk_end_sector + 1 - chunknode->disk_start_sector) / 4) - 1;
isosector = chunknode->img_end_sector + 1;
}
grub_memcpy((char *)chain + chain->img_chunk_offset + img_chunk1_size, wimchunk.chunk, img_chunk2_size);
/* part 4: override chunk */
chain->override_chunk_offset = chain->img_chunk_offset + img_chunk1_size + img_chunk2_size;
chain->override_chunk_num = 1;
override = (ventoy_override_chunk *)((char *)chain + chain->override_chunk_offset);
override->img_offset = 0;
override->override_size = g_wimiso_size;
grub_file_seek(file, 0);
grub_file_read(file, override->override_data, file->size);
dirent = (ventoy_iso9660_override *)(override->override_data + imgoffset);
dirent->first_sector = (grub_uint32_t)((file->size + 2047) / 2048);
dirent->size = (grub_uint32_t)(wimsize);
dirent->first_sector_be = grub_swap_bytes32(dirent->first_sector);
dirent->size_be = grub_swap_bytes32(dirent->size);
debug("imgoffset=%u first_sector=0x%x size=0x%x\n", imgoffset, dirent->first_sector, dirent->size);
if (ventoy_is_efi_os() == 0)
{
ventoy_windows_drive_map(chain);
}
grub_file_close(file);
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
static grub_err_t ventoy_normal_wim_chain_data(grub_file_t wimfile)
{
grub_uint32_t i = 0;
grub_uint32_t imgoffset = 0;
grub_uint32_t size = 0;
grub_uint32_t isosector = 0;
grub_uint64_t wimsize = 0;
grub_uint32_t boot_catlog = 0;
grub_uint32_t img_chunk1_size = 0;
grub_uint32_t img_chunk2_size = 0;
grub_uint32_t override_size = 0;
grub_file_t file;
grub_disk_t disk;
const char *pLastChain = NULL;
ventoy_chain_head *chain;
ventoy_iso9660_override *dirent;
ventoy_img_chunk *chunknode;
ventoy_override_chunk *override;
ventoy_img_chunk_list wimchunk;
char envbuf[128];
debug("normal wim chain data begin <%s> ...\n", wimfile->name);
if (NULL == g_wimiso_chunk_list.chunk || NULL == g_wimiso_path)
{
grub_printf("ventoy not ready\n");
return 1;
}
imgoffset = ventoy_get_wim_iso_offset(g_wimiso_path);
if (imgoffset == 0)
{
grub_printf("image offset not found\n");
return 1;
}
if (0 != ventoy_get_wim_chunklist(wimfile, &wimchunk))
{
grub_printf("Failed to get wim chunklist\n");
return 1;
}
wimsize = wimfile->size;
file = ventoy_grub_file_open(VENTOY_FILE_TYPE, "%s", g_wimiso_path);
if (!file)
@@ -2214,6 +2365,33 @@ grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char
VENTOY_CMD_RETURN(GRUB_ERR_NONE);
}
grub_err_t ventoy_cmd_wim_chain_data(grub_extcmd_context_t ctxt, int argc, char **args)
{
grub_err_t ret;
grub_file_t wimfile;
(void)ctxt;
(void)argc;
wimfile = grub_file_open(args[0], VENTOY_FILE_TYPE);
if (!wimfile)
{
return 1;
}
if (wimfile->vlnk)
{
ret = ventoy_vlnk_wim_chain_data(wimfile);
}
else
{
ret = ventoy_normal_wim_chain_data(wimfile);
}
grub_file_close(wimfile);
return ret;
}
int ventoy_chain_file_size(const char *path)
{
int size;

View File

@@ -132,7 +132,8 @@ enum grub_file_type
/* --skip-sig is specified. */
GRUB_FILE_TYPE_SKIP_SIGNATURE = 0x10000,
GRUB_FILE_TYPE_NO_DECOMPRESS = 0x20000
GRUB_FILE_TYPE_NO_DECOMPRESS = 0x20000,
GRUB_FILE_TYPE_NO_VLNK = 0x40000,
};
/* File description. */
@@ -141,6 +142,8 @@ struct grub_file
/* File name. */
char *name;
int vlnk;
/* The underlying device. */
grub_device_t device;
@@ -213,6 +216,10 @@ grub_ssize_t EXPORT_FUNC(grub_file_read) (grub_file_t file, void *buf,
grub_off_t EXPORT_FUNC(grub_file_seek) (grub_file_t file, grub_off_t offset);
grub_err_t EXPORT_FUNC(grub_file_close) (grub_file_t file);
int EXPORT_FUNC(grub_file_is_vlnk_suffix)(const char *name, int len);
int EXPORT_FUNC(grub_file_add_vlnk)(const char *src, const char *dst);
const char * EXPORT_FUNC(grub_file_get_vlnk)(const char *name, int *vlnk);
/* Return value of grub_file_size() in case file size is unknown. */
#define GRUB_FILE_SIZE_UNKNOWN 0xffffffffffffffffULL

View File

@@ -128,5 +128,6 @@ grub_fs_unregister (grub_fs_t fs)
#define FOR_FILESYSTEMS(var) FOR_LIST_ELEMENTS((var), (grub_fs_list))
grub_fs_t EXPORT_FUNC(grub_fs_probe) (grub_device_t device);
grub_fs_t EXPORT_FUNC(grub_fs_list_probe) (grub_device_t device, const char **list);
#endif /* ! GRUB_FS_HEADER */

View File

@@ -122,6 +122,8 @@ typedef struct ventoy_os_param
* vtoy_reserved[3]: vtoy_iso_format 0:iso9660 1:udf
* vtoy_reserved[4]: vtoy_windows_cd_prompt
* vtoy_reserved[5]: vtoy_linux_remount
* vtoy_reserved[6]: vtoy_vlnk
* vtoy_reserved[7~10]: vtoy_disk_sig[4] used for vlnk
*
*/
grub_uint8_t vtoy_reserved[32]; // Internal use by ventoy
@@ -151,11 +153,23 @@ typedef struct ventoy_secure_data
grub_uint8_t magic2[16]; /* VENTOY_GUID */
}ventoy_secure_data;
typedef struct ventoy_vlnk
{
ventoy_guid guid; // VENTOY_GUID
grub_uint32_t crc32; // crc32
grub_uint32_t disk_signature;
grub_uint64_t part_offset; // in bytes
char filepath[384];
grub_uint8_t reserved[96];
}ventoy_vlnk;
#pragma pack()
// compile assert check : sizeof(ventoy_os_param) must be 512
COMPILE_ASSERT(1,sizeof(ventoy_os_param) == 512);
COMPILE_ASSERT(2,sizeof(ventoy_secure_data) == 4096);
COMPILE_ASSERT(3,sizeof(ventoy_vlnk) == 512);